blob: 5533532661a447980c34118d664a44ddcfff524a [file] [log] [blame]
DRC2ff39b82011-07-28 08:38:59 +00001//
2// "$Id: fl_utf8.cxx 7975 2010-12-08 12:15:48Z AlbrechtS $"
3//
4// Unicode to UTF-8 conversion functions.
5//
6// Author: Jean-Marc Lienher ( http://oksid.ch )
7// Copyright 2000-2010 by O'ksi'D.
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Library General Public
11// License as published by the Free Software Foundation; either
12// version 2 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Library General Public License for more details.
18//
19// You should have received a copy of the GNU Library General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22// USA.
23//
24// Please report all bugs and problems on the following page:
25//
26// http://www.fltk.org/str.php
27
28
29#include <config.h>
30#include <FL/filename.H>
31#include <stdarg.h>
32
33#if defined(WIN32) && !defined(__CYGWIN__)
34# include <ctype.h>
35# include <io.h>
36# include <windows.h>
37# include <winbase.h>
38# include <process.h>
39#ifdef __CYGWIN__
40#include <wchar.h>
41#else
42#include <direct.h>
43#endif
44extern "C" {
45 int XUtf8Tolower(int ucs);
46 unsigned short XUtf8IsNonSpacing(unsigned int ucs);
47};
48
49#elif defined(__APPLE__)
50# include <stdio.h>
51# include <time.h>
52//# include <unix.h>
53# include <fcntl.h>
54# include <unistd.h>
55# include <wchar.h>
56# include <stdlib.h>
57# include <sys/types.h>
58# include <sys/stat.h>
59
60extern "C" {
61 int XUtf8Tolower(int ucs);
62 unsigned short XUtf8IsNonSpacing(unsigned int ucs);
63}
64
65#else // X-windows platform
66
67# include <FL/Xutf8.h>
68# include <sys/types.h>
69# include <sys/stat.h>
70# include <fcntl.h>
71# include <unistd.h>
72#endif // WIN32
73
74#include <FL/fl_utf8.h>
75#include <string.h>
76#include <stdlib.h>
77
78#undef fl_open
79
80/** \addtogroup fl_unicode
81 @{
82*/
83
84/*** NOTE : all functions are LIMITED to 24 bits Unicode values !!! ***/
85/*** but only 16 bits are really used under Linux and win32 ***/
86
87
88#define NBC 0xFFFF + 1
89
90static int
91Toupper(
92 int ucs)
93{
94 long i;
95 static unsigned short *table = NULL;
96
97 if (!table) {
98 table = (unsigned short*) malloc(
99 sizeof(unsigned short) * (NBC));
100 for (i = 0; i < NBC; i++) {
101 table[i] = (unsigned short) i;
102 }
103 for (i = 0; i < NBC; i++) {
104 int l;
105 l = XUtf8Tolower(i);
106 if (l != i) table[l] = (unsigned short) i;
107 }
108
109 }
110 if (ucs >= NBC || ucs < 0) return ucs;
111 return table[ucs];
112}
113
114/**
115 return the byte length of the UTF-8 sequence with first byte \p c,
116 or -1 if \p c is not valid.
117 This function is helpful for finding faulty UTF8 sequences.
118 \see fl_utf8len1
119 */
120int fl_utf8len(char c)
121{
122 if (!(c & 0x80)) return 1;
123 if (c & 0x40) {
124 if (c & 0x20) {
125 if (c & 0x10) {
126 if (c & 0x08) {
127 if (c & 0x04) {
128 return 6;
129 }
130 return 5;
131 }
132 return 4;
133 }
134 return 3;
135 }
136 return 2;
137 }
138 return -1;
139} // fl_utf8len
140
141
142/**
143 Return the byte length of the UTF-8 sequence with first byte \p c,
144 or 1 if \p c is not valid.
145 This function can be used to scan faulty UTF8 sequence, albeit ignoring invalid
146 codes.
147 \see fl_utf8len
148 */
149int fl_utf8len1(char c)
150{
151 if (!(c & 0x80)) return 1;
152 if (c & 0x40) {
153 if (c & 0x20) {
154 if (c & 0x10) {
155 if (c & 0x08) {
156 if (c & 0x04) {
157 return 6;
158 }
159 return 5;
160 }
161 return 4;
162 }
163 return 3;
164 }
165 return 2;
166 }
167 return 1;
168} // fl_utf8len1
169
170
171/**
172 returns the number of Unicode chars in the UTF-8 string
173 */
174int
175fl_utf_nb_char(
176 const unsigned char *buf,
177 int len)
178{
179 int i = 0;
180 int nbc = 0;
181 while (i < len) {
182 int cl = fl_utf8len((buf+i)[0]);//fl_utflen(buf + i, len - i);
183 if (cl < 1) cl = 1;
184 nbc++;
185 i += cl;
186 }
187 return nbc;
188}
189
190/*
191 * compare only the first n bytes
192 * return 0 if the strings are equal;
193 * return 1 if s1 is greater than s2
194 * return -1 if s1 is less than s2
195 */
196/**
197 UTF-8 aware strncasecmp - converts to lower case Unicode and tests.
198
199 \todo Correct the incorrect logic where length of strings tested
200 \todo Clarify whether n means number of bytes, or characters.
201 */
202int fl_utf_strncasecmp(const char *s1, const char *s2, int n)
203{
204 int i;
205 int s1_l;
206 int s2_l;
207 char *e1, *e2; // string end pointers
208
209 s1_l = 0;
210 while (s1_l < n && s1[s1_l]) s1_l++;
211 s2_l = 0;
212 while (s2_l < n && s2[s2_l]) s2_l++;
213
214 if (s1_l < s2_l) {
215 return -1;
216 } else if (s1_l > s2_l) {
217 return 1;
218 }
219 e1 = (char *)&s1[s1_l]; // last char to test
220 e2 = (char *)&s2[s2_l];
221 for (i = 0; i < n;) {
222 int l1, l2;
223 unsigned int u1, u2;
224 int res;
225
226// l1 = fl_utf2ucs((unsigned char*)s1 + i, n - i, &u1);
227 u1 = fl_utf8decode(s1 + i, e1, &l1);
228// l2 = fl_utf2ucs((unsigned char*)s2 + i, n - i, &u2);
229 u2 = fl_utf8decode(s2 + i, e2, &l2);
230 if (l1 - l2 != 0) return l1 - l2;
231 res = XUtf8Tolower(u1) - XUtf8Tolower(u2);
232 if (res != 0) return res;
233 if (l1 < 1) {
234 i += 1;
235 } else {
236 i += l1;
237 }
238 }
239 return 0;
240}
241
242/*
243 * return 0 if the strings are equal;
244 * return 1 if s1 is greater than s2
245 * return -1 if s1 is less than s2
246 */
247/**
248 UTF-8 aware strcasecmp - converts to Unicode and tests.
249
250 \todo Correct the incorrect logic where length of strings tested
251 */
252int fl_utf_strcasecmp(const char *s1, const char *s2)
253{
254 int s1_l = strlen(s1);
255 int s2_l = strlen(s2);
256
257 if (s1_l < s2_l) {
258 return -1;
259 } else if (s1_l > s2_l) {
260 return 1;
261 }
262 return fl_utf_strncasecmp(s1, s2, s1_l);
263}
264
265/**
266 return the Unicode lower case value of \p ucs
267 */
268int fl_tolower(unsigned int ucs)
269{
270 return XUtf8Tolower(ucs);
271}
272
273/**
274 return the Unicode upper case value of \p ucs
275 */
276int fl_toupper(unsigned int ucs)
277{
278 return Toupper(ucs);
279}
280
281/**
282 converts the str string to the lower case equivalent into buf.
283 Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode]
284 */
285int fl_utf_tolower(const unsigned char *str, int len, char *buf)
286{
287 int i;
288 int l = 0;
289 char *end = (char *)&str[len];
290 for (i = 0; i < len;) {
291 int l1, l2;
292 unsigned int u1;
293
294// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
295 u1 = fl_utf8decode((const char*)(str + i), end, &l1);
296 l2 = fl_utf8encode((unsigned int) XUtf8Tolower(u1), buf + l);
297 if (l1 < 1) {
298 i += 1;
299 } else {
300 i += l1;
301 }
302 if (l2 < 1) {
303 l += 1;
304 } else {
305 l += l2;
306 }
307
308 }
309 return l;
310}
311
312/**
313 converts the str string to the upper case equivalent into buf.
314 Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode]
315 */
316int fl_utf_toupper(const unsigned char *str, int len, char *buf)
317{
318 int i;
319 int l = 0;
320 char *end = (char *)&str[len];
321 for (i = 0; i < len;) {
322 int l1, l2;
323 unsigned int u1;
324
325// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
326 u1 = fl_utf8decode((const char*)(str + i), end, &l1);
327 l2 = fl_utf8encode((unsigned int) Toupper(u1), buf + l);
328 if (l1 < 1) {
329 i += 1;
330 } else {
331 i += l1;
332 }
333 if (l2 < 1) {
334 l += 1;
335 } else {
336 l += l2;
337 }
338 }
339 return l;
340}
341
342#if 0 // deprecated in favour of FLTK2's fl_utf8toa
343/*
344 * convert UTF-8 str to latin1
345 * Warning: buf must be at least len long
346 */
347int fl_utf2latin1(const unsigned char *str, int len, char *buf)
348{
349 int i;
350 int l = 0;
351 char *end = (char *)&str[len];
352 for (i = 0; i < len;) {
353 unsigned int u1;
354 int l1;
355
356// l1 = fl_utf2ucs((unsigned char*)str + i, len - i, &u1);
357 u1 = fl_utf8decode((const char*)(str + i), end, &l1);
358 if (u1 > 0xFF) u1 = '?';
359 buf[l] = (char) u1;
360 if (l1 < 1) {
361 i += 1;
362 } else {
363 i += l1;
364 }
365 l++;
366
367 }
368 return l;
369}
370#endif
371
372#if 0 // deprecated in favour of FLTK2's fl_utf8froma
373/*
374 * convert latin1 str to UTF-8
375 * Warning: buf must be at least 2 * len long
376 */
377int fl_latin12utf(const unsigned char *str, int len, char *buf)
378{
379 int i;
380 int l = 0;
381 int l1 = 0;
382 for (i = 0; i < len; i++) {
383 unsigned int n = (unsigned int) str[i];
384 l1 = fl_utf8encode(n, buf + l);
385 if (l1 < 1) {
386 l = l + 1;
387 } else {
388 l = l + l1;
389 }
390
391 }
392 return l;
393}
394#endif
395
396/**
397 returns true if the character is non-spacing.
398 \todo explain what non-spacing means.
399 */
400unsigned int fl_nonspacing(unsigned int ucs)
401{
402#ifdef __APPLE__
403 return (ucs==0x20); // FIXME: what does this really do?
404#else
405 return (unsigned int) XUtf8IsNonSpacing(ucs);
406#endif
407}
408
409#if defined(WIN32) && !defined(__CYGWIN__)
410static xchar *mbwbuf = NULL;
411#endif
412
413#ifdef WIN32
414unsigned int fl_codepage = 0;
415#endif
416
417#if defined (WIN32) && !defined(__CYGWIN__)
418
419static char *buf = NULL;
420static int buf_len = 0;
421static unsigned short *wbufa = NULL;
422
423// FIXME: This should *maybe* return 'const char *' instead of 'char *'
424char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
425{
426 if (!s) return (char *)"";
427 int l = 0;
428// if (buf_len < len * 2 + 1) {
429// buf_len = len * 2 + 1;
430// buf = (char*) realloc(buf, buf_len);
431// wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
432// }
433 unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length
434 wn = wn * 2 + 1;
435 if (wn >= (unsigned)buf_len) {
436 buf_len = wn;
437 buf = (char*) realloc(buf, buf_len);
438 wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
439 }
440 if (codepage < 1) codepage = fl_codepage;
441// l = fl_utf2unicode((const unsigned char *)s, len, (xchar*) wbufa);
442 l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string
443 wbufa[l] = 0;
444 buf[l] = 0;
445 l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL);
446 if (l < 0) l = 0;
447 buf[l] = 0;
448 return buf;
449}
450
451// FIXME: This should maybe return 'const char *' instead of 'char *'
452char *fl_locale_to_utf8(const char *s, int len, UINT codepage)
453{
454 if (!s) return (char *)"";
455 int l = 0;
456 if (buf_len < len * 5 + 1) {
457 buf_len = len * 5 + 1;
458 buf = (char*) realloc(buf, buf_len);
459 wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
460 }
461 if (codepage < 1) codepage = fl_codepage;
462 buf[l] = 0;
463
464 l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len);
465 if (l < 0) l = 0;
466 wbufa[l] = 0;
467// l = fl_unicode2utf((xchar*)wbufa, l, buf);
468 l = fl_utf8fromwc(buf, buf_len, (xchar*)wbufa, l);
469 buf[l] = 0;
470 return buf;
471}
472#endif
473
474/**
475 converts UTF8 to a local multi-byte character string.
476 */
477char * fl_utf2mbcs(const char *s)
478{
479 if (!s) return NULL;
480#if defined(WIN32) && !defined(__CYGWIN__)
481 int l = strlen(s);
482 static char *buf = NULL;
483
484// mbwbuf = (xchar*)realloc(mbwbuf, (l+6) * sizeof(xchar));
485// l = fl_utf2unicode((unsigned char*)s, l, mbwbuf);
486// mbwbuf[l] = 0;
487 unsigned wn = fl_utf8toUtf16(s, l, NULL, 0) + 7; // Query length
488 mbwbuf = (xchar*)realloc(mbwbuf, sizeof(xchar)*wn);
489 l = fl_utf8toUtf16(s, l, (unsigned short *)mbwbuf, wn); // Convert string
490 mbwbuf[l] = 0;
491
492 buf = (char*)realloc(buf, l * 6 + 1);
493 l = wcstombs(buf, mbwbuf, l * 6);
494 buf[l] = 0;
495 return buf;
496#else
497 return (char*) s;
498#endif
499}
500
501
502#if 0 // deprecated in favour of FLTK2's fl_utf8from_mb
503char * fl_mbcs2utf(const char *s)
504{
505 if (!s) return NULL;
506#if defined(WIN32)
507 int l = strlen(s);
508 unsigned dstlen;
509 static char *buf = NULL;
510
511 mbwbuf = (xchar*)realloc(mbwbuf,(l * 6 + 6) * sizeof(xchar));
512 l = mbstowcs(mbwbuf, s, l);
513 dstlen = l * 6 + 1;
514 buf = (char*)realloc(buf, dstlen);
515// l = fl_unicode2utf(mbwbuf, l, buf);
516 l = fl_utf8fromwc(buf, dstlen, mbwbuf, l);
517 buf[l] = 0;
518 return buf;
519#else
520 return (char*) s;
521#endif
522} // fl_mbcs2utf
523#endif
524
525#if defined(WIN32) && !defined(__CYGWIN__)
526static xchar *wbuf = NULL;
527static xchar *wbuf1 = NULL;
528#endif
529
530
531char *fl_getenv(const char* v)
532{
533#if defined (WIN32) && !defined(__CYGWIN__)
534 int l = strlen(v);
535// static xchar* wbuf = NULL;
536// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
537// wbuf[fl_utf2unicode((const unsigned char*)v, l, wbuf)] = 0;
538 unsigned wn = fl_utf8toUtf16(v, l, NULL, 0) + 1; // Query length
539 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
540 wn = fl_utf8toUtf16(v, l, (unsigned short *)wbuf, wn); // Convert string
541 wbuf[wn] = 0;
542 xchar *ret = _wgetenv(wbuf);
543 static char *buf = NULL;
544 if (ret) {
545 l = wcslen(ret);
546 wn = fl_utf8fromwc(NULL, 0, ret, l) + 1; // query length
547 buf = (char*) realloc(buf, wn);
548// buf[fl_unicode2utf(ret, l, buf)] = 0;
549 wn = fl_utf8fromwc(buf, wn, ret, l); // convert string
550 buf[wn] = 0;
551 return buf;
552 } else {
553 return NULL;
554 }
555#else
556 return getenv(v);
557#endif
558}
559
560int fl_open(const char* f, int oflags, ...)
561{
562 int pmode;
563 va_list ap;
564 va_start(ap, oflags);
565 pmode = va_arg (ap, int);
566 va_end(ap);
567#if defined (WIN32) && !defined(__CYGWIN__)
568 int l = strlen(f);
569// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
570// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
571 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
572 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
573 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
574 wbuf[wn] = 0;
575 if (pmode == -1) return _wopen(wbuf, oflags);
576 else return _wopen(wbuf, oflags, pmode);
577#else
578 if (pmode == -1) return open(f, oflags);
579 else return open(f, oflags, pmode);
580#endif
581}
582
583FILE *fl_fopen(const char* f, const char *mode)
584{
585#if defined (WIN32) && !defined(__CYGWIN__)
586 int l = strlen(f);
587// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
588// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
589 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
590 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
591 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
592 wbuf[wn] = 0;
593 l = strlen(mode);
594// wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar) * (l+1));
595// wbuf1[fl_utf2unicode((const unsigned char*)mode, l, wbuf1)] = 0;
596 wn = fl_utf8toUtf16(mode, l, NULL, 0) + 1; // Query length
597 wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar)*wn);
598 wn = fl_utf8toUtf16(mode, l, (unsigned short *)wbuf1, wn); // Convert string
599 wbuf1[wn] = 0;
600 return _wfopen(wbuf, wbuf1);
601#else
602 return fopen(f, mode);
603#endif
604}
605
606int fl_system(const char* f)
607{
608#if defined (WIN32) && !defined(__CYGWIN__)
609# ifdef __MINGW32__
610 return system(fl_utf2mbcs(f));
611# else
612 int l = strlen(f);
613// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
614// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
615 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
616 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
617 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
618 wbuf[wn] = 0;
619 return _wsystem(wbuf);
620# endif
621#else
622 return system(f);
623#endif
624}
625
626int fl_execvp(const char *file, char *const *argv)
627{
628#if defined (WIN32) && !defined(__CYGWIN__)
629#ifdef __MINGW32__
630 return _execvp(fl_utf2mbcs(file), argv);
631#else
632 int l = strlen(file);
633 int i, n, ret;
634 xchar **ar;
635// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
636// wbuf[fl_utf2unicode((const unsigned char*)file, l, wbuf)] = 0;
637 unsigned wn = fl_utf8toUtf16(file, l, NULL, 0) + 1; // Query length
638 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
639 wn = fl_utf8toUtf16(file, l, (unsigned short *)wbuf, wn); // Convert string
640 wbuf[wn] = 0;
641
642 i = 0; n = 0;
643 while (argv[i]) {i++; n++;}
644 ar = (xchar**) malloc(sizeof(xchar*) * (n + 1));
645 i = 0;
646 while (i <= n) {
647 unsigned wn;
648 l = strlen(argv[i]);
649// ar[i] = (xchar *)malloc(sizeof(xchar) * (l+1));
650// ar[i][fl_utf2unicode((const unsigned char*)argv[i], l, ar[i])] = 0;
651 wn = fl_utf8toUtf16(argv[i], l, NULL, 0) + 1; // Query length
652 ar[i] = (xchar *)malloc(sizeof(xchar)*wn);
653 wn = fl_utf8toUtf16(argv[i], l, (unsigned short *)ar[i], wn); // Convert string
654 ar[i][wn] = 0;
655 i++;
656 }
657 ar[n] = NULL;
658 ret = _wexecvp(wbuf, ar);
659 i = 0;
660 while (i <= n) {
661 free(ar[i]);
662 i++;
663 }
664 free(ar);
665 return ret;
666#endif
667#else
668 return execvp(file, argv);
669#endif
670}
671
672
673
674int fl_chmod(const char* f, int mode)
675{
676#if defined (WIN32) && !defined(__CYGWIN__)
677 int l = strlen(f);
678// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
679// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
680 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
681 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
682 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
683 wbuf[wn] = 0;
684 return _wchmod(wbuf, mode);
685#else
686 return chmod(f, mode);
687#endif
688}
689
690int fl_access(const char* f, int mode)
691{
692#if defined (WIN32) && !defined(__CYGWIN__)
693 int l = strlen(f);
694// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
695// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
696 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
697 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
698 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
699 wbuf[wn] = 0;
700 return _waccess(wbuf, mode);
701#else
702 return access(f, mode);
703#endif
704}
705
706
707int fl_stat(const char* f, struct stat *b)
708{
709#if defined(WIN32) && !defined(__CYGWIN__)
710 int l = strlen(f);
711// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
712// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
713 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
714 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
715 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
716 wbuf[wn] = 0;
717 return _wstat(wbuf, (struct _stat*)b);
718#else
719 return stat(f, b);
720#endif
721}
722
723char *fl_getcwd(char* b, int l)
724{
725 if (b == NULL) {
726 b = (char*) malloc(l+1);
727 }
728#if defined(WIN32) && !defined(__CYGWIN__)
729 static xchar *wbuf = NULL;
730 wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
731// xchar *ret = _wgetcwd(wbuf, l / 5);
732 xchar *ret = _wgetcwd(wbuf, l);
733 if (ret) {
734 unsigned dstlen = l;
735 l = wcslen(wbuf);
736// b[fl_unicode2utf(wbuf, l, b)] = 0;
737 dstlen = fl_utf8fromwc(b, dstlen, wbuf, l);
738 b[dstlen] = 0;
739 return b;
740 } else {
741 return NULL;
742 }
743#else
744 return getcwd(b, l);
745#endif
746}
747
748
749int fl_unlink(const char* f)
750{
751#if defined(WIN32) && !defined(__CYGWIN__)
752 int l = strlen(f);
753// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
754// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
755 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
756 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
757 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
758 wbuf[wn] = 0;
759 return _wunlink(wbuf);
760#else
761 return unlink(f);
762#endif
763}
764
765int fl_mkdir(const char* f, int mode)
766{
767#if defined(WIN32) && !defined(__CYGWIN__)
768 int l = strlen(f);
769// wbuf = (xchar*)realloc(wbuf, sizeof(short) * (l+1));
770// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
771 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
772 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
773 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
774 wbuf[wn] = 0;
775 return _wmkdir(wbuf);
776#else
777 return mkdir(f, mode);
778#endif
779}
780
781
782int fl_rmdir(const char* f)
783{
784#if defined (WIN32) && !defined(__CYGWIN__)
785 int l = strlen(f);
786// wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1));
787// wbuf[fl_utf2unicode((const unsigned char*)f, l, wbuf)] = 0;
788 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
789 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
790 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
791 wbuf[wn] = 0;
792 return _wrmdir(wbuf);
793#else
794 return rmdir(f);
795#endif
796}
797
798int fl_rename(const char* f, const char *n)
799{
800#if defined (WIN32) && !defined(__CYGWIN__)
801 int l = strlen(f);
802 unsigned wn = fl_utf8toUtf16(f, l, NULL, 0) + 1; // Query length
803 wbuf = (xchar*)realloc(wbuf, sizeof(xchar)*wn);
804 wn = fl_utf8toUtf16(f, l, (unsigned short *)wbuf, wn); // Convert string
805 wbuf[wn] = 0;
806 l = strlen(n);
807 wn = fl_utf8toUtf16(n, l, NULL, 0) + 1; // Query length
808 wbuf1 = (xchar*)realloc(wbuf1, sizeof(xchar)*wn);
809 wn = fl_utf8toUtf16(n, l, (unsigned short *)wbuf1, wn); // Convert string
810 wbuf1[wn] = 0;
811 return _wrename(wbuf, wbuf1);
812#else
813 return rename(f, n);
814#endif
815}
816
817// recursively create a path in the file system
818char fl_make_path( const char *path ) {
819 if (fl_access(path, 0)) {
820 const char *s = strrchr( path, '/' );
821 if ( !s ) return 0;
822 int len = s-path;
823 char *p = (char*)malloc( len+1 );
824 memcpy( p, path, len );
825 p[len] = 0;
826 fl_make_path( p );
827 free( p );
828 fl_mkdir(path, 0700);
829 }
830 return 1;
831}
832
833// strip the filename and create a path
834void fl_make_path_for_file( const char *path )
835{
836 const char *s = strrchr( path, '/' );
837 if ( !s ) return;
838 int len = s-path;
839 char *p = (char*)malloc( len+1 );
840 memcpy( p, path, len );
841 p[len] = 0;
842 fl_make_path( p );
843 free( p );
844}
845
846/** @} */
847
848//
849// End of "$Id: fl_utf8.cxx 7975 2010-12-08 12:15:48Z AlbrechtS $".
850//