You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

851 lines
21KB

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