fl_utf8.cxx 21 KB

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