Include a stripped-down version of FLTK in tree and add a USE_INCLUDED_FLTK option to build against it.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4603 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/fltk/src/fl_utf8.cxx b/common/fltk/src/fl_utf8.cxx
new file mode 100644
index 0000000..5533532
--- /dev/null
+++ b/common/fltk/src/fl_utf8.cxx
@@ -0,0 +1,850 @@
+//
+// "$Id: fl_utf8.cxx 7975 2010-12-08 12:15:48Z AlbrechtS $"
+//
+// Unicode to UTF-8 conversion functions.
+//
+// Author: Jean-Marc Lienher ( http://oksid.ch )
+// Copyright 2000-2010 by O'ksi'D.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+
+
+#include <config.h>
+#include <FL/filename.H>
+#include <stdarg.h>
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# include <ctype.h>
+# include <io.h>
+# include <windows.h>
+# include <winbase.h>
+# include <process.h>
+#ifdef __CYGWIN__
+#include <wchar.h>
+#else
+#include <direct.h>
+#endif
+extern "C" {
+ int XUtf8Tolower(int ucs);
+ unsigned short XUtf8IsNonSpacing(unsigned int ucs);
+};
+
+#elif defined(__APPLE__)
+# include <stdio.h>
+# include <time.h>
+//# include <unix.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <wchar.h>
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+
+extern "C" {
+ int XUtf8Tolower(int ucs);
+ unsigned short XUtf8IsNonSpacing(unsigned int ucs);
+}
+
+#else // X-windows platform
+
+# include <FL/Xutf8.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif // WIN32
+
+#include <FL/fl_utf8.h>
+#include <string.h>
+#include <stdlib.h>
+
+#undef fl_open
+
+/** \addtogroup fl_unicode
+ @{
+*/
+
+/*** NOTE : all functions are LIMITED to 24 bits Unicode values !!! ***/
+/*** but only 16 bits are really used under Linux and win32 ***/
+
+
+#define NBC 0xFFFF + 1
+
+static int
+Toupper(
+ int ucs)
+{
+ long i;
+ static unsigned short *table = NULL;
+
+ if (!table) {
+ table = (unsigned short*) malloc(
+ sizeof(unsigned short) * (NBC));
+ for (i = 0; i < NBC; i++) {
+ table[i] = (unsigned short) i;
+ }
+ for (i = 0; i < NBC; i++) {
+ int l;
+ l = XUtf8Tolower(i);
+ if (l != i) table[l] = (unsigned short) i;
+ }
+
+ }
+ if (ucs >= NBC || ucs < 0) return ucs;
+ return table[ucs];
+}
+
+/**
+ return the byte length of the UTF-8 sequence with first byte \p c,
+ or -1 if \p c is not valid.
+ This function is helpful for finding faulty UTF8 sequences.
+ \see fl_utf8len1
+ */
+int fl_utf8len(char c)
+{
+ if (!(c & 0x80)) return 1;
+ if (c & 0x40) {
+ if (c & 0x20) {
+ if (c & 0x10) {
+ if (c & 0x08) {
+ if (c & 0x04) {
+ return 6;
+ }
+ return 5;
+ }
+ return 4;
+ }
+ return 3;
+ }
+ return 2;
+ }
+ return -1;
+} // fl_utf8len
+
+
+/**
+ Return the byte length of the UTF-8 sequence with first byte \p c,
+ or 1 if \p c is not valid.
+ This function can be used to scan faulty UTF8 sequence, albeit ignoring invalid
+ codes.
+ \see fl_utf8len
+ */
+int fl_utf8len1(char c)
+{
+ if (!(c & 0x80)) return 1;
+ if (c & 0x40) {
+ if (c & 0x20) {
+ if (c & 0x10) {
+ if (c & 0x08) {
+ if (c & 0x04) {
+ return 6;
+ }
+ return 5;
+ }
+ return 4;
+ }
+ return 3;
+ }
+ return 2;
+ }
+ return 1;
+} // fl_utf8len1
+
+
+/**
+ returns the number of Unicode chars in the UTF-8 string
+ */
+int
+fl_utf_nb_char(
+ const unsigned char *buf,
+ int len)
+{
+ int i = 0;
+ int nbc = 0;
+ while (i < len) {
+ int cl = fl_utf8len((buf+i)[0]);//fl_utflen(buf + i, len - i);
+ if (cl < 1) cl = 1;
+ nbc++;
+ i += cl;
+ }
+ return nbc;
+}
+
+/*
+ * compare only the first n bytes
+ * return 0 if the strings are equal;
+ * return 1 if s1 is greater than s2
+ * return -1 if s1 is less than s2
+ */
+/**
+ UTF-8 aware strncasecmp - converts to lower case Unicode and tests.
+
+ \todo Correct the incorrect logic where length of strings tested
+ \todo Clarify whether n means number of bytes, or characters.
+ */
+int fl_utf_strncasecmp(const char *s1, const char *s2, int n)
+{
+ int i;
+ int s1_l;
+ int s2_l;
+ char *e1, *e2; // string end pointers
+
+ s1_l = 0;
+ while (s1_l < n && s1[s1_l]) s1_l++;
+ s2_l = 0;
+ while (s2_l < n && s2[s2_l]) s2_l++;
+
+ if (s1_l < s2_l) {
+ return -1;
+ } else if (s1_l > s2_l) {
+ return 1;
+ }
+ e1 = (char *)&s1[s1_l]; // last char to test
+ e2 = (char *)&s2[s2_l];
+ for (i = 0; i < n;) {
+ int l1, l2;
+ unsigned int u1, u2;
+ int res;
+
+// l1 = fl_utf2ucs((unsigned char*)s1 + i, n - i, &u1);
+ u1 = fl_utf8decode(s1 + i, e1, &l1);
+// l2 = fl_utf2ucs((unsigned char*)s2 + i, n - i, &u2);
+ u2 = fl_utf8decode(s2 + i, e2, &l2);
+ if (l1 - l2 != 0) return l1 - l2;
+ res = XUtf8Tolower(u1) - XUtf8Tolower(u2);
+ if (res != 0) return res;
+ if (l1 < 1) {
+ i += 1;
+ } else {
+ i += l1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * return 0 if the strings are equal;
+ * return 1 if s1 is greater than s2
+ * return -1 if s1 is less than s2
+ */
+/**
+ UTF-8 aware strcasecmp - converts to Unicode and tests.
+
+ \todo Correct the incorrect logic where length of strings tested
+ */
+int fl_utf_strcasecmp(const char *s1, const char *s2)
+{
+ int s1_l = strlen(s1);
+ int s2_l = strlen(s2);
+
+ if (s1_l < s2_l) {
+ return -1;
+ } else if (s1_l > s2_l) {
+ return 1;
+ }
+ return fl_utf_strncasecmp(s1, s2, s1_l);
+}
+
+/**
+ return the Unicode lower case value of \p ucs
+ */
+int fl_tolower(unsigned int ucs)
+{
+ return XUtf8Tolower(ucs);
+}
+
+/**
+ return the Unicode upper case value of \p ucs
+ */
+int fl_toupper(unsigned int ucs)
+{
+ return Toupper(ucs);
+}
+
+/**
+ converts the str string to the lower case equivalent into buf.
+ Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode]
+ */
+int fl_utf_tolower(const unsigned char *str, int len, char *buf)
+{
+ int i;
+ int l = 0;
+ char *end = (char *)&str[len];
+ for (i = 0; i < len;) {
+ int l1, l2;
+ unsigned int u1;
+
+// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
+ u1 = fl_utf8decode((const char*)(str + i), end, &l1);
+ l2 = fl_utf8encode((unsigned int) XUtf8Tolower(u1), buf + l);
+ if (l1 < 1) {
+ i += 1;
+ } else {
+ i += l1;
+ }
+ if (l2 < 1) {
+ l += 1;
+ } else {
+ l += l2;
+ }
+
+ }
+ return l;
+}
+
+/**
+ converts the str string to the upper case equivalent into buf.
+ Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode]
+ */
+int fl_utf_toupper(const unsigned char *str, int len, char *buf)
+{
+ int i;
+ int l = 0;
+ char *end = (char *)&str[len];
+ for (i = 0; i < len;) {
+ int l1, l2;
+ unsigned int u1;
+
+// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
+ u1 = fl_utf8decode((const char*)(str + i), end, &l1);
+ l2 = fl_utf8encode((unsigned int) Toupper(u1), buf + l);
+ if (l1 < 1) {
+ i += 1;
+ } else {
+ i += l1;
+ }
+ if (l2 < 1) {
+ l += 1;
+ } else {
+ l += l2;
+ }
+ }
+ return l;
+}
+
+#if 0 // deprecated in favour of FLTK2's fl_utf8toa
+/*
+ * convert UTF-8 str to latin1
+ * Warning: buf must be at least len long
+ */
+int fl_utf2latin1(const unsigned char *str, int len, char *buf)
+{
+ int i;
+ int l = 0;
+ char *end = (char *)&str[len];
+ for (i = 0; i < len;) {
+ unsigned int u1;
+ int l1;
+
+// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
+ u1 = fl_utf8decode((const char*)(str + i), end, &l1);
+ if (u1 > 0xFF) u1 = '?';
+ buf[l] = (char) u1;
+ if (l1 < 1) {
+ i += 1;
+ } else {
+ i += l1;
+ }
+ l++;
+
+ }
+ return l;
+}
+#endif
+
+#if 0 // deprecated in favour of FLTK2's fl_utf8froma
+/*
+ * convert latin1 str to UTF-8
+ * Warning: buf must be at least 2 * len long
+ */
+int fl_latin12utf(const unsigned char *str, int len, char *buf)
+{
+ int i;
+ int l = 0;
+ int l1 = 0;
+ for (i = 0; i < len; i++) {
+ unsigned int n = (unsigned int) str[i];
+ l1 = fl_utf8encode(n, buf + l);
+ if (l1 < 1) {
+ l = l + 1;
+ } else {
+ l = l + l1;
+ }
+
+ }
+ return l;
+}
+#endif
+
+/**
+ returns true if the character is non-spacing.
+ \todo explain what non-spacing means.
+ */
+unsigned int fl_nonspacing(unsigned int ucs)
+{
+#ifdef __APPLE__
+ return (ucs==0x20); // FIXME: what does this really do?
+#else
+ return (unsigned int) XUtf8IsNonSpacing(ucs);
+#endif
+}
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+static xchar *mbwbuf = NULL;
+#endif
+
+#ifdef WIN32
+unsigned int fl_codepage = 0;
+#endif
+
+#if defined (WIN32) && !defined(__CYGWIN__)
+
+static char *buf = NULL;
+static int buf_len = 0;
+static unsigned short *wbufa = NULL;
+
+// FIXME: This should *maybe* return 'const char *' instead of 'char *'
+char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
+{
+ if (!s) return (char *)"";
+ int l = 0;
+// if (buf_len < len * 2 + 1) {
+// buf_len = len * 2 + 1;
+// buf = (char*) realloc(buf, buf_len);
+// wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
+// }
+ unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length
+ 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_utf2unicode((const unsigned char *)s, len, (xchar*) wbufa);
+ l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string
+ 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;
+}
+
+// FIXME: This should maybe return 'const char *' instead of 'char *'
+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_unicode2utf((xchar*)wbufa, l, buf);
+ l = fl_utf8fromwc(buf, buf_len, (xchar*)wbufa, l);
+ buf[l] = 0;
+ return buf;
+}
+#endif
+
+/**
+ converts UTF8 to a local multi-byte character string.
+ */
+char * fl_utf2mbcs(const char *s)
+{
+ if (!s) return NULL;
+#if defined(WIN32) && !defined(__CYGWIN__)
+ int l = strlen(s);
+ static char *buf = NULL;
+
+// mbwbuf = (xchar*)realloc(mbwbuf, (l+6) * sizeof(xchar));
+// l = fl_utf2unicode((unsigned char*)s, l, mbwbuf);
+// mbwbuf[l] = 0;
+ unsigned wn = fl_utf8toUtf16(s, l, NULL, 0) + 7; // Query length
+ mbwbuf = (xchar*)realloc(mbwbuf, sizeof(xchar)*wn);
+ l = fl_utf8toUtf16(s, l, (unsigned short *)mbwbuf, wn); // Convert string
+ mbwbuf[l] = 0;
+
+ buf = (char*)realloc(buf, l * 6 + 1);
+ l = wcstombs(buf, mbwbuf, l * 6);
+ buf[l] = 0;
+ return buf;
+#else
+ return (char*) s;
+#endif
+}
+
+
+#if 0 // deprecated in favour of FLTK2's fl_utf8from_mb
+char * fl_mbcs2utf(const char *s)
+{
+ if (!s) return NULL;
+#if defined(WIN32)
+ int l = strlen(s);
+ unsigned dstlen;
+ static char *buf = NULL;
+
+ mbwbuf = (xchar*)realloc(mbwbuf,(l * 6 + 6) * sizeof(xchar));
+ l = mbstowcs(mbwbuf, s, l);
+ dstlen = l * 6 + 1;
+ buf = (char*)realloc(buf, dstlen);
+// l = fl_unicode2utf(mbwbuf, l, buf);
+ l = fl_utf8fromwc(buf, dstlen, mbwbuf, l);
+ buf[l] = 0;
+ return buf;
+#else
+ return (char*) s;
+#endif
+} // fl_mbcs2utf
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+static xchar *wbuf = NULL;
+static xchar *wbuf1 = NULL;
+#endif
+
+
+char *fl_getenv(const char* v)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(v);
+// static xchar* wbuf = NULL;
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)v, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(v, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(v, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ xchar *ret = _wgetenv(wbuf);
+ static char *buf = NULL;
+ if (ret) {
+ l = wcslen(ret);
+ wn = fl_utf8fromwc(NULL, 0, ret, l) + 1; // query length
+ buf = (char*) realloc(buf, wn);
+// buf[fl_unicode2utf(ret, l, buf)] = 0;
+ wn = fl_utf8fromwc(buf, wn, ret, l); // convert string
+ buf[wn] = 0;
+ return buf;
+ } else {
+ return NULL;
+ }
+#else
+ return getenv(v);
+#endif
+}
+
+int fl_open(const char* f, int oflags, ...)
+{
+ int pmode;
+ va_list ap;
+ va_start(ap, oflags);
+ pmode = va_arg (ap, int);
+ va_end(ap);
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ if (pmode == -1) return _wopen(wbuf, oflags);
+ else return _wopen(wbuf, oflags, pmode);
+#else
+ if (pmode == -1) return open(f, oflags);
+ else return open(f, oflags, pmode);
+#endif
+}
+
+FILE *fl_fopen(const char* f, const char *mode)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ l = strlen(mode);
+// wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar) * (l+1));
+// wbuf1[fl_utf2unicode((const unsigned char*)mode, l, wbuf1)] = 0;
+ wn = fl_utf8toUtf16(mode, l, NULL, 0) + 1; // Query length
+ wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(mode, l, (unsigned short *)wbuf1, wn); // Convert string
+ wbuf1[wn] = 0;
+ return _wfopen(wbuf, wbuf1);
+#else
+ return fopen(f, mode);
+#endif
+}
+
+int fl_system(const char* f)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+# ifdef __MINGW32__
+ return system(fl_utf2mbcs(f));
+# else
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wsystem(wbuf);
+# endif
+#else
+ return system(f);
+#endif
+}
+
+int fl_execvp(const char *file, char *const *argv)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+#ifdef __MINGW32__
+ return _execvp(fl_utf2mbcs(file), argv);
+#else
+ int l = strlen(file);
+ int i, n, ret;
+ xchar **ar;
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)file, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(file, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(file, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+
+ i = 0; n = 0;
+ while (argv[i]) {i++; n++;}
+ ar = (xchar**) malloc(sizeof(xchar*) * (n + 1));
+ i = 0;
+ while (i <= n) {
+ unsigned wn;
+ l = strlen(argv[i]);
+// ar[i] = (xchar *)malloc(sizeof(xchar) * (l+1));
+// ar[i][fl_utf2unicode((const unsigned char*)argv[i], l, ar[i])] = 0;
+ wn = fl_utf8toUtf16(argv[i], l, NULL, 0) + 1; // Query length
+ ar[i] = (xchar *)malloc(sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(argv[i], l, (unsigned short *)ar[i], wn); // Convert string
+ ar[i][wn] = 0;
+ i++;
+ }
+ ar[n] = NULL;
+ ret = _wexecvp(wbuf, ar);
+ i = 0;
+ while (i <= n) {
+ free(ar[i]);
+ i++;
+ }
+ free(ar);
+ return ret;
+#endif
+#else
+ return execvp(file, argv);
+#endif
+}
+
+
+
+int fl_chmod(const char* f, int mode)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wchmod(wbuf, mode);
+#else
+ return chmod(f, mode);
+#endif
+}
+
+int fl_access(const char* f, int mode)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _waccess(wbuf, mode);
+#else
+ return access(f, mode);
+#endif
+}
+
+
+int fl_stat(const char* f, struct stat *b)
+{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wstat(wbuf, (struct _stat*)b);
+#else
+ return stat(f, b);
+#endif
+}
+
+char *fl_getcwd(char* b, int l)
+{
+ if (b == NULL) {
+ b = (char*) malloc(l+1);
+ }
+#if defined(WIN32) && !defined(__CYGWIN__)
+ static xchar *wbuf = NULL;
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// xchar *ret = _wgetcwd(wbuf, l / 5);
+ xchar *ret = _wgetcwd(wbuf, l);
+ if (ret) {
+ unsigned dstlen = l;
+ l = wcslen(wbuf);
+// b[fl_unicode2utf(wbuf, l, b)] = 0;
+ dstlen = fl_utf8fromwc(b, dstlen, wbuf, l);
+ b[dstlen] = 0;
+ return b;
+ } else {
+ return NULL;
+ }
+#else
+ return getcwd(b, l);
+#endif
+}
+
+
+int fl_unlink(const char* f)
+{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wunlink(wbuf);
+#else
+ return unlink(f);
+#endif
+}
+
+int fl_mkdir(const char* f, int mode)
+{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(short) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wmkdir(wbuf);
+#else
+ return mkdir(f, mode);
+#endif
+}
+
+
+int fl_rmdir(const char* f)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
+// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ return _wrmdir(wbuf);
+#else
+ return rmdir(f);
+#endif
+}
+
+int fl_rename(const char* f, const char *n)
+{
+#if defined (WIN32) && !defined(__CYGWIN__)
+ int l = strlen(f);
+ unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
+ wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
+ wbuf[wn] = 0;
+ l = strlen(n);
+ wn = fl_utf8toUtf16(n, l, NULL, 0) + 1; // Query length
+ wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar)*wn);
+ wn = fl_utf8toUtf16(n, l, (unsigned short *)wbuf1, wn); // Convert string
+ wbuf1[wn] = 0;
+ return _wrename(wbuf, wbuf1);
+#else
+ return rename(f, n);
+#endif
+}
+
+// recursively create a path in the file system
+char fl_make_path( const char *path ) {
+ if (fl_access(path, 0)) {
+ const char *s = strrchr( path, '/' );
+ if ( !s ) return 0;
+ int len = s-path;
+ char *p = (char*)malloc( len+1 );
+ memcpy( p, path, len );
+ p[len] = 0;
+ fl_make_path( p );
+ free( p );
+ fl_mkdir(path, 0700);
+ }
+ return 1;
+}
+
+// strip the filename and create a path
+void fl_make_path_for_file( const char *path )
+{
+ const char *s = strrchr( path, '/' );
+ if ( !s ) return;
+ int len = s-path;
+ char *p = (char*)malloc( len+1 );
+ memcpy( p, path, len );
+ p[len] = 0;
+ fl_make_path( p );
+ free( p );
+}
+
+/** @} */
+
+//
+// End of "$Id: fl_utf8.cxx 7975 2010-12-08 12:15:48Z AlbrechtS $".
+//