lcDefConv.c revision 1ab64890
1/* $Xorg: lcDefConv.c,v 1.3 2000/08/17 19:45:17 cpqbld Exp $ */
2/*
3 * Copyright 1992, 1993 by TOSHIBA Corp.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation for any purpose and without fee is hereby granted, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of TOSHIBA not be used in advertising
10 * or publicity pertaining to distribution of the software without specific,
11 * written prior permission. TOSHIBA make no representations about the
12 * suitability of this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 *
15 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 * SOFTWARE.
22 *
23 * Author: Katsuhisa Yano	TOSHIBA Corp.
24 *			   	mopi@osa.ilab.toshiba.co.jp
25 */
26/*
27 * 2000
28 * Modifier: Ivan Pascal        The XFree86 Project
29 */
30/* $XFree86: xc/lib/X11/lcDefConv.c,v 1.6 2001/01/17 19:41:53 dawes Exp $ */
31
32/*
33 * The default locale loader.
34 * Supports: one byte per char (iso8859 like) locales.
35 * How: converts bytes to wide characters in a 1:1 manner.
36 * Platforms: all systems.
37 */
38
39#ifdef HAVE_CONFIG_H
40#include <config.h>
41#endif
42#include "Xlibint.h"
43#include "XlcGeneric.h"
44
45#ifndef MB_LEN_MAX
46#define MB_LEN_MAX 6
47#endif
48
49#if !defined(macII) && !defined(Lynx_22) && !defined(X_LOCALE)
50#define STDCVT
51#endif
52
53#define GR	0x80
54#define GL	0x7f
55
56typedef struct _StateRec *State;
57typedef struct _StateRec {
58    CodeSet     GL_codeset;
59    CodeSet     GR_codeset;
60    wchar_t     wc_mask;
61    wchar_t     wc_encode_mask;
62    Bool        (*MBtoWC) (State state, const char *ch, wchar_t *wc);
63    Bool        (*WCtoMB) (State state, wchar_t wc, char *ch);
64} StateRec;
65
66static
67Bool MBtoWCdef(
68    State    state,
69    const char *ch,
70    wchar_t  *wc)
71{
72    wchar_t wc_encoding;
73    CodeSet codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset;
74    if (!codeset)
75	return False;
76    wc_encoding = codeset->wc_encoding;
77    *wc = ((wchar_t) *ch & state->wc_mask) | wc_encoding;
78    return True;
79}
80
81#ifdef STDCVT
82static
83Bool MBtoWCstd(
84    State   state,
85    const char *ch,
86    wchar_t *wc)
87{
88    return (mbtowc(wc, ch, 1) == 1);
89}
90#endif
91
92static
93Bool WCtoMBdef(
94    State   state,
95    wchar_t wc,
96    char    *ch)
97{
98    wchar_t wc_encoding = wc & state->wc_encode_mask;
99    CodeSet codeset;
100
101    codeset = state->GL_codeset;
102    if (codeset && (wc_encoding == codeset->wc_encoding)) {
103	*ch = wc & state->wc_mask;
104	return True;
105    }
106    codeset = state->GR_codeset;
107    if (codeset && (wc_encoding == codeset->wc_encoding)) {
108	*ch = (wc & state->wc_mask) | GR;
109	return True;
110    }
111    return False;
112}
113
114#ifdef STDCVT
115static
116Bool WCtoMBstd(
117    State   state,
118    wchar_t wc,
119    char    *ch)
120{
121    return (wctomb(ch, wc) == 1);
122}
123#endif
124
125static
126XlcCharSet get_charset(
127    State  state,
128    char   side)
129{
130    CodeSet codeset = side ? state->GR_codeset : state->GL_codeset;
131    if (codeset) {
132	int i;
133	XlcCharSet charset;
134	for (i = 0; i < codeset->num_charsets; i++) {
135	    charset = codeset->charset_list[i];
136	    if (*charset->ct_sequence != '\0')
137		return charset;
138	}
139	return *(codeset->charset_list);
140    }
141    return (XlcCharSet) NULL;
142}
143
144static int
145def_mbstowcs(
146    XlcConv conv,
147    XPointer *from,
148    int *from_left,
149    XPointer *to,
150    int *to_left,
151    XPointer *args,
152    int num_args)
153{
154    const char *src = (const char *) *from;
155    wchar_t *dst = (wchar_t *) * to;
156    State state = (State) conv->state;
157    int unconv = 0;
158
159    if (from == NULL || *from == NULL)
160	return 0;
161
162    while (*from_left && *to_left) {
163	(*from_left)--;
164	if (state->MBtoWC (state, src++, dst)) {
165	    dst++;
166	    (*to_left)--;
167	} else {
168	    unconv++;
169	}
170    }
171    *from = (XPointer) src;
172    *to = (XPointer) dst;
173    return unconv;
174}
175
176static int
177def_wcstombs(
178    XlcConv conv,
179    XPointer *from,
180    int *from_left,
181    XPointer *to,
182    int *to_left,
183    XPointer *args,
184    int num_args)
185{
186    const wchar_t *src = (const wchar_t *) * from;
187    char  *dst = (char *) *to;
188    State state = (State) conv->state;
189    char ch[MB_LEN_MAX];
190    int unconv = 0;
191
192    if (from == NULL || *from == NULL)
193	return 0;
194
195    while (*from_left && *to_left) {
196	(*from_left)--;
197	if (state->WCtoMB (state, *src++, ch)) {
198	    *dst++ = *ch;
199	    (*to_left)--;
200	} else {
201	    unconv++;
202	}
203    }
204    *from = (XPointer) src;
205    *to = (XPointer) dst;
206    return unconv;
207}
208
209static int
210mbstostr(
211    XlcConv conv,
212    XPointer *from,
213    int *from_left,
214    XPointer *to,
215    int *to_left,
216    XPointer *args,
217    int num_args)
218{
219    const char *src = (const char *) *from;
220    char *dst = (char *) *to;
221    CodeSet codeset;
222    State state = (State) conv->state;
223    char ch;
224    int unconv = 0;
225
226    if (from == NULL || *from == NULL)
227	return 0;
228
229    while (*from_left && *to_left) {
230	ch = *src++;
231	(*from_left)--;
232
233	codeset = (ch & GR) ? state->GR_codeset : state->GL_codeset;
234	if (codeset && codeset->string_encoding) {
235	    *dst++ = ch;
236	    (*to_left)--;
237	} else {
238	    unconv++;
239	}
240    }
241    *from = (XPointer) src;
242    *to = (XPointer) dst;
243    return unconv;
244}
245
246static int
247wcstostr(
248    XlcConv conv,
249    XPointer *from,
250    int *from_left,
251    XPointer *to,
252    int *to_left,
253    XPointer *args,
254    int num_args)
255{
256    const wchar_t *src = (const wchar_t *) *from;
257    char *dst = (char *) *to;
258    CodeSet codeset;
259    State state = (State) conv->state;
260    char ch[MB_LEN_MAX];
261    int unconv = 0;
262
263    if (from == NULL || *from == NULL)
264	return 0;
265
266    while (*from_left && *to_left) {
267	(*from_left)--;
268	if (state->WCtoMB (state, *src++, ch)) {
269	    codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset;
270	    if (codeset && codeset->string_encoding) {
271		*dst++ = *ch;
272		(*to_left)--;
273	    } else {
274		unconv++;
275	    }
276	} else {
277	    unconv++;
278	}
279    }
280    *from = (XPointer) src;
281    *to = (XPointer) dst;
282    return unconv;
283}
284
285static int
286mbstocs(
287    XlcConv conv,
288    XPointer *from,
289    int *from_left,
290    XPointer *to,
291    int *to_left,
292    XPointer *args,
293    int num_args)
294{
295    const char *src = (const char *) *from;
296    char *dst = (char *) *to;
297    int length;
298    State state = (State) conv->state;
299    char cur_side;
300    int unconv = 0;
301
302    if (from == NULL || *from == NULL)
303	return 0;
304
305    length = min(*from_left, *to_left);
306
307    cur_side = *src & GR;
308    while (length) {
309	if ((char) (*src & GR) != cur_side)
310	    break;
311	*dst++ = *src++;
312	length--;
313    }
314
315    if (num_args > 0) {
316	XlcCharSet      charset = get_charset(state, cur_side);
317	if (charset) {
318	    *((XlcCharSet *) args[0]) = charset;
319	} else {
320	    dst = *to;
321	    unconv = -1;
322	}
323    }
324    *from_left -= src - (char *) *from;
325    *to_left -= dst - (char *) *to;
326    *from = (XPointer) src;
327    *to = (XPointer) dst;
328    return unconv;
329}
330
331static int
332wcstocs(
333    XlcConv conv,
334    XPointer *from,
335    int *from_left,
336    XPointer *to,
337    int *to_left,
338    XPointer *args,
339    int num_args)
340{
341    const wchar_t *src = (const wchar_t *) * from;
342    char *dst = (char *) *to;
343    State state = (State) conv->state;
344    char cur_side = 0, ch[MB_LEN_MAX];
345    int unconv = 0;
346    Bool found = False;
347
348    if (from == NULL || *from == NULL)
349	return 0;
350
351    while (*from_left) {
352	if ((found = state->WCtoMB (state, *src, ch)))
353	    break;
354	unconv++;
355	src++;
356	(*from_left)--;
357    }
358
359    if (found) {
360	cur_side = *ch & GR;
361	while (*from_left && *to_left) {
362	    (*from_left)--;
363	    if (state->WCtoMB (state, *src++, ch)) {
364		if ((char) (*ch & GR) != cur_side) {
365		    src--;
366		    (*from_left)++;
367		    break;
368		} else {
369		    *dst++ = *ch;
370		    (*to_left)--;
371		}
372	    } else {
373		unconv++;
374	    }
375	}
376    } else {
377	unconv++;
378    }
379
380    if (num_args > 0) {
381	XlcCharSet charset = get_charset(state, cur_side);
382	if (charset) {
383	    *((XlcCharSet *) args[0]) = charset;
384	} else {
385	    unconv = -1;
386	}
387    }
388    *from = (XPointer) src;
389    *to = (XPointer) dst;
390    return unconv;
391}
392
393static int
394cstombs(
395    XlcConv conv,
396    XPointer *from,
397    int *from_left,
398    XPointer *to,
399    int *to_left,
400    XPointer *args,
401    int num_args)
402{
403    const char *src = (const char *) *from;
404    char *dst = (char *) *to;
405    CodeSet codeset;
406    XlcCharSet charset;
407    State state = (State) conv->state;
408    unsigned char cur_side = 0;
409    int i;
410    Bool found = False;
411
412    if (from == NULL || *from == NULL)
413	return 0;
414
415    if (num_args > 0) {
416	charset = (XlcCharSet) args[0];
417	if (charset == NULL)
418	    return -1;
419    } else {
420	return -1;
421    }
422
423    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
424	codeset = state->GL_codeset;
425	if (codeset) {
426	    for (i = 0; i < codeset->num_charsets; i++)
427		if (charset == codeset->charset_list[i]) {
428		    found = True;
429		    cur_side = 0;
430		    break;
431		}
432	}
433    }
434    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
435	codeset = state->GR_codeset;
436	if (codeset) {
437	    for (i = 0; i < codeset->num_charsets; i++)
438		if (charset == codeset->charset_list[i]) {
439		    found = True;
440		    cur_side = GR;
441		    break;
442		}
443	}
444    }
445    if (found) {
446	int length = min(*from_left, *to_left);
447	while (length) {
448	    *dst++ = *src++ | cur_side;
449	    length--;
450	}
451    } else {
452	return -1;
453    }
454
455    *from_left -= src - (char *) *from;
456    *to_left -= dst - (char *) *to;
457    *from = (XPointer) src;
458    *to = (XPointer) dst;
459    return 0;
460}
461
462static int
463cstowcs(
464    XlcConv conv,
465    XPointer *from,
466    int *from_left,
467    XPointer *to,
468    int *to_left,
469    XPointer *args,
470    int num_args)
471{
472    const char *src = (const char *) *from;
473    wchar_t *dst = (wchar_t *) * to;
474    CodeSet codeset;
475    XlcCharSet charset;
476    State state = (State) conv->state;
477    Bool found = False;
478    int i, unconv = 0;
479    unsigned char cur_side = 0;
480
481    if (from == NULL || *from == NULL)
482	return 0;
483
484    if (num_args > 0) {
485	charset = (XlcCharSet) args[0];
486	if (charset == NULL)
487	    return -1;
488    } else {
489	return -1;
490    }
491
492    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
493	codeset = state->GL_codeset;
494	if (codeset) {
495	    for (i = 0; i < codeset->num_charsets; i++)
496		if (charset == codeset->charset_list[i]) {
497		    found = True;
498		    cur_side = 0;
499		    break;
500		}
501	}
502    }
503    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
504	codeset = state->GR_codeset;
505	if (codeset) {
506	    for (i = 0; i < codeset->num_charsets; i++)
507		if (charset == codeset->charset_list[i]) {
508		    found = True;
509		    cur_side = GR;
510		    break;
511		}
512	}
513    }
514    if (found) {
515	char ch;
516	while (*from_left && *to_left) {
517	    ch = *src++ | cur_side;
518	    (*from_left)--;
519	    if (state->MBtoWC (state, &ch, dst)) {
520		dst++;
521		(*to_left)--;
522	    } else {
523		unconv++;
524	    }
525	}
526    } else {
527	return -1;
528    }
529    *from = (XPointer) src;
530    *to = (XPointer) dst;
531    return unconv;
532}
533
534static int
535strtombs(
536    XlcConv conv,
537    XPointer *from,
538    int *from_left,
539    XPointer *to,
540    int *to_left,
541    XPointer *args,
542    int num_args)
543{
544    const char *src = (const char *) *from;
545    char *dst = (char *) *to;
546    int length;
547
548    if (from == NULL || *from == NULL)
549	return 0;
550
551    length = min(*from_left, *to_left);
552    while (length) {
553	*dst++ = *src++;
554	length--;
555    }
556
557    *from_left -= src - (char *) *from;
558    *to_left -= dst - (char *) *to;
559    *from = (XPointer) src;
560    *to = (XPointer) dst;
561    return 0;
562}
563
564static void
565close_converter(
566    XlcConv conv)
567{
568    if (conv->state)
569	Xfree((char *) conv->state);
570
571    Xfree((char *) conv);
572}
573
574static XlcConv
575create_conv(
576    XLCd lcd,
577    XlcConvMethods methods)
578{
579    XlcConv conv;
580    State state;
581
582    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
583    if (conv == NULL)
584	return (XlcConv) NULL;
585
586    state = (State) Xmalloc(sizeof(StateRec));
587    if (state == NULL) {
588	close_converter(conv);
589	return (XlcConv) NULL;
590    }
591    state->GL_codeset = XLC_GENERIC(lcd, initial_state_GL);
592    state->GR_codeset = XLC_GENERIC(lcd, initial_state_GR);
593    state->wc_mask = (1 << XLC_GENERIC(lcd, wc_shift_bits)) - 1;
594    state->wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask);
595
596#ifdef STDCVT
597    if (XLC_GENERIC(lcd, use_stdc_env) == True)
598	state->MBtoWC = &MBtoWCstd;
599    else
600#endif
601	state->MBtoWC = &MBtoWCdef;
602
603#ifdef STDCVT
604    if (XLC_GENERIC(lcd, use_stdc_env) == True)
605	state->WCtoMB = &WCtoMBstd;
606    else
607#endif
608	state->WCtoMB = &WCtoMBdef;
609
610    conv->methods = methods;
611    conv->state = (XPointer) state;
612
613    return conv;
614}
615
616static XlcConvMethodsRec mbstowcs_methods = {
617    close_converter,
618    def_mbstowcs,
619    NULL
620};
621
622static XlcConv
623open_mbstowcs(
624    XLCd from_lcd,
625    const char *from_type,
626    XLCd to_lcd,
627    const char *to_type)
628{
629    return create_conv(from_lcd, &mbstowcs_methods);
630}
631
632static XlcConvMethodsRec mbstostr_methods = {
633    close_converter,
634    mbstostr,
635    NULL
636};
637
638static XlcConv
639open_mbstostr(
640    XLCd from_lcd,
641    const char *from_type,
642    XLCd to_lcd,
643    const char *to_type)
644{
645    return create_conv(from_lcd, &mbstostr_methods);
646}
647
648static XlcConvMethodsRec mbstocs_methods = {
649    close_converter,
650    mbstocs,
651    NULL
652};
653
654static XlcConv
655open_mbstocs(
656    XLCd from_lcd,
657    const char *from_type,
658    XLCd to_lcd,
659    const char *to_type)
660{
661    return create_conv(from_lcd, &mbstocs_methods);
662}
663
664static XlcConvMethodsRec wcstombs_methods = {
665    close_converter,
666    def_wcstombs,
667    NULL
668};
669
670static XlcConv
671open_wcstombs(
672    XLCd from_lcd,
673    const char *from_type,
674    XLCd to_lcd,
675    const char *to_type)
676{
677    return create_conv(from_lcd, &wcstombs_methods);
678}
679
680static XlcConvMethodsRec wcstostr_methods = {
681    close_converter,
682    wcstostr,
683    NULL
684};
685
686static XlcConv
687open_wcstostr(
688    XLCd from_lcd,
689    const char *from_type,
690    XLCd to_lcd,
691    const char *to_type)
692{
693    return create_conv(from_lcd, &wcstostr_methods);
694}
695
696static XlcConvMethodsRec wcstocs_methods = {
697    close_converter,
698    wcstocs,
699    NULL
700};
701
702static XlcConv
703open_wcstocs(
704    XLCd from_lcd,
705    const char *from_type,
706    XLCd to_lcd,
707    const char *to_type)
708{
709    return create_conv(from_lcd, &wcstocs_methods);
710}
711
712static XlcConvMethodsRec strtombs_methods = {
713    close_converter,
714    strtombs,
715    NULL
716};
717
718static XlcConv
719open_strtombs(
720    XLCd from_lcd,
721    const char *from_type,
722    XLCd to_lcd,
723    const char *to_type)
724{
725    return create_conv(from_lcd, &strtombs_methods);
726}
727
728static XlcConvMethodsRec cstombs_methods = {
729    close_converter,
730    cstombs,
731    NULL
732};
733
734static XlcConv
735open_cstombs(
736    XLCd from_lcd,
737    const char *from_type,
738    XLCd to_lcd,
739    const char *to_type)
740{
741    return create_conv(from_lcd, &cstombs_methods);
742}
743
744static XlcConvMethodsRec cstowcs_methods = {
745    close_converter,
746    cstowcs,
747    NULL
748};
749
750static XlcConv
751open_cstowcs(
752    XLCd from_lcd,
753    const char *from_type,
754    XLCd to_lcd,
755    const char *to_type)
756{
757    return create_conv(from_lcd, &cstowcs_methods);
758}
759
760XLCd
761_XlcDefaultLoader(
762    const char *name)
763{
764    XLCd lcd;
765
766    lcd = _XlcCreateLC(name, _XlcGenericMethods);
767    if (lcd == NULL)
768	return lcd;
769
770    if (XLC_PUBLIC(lcd, mb_cur_max) != 1){
771        _XlcDestroyLC(lcd);
772        return (XLCd) NULL;
773    }
774
775    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs);
776    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr);
777    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs);
778    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbstocs);
779
780    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs);
781    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr);
782    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
783
784    _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs);
785    _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_mbstowcs);
786
787    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs);
788    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
789
790    _XlcAddUtf8Converters(lcd);
791
792    return lcd;
793}
794