Remove UXPDS support
[oweals/cde.git] / cde / lib / DtHelp / CvString.c
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 /* $XConsortium: CvString.c /main/4 1996/08/30 15:28:00 cde-hp $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:     CvString.c
28  **
29  **   Project:  Cde DtHelp
30  **
31  **   Description: Semi private string functions - can be platform dependent.
32  **                These routines are straight C code. They do not require
33  **                includes to know about the Canvas Engine, the Help
34  **                dialogs or anything else.
35  **
36  **
37  **  (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
38  **
39  **  (c) Copyright 1993, 1994 Hewlett-Packard Company
40  **  (c) Copyright 1993, 1994 International Business Machines Corp.
41  **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
42  **  (c) Copyright 1993, 1994 Novell, Inc.
43  **
44  **
45  **
46  ****************************************************************************
47  ************************************<+>*************************************/
48 /*
49  * system includes
50  */
51 #include <stdlib.h>
52 #include <string.h>
53
54 /*
55  * private includes
56  */
57 #include "CvStringI.h"
58
59 /******************************************************************************
60  *
61  * Private variables and defines.
62  *
63  *****************************************************************************/
64 #define REALLOC_INCR    10
65
66 /******************************************************************************
67  *
68  * Semi Public Functions
69  *
70  *****************************************************************************/
71 /******************************************************************************
72  * Function: _DtCvStrLen (const void *p1, int type)
73  *
74  * Paramenters:
75  *              p1      Specifies the string or wide char array to process.
76  *              type    Specifies the type p1 is. 0 indicaates a string.
77  *                      non-zero indicates a wide char array.
78  * Returns:
79  *              >= 0    If p1 is non-null.
80  *              -1      If p1 is null.
81  *
82  * Purpose:
83  *      Returns in number of characters in p1.
84  *
85  *****************************************************************************/
86 int
87 _DtCvStrLen (
88     const void    *p1,
89     int            type )
90 {
91     int            len = 0;
92     const wchar_t *wcs;
93
94     if (0 == type)
95         return (strlen((const char *) p1));
96
97     wcs = (wchar_t *) p1;
98     while (0 != *wcs)
99       {
100         wcs++;
101         len++;
102       }
103
104     return len;
105 }
106
107 /******************************************************************************
108  * Function: _DtCvStrPtr (const void *p1, int type, int count)
109  *
110  * Paramenters:
111  *              p1      Specifies the string or wide char array to process.
112  *              type    Specifies the type p1 is. 0 indicaates a string.
113  *                      non-zero indicates a wide char array.
114  *              count   Specifies an index into p1.
115  * Returns:
116  *              ptr     If everything works okay.
117  *              NULL    If problems.
118  *
119  * Purpose:
120  *      Get to a point in the wide character or char string.
121  *
122  *****************************************************************************/
123 void *
124 _DtCvStrPtr (
125     const void    *p1,
126     int            type,
127     int            count)
128 {
129
130     if (0 == type)
131         return ((void *) (((char *) p1) + count));
132
133     return ((void *) (((wchar_t *) p1) + count));
134 }
135
136 /******************************************************************************
137  * Function: _DtCvChar (const void *p1, int type, int count)
138  *
139  * Paramenters:
140  *              p1      Specifies the string or wide char array to process.
141  *              type    Specifies the type p1 is. 0 indicaates a string.
142  *                      non-zero indicates a wide char array.
143  *              count   Specifies an index into p1.
144  * Returns:
145  *              value           If everything works okay.
146  *              (wchar_t) -1    If problems.
147  *
148  * Purpose:
149  *      Get a character value.
150  *
151  *****************************************************************************/
152 wchar_t
153 _DtCvChar (
154     const void    *p1,
155     int            type,
156     int            count)
157 {
158     wchar_t value = (wchar_t) -1;
159
160     if (0 == type)
161         value = *(((char *) p1) + count);
162     else
163         value = *(((wchar_t *) p1) + count);
164
165     return (value);
166 }
167
168 /******************************************************************************
169  * Function: _DtCvStrcspn (const void *s1, const char *s2, type, &ret_len)
170  *
171  *      Returns in 'ret_len' the length of the initial segment of string
172  *      s1 which consists entirely of characters not found in string s2.
173  *
174  *      if type is 0, then s1 is a char* string.
175  *      if type is not 0, then s1 is a wchar_t* string.
176  *
177  *      s2 cannot be more than 15 characters if looking a wide character
178  *      string in s1.
179  *
180  * Returns:
181  *      -1  If found an invalid character.
182  *       0  If found a character in string s2
183  *       1  If found the null byte character.
184  *       2  s2 contained more than 15 characters, but found one of the
185  *          first fifteen characters in string s2.
186  *       3  s2 contained more than 15 characters, and didn't find any
187  *          of the first fifteen characters in string s2.
188  *****************************************************************************/
189 int
190 _DtCvStrcspn (
191     const void    *s1,
192     const char    *s2,
193     int            type,
194     int           *ret_len )
195 {
196     size_t         num;
197     wchar_t        widec[16];
198     const wchar_t *wcp;
199     const wchar_t *wcp2;
200
201     if (NULL == s1)
202       {
203         *ret_len = 0;
204         return 0;
205       }
206
207     if ((0 == type && '\0' == *((char *) s1)) ||
208         (0 != type && 0 == *((wchar_t *) s1)))
209       {
210         *ret_len = 0;
211         return 1;
212       }
213
214     if (NULL == s2 || '\0' == *s2)
215       {
216         *ret_len = _DtCvStrLen (s1, type);
217         return 1;
218       }
219
220     if (0 == type)
221       {
222         /*
223          * no need to go through any hassle, just use the 3C function
224          */
225         *ret_len = strcspn ((char *) s1, s2);
226         if ('\0' == ((char *) s1)[*ret_len])
227             return 1;
228         return 0;
229       }
230
231     /*
232      * convert the test string into a wide char array
233      */
234     num = mbstowcs(widec, s2, 16);
235     if ((size_t) -1 == num)
236         return -1;
237
238     /*
239      * force a null termination of the array
240      */
241     widec[15] = 0;
242
243     /*
244      * if greater than 15 characters were converted, set the flag to 2
245      */
246     num = ((num > 15) ? 2 : 0);
247
248     wcp = s1;
249     while (0 != *wcp)
250       {
251         wcp2 = widec;
252         while (0 != *wcp2)
253           {
254             if (*wcp2 == *wcp)
255               {
256                 *ret_len = wcp - (wchar_t *) s1;
257                 return 0 + num;
258               }
259             wcp2++;
260           }
261         wcp++;
262       }
263
264     *ret_len = wcp - (wchar_t *) s1;
265     return 1 + num;
266 }
267
268 /****************************************************************************
269  * Function:    void **_DtCvAddPtrToArray (void **array, void *ptr)
270  *
271  * Parameters:  array           A pointer to a NULL-terminated array
272  *                              of pointers.
273  *              ptr             The pointer which is to be added to
274  *                              the end of the array.
275  *
276  * Returns:     A pointer to the NULL-terminated array created
277  *              by adding 'ptr' to the end of 'array'.
278  *
279  * Purpose:     Add a new element to a NULL-terminated array of pointers.
280  *              These are typed as "void *" so that they can be used with
281  *              pointers to any type of data.
282  *
283  ****************************************************************************/
284 void **
285 _DtCvAddPtrToArray (
286        void  **array,
287        void   *ptr)
288 {
289
290     void **nextP = NULL;
291     int numElements;
292
293     /* If this is the first item for the array, malloc the array and set
294        nextP to point to the first element. */
295     if (array == NULL || *array == NULL) {
296         array = (void **) malloc (REALLOC_INCR * sizeof (void *));
297
298         nextP = array;
299     }
300
301     else {
302
303         /* Find the NULL pointer at the end of the array. */
304         numElements = 0;
305         for (nextP = array; *nextP != NULL; nextP++)
306                 numElements++;
307
308         /* The array always grows by chunks of size REALLOC_INCR.  So see if
309            it currently is an exact multiple of REALLOC_INCR size (remember to
310            count the NULL pointer).  If it is then it must be full, so realloc
311            another chunk.  Also remember to move 'nextP' because the array
312            will probably move in memory. */
313         if ((numElements + 1) % REALLOC_INCR == 0) {
314             array = (void **) realloc (array,
315                         (numElements + 1 + REALLOC_INCR) * sizeof (void *));
316             if (array)
317                 nextP = array + numElements;
318             else
319                 nextP = NULL;
320         }
321     }
322
323     if (nextP)
324       {
325         *nextP++ = ptr;
326         *nextP = NULL;
327       }
328
329     return (array);
330 }
331
332 /******************************************************************************
333  * Function:     int _DtCvFreeArray (void **array)
334  *
335  * Parameters:   array           A pointer to the NULL-terminated
336  *                               string array which is to be freed.
337  *
338  * Return Value: 0 if successful, -1 if a failure occurs
339  *
340  * Purpose:      Free the memory used for a NULL-terminated string array.
341  *
342  ******************************************************************************/
343 int
344 _DtCvFreeArray (void **array)
345 {
346     void        **next;
347
348     if (array == NULL)
349         return -1;
350
351     for (next = array; *next != NULL; next++)
352         free (*next);
353
354     free (array);
355     return (0);
356 }
357
358 #if defined(_AIX) || defined (USL)
359 /*****************************************************************************
360  * Function: _DtCvStrCaseCmp
361  *
362  * Parameters:
363  *
364  * Return Value:
365  *
366  * Purpose: IBM and USL do not support the 'strcasecmp' routine. This takes it's
367  *          place.
368  *****************************************************************************/
369 int
370 _DtCvStrCaseCmp (
371     const char  *s1,
372     const char  *s2)
373 {
374     int   c1;
375     int   c2;
376     int   result = 0;
377
378     if (s1 == s2)    return  0;
379     if (NULL == s1)  return -1;
380     if (NULL == s2)  return  1;
381
382
383     while (result == 0 && *s1 != '\0' && *s2 != '\0')
384       {
385         c1 = (unsigned char) *s1;
386         c2 = (unsigned char) *s2;
387
388         if (isupper(c1))
389             c1 = _tolower(c1);
390         if (isupper(c2))
391             c2 = _tolower(c2);
392
393         result = c1 - c2;
394         s1++;
395         s2++;
396       }
397
398     if (result == 0 && (*s1 != '\0' || *s2 != '\0'))
399       {
400         c1 = (unsigned char) *s1;
401         c2 = (unsigned char) *s2;
402
403         if (isupper(c1))
404             c1 = _tolower(c1);
405         if (isupper(c2))
406             c2 = _tolower(c2);
407
408         result = c1 - c2;
409       }
410
411     return result;
412 }
413 #endif /* _AIX or USL */
414
415 /*****************************************************************************
416  * Function: _DtCvStrNCaseCmpLatin1()
417  *
418  * Purpose: Does not use the tolower() functions to determine the lower
419  *          case of a character.  On some platforms, using tolower() on
420  *          the upper case of a typical Latin1 character does not match
421  *          it's Latin1 one lower case.
422  *
423  *          This routine is to be used only when we want to map strict
424  *          Latin1 characters to it's lower case.  I.e.  when we -know-
425  *          the data is in English.
426  *****************************************************************************/
427 int
428 _DtCvStrNCaseCmpLatin1 (
429     const char  *s1,
430     const char  *s2,
431     size_t       n)
432 {
433     int   c1;
434     int   c2;
435     int   result = 0;
436
437     if (s1 == s2 || n < 1) return  0;
438     if (NULL == s1)        return -1;
439     if (NULL == s2)        return  1;
440
441
442     while (result == 0 && *s1 != '\0' && *s2 != '\0' && n > 0)
443       {
444         c1 = (unsigned char) *s1;
445         c2 = (unsigned char) *s2;
446
447         c1 = _DtCvToLower(c1);
448         c2 = _DtCvToLower(c2);
449
450         result = c1 - c2;
451         s1++;
452         s2++;
453         n--;
454       }
455
456     if (result == 0 && n > 0 && (*s1 != '\0' || *s2 != '\0'))
457       {
458         c1 = (unsigned char) *s1;
459         c2 = (unsigned char) *s2;
460
461         c1 = _DtCvToLower(c1);
462         c2 = _DtCvToLower(c2);
463
464         result = c1 - c2;
465       }
466
467     return result;
468 }
469
470 /*****************************************************************************
471  * Function: _DtCvStrCaseCmpLatin1
472  *
473  * Purpose: Does not use the tolower() functions to determine the lower
474  *          case of a character.  On some platforms, using tolower() on
475  *          the upper case of a typical Latin1 character does not match
476  *          it's Latin1 one lower case.
477  *
478  *          This routine is to be used only when we want to map strict
479  *          Latin1 characters to it's lower case.  I.e.  when we -know-
480  *          the data is in English.
481  *****************************************************************************/
482 int
483 _DtCvStrCaseCmpLatin1 (
484     const char  *s1,
485     const char  *s2)
486 {
487     int   c1;
488     int   c2;
489     int   result = 0;
490
491     if (s1 == s2)    return  0;
492     if (NULL == s1)  return -1;
493     if (NULL == s2)  return  1;
494
495
496     while (result == 0 && *s1 != '\0' && *s2 != '\0')
497       {
498         c1 = (unsigned char) *s1;
499         c2 = (unsigned char) *s2;
500
501         c1 = _DtCvToLower(c1);
502         c2 = _DtCvToLower(c2);
503
504         result = c1 - c2;
505         s1++;
506         s2++;
507       }
508
509     if (result == 0 && (*s1 != '\0' || *s2 != '\0'))
510       {
511         c1 = (unsigned char) *s1;
512         c2 = (unsigned char) *s2;
513
514         c1 = _DtCvToLower(c1);
515         c2 = _DtCvToLower(c2);
516
517         result = c1 - c2;
518       }
519
520     return result;
521 }
522