StringFuncs.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  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 librararies 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. /*
  46. * system includes
  47. */
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <limits.h>
  51. #include <errno.h>
  52. #include <locale.h> /* getlocale(), LOCALE_STATUS, LC_xxx */
  53. #if defined(_AIX) || defined(USL) || defined(__uxp__) || defined(CSRG_BASED)
  54. #include <ctype.h>
  55. #endif
  56. #include "CvStringI.h" /* for string functions used by Canvas Engine */
  57. #include "StringFuncsI.h" /* for _CEStrcollProc */
  58. #if !defined(linux)
  59. # include <iconv.h>
  60. #else
  61. # define iconv_t int
  62. # define iconv_open(a, b) ((iconv_t) -1)
  63. # define iconv(a, b, c, d, e) ((size_t) 0)
  64. # define iconv_close(a) (0)
  65. #endif
  66. #ifdef ICONV_INBUF_CONST
  67. # define ICONV_INBUF_TYPE const char **
  68. #else
  69. # define ICONV_INBUF_TYPE char **
  70. #endif
  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. register char c;
  442. register const char * tstr;
  443. register 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. #if defined(__hpux)
  475. struct locale_data * li;
  476. #else
  477. char * locale;
  478. #endif
  479. extern int strcoll(const char *,const char *);
  480. #if defined(_AIX) || defined(USL) || defined(__uxp__)
  481. extern int _DtHelpCeStrCaseCmp(const char *,const char *);
  482. #else
  483. extern int strcasecmp(const char *,const char *);
  484. #endif
  485. #define C_LANG "C"
  486. /* if locale is C, use the explicit case insensitive compare */
  487. #if defined(__hpux)
  488. li = getlocale(LOCALE_STATUS);
  489. if ( NULL == li->LC_COLLATE_D || strcmp(C_LANG,li->LC_COLLATE_D) == 0 )
  490. Clang = 1;
  491. #else
  492. locale = setlocale(LC_COLLATE,NULL); /* put locale in buf */
  493. if (strcmp(locale,C_LANG) == 0)
  494. Clang = 1;
  495. #endif
  496. if (Clang)
  497. #if defined(_AIX) || defined(USL) || defined(__uxp__)
  498. return _DtHelpCeStrCaseCmp;
  499. #else
  500. return strcasecmp;
  501. #endif
  502. return strcoll;
  503. }
  504. /*****************************************************************************
  505. * Function: String _DtHelpCeStripSpaces (string)
  506. *
  507. *
  508. * Parameters: String to process
  509. *
  510. * Return Value: Processed string
  511. *
  512. * Purpose: Strip all leading and trailing spaces.
  513. * Processing is in place
  514. *
  515. *****************************************************************************/
  516. char * _DtHelpCeStripSpaces (
  517. char * string)
  518. {
  519. int i;
  520. int multiLen = MB_CUR_MAX;
  521. char * space;
  522. if (string == NULL)
  523. return (string);
  524. /* Strip off leading spaces first */
  525. i = 0;
  526. while ((multiLen == 1 || (mblen(string + i, MB_LEN_MAX) == 1)) &&
  527. isspace((unsigned char) string[i]))
  528. {
  529. i++;
  530. }
  531. /* Copy over the leading spaces */
  532. strcpy(string, string + i);
  533. /* Drop out, if the string is now empty */
  534. if ((i = strlen(string) - 1) < 0)
  535. return(string);
  536. /* Strip off trailing spaces */
  537. if (multiLen == 1)
  538. {
  539. /* No multibyte; simply work back through the string */
  540. while ((i >= 0) && (isspace((unsigned char) string[i])))
  541. i--;
  542. string[i + 1] = '\0';
  543. }
  544. else
  545. {
  546. /* Work forward, looking for a trailing space of spaces */
  547. int len;
  548. i = 0;
  549. space = NULL;
  550. while (string[i])
  551. {
  552. if ( ((len =mblen(string + i, MB_LEN_MAX)) == 1)
  553. && isspace((unsigned char) string[i]))
  554. {
  555. /* Found a space */
  556. if (space == NULL)
  557. space = string + i;
  558. }
  559. else if (space)
  560. space = NULL;
  561. /* if there is an invalid character, treat as a valid one-byte */
  562. if (len == -1)
  563. len = 1;
  564. i += len;
  565. }
  566. if (space)
  567. *space = '\0';
  568. }
  569. return (string);
  570. }
  571. /*****************************************************************************
  572. * Function: void _DtHelpCeCompressSpace (string)
  573. *
  574. * Parameters: string to process
  575. *
  576. * Return Value: processed string
  577. *
  578. * Purpose: This function strips all leading and trailing spaces
  579. * from the string; it also compresses any intervening
  580. * spaces into a single space. This is useful when
  581. * comparing name strings. For instance, the string:
  582. * " First Middle Last "
  583. *
  584. * would compress to:
  585. *
  586. * "First Middle Last"
  587. *
  588. * Processing is in place.
  589. *
  590. *****************************************************************************/
  591. void _DtHelpCeCompressSpace (
  592. char * string)
  593. {
  594. char * ptr;
  595. /* Strip leading and trailing spaces */
  596. _DtHelpCeStripSpaces(string);
  597. /* Compress intervening spaces */
  598. _DtHelpCeStrchr(string, " ", 1, &ptr);
  599. while (ptr)
  600. {
  601. /* Skip over the one space we plan to keep */
  602. ptr++;
  603. _DtHelpCeStripSpaces(ptr);
  604. _DtHelpCeStrchr(ptr, " ", 1, &ptr);
  605. }
  606. }
  607. /*****************************************************************************
  608. * Function: void _DtHelpCeIconvStr1Step (string)
  609. *
  610. * Parameters:
  611. * fromCode; codeset name
  612. * fromStr; string to convert
  613. * toCode; codeset name
  614. * ret_toStr; converted str; this string is malloc'd by this routine
  615. * and the CALLER MUST FREE it when no longer needed.
  616. * dflt1; 1-byte default char
  617. * dflt2; 2-byte default char
  618. *
  619. * Return Value:
  620. * 0: ok
  621. * -1: missing (NULL) argument
  622. * -2: no translation available from fromCode to toCode
  623. * -3: couldn't allocate memory
  624. * -4: couldn't start conversion
  625. * -5: incomplete multibyte char
  626. * -6: invalid char found
  627. *
  628. * Purpose:
  629. * Converts string from fromCode to toCode using iconv(3)
  630. * It expects the codeset strings to be iconv(3) compatible.
  631. * Generally, compatible strings can be retrieved using
  632. * the _DtHelpCeXlateStdToOpLocale() call.
  633. *
  634. * Comments:
  635. * iconv(3) is standardized in XPG4, which is just starting
  636. * to be supported. Below are several different implementations
  637. * of _DtHelpCeIconvStr, each using what is available on different
  638. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  639. *****************************************************************************/
  640. int _DtHelpCeIconvStr1Step(
  641. const char * fromCode, /* codeset name */
  642. const char * fromStr, /* string to convert */
  643. const char * toCode, /* codeset name */
  644. char * * ret_toStr, /* converted str */
  645. int dflt1, /* 1-byte default char */
  646. int dflt2) /* 2-byte default char */
  647. {
  648. _DtHelpCeIconvContextRec * iconvContext;
  649. int ret;
  650. ret = _DtHelpCeIconvOpen(&iconvContext,fromCode,toCode,dflt1,dflt2);
  651. if (0 == ret)
  652. ret = _DtHelpCeIconvStr(iconvContext,fromStr, ret_toStr,NULL,NULL,0);
  653. _DtHelpCeIconvClose(&iconvContext);
  654. return ret;
  655. }
  656. /*****************************************************************************
  657. * Function: void _DtHelpCeIconvOpen (string)
  658. *
  659. * Parameters:
  660. * iconvContext context
  661. * fromStr; string to convert
  662. * ret_toStr; converted str; this string is malloc'd by this routine
  663. * and the CALLER MUST FREE it when no longer needed.
  664. * dflt1; 1-byte default char
  665. * dflt2; 2-byte default char
  666. *
  667. * Return Value:
  668. * 0: ok
  669. * -1: missing (NULL) argument
  670. * -2: no translation available from fromCode to toCode
  671. * -3: couldn't allocate memory
  672. * -4: couldn't start conversion
  673. * -5: incomplete multibyte char
  674. * -6: invalid char found
  675. *
  676. * Purpose:
  677. * Opens an iconv table/algorithm to convert string from
  678. * fromCode to toCode using iconv(3)
  679. * It expects the codeset strings to be iconv(3) compatible.
  680. * Generally, compatible strings can be retrieved using
  681. * the _DtHelpCeXlateStdToOpLocale() call.
  682. *
  683. * Comments:
  684. * iconv(3) is standardized in XPG4, which is just starting
  685. * to be supported. Below are several different implementations
  686. * of _DtHelpCeIconvStr, each using what is available on different
  687. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  688. *****************************************************************************/
  689. int _DtHelpCeIconvOpen(
  690. _DtHelpCeIconvContext * ret_iconvContext, /* iconv */
  691. const char * fromCode, /* codeset name */
  692. const char * toCode, /* codeset name */
  693. int dflt1, /* 1-byte default char */
  694. int dflt2) /* 2-byte default char */
  695. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  696. int err; /* error code of function */
  697. _DtHelpCeIconvContextRec * ic;
  698. #define BAD (-1)
  699. #define MEM_INC 20
  700. err = 0; /* ok */
  701. /* check args */
  702. if (!ret_iconvContext || !fromCode || !toCode )
  703. return -1; /* RETURN error */
  704. /* init state */
  705. ic = *ret_iconvContext = calloc(1,sizeof(_DtHelpCeIconvContextRec));
  706. if (NULL == ic) return -3; /* RETURN error */
  707. if ( strcmp(fromCode,toCode) == 0 )
  708. {
  709. ic->cd = (iconv_t) BAD; /* BAD means use strdup() */
  710. goto success;
  711. }
  712. ic->cd = iconv_open(toCode,fromCode);
  713. if ( ic->cd == (iconv_t) BAD )
  714. {
  715. err = -4; /* error */
  716. goto success;
  717. }
  718. success:
  719. ic->fromCodeset = strdup(fromCode);
  720. ic->toCodeset = strdup(toCode);
  721. return err; /* RETURN status */
  722. }
  723. /*****************************************************************************
  724. * Function: void _DtHelpCeIconvStr (string)
  725. *
  726. * Parameters:
  727. * iconvContext context for the conversion
  728. * fromStr; string to convert
  729. * ret_toStr; converted str; this string is malloc'd by this routine
  730. * and the CALLER MUST FREE it when no longer needed.
  731. * toStrBuf; for efficiency, can pass in a buf
  732. * toStrBufLen; length of buf
  733. *
  734. * Return Value:
  735. * 0: ok
  736. * -1: missing (NULL) argument
  737. * -2: no translation available from fromCode to toCode
  738. * -3: couldn't allocate memory
  739. * -4: couldn't start conversion
  740. * -5: incomplete multibyte char
  741. * -6: invalid char found
  742. *
  743. * Purpose:
  744. * Converts string from fromCode to toCode using iconv(3)
  745. * If toStrBuf is NULL, memory for the converted string
  746. * will be malloced as needed.
  747. * If toStrBuf is not NULL, the conversion will use up
  748. * to toStrBufLen bytes of the buffer and then realloc
  749. * more memory if needed.
  750. * If toStrBuf is not NULL, the size of the buf is
  751. * returned in ret_toStrLen; otherwise, the value is
  752. * not set.
  753. * ret_toStr receives the pointer to the buf, which may
  754. * be different from toStrBuf if memory was allocated
  755. * or NULL if an error occurred. If toStrBuf is
  756. * not NULL and memory must be allocated, a realloc()
  757. * call is used, possibly invalidating the toStrBuf ptr.
  758. * ret_toStrLen receives the length of the buffer if
  759. * toStrBuf is not NULL. If it is NULL, the length
  760. * is not returned.
  761. * Comments:
  762. * iconv(3) is standardized in XPG4, which is just starting
  763. * to be supported. Below are several different implementations
  764. * of _DtHelpCeIconvStr, each using what is available on different
  765. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  766. *****************************************************************************/
  767. int _DtHelpCeIconvStr(
  768. _DtHelpCeIconvContext iconvContext, /* iconv */
  769. const char * fromStr, /* string to convert */
  770. char * * ret_toStr, /* converted str */
  771. size_t * ret_toStrLen, /* converted str */
  772. char * toStrBuf, /* for efficiency, can pass in a buf */
  773. size_t toStrBufLen) /* length of buf */
  774. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  775. char * toStr; /* ptr to tostr memory */
  776. int toStrSize; /* size of mallocd string */
  777. size_t inBytesLeft; /* bytes left to use from input buf */
  778. const char * inChar; /* ptr into fromstr */
  779. char * outChar; /* ptr into tostr */
  780. size_t outBytesLeft; /* bytes left in the output str */
  781. int err; /* error code of function */
  782. #define BAD (-1)
  783. #define MEM_INC 20
  784. /* init ret values; allows function to be called nicely in a loop. */
  785. if (ret_toStr) *ret_toStr = toStrBuf;
  786. if (ret_toStrLen) *ret_toStrLen = toStrBufLen;
  787. /* check args */
  788. if ( !iconvContext || !fromStr || !ret_toStr
  789. || (!ret_toStrLen && toStrBuf))
  790. return -1; /* RETURN error */
  791. /* just do a straight copy if codesets the same or invalid context */
  792. if ( iconvContext->cd == (iconv_t) BAD )
  793. {
  794. if (NULL == toStrBuf)
  795. {
  796. *ret_toStr = strdup(fromStr);
  797. }
  798. else /* reuse the buffer */
  799. {
  800. int len = strlen(fromStr);
  801. if (len > toStrBufLen)
  802. *ret_toStr = realloc(toStrBuf,len);
  803. else
  804. {
  805. *ret_toStr = toStrBuf;
  806. len = toStrBufLen;
  807. }
  808. /* set return values */
  809. strcpy(*ret_toStr,fromStr);
  810. *ret_toStrLen = len;
  811. }
  812. return (NULL != *ret_toStr ? 0 : -3); /* RETURN result */
  813. }
  814. /* init ptrs */
  815. toStr = toStrBuf;
  816. toStrSize = (NULL == toStrBuf ? 0 : toStrBufLen);
  817. inChar = fromStr;
  818. inBytesLeft = strlen(fromStr);
  819. outChar = toStr;
  820. outBytesLeft = toStrSize;
  821. /* translate the string */
  822. err = -3;
  823. while ( inBytesLeft > 0 )
  824. {
  825. /* convert a character */
  826. if(iconv(iconvContext->cd, (ICONV_INBUF_TYPE)&inChar,
  827. &inBytesLeft,&outChar,&outBytesLeft) == -1)
  828. {
  829. switch(errno)
  830. {
  831. case 0: /* no error */
  832. continue;
  833. case EINVAL: /* inChar pts to incomplete multibyte char */
  834. inBytesLeft = 0; /* end the translation */
  835. err = -5;
  836. break;
  837. case EILSEQ: /* invalid char at inChar */
  838. inBytesLeft = 0; /* end the translation */
  839. err = -6;
  840. break;
  841. case E2BIG: /* no room in toStr */
  842. /* provide enough mem in the toStr */
  843. if (outBytesLeft < sizeof(wchar_t))
  844. {
  845. size_t offset = outChar - (char *) toStr;
  846. outBytesLeft += MEM_INC;
  847. toStrSize += MEM_INC;
  848. toStr = realloc(toStr,toStrSize * sizeof(char));
  849. if (NULL == toStr)
  850. {
  851. inBytesLeft = 0; /* end the translation */
  852. err = -3;
  853. break; /* BREAK */
  854. }
  855. outChar = (char *) (toStr + offset); /* recalc ptr */
  856. }
  857. break;
  858. default:
  859. inBytesLeft = 0; /* breakout of loop */
  860. break;
  861. } /* switch on convertsion result */
  862. } /* if an error */
  863. } /* while chars left to translate */
  864. /* set the EOS */
  865. if(outChar) *outChar = EOS;
  866. /* set return values */
  867. *ret_toStr = (char *) toStr;
  868. if (toStrBuf) *ret_toStrLen = toStrSize;
  869. return (NULL != toStr ? 0 : err); /* RETURN result */
  870. }
  871. /*****************************************************************************
  872. * Function: void _DtHelpCeIconvClose()
  873. *
  874. * Parameters:
  875. * io_iconvContext; context
  876. *
  877. * Return Value: none
  878. *
  879. * Purpose:
  880. * Closes an iconv context used to convert
  881. * fromCode to toCode using iconv(3)
  882. *
  883. * Comments:
  884. * iconv(3) is standardized in XPG4, which is just starting
  885. * to be supported. Below are several different implementations
  886. * of _DtHelpCeIconvStr, each using what is available on different
  887. * platforms. If no code is #ifdef'd, the XPG4 code defaults.
  888. *****************************************************************************/
  889. void _DtHelpCeIconvClose(
  890. _DtHelpCeIconvContext * io_iconvContext)
  891. { /* XPG4-compliant code (args dflt1 & dflt2 are ignored in this code) */
  892. _DtHelpCeIconvContextRec * ic;
  893. if (!io_iconvContext || NULL == *io_iconvContext) return;
  894. ic = *io_iconvContext;
  895. if ( ic->cd != (iconv_t) BAD )
  896. iconv_close(ic->cd);
  897. if (ic->fromCodeset) free(ic->fromCodeset);
  898. if (ic->toCodeset) free(ic->toCodeset);
  899. free(ic);
  900. *io_iconvContext = NULL;
  901. }
  902. /*****************************************************************************
  903. * Function: void _DtHelpCeIconvContextSuitable()
  904. *
  905. * Parameters:
  906. * iconvContext: context
  907. * fromCode: proposed fromCodeset
  908. * toCode: proposed toCodeset
  909. *
  910. * Return Value: True: proposed conversion compatible with this context
  911. * False: proposed conversion is not compatible
  912. *
  913. * Purpose:
  914. * Checks whether the proposed conversion from
  915. * fromCodeset to toCodeset can be handled by
  916. * the iconv context that already exists.
  917. *
  918. * Comments:
  919. * This function is designed to allow a context
  920. * to stay open as long as possible and avoid
  921. * closing and then reopening the contexts for
  922. * the same conversion.
  923. *****************************************************************************/
  924. int _DtHelpCeIconvContextSuitable(
  925. _DtHelpCeIconvContext iconvContext,
  926. const char * fromCode,
  927. const char * toCode)
  928. {
  929. if ( !iconvContext
  930. || !iconvContext->fromCodeset
  931. || !iconvContext->toCodeset
  932. || !fromCode
  933. || !toCode)
  934. return False;
  935. if ( strcmp(iconvContext->fromCodeset,fromCode) == 0
  936. && strcmp(iconvContext->toCodeset,toCode) == 0)
  937. return True;
  938. return False;
  939. }
  940. #if defined(_AIX) || defined (USL) || defined(__uxp__)
  941. /*****************************************************************************
  942. * Function: _DtHelpCeStrCaseCmp
  943. *
  944. * Parameters:
  945. *
  946. * Return Value:
  947. *
  948. * Purpose: IBM and USL do not support the 'strcasecmp' routine. This takes it's
  949. * place.
  950. *****************************************************************************/
  951. int
  952. _DtHelpCeStrCaseCmp (
  953. const char *s1,
  954. const char *s2)
  955. {
  956. return (_DtCvStrCaseCmp(s1, s2));
  957. }
  958. #endif /* _AIX or USL */
  959. /******************************************************************************
  960. * Function: int _DtHelpCeFreeStringArray (char **array)
  961. *
  962. * Parameters: array A pointer to the NULL-terminated
  963. * string array which is to be freed.
  964. *
  965. * Return Value: 0 if successful, -1 if a failure occurs
  966. *
  967. * Purpose: Free the memory used for a NULL-terminated string array.
  968. *
  969. ******************************************************************************/
  970. int
  971. _DtHelpCeFreeStringArray (char **array)
  972. {
  973. char **next;
  974. if (array == NULL)
  975. return -1;
  976. for (next = array; *next != NULL; next++)
  977. free (*next);
  978. free (array);
  979. return (0);
  980. }
  981. /****************************************************************************
  982. * Function: void **_DtHelpCeAddPtrToArray (void **array, void *ptr)
  983. *
  984. * Parameters: array A pointer to a NULL-terminated array
  985. * of pointers.
  986. * ptr The pointer which is to be added to
  987. * the end of the array.
  988. *
  989. * Returns: A pointer to the NULL-terminated array created
  990. * by adding 'ptr' to the end of 'array'.
  991. *
  992. * Purpose: Add a new element to a NULL-terminated array of pointers.
  993. * These are typed as "void *" so that they can be used with
  994. * pointers to any type of data.
  995. *
  996. ****************************************************************************/
  997. void **
  998. _DtHelpCeAddPtrToArray (
  999. void **array,
  1000. void *ptr)
  1001. {
  1002. return (_DtCvAddPtrToArray(array, ptr));
  1003. }
  1004. /*****************************************************************************
  1005. * Function: _DtHelpCeStrCaseCmpLatin1
  1006. *
  1007. * Parameters:
  1008. *
  1009. * Return Value:
  1010. *
  1011. * Purpose: Use a version of CaseCmp that does not go through tolower().
  1012. * This routine should be used only for compares that now the
  1013. * strings are in English (iso8859-1) and do not want setlocale
  1014. * to screw it up.
  1015. *****************************************************************************/
  1016. int
  1017. _DtHelpCeStrCaseCmpLatin1 (
  1018. const char *s1,
  1019. const char *s2)
  1020. {
  1021. return (_DtCvStrCaseCmpLatin1(s1, s2));
  1022. }
  1023. /*****************************************************************************
  1024. * Function: _DtHelpCeStrNCaseCmpLatin1
  1025. *
  1026. * Parameters:
  1027. *
  1028. * Return Value:
  1029. *
  1030. * Purpose: Use a version of CaseCmp that does not go through tolower().
  1031. * This routine should be used only for compares that now the
  1032. * strings are in English (iso8859-1) and do not want setlocale
  1033. * to screw it up.
  1034. *****************************************************************************/
  1035. int
  1036. _DtHelpCeStrNCaseCmpLatin1 (
  1037. const char *s1,
  1038. const char *s2,
  1039. size_t n)
  1040. {
  1041. return (_DtCvStrNCaseCmpLatin1(s1, s2, n));
  1042. }