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