#include <config.h>
#include <FL/platform.H>
#include "Fl_WinAPI_System_Driver.H"
#include <FL/Fl.H>
#include <FL/fl_utf8.h>
#include <FL/filename.H>
#include <FL/Fl_File_Browser.H>
#include <FL/Fl_File_Icon.H>
#include "../../Fl_String.H"
#include "../../flstring.h"
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>
#include <rpc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <shellapi.h>
#include <wchar.h>
#include <process.h>
#include <locale.h>
#include <time.h>
#include <direct.h>
#include <io.h>
#include <fcntl.h>
#if !(defined _WIN32_IE) || (_WIN32_IE < 0x0500)
# undef _WIN32_IE
# define _WIN32_IE 0x0500
#endif
#include <shlobj.h>
typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid);
# ifdef DIRECTORY
# undef DIRECTORY
# endif
#ifdef __CYGWIN__
# include <mntent.h>
#endif
#ifndef DEBUG_HOME_DIRECTORY_NAME
#define DEBUG_HOME_DIRECTORY_NAME 0
#endif
#if DEBUG_HOME_DIRECTORY_NAME
static void print_env(const char *ev) {
const char *val = getenv(ev);
printf("%-30.30s = \"%s\"\n", ev, val ? val : "<null>");
fflush(stdout);
}
#endif
static inline int isdirsep(char c) { return c == '/' || c == '\\'; }
static wchar_t *mbwbuf = NULL;
static wchar_t *wbuf = NULL;
static wchar_t *wbuf1 = NULL;
extern "C" {
int fl_scandir(const char *dirname, struct dirent ***namelist,
int (*select)(struct dirent *),
int (*compar)(struct dirent **, struct dirent **),
char *errmsg, int errmsg_len);
}
static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8);
unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn);
wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); wbuf[wn] = 0;
return wbuf;
}
static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) {
unsigned len = (unsigned)wcslen(wstr);
unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; utf8 = (char *)realloc(utf8, wn);
wn = fl_utf8fromwc(utf8, wn, wstr, len); utf8[wn] = 0;
return utf8;
}
void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) {
}
void Fl_WinAPI_System_Driver::error(const char *format, va_list args) {
char buf[1024];
vsnprintf(buf, 1024, format, args);
MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
}
void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) {
char buf[1024];
vsnprintf(buf, 1024, format, args);
MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL);
::exit(1);
}
char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) {
static char *buf = NULL;
if (!utf8) return NULL;
unsigned len = (unsigned)strlen(utf8);
unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn);
len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); mbwbuf[len] = 0;
buf = (char*)realloc(buf, len * 6 + 1);
len = (unsigned)wcstombs(buf, mbwbuf, len * 6);
buf[len] = 0;
return buf;
}
char *Fl_WinAPI_System_Driver::getenv(const char *var) {
static char *buf = NULL;
wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf));
if (!ret) return NULL;
return wchar_to_utf8(ret, buf);
}
int Fl_WinAPI_System_Driver::putenv(const char *var) {
unsigned len = (unsigned)strlen(var);
unsigned wn = fl_utf8toUtf16(var, len, NULL, 0) + 1; wchar_t *wbuf = (wchar_t *)malloc(sizeof(wchar_t) * wn);
wn = fl_utf8toUtf16(var, len, (unsigned short *)wbuf, wn);
wbuf[wn] = 0;
int ret = _wputenv(wbuf);
free(wbuf);
return ret;
}
int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) {
utf8_to_wchar(fnam, wbuf);
if (pmode == -1) return _wopen(wbuf, oflags);
else return _wopen(wbuf, oflags, pmode);
}
int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) {
if (oflags == 0) oflags = _O_RDONLY;
oflags |= (binary ? _O_BINARY : _O_TEXT);
return this->open(fnam, oflags, pmode);
}
FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) {
utf8_to_wchar(fnam, wbuf);
utf8_to_wchar(mode, wbuf1);
return _wfopen(wbuf, wbuf1);
}
int Fl_WinAPI_System_Driver::system(const char *cmd) {
return _wsystem(utf8_to_wchar(cmd, wbuf));
}
int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) {
int n = 0;
while (argv[n]) n++; wchar_t **ar = (wchar_t **)calloc(sizeof(wchar_t *), n + 1);
for (int i = 0; i < n; i++)
ar[i] = utf8_to_wchar(argv[i], ar[i]); utf8_to_wchar(file, wbuf);
_wexecvp(wbuf, ar); for (int i = 0; i < n; i++)
free(ar[i]);
free(ar);
return -1; }
int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) {
return _wchmod(utf8_to_wchar(fnam, wbuf), mode);
}
int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) {
return _waccess(utf8_to_wchar(fnam, wbuf), mode);
}
int Fl_WinAPI_System_Driver::flstat(const char *fnam, struct stat *b) {
unsigned len = (unsigned)strlen(fnam);
if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\'))
len--;
return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b);
}
char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) {
static wchar_t *wbuf = NULL;
wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1));
wchar_t *ret = _wgetcwd(wbuf, len);
if (!ret) return NULL;
unsigned dstlen = (unsigned)len;
len = (int)wcslen(wbuf);
dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len);
buf[dstlen] = 0;
return buf;
}
int Fl_WinAPI_System_Driver::chdir(const char *path) {
return _wchdir(utf8_to_wchar(path, wbuf));
}
int Fl_WinAPI_System_Driver::unlink(const char *fnam) {
return _wunlink(utf8_to_wchar(fnam, wbuf));
}
int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) {
return _wmkdir(utf8_to_wchar(fnam, wbuf));
}
int Fl_WinAPI_System_Driver::rmdir(const char *fnam) {
return _wrmdir(utf8_to_wchar(fnam, wbuf));
}
int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) {
utf8_to_wchar(fnam, wbuf);
utf8_to_wchar(newnam, wbuf1);
return _wrename(wbuf, wbuf1);
}
int Fl_WinAPI_System_Driver::args_to_utf8(int argc, char ** &argv) {
int i;
LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
argv = (char **)malloc((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++) {
int u8size = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, NULL, 0, NULL, NULL); if (u8size > 0) {
char *strbuf = (char*)::malloc(u8size);
int ret = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, strbuf, u8size, NULL, NULL);
if (ret) {
argv[i] = strbuf;
} else {
argv[i] = _strdup("");
::free(strbuf);
}
} else {
argv[i] = _strdup("");
}
}
argv[argc] = NULL;
LocalFree(wideArgv);
return argc;
}
static char *buf = NULL;
static int buf_len = 0;
static unsigned short *wbufa = NULL;
unsigned int fl_codepage = 0;
char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
{
if (!s) return (char *)"";
int l = 0;
unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); wn = wn * 2 + 1;
if (wn >= (unsigned)buf_len) {
buf_len = wn;
buf = (char*) realloc(buf, buf_len);
wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
}
if (codepage < 1) codepage = fl_codepage;
l = fl_utf8toUtf16(s, len, wbufa, wn); wbufa[l] = 0;
buf[l] = 0;
l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL);
if (l < 0) l = 0;
buf[l] = 0;
return buf;
}
char *fl_locale_to_utf8(const char *s, int len, UINT codepage)
{
if (!s) return (char *)"";
int l = 0;
if (buf_len < len * 5 + 1) {
buf_len = len * 5 + 1;
buf = (char*) realloc(buf, buf_len);
wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
}
if (codepage < 1) codepage = fl_codepage;
buf[l] = 0;
l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len);
if (l < 0) l = 0;
wbufa[l] = 0;
l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l);
buf[l] = 0;
return buf;
}
unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) {
return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen);
}
unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen) {
unsigned i = 0;
unsigned count = 0;
if (dstlen) for (;;) {
unsigned ucs;
if (i >= srclen) {
dst[count] = 0;
return count;
}
ucs = src[i++];
if (ucs < 0x80U) {
dst[count++] = ucs;
if (count >= dstlen) {dst[count-1] = 0; break;}
} else if (ucs < 0x800U) {
if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
dst[count++] = 0xc0 | (ucs >> 6);
dst[count++] = 0x80 | (ucs & 0x3F);
} else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
src[i] >= 0xdc00 && src[i] <= 0xdfff) {
unsigned ucs2 = src[i++];
ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff);
if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;}
dst[count++] = 0xf0 | (ucs >> 18);
dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
dst[count++] = 0x80 | (ucs & 0x3F);
} else {
if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;}
dst[count++] = 0xe0 | (ucs >> 12);
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
dst[count++] = 0x80 | (ucs & 0x3F);
}
}
while (i < srclen) {
unsigned ucs = src[i++];
if (ucs < 0x80U) {
count++;
} else if (ucs < 0x800U) {
count += 2;
} else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) {
++i;
count += 4;
} else {
count += 3;
}
}
return count;
}
int Fl_WinAPI_System_Driver::utf8locale()
{
static int ret = (GetACP() == CP_UTF8);
return ret;
}
unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) {
wchar_t lbuf[1024];
wchar_t *buf = lbuf;
unsigned length = fl_utf8towc(src, srclen, buf, 1024);
unsigned ret;
if (length >= 1024) {
buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
fl_utf8towc(src, srclen, buf, length+1);
}
if (dstlen) {
ret =
WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0);
dst[ret] = 0;
}
if (dstlen==0 || ret >= dstlen-1)
ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
if (buf != lbuf) free(buf);
return ret;
}
unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) {
wchar_t lbuf[1024];
wchar_t *buf = lbuf;
unsigned length;
unsigned ret;
length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024);
if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) {
length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0);
buf = (wchar_t*)(malloc(length*sizeof(wchar_t)));
MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length);
}
ret = fl_utf8fromwc(dst, dstlen, buf, length);
if (buf != lbuf) free((void*)buf);
return ret;
}
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
static _locale_t c_locale = NULL;
#endif
int Fl_WinAPI_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
if (!c_locale)
c_locale = _create_locale(LC_NUMERIC, "C");
int retval = _vfprintf_l(output, format, c_locale, args);
#else
char *saved_locale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C");
int retval = vfprintf(output, format, args);
setlocale(LC_NUMERIC, saved_locale);
#endif
return retval;
}
int Fl_WinAPI_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
if (!c_locale)
c_locale = _create_locale(LC_NUMERIC, "C");
int retval = _vsnprintf_l(output, output_size, format, c_locale, args);
#else
char *saved_locale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C");
int retval = vsnprintf(output, output_size, format, args);
setlocale(LC_NUMERIC, saved_locale);
#endif
return retval;
}
int Fl_WinAPI_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) {
char *saved_locale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C");
int retval = vsscanf(input, format, args);
setlocale(LC_NUMERIC, saved_locale);
return retval;
}
int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
int (*sort)(struct dirent **, struct dirent **),
char *errmsg, int errmsg_sz) {
return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz);
}
int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
char *temp = new char[tolen];
strlcpy(temp,from, tolen);
char *start = temp;
char *end = temp+strlen(temp);
int ret = 0;
for (char *a=temp; a<end; ) { char *e; for (e=a; e<end && !isdirsep(*e); e++) {} const char *value = 0; switch (*a) {
case '~': if (e <= a+1) { value = home_directory_name();
}
break;
case '$':
{char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
break;
}
if (value) {
if (isdirsep(value[0])) start = a;
if (value[0] && value[1]==':') start = a;
int t = (int) strlen(value); if (isdirsep(value[t-1])) t--;
if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
memmove(a+t, e, end+1-e);
end = a+t+(end-e);
*end = '\0';
memcpy(a, value, t);
ret++;
} else {
a = e+1;
if (*e == '\\') {*e = '/'; ret++;} }
}
strlcpy(to, start, tolen);
delete[] temp;
return ret;
}
int Fl_WinAPI_System_Driver::filename_relative(char *to, int tolen, const char *dest_dir, const char *base_dir) {
if (!to || !dest_dir || !base_dir) {
return 0;
}
if ( (unsigned)base_dir[0] < 128 && isalpha(base_dir[0]) && base_dir[1] == ':'
&& (unsigned)dest_dir[0] < 128 && isalpha(dest_dir[0]) && dest_dir[1] == ':') {
if (tolower(base_dir[0]) != tolower(dest_dir[0])) {
strlcpy(to, dest_dir, tolen);
return 0;
}
base_dir += 2;
dest_dir += 2;
}
if (!isdirsep(*base_dir) || !isdirsep(*dest_dir)) {
strlcpy(to, dest_dir, tolen);
return 0;
}
const char *base_i = base_dir; const char *base_s = base_dir; const char *dest_i = dest_dir; const char *dest_s = dest_dir;
for (;;) {
#if 0#else base_i += fl_utf8len1(*base_i);
int b = fl_tolower(fl_utf8decode(base_i, NULL, NULL));
dest_i += fl_utf8len1(*dest_i);
int d = fl_tolower(fl_utf8decode(dest_i, NULL, NULL));
#endif
int b0 = (b == 0) || (isdirsep(b));
int d0 = (d == 0) || (isdirsep(d));
if (b0 && d0) {
base_s = base_i;
dest_s = dest_i;
}
if (b == 0 || d == 0)
break;
if (b != d)
break;
}
if ( (base_i[0] == 0 || (isdirsep(base_i[0]) && base_i[1] == 0))
&& (dest_i[0] == 0 || (isdirsep(dest_i[0]) && dest_i[1] == 0))) {
strlcpy(to, ".", tolen);
return 0;
}
to[0] = '\0';
to[tolen - 1] = '\0';
int n_up = 0;
for (;;) {
char b = *base_s++;
if (b == 0)
break;
if (isdirsep(b) && *base_s)
n_up++;
}
if (n_up > 0)
strlcat(to, "..", tolen);
for (; n_up > 1; --n_up)
strlcat(to, "/..", tolen);
if (*dest_s) {
if (n_up)
strlcat(to, "/", tolen);
strlcat(to, dest_s + 1, tolen);
}
return 1;
}
int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) {
if (isdirsep(*from) || *from == '|' || from[1]==':' || !base) {
strlcpy(to, from, tolen);
return 0;
}
char *a;
char *temp = new char[tolen];
const char *start = from;
strlcpy(temp, base, tolen);
for (a = temp; *a; a++) if (*a=='\\') *a = '/';
if (isdirsep(*(a-1))) a--;
while (*start == '.') {
if (start[1]=='.' && (isdirsep(start[2]) || start[2]==0) ) {
char *b;
for (b = a-1; b >= temp && !isdirsep(*b); b--) {}
if (b < temp) break;
a = b;
if (start[2] == 0)
start += 2;
else
start += 3;
} else if (isdirsep(start[1])) {
start += 2;
} else if (!start[1]) {
start ++;
break;
} else
break;
}
*a++ = '/';
strlcpy(a,start,tolen - (a - temp));
strlcpy(to, temp, tolen);
delete[] temp;
return 1;
}
int Fl_WinAPI_System_Driver::filename_isdir(const char *n) {
char fn[4]; int length = (int)strlen(n);
if (length > 0 && isdirsep(n[length - 1]))
length --;
if (length < 1)
return 0;
if (length == 2 && isalpha(n[0]) && n[1] == ':') { fn[0] = n[0];
strcpy(fn + 1, ":/");
n = fn;
length = 3;
}
utf8_to_wchar(n, wbuf, length);
DWORD fa = GetFileAttributesW(wbuf);
return (fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY);
}
int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n) {
if (*n && isdirsep(n[strlen(n) - 1])) return 1;
return filename_isdir(n);
}
const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) {
const char *q = 0;
const char *p = buf;
for (p = buf; *p; p++) {
if (isdirsep(*p) ) q = 0;
else if (*p == '.') q = p;
}
return q ? q : p;
}
int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen) {
if (msg) snprintf(msg, msglen, "open %s", uri);
return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32);
}
int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename,
int lname, Fl_File_Icon *icon) {
int num_files = 0;
# ifdef __CYGWIN__
FILE *m = setmntent("/-not-used-", "r");
struct mntent *p;
while ((p = getmntent (m)) != NULL) {
browser->add(p->mnt_dir, icon);
num_files ++;
}
endmntent(m);
# else
DWORD drives; drives = GetLogicalDrives();
for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1) {
if (drives & 1) {
snprintf(filename, lname, "%c:/", i);
if (i < 'C') browser->add(filename, icon);
else
browser->add(filename, icon);
num_files ++;
}
}
# endif return num_files;
}
int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
size_t name_size, dirent ***pfiles,
Fl_File_Sort_F *sort,
char *errmsg, int errmsg_sz)
{
strlcpy(filename, directory, name_size);
int i = (int) (strlen(filename) - 1);
if (i == 2 && filename[1] == ':' &&
(filename[2] == '/' || filename[2] == '\\'))
filename[2] = '/';
else if (filename[i] != '/' && filename[i] != '\\')
strlcat(filename, "/", name_size);
return filename_list(filename, pfiles, sort, errmsg, errmsg_sz);
}
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
{
static HMODULE hMod = NULL;
UUID ud;
UUID *pu = &ud;
int got_uuid = 0;
if (!hMod) { hMod = LoadLibrary("Rpcrt4.dll");
}
if (hMod) { uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate");
if (uuid_crt != NULL) {
RPC_STATUS rpc_res = uuid_crt(pu);
if ( (rpc_res == RPC_S_OK) || (rpc_res == RPC_S_UUID_LOCAL_ONLY) || (rpc_res == RPC_S_UUID_NO_ADDRESS) ) {
got_uuid = -1;
snprintf(uuidBuffer, 36+1, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1],
pu->Data4[2], pu->Data4[3], pu->Data4[4],
pu->Data4[5], pu->Data4[6], pu->Data4[7]);
}
}
}
if (got_uuid == 0) { unsigned char b[16];
time_t t = time(0); b[0] = (unsigned char)t;
b[1] = (unsigned char)(t>>8);
b[2] = (unsigned char)(t>>16);
b[3] = (unsigned char)(t>>24);
int r = rand(); b[4] = (unsigned char)r;
b[5] = (unsigned char)(r>>8);
b[6] = (unsigned char)(r>>16);
b[7] = (unsigned char)(r>>24);
union { void *pv; unsigned char a[sizeof(void*)]; } v;
v.pv = (void *)(&t);
b[8] = v.a[0];
b[9] = v.a[1];
b[10] = v.a[2];
b[11] = v.a[3];
TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(name, &nSize);
for (int ii = 0; ii < 4; ii++) {
b[12 + ii] = (unsigned char)name[ii];
}
snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
}
}
char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences * , Fl_Preferences::Root root, const char *vendor,
const char *application)
{
static char *filename = 0L;
if (!filename) filename = (char*)::malloc(2 * FL_PATH_MAX);
HRESULT res;
int appdata = CSIDL_APPDATA; if ((root & Fl_Preferences::ROOT_MASK) == Fl_Preferences::SYSTEM)
appdata = CSIDL_COMMON_APPDATA;
res = SHGetFolderPathW(NULL, appdata, NULL, SHGFP_TYPE_CURRENT, (LPWSTR)filename); if (res != S_OK) {
return 0L;
}
char *buf = NULL;
wchar_to_utf8((wchar_t *)filename, buf); strcpy(filename, buf);
free(buf);
if ( (vendor==0L) || (vendor[0]==0) )
vendor = "unknown";
if ( (application==0L) || (application[0]==0) )
application = "unknown";
snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename),
"/%s/%s.prefs", vendor, application);
for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
return filename;
}
void *Fl_WinAPI_System_Driver::load(const char *filename) {
return LoadLibraryW(utf8_to_wchar(filename, wbuf));
}
void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h)
{
for (int i = w * h; i > 0; i --, ptr += 4) {
if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
}
}
const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start)
{
const char *p = strchr(start, '/');
if (!p) p = strchr(start, '\\');
return p;
}
int Fl_WinAPI_System_Driver::file_type(const char *filename)
{
int filetype;
if (filename[strlen(filename) - 1] == '/')
filetype = Fl_File_Icon::DIRECTORY;
else if (filename_isdir(filename))
filetype = Fl_File_Icon::DIRECTORY;
else
filetype = Fl_File_Icon::PLAIN;
return filetype;
}
const char *Fl_WinAPI_System_Driver::home_directory_name()
{
static Fl_String home;
if (!home.empty())
return home.c_str();
#if (DEBUG_HOME_DIRECTORY_NAME)
print_env("HOMEDRIVE");
print_env("HOMEPATH");
print_env("UserProfile");
print_env("HOME");
#endif
if (home.empty()) {
const char *home_drive = getenv("HOMEDRIVE");
if (home_drive) {
home = home_drive; const char *home_path = getenv("HOMEPATH");
if (home_path) {
home.append(home_path);
} else {
home.clear(); } } }
if (home.empty()) {
const char *h = getenv("UserProfile");
if (h)
home = h;
}
if (home.empty()) {
const char *h = getenv("HOME");
if (h)
home = h;
}
if (home.empty()) {
home = "~/"; }
for (int i = 0; i < home.size(); ++i) {
if (home[i] == '\\')
home[i] = '/';
}
#if (DEBUG_HOME_DIRECTORY_NAME)
printf("home_directory_name() returns \"%s\"\n", home.c_str());
fflush(stdout);
#endif
return home.c_str();
}
void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) {
struct _timeb t;
_ftime(&t);
*sec = t.time;
*usec = t.millitm * 1000;
}
extern void (*fl_lock_function)();
extern void (*fl_unlock_function)();
static DWORD main_thread;
static CRITICAL_SECTION cs;
static CRITICAL_SECTION *cs_ring;
void Fl_WinAPI_System_Driver::unlock_ring() {
LeaveCriticalSection(cs_ring);
}
void Fl_WinAPI_System_Driver::lock_ring() {
if (!cs_ring) {
cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(cs_ring);
}
EnterCriticalSection(cs_ring);
}
static void unlock_function() {
LeaveCriticalSection(&cs);
}
static void lock_function() {
EnterCriticalSection(&cs);
}
int Fl_WinAPI_System_Driver::lock() {
if (!main_thread) InitializeCriticalSection(&cs);
lock_function();
if (!main_thread) {
fl_lock_function = lock_function;
fl_unlock_function = unlock_function;
main_thread = GetCurrentThreadId();
}
return 0;
}
void Fl_WinAPI_System_Driver::unlock() {
unlock_function();
}
void Fl_WinAPI_System_Driver::awake(void* msg) {
PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0);
}
int Fl_WinAPI_System_Driver::close_fd(int fd) {
return _close(fd);
}