StringFuncs.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: StringFuncs.c /main/15 1998/03/19 09:49:44 mgreess $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: StringFuncs.c
  28. **
  29. ** Project: Cde DtHelp
  30. **
  31. ** Description: Semi private string functions - can be platform dependent.
  32. **
  33. **
  34. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  35. **
  36. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  37. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  38. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  39. ** (c) Copyright 1993, 1994 Novell, Inc.
  40. **
  41. **
  42. **
  43. ****************************************************************************
  44. ************************************<+>*************************************/
  45. #ifdef HAVE_CONFIG_H
  46. #include <cde_config.h>
  47. #endif
  48. /*
  49. * system includes
  50. */
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <limits.h>
  54. #include <errno.h>
  55. #include <locale.h> /* getlocale(), LOCALE_STATUS, LC_xxx */
  56. #if defined(_AIX) || defined(CSRG_BASED) || defined(__linux__)
  57. #include <ctype.h>
  58. #endif
  59. #include "CvStringI.h" /* for string functions used by Canvas Engine */
  60. #include "StringFuncsI.h" /* for _CEStrcollProc */
  61. /* JET: This was if !defined(linux), which is wrong. We should use the
  62. * real deal on linux too */
  63. #include <iconv.h>
  64. #if 0
  65. # define iconv_t int
  66. # define iconv_open(a, b) ((iconv_t) -1)
  67. # define iconv(a, b, c, d, e) ((size_t) 0)
  68. # define iconv_close(a) (0)
  69. #endif
  70. #define ICONV_INBUF_TYPE ICONV_CONST char **
  71. /**** Types ****/
  72. /* Private structure of the IconvContext. Public
  73. structure doesn't reveal implementation. */
  74. typedef struct _DtHelpCeIconvContextRec
  75. {
  76. iconv_t cd;
  77. int tableSize;
  78. unsigned char * table; /* translation table */
  79. char * fromCodeset;
  80. char * toCodeset;
  81. } _DtHelpCeIconvContextRec;
  82. #ifndef True
  83. #define True 1
  84. #endif
  85. #ifndef TRUE
  86. #define TRUE 1
  87. #endif
  88. #ifndef False
  89. #define False 0
  90. #endif
  91. #ifndef FALSE
  92. #define FALSE 0
  93. #endif
  94. /******************************************************************************
  95. *
  96. * Private variables and defines.
  97. *
  98. *****************************************************************************/
  99. #define EOS '\0'
  100. /******************************************************************************
  101. *
  102. * Semi Public Functions
  103. *
  104. *****************************************************************************/
  105. /******************************************************************************
  106. * Function: _DtHelpCeStrcspn (const char *s1, const char *s2, max_len, &ret_len)
  107. *
  108. * Returns in 'ret_len' the length of the initial segment of string
  109. * s1 which consists entirely of characters not found in string s2.
  110. *
  111. * Returns:
  112. * -1 If found an invalid character.
  113. * 0 If found a character in string s2
  114. * 1 If found the null byte character.
  115. *****************************************************************************/
  116. int
  117. _DtHelpCeStrcspn (
  118. const char *s1,
  119. const char *s2,
  120. int max_len,
  121. int *ret_len )
  122. {
  123. int len;
  124. int len2;
  125. const char *p1;
  126. const char *p2;
  127. if (!s1)
  128. {
  129. *ret_len = 0;
  130. return 0;
  131. }
  132. if (*s1 == '\0')
  133. {
  134. *ret_len = 0;
  135. return 1;
  136. }
  137. if (!s2 || *s2 == '\0')
  138. {
  139. *ret_len = strlen (s1);
  140. return 1;
  141. }
  142. if (max_len == 1)
  143. {
  144. /*
  145. * no need to go through any hassle, just use the 3C function
  146. */
  147. *ret_len = strcspn (s1, s2);
  148. if (s1[*ret_len] == '\0')
  149. return 1;
  150. return 0;
  151. }
  152. p1 = s1;
  153. while (*p1 != '\0')
  154. {
  155. len = mblen (p1, max_len);
  156. if (len == -1)
  157. {
  158. /*
  159. * we found an invalid character
  160. * return the length found so far and the flag.
  161. */
  162. *ret_len = p1 - s1;
  163. return -1;
  164. }
  165. p2 = s2;
  166. while (*p2 != '\0')
  167. {
  168. len2 = mblen (p2, max_len);
  169. if (len2 == -1)
  170. len2 = 1;
  171. if (len2 == len && strncmp (p1, p2, len) == 0)
  172. {
  173. *ret_len = p1 - s1;
  174. return 0;
  175. }
  176. p2 += len2;
  177. }
  178. p1 += len;
  179. }
  180. *ret_len = p1 - s1;
  181. return 1;
  182. }
  183. /******************************************************************************
  184. * Function: _DtHelpCeStrspn (const char *s1, const char *s2, max_len, &ret_len)
  185. *
  186. * Returns in 'ret_len' the length of the initial segment of string
  187. * s1 which consists entirely of characters found in string s2.
  188. *
  189. * Returns:
  190. * -1 If found an invalid character.
  191. * 0 If found a character not in string s2
  192. * 1 If found the null byte character.
  193. *****************************************************************************/
  194. int
  195. _DtHelpCeStrspn (
  196. char *s1,
  197. char *s2,
  198. int max_len,
  199. int *ret_len )
  200. {
  201. int len;
  202. int len2;
  203. char *p1;
  204. char *p2;
  205. char found;
  206. if (!s1 || !s2 || *s2 == '\0')
  207. {
  208. *ret_len = 0;
  209. return 0;
  210. }
  211. if (*s1 == '\0')
  212. {
  213. *ret_len = 0;
  214. return 1;
  215. }
  216. if (max_len == 1)
  217. {
  218. /*
  219. * no need to go through any hassle, just use the 3C function
  220. */
  221. *ret_len = strspn (s1, s2);
  222. if (s1[*ret_len] == '\0')
  223. return 1;
  224. return 0;
  225. }
  226. p1 = s1;
  227. found = True;
  228. while (*p1 != '\0' && found)
  229. {
  230. len = mblen (p1, max_len);
  231. if (len == -1)
  232. {
  233. /*
  234. * we found an invalid character
  235. * return the length found so far and the flag.
  236. */
  237. *ret_len = p1 - s1;
  238. return -1;
  239. }
  240. p2 = s2;
  241. found = False;
  242. while (*p2 != '\0' && !found)
  243. {
  244. len2 = mblen (p2, max_len);
  245. if (len2 == -1)
  246. len2 = 1;
  247. if (len2 == len && strncmp (p1, p2, len) == 0)
  248. found = True;
  249. p2 += len2;
  250. }
  251. if (found)
  252. p1 += len;
  253. }
  254. *ret_len = p1 - s1;
  255. if (found)
  256. return 1;
  257. return 0;
  258. }
  259. /******************************************************************************
  260. * Function: _DtHelpCeStrchr (char *s1, char *value, max_len, ret_ptr)
  261. *
  262. * Returns in 'ret_ptr' the address of the first occurence of 'value'
  263. * in string s1.
  264. *
  265. * Returns:
  266. * -1 If found an invalid character.
  267. * 0 If found value in string s2
  268. * 1 If found the null byte character without finding 'value'.
  269. * 'ret_ptr' will also be null in this case.
  270. *****************************************************************************/
  271. int
  272. _DtHelpCeStrchr (
  273. const char *s1,
  274. const char *value,
  275. int max_len,
  276. char **ret_ptr )
  277. {
  278. int len;
  279. int valLen;
  280. const char *p1;
  281. *ret_ptr = NULL;
  282. if (s1 == NULL || *s1 == '\0')
  283. return 1;
  284. if (max_len == 1)
  285. {
  286. *ret_ptr = strchr (s1, ((int)*value));
  287. if (*ret_ptr)
  288. return 0;
  289. return 1;
  290. }
  291. p1 = s1;
  292. valLen = mblen(value, max_len);
  293. if (valLen < 1)
  294. return -1;
  295. while (*p1 != '\0')
  296. {
  297. len = mblen (p1, max_len);
  298. if (len == -1)
  299. return -1;
  300. if (len == valLen && strncmp(p1, value, len) == 0)
  301. {
  302. *ret_ptr = (char *)p1;
  303. return 0;
  304. }
  305. p1 += len;
  306. }
  307. return 1;
  308. }
  309. /******************************************************************************
  310. * Function: _DtHelpCeStrrchr (char *s1, char *value, max_len, ret_ptr)
  311. *
  312. * Returns in 'ret_ptr' the address of the last occurence of 'value'
  313. * in string s1.
  314. *
  315. * Returns:
  316. * -1 If found an invalid character.
  317. * 0 If found value in string s2
  318. * 1 If found the null byte character without finding 'value'.
  319. * 'ret_ptr' will also be null in this case.
  320. *****************************************************************************/
  321. int
  322. _DtHelpCeStrrchr (
  323. const char *s1,
  324. const char *value,
  325. int max_len,
  326. char **ret_ptr )
  327. {
  328. int len;
  329. int valLen;
  330. const char *p1;
  331. *ret_ptr = NULL;
  332. if (s1 == NULL || *s1 == '\0')
  333. return 1;
  334. if (max_len == 1)
  335. {
  336. *ret_ptr = strrchr (s1, ((int)*value));
  337. if (*ret_ptr != NULL)
  338. return 0;
  339. return 1;
  340. }
  341. p1 = s1;
  342. valLen = mblen(value, max_len);
  343. if (valLen < 1)
  344. return -1;
  345. while (*p1 != '\0')
  346. {
  347. len = mblen (p1, max_len);
  348. if (len == -1)
  349. return -1;
  350. if (len == valLen && strncmp(p1, value, len) == 0)
  351. *ret_ptr = (char *)p1;
  352. p1 += len;
  353. }
  354. if (*ret_ptr != NULL)
  355. return 0;
  356. return 1;
  357. }
  358. /******************************************************************************
  359. * Function: _DtHelpCeCountChars (char *s1, max_len, ret_len)
  360. *
  361. * Returns in 'ret_len' the number of characters (not bytes)
  362. * in string s1.
  363. *
  364. * Returns:
  365. * -1 If found an invalid character. 'ret_len' contains the
  366. * number of 'good' characters found.
  367. * 0 If successful.
  368. *****************************************************************************/
  369. int
  370. _DtHelpCeCountChars (
  371. char *s1,
  372. int max_len,
  373. int *ret_len )
  374. {
  375. int len;
  376. *ret_len = 0;
  377. if (s1)
  378. {
  379. if (max_len == 1)
  380. *ret_len = strlen (s1);
  381. else
  382. {
  383. while (*s1)
  384. {
  385. len = mblen (s1, max_len);
  386. if (len == -1)
  387. return -1;
  388. *ret_len = *ret_len + 1;
  389. s1 += len;
  390. }
  391. }
  392. }
  393. return 0;
  394. }
  395. /*****************************************************************************
  396. * Function: _DtHelpCeUpperCase
  397. *
  398. * Parameters: string Specifies the string to change into
  399. * upper case.
  400. *
  401. * Return Value: Nothing
  402. *
  403. * Purpose: To change all lower case characters into upper case.
  404. *
  405. *****************************************************************************/
  406. void
  407. _DtHelpCeUpperCase ( char *string )
  408. {
  409. int len;
  410. if (string)
  411. {
  412. while (*string != '\0')
  413. {
  414. len = mblen (string, MB_CUR_MAX);
  415. if (len == 1)
  416. {
  417. *string = (unsigned char) toupper (*(unsigned char *)string);
  418. string++;
  419. }
  420. else if (len > 0)
  421. string += len;
  422. else
  423. return;
  424. }
  425. }
  426. }
  427. /************************************************************************
  428. * Function: _DtHelpCeStrHashToKey
  429. *
  430. * Parameters: C-format string to hash
  431. *
  432. * Purpose:
  433. * Does a very simple hash operation on the string and returns the value
  434. *
  435. * Returns: hash value
  436. *
  437. ************************************************************************/
  438. int _DtHelpCeStrHashToKey(
  439. const char * str)
  440. {
  441. char c;
  442. const char * tstr;
  443. int key = 0;
  444. if (!str) return 0; /* RETURN */
  445. for (tstr = str; (c = *tstr++); )
  446. key = (key << 1) + c;
  447. return key;
  448. }
  449. /******************************************************************************
  450. * Function: _DtHelpCeGetStrcollProc
  451. *
  452. * Parameters: none
  453. *
  454. * Returns: Ptr to the proper collation function to use
  455. * If the codeset of the locale is "C", then it is
  456. * strcasecmp(). If it's not, then it is strcoll().
  457. *
  458. * Purpose: When the codeset of the locale "C", strcoll()
  459. * performs collation identical to strcmp(), which is
  460. * strictly bitwise.
  461. *
  462. * To get case-insensitive collation, you need to use
  463. * strcasecmp() instead. If codeset != "C", then
  464. * strcoll() collates according to the language
  465. * setting.
  466. *
  467. * Warning: This code is not multi-thread safe. The multi-thread
  468. * safe setlocale must be used instead to make it so.
  469. *
  470. *****************************************************************************/
  471. _CEStrcollProc _DtHelpCeGetStrcollProc(void)
  472. {
  473. int Clang = 0;
  474. char * locale;
  475. extern int strcoll(const char *,const char *);
  476. #if defined(_AIX)
  477. extern int _DtHelpCeStrCaseCmp(const char *,const char *);
  478. #else
  479. extern int strcasecmp(const char *,const char *);
  480. #endif
  481. #define C_LANG "C"
  482. /* if locale is C, use the explicit case insensitive compare */
  483. locale = setlocale(LC_COLLATE,NULL); /* put locale in buf */
  484. if (strcmp(locale,C_LANG) == 0)
  485. Clang = 1;
  486. if (Clang)
  487. #if defined(_AIX)
  488. return _DtHelpCeStrCaseCmp;
  489. #else
  490. return strcasecmp;
  491. #endif
  492. return strcoll;
  493. }
  494. /*****************************************************************************
  495. * Function: String _DtHelpCeStripSpaces (string)
  496. *
  497. *
  498. * Parameters: String to process
  499. *
  500. * Return Value: Processed string
  501. *
  502. * Purpose: Strip all leading and trailing spaces.
  503. * Processing is in place
  504. *
  505. *****************************************************************************/
  506. char * _DtHelpCeStripSpaces (
  507. char * string)
  508. {
  509. int i;
  510. int multiLen = MB_CUR_MAX;
  511. char * space;
  512. if (string == NULL)
  513. return (string);
  514. /* Strip off leading spaces first */
  515. i = 0;
  516. while ((multiLen == 1 || (mblen(string + i, MB_LEN_MAX) == 1)) &&
  517. isspace((unsigned char) string[i]))
  518. {
  519. i++;
  520. }
  521. /* Copy over the leading spaces */
  522. strcpy(string, string + i);
  523. /* Drop out, if the string is now empty */
  524. if ((i = strlen(string) - 1) < 0)
  525. return(string);
  526. /* Strip off trailing spaces */
  527. if (multiLen == 1)
  528. {
  529. /* No multibyte; simply work back through the string */
  530. while ((i >= 0) && (isspace((unsigned char) string[i])))
  531. i--;
  532. string[i + 1] = '\0';
  533. }
  534. else
  535. {
  536. /* Work forward, looking for a trailing space of spaces */
  537. int len;
  538. i = 0;
  539. space = NULL;
  540. while (string[i])
  541. {
  542. if ( ((len =mblen(string + i, MB_LEN_MAX)) == 1)
  543. && isspace((unsigned char) string[i]))
  544. {
  545. /* Found a space */
  546. if (space == NULL)
  547. space = string + i;
  548. }
  549. else if (space)
  550. space = NULL;
  551. /* if there is an invalid character, treat as a valid one-byte */
  552. if (len == -1)
  553. len = 1;
  554. i += len;
  555. }
  556. if (space)
  557. *space = '\0';
  558. }
  559. return (string);
  560. }
  561. /*****************************************************************************
  562. * Function: void _DtHelpCeCompressSpace (string)
  563. *
  564. * Parameters: string to process
  565. *
  566. * Return Value: processed string
  567. *
  568. * Purpose: This function strips all leading and trailing spaces
  569. * from the string; it also compresses any intervening
  570. * spaces into a single space. This is useful when
  571. * comparing name strings. For instance, the string:
  572. * " First Middle Last "
  573. *
  574. * would compress to:
  575. *
  576. * "First Middle Last"
  577. *
  578. * Processing is in place.
  579. *
  580. *****************************************************************************/
  581. void _DtHelpCeCompressSpace (
  582. char * string)
  583. {
  584. char * ptr;
  585. /* Strip leading and trailing spaces */
  586. _DtHelpCeStripSpaces(string);
  587. /* Compress intervening spaces */
  588. _DtHelpCeStrchr(string, " ", 1, &ptr);
  589. while (ptr)
  590. {
  591. /* Skip over the one space we plan to keep */
  592. ptr++;
  593. _DtHelpCeStripSpaces(ptr);
  594. _DtHelpCeStrchr(ptr, " ", 1, &ptr);
  595. }
  596. }
  597. /*****************************************************************************
  598. * Function: void _DtHelpCeIconvStr1Step (string)
  599. *
  600. * Parameters:
  601. * fromCode; codeset name
  602. * fromStr; string to convert
  603. * toCode; codeset name
  604. * ret_toStr; converted str; this string is malloc'd by this routine
  605. * and the CALLER MUST FREE it when no longer needed.
  606. * dflt1; 1-byte default char
  607. * dflt2; 2-byte default char
  608. *
  609. * Return Value:
  610. * 0: ok
  611. * -1: missing (NULL) argument
  612. * -2: no translation available from fromCode to toCode
  613. * -3: couldn't allocate memory
  614. * -4: couldn't start conversion
  615. * -5: incomplete multibyte char
  616. * -6: invalid char found
  617. *
  618. * Purpose:
  619. * Converts string from fromCode to toCode using iconv(3)
  620. * It expects the codeset strings to be iconv(3) compatible.
  621. *
  622. * Comments:
  623. * iconv(3) is standardized in XPG4, which is just starting
  624. * to be supported. Below are several different implementations
  625. * of _DtHelpCeIconvStr, each using what is available on different
  626. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  627. *****************************************************************************/
  628. int _DtHelpCeIconvStr1Step(
  629. const char * fromCode, /* codeset name */
  630. const char * fromStr, /* string to convert */
  631. const char * toCode, /* codeset name */
  632. char * * ret_toStr, /* converted str */
  633. int dflt1, /* 1-byte default char */
  634. int dflt2) /* 2-byte default char */
  635. {
  636. _DtHelpCeIconvContextRec * iconvContext;
  637. int ret;
  638. ret = _DtHelpCeIconvOpen(&iconvContext,fromCode,toCode,dflt1,dflt2);
  639. if (0 == ret)
  640. ret = _DtHelpCeIconvStr(iconvContext,fromStr, ret_toStr,NULL,NULL,0);
  641. _DtHelpCeIconvClose(&iconvContext);
  642. return ret;
  643. }
  644. /*****************************************************************************
  645. * Function: void _DtHelpCeIconvOpen (string)
  646. *
  647. * Parameters:
  648. * iconvContext context
  649. * fromStr; string to convert
  650. * ret_toStr; converted str; this string is malloc'd by this routine
  651. * and the CALLER MUST FREE it when no longer needed.
  652. * dflt1; 1-byte default char
  653. * dflt2; 2-byte default char
  654. *
  655. * Return Value:
  656. * 0: ok
  657. * -1: missing (NULL) argument
  658. * -2: no translation available from fromCode to toCode
  659. * -3: couldn't allocate memory
  660. * -4: couldn't start conversion
  661. * -5: incomplete multibyte char
  662. * -6: invalid char found
  663. *
  664. * Purpose:
  665. * Opens an iconv table/algorithm to convert string from
  666. * fromCode to toCode using iconv(3)
  667. * It expects the codeset strings to be iconv(3) compatible.
  668. *
  669. * Comments:
  670. * iconv(3) is standardized in XPG4, which is just starting
  671. * to be supported. Below are several different implementations
  672. * of _DtHelpCeIconvStr, each using what is available on different
  673. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  674. *****************************************************************************/
  675. int _DtHelpCeIconvOpen(
  676. _DtHelpCeIconvContext * ret_iconvContext, /* iconv */
  677. const char * fromCode, /* codeset name */
  678. const char * toCode, /* codeset name */
  679. int dflt1, /* 1-byte default char */
  680. int dflt2) /* 2-byte default char */
  681. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  682. int err; /* error code of function */
  683. _DtHelpCeIconvContextRec * ic;
  684. #define BAD (-1)
  685. #define MEM_INC 20
  686. err = 0; /* ok */
  687. /* check args */
  688. if (!ret_iconvContext || !fromCode || !toCode )
  689. return -1; /* RETURN error */
  690. /* init state */
  691. ic = *ret_iconvContext = calloc(1,sizeof(_DtHelpCeIconvContextRec));
  692. if (NULL == ic) return -3; /* RETURN error */
  693. if ( strcmp(fromCode,toCode) == 0 )
  694. {
  695. ic->cd = (iconv_t) BAD; /* BAD means use strdup() */
  696. goto success;
  697. }
  698. ic->cd = iconv_open(toCode,fromCode);
  699. if ( ic->cd == (iconv_t) BAD )
  700. {
  701. err = -4; /* error */
  702. goto success;
  703. }
  704. success:
  705. ic->fromCodeset = strdup(fromCode);
  706. ic->toCodeset = strdup(toCode);
  707. return err; /* RETURN status */
  708. }
  709. /*****************************************************************************
  710. * Function: void _DtHelpCeIconvStr (string)
  711. *
  712. * Parameters:
  713. * iconvContext context for the conversion
  714. * fromStr; string to convert
  715. * ret_toStr; converted str; this string is malloc'd by this routine
  716. * and the CALLER MUST FREE it when no longer needed.
  717. * toStrBuf; for efficiency, can pass in a buf
  718. * toStrBufLen; length of buf
  719. *
  720. * Return Value:
  721. * 0: ok
  722. * -1: missing (NULL) argument
  723. * -2: no translation available from fromCode to toCode
  724. * -3: couldn't allocate memory
  725. * -4: couldn't start conversion
  726. * -5: incomplete multibyte char
  727. * -6: invalid char found
  728. *
  729. * Purpose:
  730. * Converts string from fromCode to toCode using iconv(3)
  731. * If toStrBuf is NULL, memory for the converted string
  732. * will be malloced as needed.
  733. * If toStrBuf is not NULL, the conversion will use up
  734. * to toStrBufLen bytes of the buffer and then realloc
  735. * more memory if needed.
  736. * If toStrBuf is not NULL, the size of the buf is
  737. * returned in ret_toStrLen; otherwise, the value is
  738. * not set.
  739. * ret_toStr receives the pointer to the buf, which may
  740. * be different from toStrBuf if memory was allocated
  741. * or NULL if an error occurred. If toStrBuf is
  742. * not NULL and memory must be allocated, a realloc()
  743. * call is used, possibly invalidating the toStrBuf ptr.
  744. * ret_toStrLen receives the length of the buffer if
  745. * toStrBuf is not NULL. If it is NULL, the length
  746. * is not returned.
  747. * Comments:
  748. * iconv(3) is standardized in XPG4, which is just starting
  749. * to be supported. Below are several different implementations
  750. * of _DtHelpCeIconvStr, each using what is available on different
  751. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  752. *****************************************************************************/
  753. int _DtHelpCeIconvStr(
  754. _DtHelpCeIconvContext iconvContext, /* iconv */
  755. const char * fromStr, /* string to convert */
  756. char * * ret_toStr, /* converted str */
  757. size_t * ret_toStrLen, /* converted str */
  758. char * toStrBuf, /* for efficiency, can pass in a buf */
  759. size_t toStrBufLen) /* length of buf */
  760. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  761. char * toStr; /* ptr to tostr memory */
  762. int toStrSize; /* size of mallocd string */
  763. size_t inBytesLeft; /* bytes left to use from input buf */
  764. const char * inChar; /* ptr into fromstr */
  765. char * outChar; /* ptr into tostr */
  766. size_t outBytesLeft; /* bytes left in the output str */
  767. int err; /* error code of function */
  768. #define BAD (-1)
  769. #define MEM_INC 20
  770. /* init ret values; allows function to be called nicely in a loop. */
  771. if (ret_toStr) *ret_toStr = toStrBuf;
  772. if (ret_toStrLen) *ret_toStrLen = toStrBufLen;
  773. /* check args */
  774. if ( !iconvContext || !fromStr || !ret_toStr
  775. || (!ret_toStrLen && toStrBuf))
  776. return -1; /* RETURN error */
  777. /* just do a straight copy if codesets the same or invalid context */
  778. if ( iconvContext->cd == (iconv_t) BAD )
  779. {
  780. if (NULL == toStrBuf)
  781. {
  782. *ret_toStr = strdup(fromStr);
  783. }
  784. else /* reuse the buffer */
  785. {
  786. int len = strlen(fromStr) + 1;
  787. if (len > toStrBufLen)
  788. *ret_toStr = realloc(toStrBuf,len);
  789. else
  790. {
  791. *ret_toStr = toStrBuf;
  792. len = toStrBufLen;
  793. }
  794. /* set return values */
  795. strcpy(*ret_toStr,fromStr);
  796. *ret_toStrLen = len;
  797. }
  798. return (NULL != *ret_toStr ? 0 : -3); /* RETURN result */
  799. }
  800. /* init ptrs */
  801. toStr = toStrBuf;
  802. toStrSize = (NULL == toStrBuf ? 0 : toStrBufLen);
  803. inChar = fromStr;
  804. inBytesLeft = strlen(fromStr);
  805. outChar = toStr;
  806. outBytesLeft = toStrSize;
  807. /* translate the string */
  808. err = -3;
  809. while ( inBytesLeft > 0 )
  810. {
  811. /* convert a character */
  812. if(iconv(iconvContext->cd, (ICONV_INBUF_TYPE)&inChar,
  813. &inBytesLeft,&outChar,&outBytesLeft) == -1)
  814. {
  815. switch(errno)
  816. {
  817. case 0: /* no error */
  818. continue;
  819. case EINVAL: /* inChar pts to incomplete multibyte char */
  820. inBytesLeft = 0; /* end the translation */
  821. err = -5;
  822. break;
  823. case EILSEQ: /* invalid char at inChar */
  824. inBytesLeft = 0; /* end the translation */
  825. err = -6;
  826. break;
  827. case E2BIG: /* no room in toStr */
  828. /* provide enough mem in the toStr */
  829. if (outBytesLeft < sizeof(wchar_t))
  830. {
  831. size_t offset = outChar - (char *) toStr;
  832. outBytesLeft += MEM_INC;
  833. toStrSize += MEM_INC;
  834. toStr = realloc(toStr,toStrSize * sizeof(char));
  835. if (NULL == toStr)
  836. {
  837. inBytesLeft = 0; /* end the translation */
  838. err = -3;
  839. break; /* BREAK */
  840. }
  841. outChar = (char *) (toStr + offset); /* recalc ptr */
  842. }
  843. break;
  844. default:
  845. inBytesLeft = 0; /* breakout of loop */
  846. break;
  847. } /* switch on convertsion result */
  848. } /* if an error */
  849. } /* while chars left to translate */
  850. /* set the EOS */
  851. if(outChar) *outChar = EOS;
  852. /* set return values */
  853. *ret_toStr = (char *) toStr;
  854. if (toStrBuf) *ret_toStrLen = toStrSize;
  855. return (NULL != toStr ? 0 : err); /* RETURN result */
  856. }
  857. /*****************************************************************************
  858. * Function: void _DtHelpCeIconvClose()
  859. *
  860. * Parameters:
  861. * io_iconvContext; context
  862. *
  863. * Return Value: none
  864. *
  865. * Purpose:
  866. * Closes an iconv context used to convert
  867. * fromCode to toCode using iconv(3)
  868. *
  869. * Comments:
  870. * iconv(3) is standardized in XPG4, which is just starting
  871. * to be supported. Below are several different implementations
  872. * of _DtHelpCeIconvStr, each using what is available on different
  873. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  874. *****************************************************************************/
  875. void _DtHelpCeIconvClose(
  876. _DtHelpCeIconvContext * io_iconvContext)
  877. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  878. _DtHelpCeIconvContextRec * ic;
  879. if (!io_iconvContext || NULL == *io_iconvContext) return;
  880. ic = *io_iconvContext;
  881. if ( ic->cd != (iconv_t) BAD )
  882. iconv_close(ic->cd);
  883. if (ic->fromCodeset) free(ic->fromCodeset);
  884. if (ic->toCodeset) free(ic->toCodeset);
  885. free(ic);
  886. *io_iconvContext = NULL;
  887. }
  888. /*****************************************************************************
  889. * Function: void _DtHelpCeIconvContextSuitable()
  890. *
  891. * Parameters:
  892. * iconvContext: context
  893. * fromCode: proposed fromCodeset
  894. * toCode: proposed toCodeset
  895. *
  896. * Return Value: True: proposed conversion compatible with this context
  897. * False: proposed conversion is not compatible
  898. *
  899. * Purpose:
  900. * Checks whether the proposed conversion from
  901. * fromCodeset to toCodeset can be handled by
  902. * the iconv context that already exists.
  903. *
  904. * Comments:
  905. * This function is designed to allow a context
  906. * to stay open as long as possible and avoid
  907. * closing and then reopening the contexts for
  908. * the same conversion.
  909. *****************************************************************************/
  910. int _DtHelpCeIconvContextSuitable(
  911. _DtHelpCeIconvContext iconvContext,
  912. const char * fromCode,
  913. const char * toCode)
  914. {
  915. if ( !iconvContext
  916. || !iconvContext->fromCodeset
  917. || !iconvContext->toCodeset
  918. || !fromCode
  919. || !toCode)
  920. return False;
  921. if ( strcmp(iconvContext->fromCodeset,fromCode) == 0
  922. && strcmp(iconvContext->toCodeset,toCode) == 0)
  923. return True;
  924. return False;
  925. }
  926. #if defined(_AIX)
  927. /*****************************************************************************
  928. * Function: _DtHelpCeStrCaseCmp
  929. *
  930. * Parameters:
  931. *
  932. * Return Value:
  933. *
  934. * Purpose: IBM does not support the 'strcasecmp' routine. This takes it's
  935. * place.
  936. *****************************************************************************/
  937. int
  938. _DtHelpCeStrCaseCmp (
  939. const char *s1,
  940. const char *s2)
  941. {
  942. return (_DtCvStrCaseCmp(s1, s2));
  943. }
  944. #endif /* _AIX */
  945. /******************************************************************************
  946. * Function: int _DtHelpCeFreeStringArray (char **array)
  947. *
  948. * Parameters: array A pointer to the NULL-terminated
  949. * string array which is to be freed.
  950. *
  951. * Return Value: 0 if successful, -1 if a failure occurs
  952. *
  953. * Purpose: Free the memory used for a NULL-terminated string array.
  954. *
  955. ******************************************************************************/
  956. int
  957. _DtHelpCeFreeStringArray (char **array)
  958. {
  959. char **next;
  960. if (array == NULL)
  961. return -1;
  962. for (next = array; *next != NULL; next++)
  963. free (*next);
  964. free (array);
  965. return (0);
  966. }
  967. /****************************************************************************
  968. * Function: void **_DtHelpCeAddPtrToArray (void **array, void *ptr)
  969. *
  970. * Parameters: array A pointer to a NULL-terminated array
  971. * of pointers.
  972. * ptr The pointer which is to be added to
  973. * the end of the array.
  974. *
  975. * Returns: A pointer to the NULL-terminated array created
  976. * by adding 'ptr' to the end of 'array'.
  977. *
  978. * Purpose: Add a new element to a NULL-terminated array of pointers.
  979. * These are typed as "void *" so that they can be used with
  980. * pointers to any type of data.
  981. *
  982. ****************************************************************************/
  983. void **
  984. _DtHelpCeAddPtrToArray (
  985. void **array,
  986. void *ptr)
  987. {
  988. return (_DtCvAddPtrToArray(array, ptr));
  989. }
  990. /*****************************************************************************
  991. * Function: _DtHelpCeStrCaseCmpLatin1
  992. *
  993. * Parameters:
  994. *
  995. * Return Value:
  996. *
  997. * Purpose: Use a version of CaseCmp that does not go through tolower().
  998. * This routine should be used only for compares that now the
  999. * strings are in English (iso8859-1) and do not want setlocale
  1000. * to screw it up.
  1001. *****************************************************************************/
  1002. int
  1003. _DtHelpCeStrCaseCmpLatin1 (
  1004. const char *s1,
  1005. const char *s2)
  1006. {
  1007. return (_DtCvStrCaseCmpLatin1(s1, s2));
  1008. }
  1009. /*****************************************************************************
  1010. * Function: _DtHelpCeStrNCaseCmpLatin1
  1011. *
  1012. * Parameters:
  1013. *
  1014. * Return Value:
  1015. *
  1016. * Purpose: Use a version of CaseCmp that does not go through tolower().
  1017. * This routine should be used only for compares that now the
  1018. * strings are in English (iso8859-1) and do not want setlocale
  1019. * to screw it up.
  1020. *****************************************************************************/
  1021. int
  1022. _DtHelpCeStrNCaseCmpLatin1 (
  1023. const char *s1,
  1024. const char *s2,
  1025. size_t n)
  1026. {
  1027. return (_DtCvStrNCaseCmpLatin1(s1, s2, n));
  1028. }