dtcm: Resolve CID 87562
[oweals/cde.git] / cde / programs / dtcm / dtcm / cm_i18n.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 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 /*******************************************************************************
24 **
25 **  cm_i18n.c
26 **
27 **  $TOG: cm_i18n.c /main/9 1998/04/01 17:26:31 mgreess $
28 **
29 **  RESTRICTED CONFIDENTIAL INFORMATION:
30 **
31 **  The information in this document is subject to special
32 **  restrictions in a confidential disclosure agreement between
33 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
35 **  Sun's specific written approval.  This document and all copies
36 **  and derivative works thereof must be returned or destroyed at
37 **  Sun's request.
38 **
39 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40 **
41 *******************************************************************************/
42
43 /*                                                                      *
44  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
45  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
46  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
47  * (c) Copyright 1993, 1994 Novell, Inc.                                *
48  */
49
50 #ifndef lint
51 #endif
52
53 #include <stdio.h>
54 #include <errno.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <string.h>
58 #include <ctype.h>
59 #include <time.h>
60 /*
61
62 This include has been left out for the moment because of a 
63 definition of the symbol "single" in rtable4.h.  This 
64 should be fixed in the future.
65
66 #include <floatingpoint.h>
67 */
68 #include <locale.h>
69 #include <sys/param.h>       /* for MAXPATHLEN */
70 #include <Xm/Xm.h>
71
72 #include <langinfo.h>
73 /* Iconv not defined for linux.  Use the EUSCompat stubs instead. */
74 #if !defined(linux)
75 #  include <iconv.h>
76 #endif
77 #include <EUSCompat.h>
78
79 #include "util.h"
80 #include "timeops.h"
81 #include "cm_i18n.h"
82 #include "deskset.h"
83 /*
84 #include "gettext.h"
85 */
86
87 char *fontset1[2]; 
88 char *fontset2[2];
89 int use_octal = FALSE;
90
91
92 int 
93 is_comment(char line[MAX_LINE_LEN])
94 {
95         char ch[2];
96
97         strncpy(ch, line, 1);
98         if ( strcmp((char *)ch, COMMENT_SYMBOL) == 0 ) {
99                 return 1;       
100         } else {
101                 return 0;       
102         }
103 }
104
105
106 int 
107 match_locale(char *locale, char line[MAX_LINE_LEN])
108 {
109         char loc[MAX_LINE_LEN]; 
110
111         if ( !isalpha(line[0]) ) {
112                 return 0;
113         }
114         (void) sscanf(line, "%s", loc);
115         if ( strcmp(loc, locale) == 0 ) {
116                 return 1;
117         } else {
118                 return 0;
119         }
120 }
121
122 /*
123  * The following code was very similar to what was developped for dtmail's
124  * conversion mechanism. See libDtMail/RFC/RFCMIME.C ! Have fun !
125  */
126 #define WORKSIZE 1024
127 static void           *_i18nwork1 = NULL;
128 static unsigned long  _i18nsize1 = 0;
129 static int            shouldAlloc1 = ~0;
130 static int            isFirstCall = ~0;
131 static iconv_t        CD = (iconv_t)-1;
132 static int            amI_932 = ~0;
133
134 #ifdef ICONV_INBUF_CONST
135 # define ICONV_INBUF_TYPE       const char **
136 #else
137 # define ICONV_INBUF_TYPE       char **
138 #endif
139
140 void _converter_( void *from, unsigned long from_len,
141                         void **to,  unsigned long *to_len )
142 {
143     char          *InBuf;
144     size_t        InBytesLeft;
145     char          *OutBuf = NULL;
146     size_t        OutBytesLeft = 0;
147     size_t        _OutBytesLeft = 0;
148     size_t        iconv_ret;
149     size_t        converted_num = 0;
150
151     *to = NULL;
152     *to_len = 0;
153
154     if ( shouldAlloc1 ) {
155         /* Obtain work area */
156         _i18nwork1 = (size_t *)malloc( WORKSIZE );
157         if ( !_i18nwork1 ) {
158             _i18nwork1 = NULL;
159             return;
160         }
161         _i18nsize1 = WORKSIZE; 
162         shouldAlloc1 = 0;
163     }
164 #ifdef _AIX
165     if ( isFirstCall ) {
166         if ( ( CD = iconv_open( "IBM-eucJP", "IBM-932" ) ) == (iconv_t)-1 )
167             return; /* no converter */
168         amI_932 = !strncasecmp( "IBM-932", nl_langinfo( CODESET ), 7 );
169         isFirstCall = 0;
170     }
171 #endif /* _AIX */
172
173     if ( ( !amI_932 ) || ( CD == (iconv_t)-1 ) )
174         return;
175
176     InBuf        = (char *)from;
177     InBytesLeft  = from_len;
178     OutBytesLeft = _i18nsize1;
179     OutBuf = (char *)_i18nwork1;
180
181     while( 1 ) {
182         /*
183          * InBuf
184          *  v
185          * +----------------------------+
186          * | |                        | |
187          * +----------------------------+
188          *  <-------------------------->
189          *          InBytesLeft
190          *
191          *             |
192          *             | iconv()
193          *             V
194          * (_i18nwork1)
195          * OutBuf
196          *  v
197          * +----------------------------+
198          * | |                        | |
199          * +----------------------------+
200          *  <-------------------------->
201          *          InBytesLeft
202          */
203
204         iconv_ret = iconv( CD, (ICONV_INBUF_TYPE)&InBuf, &InBytesLeft,
205                                &OutBuf, &OutBytesLeft );
206         if ( iconv_ret == 0 ) {
207             /* iconv done
208              *                             InBuf
209              *                               v
210              * +----------------------------+
211              * |XXXXXXXXXXXXXXXXXXXXXXXXXXXX|
212              * +----------------------------+
213              *                               
214              *                               InBytesLeft=0
215              *
216              * (_i18nwork1)
217              *  |               OutBuf
218              *  V                 v
219              * +----------------------------+
220              * |XXXXXXXXXXXXXXXXX| |      | |
221              * +----------------------------+
222              *  <---------------> <-------->
223              *   converted_num    OutBytesLeft
224              */
225             converted_num = (unsigned long)((char *)OutBuf-(char *)_i18nwork1);
226             *to = (void *)_i18nwork1;
227             *to_len = (unsigned long)converted_num;
228             break;
229         } else {
230             if ( errno == E2BIG ) {
231                 /* Overflow. still data is left.
232                  *               InBuf
233                  *                 v
234                  * +----------------------------+
235                  * |XXXXXXXXXXXXXX| |         | |
236                  * +----------------------------+
237                  *                 <----------->
238                  *                  InBytesLeft
239                  *
240                  * (_i18nwork1)
241                  *  |                         OutBuf
242                  *  V                          v
243                  * +----------------------------+
244                  * |XXXXXXXXXXXXXXXXXXXXXXXXXXX |
245                  * +----------------------------+
246                  *  <-------------------------> 
247                  *          converted_num      OutBytesLeft=?
248                  */
249                 void *_p;
250
251                 /* Check how many converted already. */
252
253                 converted_num =
254                         (unsigned long)((char *)OutBuf - (char *)_i18nwork1);
255                 _i18nsize1 += WORKSIZE;
256                 _p = realloc( _i18nwork1, _i18nsize1 );
257                 if ( !_p ) {
258                     *to = NULL;
259                     *to_len = 0;
260                     free( _i18nwork1 );
261                     _i18nwork1 = NULL;
262                     _i18nsize1 = 0;
263                     shouldAlloc1 = ~0;
264                     break;
265                 } else {
266                     _i18nwork1 = _p;
267                     OutBuf = (char *)((char*)_i18nwork1 + converted_num);
268                     OutBytesLeft += WORKSIZE;
269                 }  
270             } else {
271                 *to = NULL;
272                 *to_len = 0;
273                 break;
274             }
275         }
276     }
277
278     /*
279      * NULL terminate
280      */
281     if ( _i18nsize1 > converted_num ) {
282         ((char *)_i18nwork1)[converted_num] = '\0';
283     } else { /* _i18nsize1 == converted_num */
284         void *_p;
285
286         _i18nsize1++;
287         _p = realloc( _i18nwork1, _i18nsize1 );
288
289         if ( !_p ) {
290             *to = NULL;
291             *to_len = 0;
292             free( _i18nwork1 );
293             _i18nwork1 = NULL;
294             _i18nsize1 = 0;
295             shouldAlloc1 = ~0;
296         } else {
297             _i18nwork1 = _p;
298             ((char *)_i18nwork1)[converted_num] = '\0';
299         }
300     }
301 }
302
303 /* The following routine is specific to using FMapType 3 composite fonts
304  * in postscript.  Kanji, Asian specific?
305  */
306 char *
307 euc_to_octal(char *srcStr)
308 {
309         int inKanji = FALSE;
310         char buf[64];
311         static char dstStr[512];
312         int i;
313         int len = cm_strlen(srcStr);
314
315 #ifdef SVR4
316         memset(dstStr, 0, sizeof(dstStr));
317 #else
318         bzero(dstStr, sizeof(dstStr));
319 #endif /* SVR4 */
320         for (i = 0; i < len; i++) {
321                 if (inKanji) {
322                         if (!isEUC(srcStr[i])) {
323                                 inKanji = FALSE;
324                                 /* NOT NEEDED FOR FMapType 4 (or 5)
325                                 cm_strcat(dstStr, "\\377\\000");
326                                 */
327                         }
328                 }
329                 else {
330                         if (isEUC(srcStr[i])) {
331                                 inKanji = TRUE;
332                                 /* NOT NEEDED FOR FMapType 4 (or 5)
333                                 cm_strcat(dstStr, "\\377\\001");
334                                 */
335                         }
336                 }
337                 if (inKanji) {
338                         sprintf(buf, "\\%3.3o\\%3.3o", srcStr[i] & 0xff, srcStr[i+1] & 0xff);
339                         i++;
340                 }
341                 else {
342                         sprintf(buf, "%c", srcStr[i]);
343                 }
344                 cm_strcat(dstStr, buf);
345         }
346         return dstStr;
347 }
348
349
350 /* This routine should be in libdeskset.
351  * This routine uses fconvert() to avoid locale conversion.
352  */
353 /* 310 characters are the minimum needed to accommodate any double-precision
354  * value + 1 null terminator.
355  */
356 #define DBL_SIZE  311
357 /*
358  *  Returns a null terminated formatted string.
359  *  If error is encountered, such as malloc() failed, then return NULL.
360  *  The caller of this function should beware that the return value is
361  *  a static buffer declared within this function and the value of it may
362  *  change.
363  */
364 char *
365 cm_printf(double value, int decimal_pt)
366 {
367         int sign = 0;
368         int deci_pt = 0;
369         int buf_cnt = 0;
370         int formatted_cnt = 0;
371         int buf_len = 0;
372         char *buf = NULL;
373         static char *formatted = NULL;
374
375         if ( formatted != NULL ) {
376                 free(formatted);
377                 formatted = NULL;
378         }
379         if ( (value == (double)0) && (decimal_pt == 0) ) {
380                 formatted = (char *)cm_strdup("0");
381                 return formatted;
382         }
383         if ( (buf = (char *)malloc(DBL_SIZE + decimal_pt)) == NULL ) {
384                 return (char *)NULL;
385         }
386         if ( (formatted = (char *)calloc(1, DBL_SIZE + decimal_pt)) == NULL ) {
387                 free(buf);
388                 return (char *)NULL;
389         }
390 #ifdef SunOS
391         fconvert(value, decimal_pt, &deci_pt, &sign, buf);
392 #elif defined(CSRG_BASED)
393         snprintf(buf, decimal_pt, "%f", value);
394 #else
395         /* this version, available on the HP and AIX machine is not reentrant. */
396
397         strcpy(buf, fcvt(value, decimal_pt, &deci_pt, &sign));
398 #endif
399         if ( sign ) {
400                 strcpy(formatted, "-");
401         }
402         buf_len = deci_pt + decimal_pt;
403         if ( deci_pt ) {
404                 strncat(formatted, buf, deci_pt);
405         } else {    /* zero */
406                 strcat(formatted, "0"); 
407         }
408         if ( deci_pt == buf_len ) {
409                 strcat(formatted, "\0");
410                 free(buf);
411                 return formatted;
412         }
413         strcat(formatted, ".");
414         for ( formatted_cnt = strlen(formatted), buf_cnt = deci_pt;  buf_cnt < buf_len;  buf_cnt++, formatted_cnt++ ) {
415                 formatted[formatted_cnt] = buf[buf_cnt];
416         }
417         formatted[formatted_cnt] = '\0';
418         free(buf);
419         return formatted;       
420 }