#ifndef _GTCACA_WIN_COMPAT_H_
#define _GTCACA_WIN_COMPAT_H_
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/stat.h>
#include <basetsd.h>
#if defined(__MINGW32__)
#include <unistd.h>
#include <dirent.h>
#else
#ifndef _SSIZE_T_DEFINED
typedef SSIZE_T ssize_t;
#define _SSIZE_T_DEFINED
#endif
#define isatty(fd) _isatty(fd)
#define write(fd, buf, n) _write((fd), (buf), (unsigned int)(n))
static __inline void usleep(unsigned long usec) { Sleep((DWORD)(usec / 1000UL)); }
#ifndef strcasecmp
#define strcasecmp(a, b) _stricmp((a), (b))
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#endif
struct dirent { char d_name[MAX_PATH]; };
typedef struct GTCACA_DIR_s {
HANDLE handle;
WIN32_FIND_DATAA find;
int first;
struct dirent entry;
} DIR;
static __inline DIR *opendir(const char *path) {
DIR *d;
char pattern[MAX_PATH];
d = (DIR *)malloc(sizeof(DIR));
if (!d) return NULL;
snprintf(pattern, sizeof pattern, "%s\\*", path);
d->handle = FindFirstFileA(pattern, &d->find);
if (d->handle == INVALID_HANDLE_VALUE) { free(d); return NULL; }
d->first = 1;
return d;
}
static __inline struct dirent *readdir(DIR *d) {
if (!d->first && !FindNextFileA(d->handle, &d->find)) return NULL;
d->first = 0;
strncpy(d->entry.d_name, d->find.cFileName, MAX_PATH - 1);
d->entry.d_name[MAX_PATH - 1] = '\0';
return &d->entry;
}
static __inline int closedir(DIR *d) {
if (d) {
if (d->handle != INVALID_HANDLE_VALUE) FindClose(d->handle);
free(d);
}
return 0;
}
#endif
#if defined(__MINGW32__) && defined(_GNU_SOURCE) && __USE_MINGW_ANSI_STDIO
# define GTCACA_HAVE_ASPRINTF 1
#endif
#ifndef GTCACA_HAVE_ASPRINTF
static __inline int asprintf(char **strp, const char *fmt, ...) {
va_list ap;
int len;
va_start(ap, fmt);
len = _vscprintf(fmt, ap);
va_end(ap);
if (len < 0) { *strp = NULL; return -1; }
*strp = (char *)malloc((size_t)len + 1);
if (!*strp) return -1;
va_start(ap, fmt);
len = vsnprintf(*strp, (size_t)len + 1, fmt, ap);
va_end(ap);
return len;
}
#endif
static __inline char *realpath(const char *path, char *resolved) {
return _fullpath(resolved, path, _MAX_PATH);
}
static __inline void gtcaca_win_enable_vt(void) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
if (h != INVALID_HANDLE_VALUE && GetConsoleMode(h, &mode))
SetConsoleMode(h, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
}
#endif
#endif