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