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