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