lcGenConv.c revision 61b2299d
1/* $Xorg: lcGenConv.c,v 1.5 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 *  (c) Copyright 1995 FUJITSU LIMITED
28 *  This is source code modified by FUJITSU LIMITED under the Joint
29 *  Development Agreement for the CDE/Motif PST.
30 *
31 *   Modifier: Masayoshi Shimamura      FUJITSU LIMITED
32 *
33 */
34/*
35 *  2000
36 *  Modifier: Ivan Pascal      The XFree86 Project
37 */
38/* $XFree86: xc/lib/X11/lcGenConv.c,v 3.27tsi Exp $ */
39
40/*
41 * A generic locale loader for all kinds of ISO-2022 based codesets.
42 * Supports: all locales.
43 * How: Provides generic converters for ISO-2022 based codesets. Extensible as
44 *      far as ISO-2022 is extensible: codesets can be given by name in the
45 *      stream. Overall distinction between GL (0x00..0x7f) and GR (0x80..0xff).
46 *      In every chunk between escape sequences, the number of bytes per
47 *      character (char_size) is constant.
48 * Platforms: all systems.
49 */
50
51#ifdef HAVE_CONFIG_H
52#include <config.h>
53#endif
54#include "Xlibint.h"
55#include "XlcGeneric.h"
56#include <stdio.h>
57
58#if !defined(macII) && !defined(Lynx_22) && !defined(X_LOCALE)
59#define STDCVT
60#endif
61
62typedef struct _CTDataRec {
63    const char *name;
64    const char *encoding; /* Compound Text encoding */
65} CTDataRec, *CTData;
66
67static CTDataRec directionality_data[] =
68{
69    { "BEGIN_LEFT-TO-RIGHT_TEXT", "\2331]" },
70    { "BEGIN_RIGHT-TO-LEFT_TEXT", "\2332]" },
71    { "END_OF_STRING", "\233]" },
72};
73
74typedef struct _StateRec {
75    XLCd lcd;
76    /* CT state */
77    XlcCharSet charset;		/* charset of current state */
78    XlcCharSet GL_charset;	/* charset of initial state in GL */
79    XlcCharSet GR_charset;	/* charset of initial state in GR */
80    /* MB shift state */
81    CodeSet  GL_codeset;
82    CodeSet  GR_codeset;
83} StateRec, *State;
84
85#define GR      0x80    /* begins right-side (non-ascii) region */
86#define GL      0x7f    /* ends left-side (ascii) region        */
87#define ESC	0x1b
88#define CSI	0x9b
89#define STX	0x02
90
91#define isrightside(c)   ((c) & GR)
92#define isleftside(c)  (!isrightside(c))
93
94/* Forward declarations for local routines. */
95static int mbstocts (XlcConv conv, XPointer *from, int *from_left,
96		     XPointer *to, int *to_left, XPointer *args, int num_args);
97static int ctstombs (XlcConv conv, XPointer *from, int *from_left,
98		     XPointer *to, int *to_left, XPointer *args, int num_args);
99static int cstombs (XlcConv conv, XPointer *from, int *from_left,
100		    XPointer *to, int *to_left, XPointer *args, int num_args);
101
102/* ------------------------------------------------------------------------- */
103/*				Misc                                         */
104/* ------------------------------------------------------------------------- */
105
106static int
107compare(
108    const char *src,
109    const char *encoding,
110    int length)
111{
112    const char *start = src;
113
114    while (length-- > 0) {
115	if (*src++ != *encoding++)
116	    return 0;
117	if (*encoding == '\0')
118	    return src - start;
119    }
120
121    return 0;
122}
123
124static unsigned long
125conv_to_dest(
126    Conversion conv,
127    unsigned long code)
128{
129    int i;
130    int conv_num = conv->conv_num;
131    FontScope convlist = conv->convlist;
132
133    for (i = 0; i < conv_num; i++) {
134  	if (convlist[i].start <= code && code <= convlist[i].end) {
135	    switch (convlist[i].shift_direction) {
136	    case '+':
137	        return(code + convlist[i].shift);
138	    case '-':
139		return(code - convlist[i].shift);
140            default:
141		return(code);
142	    }
143	}
144    }
145
146    return(code);
147}
148
149static unsigned long
150conv_to_source(
151    Conversion conv,
152    unsigned long code)
153{
154    int i;
155    int conv_num;
156    FontScope convlist;
157    unsigned long start_p;
158    unsigned long start_m;
159    unsigned long end_p;
160    unsigned long end_m;
161
162    if (!conv)
163	return(code);
164
165    conv_num = conv->conv_num;
166    convlist = conv->convlist;
167
168    for (i = 0; i < conv_num; i++) {
169        switch (convlist[i].shift_direction) {
170	case '+':
171            start_p = convlist[i].start + convlist[i].shift;
172            end_p = convlist[i].end + convlist[i].shift;
173	    if (start_p <= code && code <= end_p)
174		return(code - convlist[i].shift);
175            break;
176	case '-':
177            start_m = convlist[i].start - convlist[i].shift;
178            end_m = convlist[i].end - convlist[i].shift;
179	    if (start_m <= code && code <= end_m)
180		return(code + convlist[i].shift);
181            break;
182        default:
183	    continue;
184	}
185    }
186
187    return(code);
188}
189
190static unsigned long
191mb_to_gi(
192    unsigned long mb,
193    CodeSet codeset)
194{
195    int i;
196    unsigned long mb_tmp, mask = 0;
197
198    if (codeset->mbconv) {
199	mb_tmp = conv_to_dest(codeset->mbconv, mb);
200	if (mb_tmp != mb)
201	    return(mb_tmp);
202    }
203
204    if (codeset->side == XlcC0 || codeset->side == XlcGL ||
205	codeset->side == XlcC1 || codeset->side == XlcGR) {
206
207        for (i = 0; i < codeset->length; i++)
208	    mask = (mask << 8) | GL;
209	mb = mb & mask;
210    }
211
212    return(mb);
213}
214
215static unsigned long
216gi_to_mb(
217    unsigned long glyph_index,
218    CodeSet codeset)
219{
220    int i;
221    unsigned long mask = 0;
222
223    if (codeset->side == XlcC1 || codeset->side == XlcGR) {
224        for (i = 0; i < codeset->length; i++)
225	    mask = (mask << 8) | GR;
226	glyph_index = glyph_index | mask;
227    }
228
229    if (codeset->mbconv)
230        return( conv_to_source(codeset->mbconv, glyph_index) );
231
232    return(glyph_index);
233}
234
235static Bool
236gi_to_wc(
237    XLCd lcd,
238    unsigned long glyph_index,
239    CodeSet codeset,
240    wchar_t *wc)
241{
242    unsigned char mask = 0;
243    unsigned long wc_encoding = codeset->wc_encoding;
244    int length = codeset->length;
245    unsigned long wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits);
246
247    mask = (1 << wc_shift_bits) - 1 ;
248
249    for (*wc = 0, length--; length >= 0; length--)
250	*wc = (*wc << wc_shift_bits) | ((glyph_index >> (length * 8 )) & mask);
251
252    *wc = *wc | wc_encoding;
253
254    return(True);
255}
256
257static Bool
258wc_to_gi(
259    XLCd lcd,
260    wchar_t wc,
261    unsigned long *glyph_index,
262    CodeSet *codeset)
263{
264    int i;
265    unsigned char mask = 0;
266    unsigned long wc_encoding;
267    unsigned long wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask);
268    unsigned long wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits);
269    int codeset_num = XLC_GENERIC(lcd, codeset_num);
270    CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list);
271
272    wc_encoding = wc & wc_encode_mask;
273    for (*codeset = NULL, i = 0; i < codeset_num; i++) {
274	if (wc_encoding == codeset_list[i]->wc_encoding) {
275	    *codeset = codeset_list[i];
276	    break;
277        }
278    }
279    if (*codeset == NULL)
280	return(False);
281
282    mask = (1 << wc_shift_bits) - 1 ;
283
284    wc = wc & ~wc_encode_mask;
285    for (*glyph_index = 0, i = (*codeset)->length - 1; i >= 0; i--)
286	*glyph_index = (*glyph_index << 8) |
287		      ( ((unsigned long)wc >> (i * wc_shift_bits)) & mask );
288
289    return(True);
290}
291
292static CodeSet
293mb_parse_codeset(
294    State state,
295    int num,
296    const char **inbufptr,
297    int *from_left)
298{
299    int len;
300    int from_len = (*from_left) + 1;
301    const char *src = (*inbufptr) - 1;
302    ParseInfo *mb_parse_list = XLC_GENERIC(state->lcd, mb_parse_list);
303    ParseInfo parse_info;
304    CodeSet codeset;
305
306    for (--num ; (parse_info = mb_parse_list[num]) != NULL; num++) {
307       len = compare(src, parse_info->encoding, from_len);
308       if (len > 0) {
309           codeset = parse_info->codeset;
310           if (parse_info->type == E_LSL)
311               state->GL_codeset = codeset;
312           else if (parse_info->type == E_LSR)
313               state->GR_codeset = codeset;
314           --len;
315           *inbufptr += len;
316           *from_left -= len;
317           return codeset;
318       }
319    }
320    return (CodeSet) NULL;
321}
322
323static CodeSet
324byteM_parse_codeset(
325    XLCd lcd,
326    const char *inbufptr)
327{
328    unsigned char ch;
329    CodeSet codeset;
330    ByteInfoList byteM;
331    ByteInfoListRec byteM_rec;
332    ByteInfo byteinfo;
333    ByteInfoRec byteinfo_rec;
334    Bool hit = False;
335    int i, j, k;
336
337    int codeset_num               = XLC_GENERIC(lcd, codeset_num);
338    CodeSet *codeset_list         = XLC_GENERIC(lcd, codeset_list);
339
340    for (i = 0; i < codeset_num; i++) {
341        codeset = codeset_list[i];
342        byteM = codeset->byteM;
343        if (codeset->side != XlcNONE || byteM == NULL)
344	    continue;
345
346        for (j = 0; j < codeset->length; j++) {
347	    ch = *((unsigned char *)(inbufptr + j));
348	    byteM_rec = byteM[j];
349	    byteinfo = byteM_rec.byteinfo;
350
351	    for (hit = False, k = 0; k < byteM_rec.byteinfo_num; k++) {
352	        byteinfo_rec = byteinfo[k];
353	        if (byteinfo_rec.start <= ch && ch <= byteinfo_rec.end) {
354	            hit = True;
355		    break;
356                }
357            }
358
359            if (!hit)
360		break;
361        }
362
363        if (hit)
364	    return(codeset);
365    }
366
367    return(NULL);
368}
369
370#define GLGR_parse_codeset(ch) \
371     (isrightside(ch) ? (state->GR_codeset) : \
372                        (state->GL_codeset) )
373
374static XlcCharSet
375gi_parse_charset(
376    unsigned long glyph_index,
377    CodeSet codeset)
378{
379    int i;
380    XlcCharSet *charset_list = codeset->charset_list;
381    int num_charsets = codeset->num_charsets;
382    ExtdSegment ctextseg = codeset->ctextseg;
383    XlcCharSet charset = NULL;
384    int area_num;
385    FontScope area;
386
387    /* lockup ct sequence */
388    for (i = 0; i < num_charsets; i++) {
389	charset = charset_list[i];
390        if (*charset->ct_sequence != '\0')
391	    break;
392    }
393    if (i >= num_charsets)
394	return(NULL);
395
396    if (charset->source != CSsrcStd)
397        return (charset);
398
399    if (!ctextseg)
400        return(charset);
401
402    area = ctextseg->area;
403    area_num = ctextseg->area_num;
404
405    for (i = 0; i < area_num; i++) {
406
407        if (area[i].start <= glyph_index && glyph_index <= area[i].end) {
408
409	    charset = ctextseg->charset;
410
411            if (*charset->ct_sequence == '\0')
412                return(NULL);
413
414	    break;
415	}
416    }
417
418    return(charset);
419}
420
421static Bool
422ct_parse_csi(
423    const char *inbufptr,
424    int *ctr_seq_len)
425{
426    int i;
427    int num = sizeof(directionality_data) / sizeof(directionality_data[0]);
428
429    for (i = 0; i < num; i++) {
430	if ( !(*ctr_seq_len = strlen(directionality_data[i].encoding)) )
431	    continue;
432
433	if ( strncmp(inbufptr, directionality_data[i].encoding,
434						*ctr_seq_len) == 0)
435            return(True);
436    }
437
438    return(False);
439}
440
441static int
442cmp_esc_sequence(
443    const char *inbufptr,
444    XlcCharSet charset)
445{
446    int seq_len, name_len, total_len;
447    unsigned char byte_m, byte_l;
448    const char *ct_sequence =  charset->ct_sequence;
449    const char *encoding_name = charset->encoding_name;
450
451    /* check esc sequence */
452    if ( !(seq_len = strlen(ct_sequence) ) )
453	return(0);
454    if ( strncmp(inbufptr, ct_sequence, seq_len) != 0)
455	return(0);
456
457    /* Standard Character Set Encoding ? */
458    if (charset->source == CSsrcStd)
459        return(seq_len);
460
461    /*
462     *   Non-Standard Character Set Encoding
463     *
464     * +--- ---+-----+-----+-----+----   ----+-----+-----+-------   ------+
465     * | ctseq |  M  |  L  |     encoding name     | STX |     contents   |
466     * +--- ---+-----+-----+-----+----   ----+-----+-----+-------   ------+
467     *  4bytes  1byte 1byte     variable length     1byte  variable length
468     * 	                   |                                              |
469     * 	                   +----------------------------------------------+
470     * 	                     rest length  = ((M - 128) * 128) + (L - 128)
471     */
472
473    /* get length of encoding name */
474    inbufptr += seq_len;
475    byte_m = *inbufptr++;
476    byte_l = *inbufptr++;
477    name_len = strlen(encoding_name);
478
479    if (((byte_m - 128) * 128 + (byte_l - 128) - 1) < name_len)
480	return(0);
481
482    if ( _XlcNCompareISOLatin1(inbufptr, encoding_name, name_len) != 0 )
483	return(0);
484
485    /* check STX (Start of Text) */
486    inbufptr = inbufptr + name_len;
487    if ( *inbufptr != STX )
488	return(0);
489
490    total_len = seq_len + name_len + 3;
491    return(total_len);
492}
493
494static Bool
495ct_parse_charset(
496    XLCd lcd,
497    const char *inbufptr,
498    XlcCharSet *charset,
499    int *ctr_seq_len)
500{
501    int i, j;
502    ExtdSegment ctextseg;
503    int num_charsets;
504    XlcCharSet *charset_list;
505    CodeSet codeset;
506    int codeset_num       = XLC_GENERIC(lcd, codeset_num);
507    CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list);
508    int segment_conv_num  = XLC_GENERIC(lcd, segment_conv_num);
509    SegConv segment_conv  = XLC_GENERIC(lcd, segment_conv);
510
511    /* get charset from XLC_XLOCALE by escape sequence */
512
513    for (i = 0; i < codeset_num; i++) {
514	codeset = codeset_list[i];
515
516	num_charsets = codeset->num_charsets;
517	charset_list = codeset->charset_list;
518	ctextseg     = codeset->ctextseg;
519
520	for (j = 0; j < num_charsets; j++) {
521	    *charset = charset_list[j];
522            if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset)))
523		return(True);
524	}
525
526	if (ctextseg) {
527	    *charset = ctextseg->charset;
528            if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset)))
529		return(True);
530	}
531    }
532
533    /* get charset from XLC_SEGMENTCONVERSION by escape sequence */
534
535    if (!segment_conv)
536	return(False);
537
538    for (i = 0; i < segment_conv_num; i++) {
539	*charset = segment_conv[i].source;
540        if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset)))
541	    return(True);
542	*charset = segment_conv[i].dest;
543        if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset)))
544	    return(True);
545    }
546
547    return(False);
548}
549
550static Bool
551segment_conversion(
552    XLCd lcd,
553    XlcCharSet *charset,
554    unsigned long *glyph_index)
555{
556    int i;
557    int segment_conv_num = XLC_GENERIC(lcd, segment_conv_num);
558    SegConv segment_conv = XLC_GENERIC(lcd, segment_conv);
559    FontScopeRec range;
560    ConversionRec conv_rec;
561
562    if (!segment_conv)
563	return(True);
564
565    for (i = 0; i < segment_conv_num; i++) {
566	if (segment_conv[i].source == *charset)
567	    break;
568    }
569
570    if (i >= segment_conv_num)
571	return(True);
572
573    range = segment_conv[i].range;
574    if (*glyph_index < range.start || range.end < *glyph_index)
575	return(True);
576
577    *charset = segment_conv[i].dest;
578    conv_rec.conv_num = segment_conv[i].conv_num;
579    conv_rec.convlist = segment_conv[i].conv;
580    *glyph_index = conv_to_dest(&conv_rec, *glyph_index);
581
582    return(True);
583}
584
585static CodeSet
586_XlcGetCodeSetFromName(
587    XLCd lcd,
588    const char *name)
589{
590    int i, j;
591    XlcCharSet charset;
592    int num_charsets;
593    XlcCharSet *charset_list;
594    CodeSet codeset;
595
596    int codeset_num       = XLC_GENERIC(lcd, codeset_num);
597    CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list);
598
599    for (i = 0; i < codeset_num; i++) {
600        codeset = codeset_list[i];
601
602        num_charsets = codeset->num_charsets;
603        charset_list = codeset->charset_list;
604
605        for (j = 0; j < num_charsets; j++) {
606            charset = charset_list[j];
607
608            if (!strlen(charset->name))
609                continue;
610            if ( strcmp(charset->name, name) == 0)
611                return(codeset);
612        }
613    }
614
615    return(NULL);
616}
617
618static Bool
619_XlcGetCodeSetFromCharSet(
620    XLCd lcd,
621    XlcCharSet charset,
622    CodeSet *codeset,
623    unsigned long *glyph_index)
624{
625    int j, num;
626    CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list);
627    XlcCharSet *charset_list;
628    int codeset_num, num_charsets;
629    Conversion ctconv;
630    unsigned long glyph_index_tmp = 0;
631    ExtdSegment ctextseg;
632
633    codeset_num = XLC_GENERIC(lcd, codeset_num);
634
635    for (num = 0 ; num < codeset_num; num++) {
636        *codeset = codeset_list[num];
637        ctconv = (*codeset)->ctconv;
638	ctextseg = (*codeset)->ctextseg;
639
640        num_charsets = (*codeset)->num_charsets;
641        charset_list = (*codeset)->charset_list;
642
643        glyph_index_tmp = conv_to_source(ctconv, *glyph_index);
644
645        if (charset->source == CSsrcStd) {
646
647            /* Standard Character Set Encoding */
648	    if (glyph_index_tmp == *glyph_index) {
649                for (j = 0; j < num_charsets; j++) {
650                    if (charset_list[j] == charset) {
651                        goto end_loop;
652                    }
653                }
654            }
655
656	} else {
657
658            /* Non-Standard Character Set Encoding */
659            for (j = 0; j < num_charsets; j++) {
660                if (charset_list[j] == charset) {
661                    goto end_loop;
662                }
663            }
664
665            if (glyph_index_tmp != *glyph_index) {
666		if (ctextseg && ctextseg->charset == charset) {
667		    goto end_loop;
668                }
669            }
670
671	}
672
673    }
674
675end_loop:
676    if (num < codeset_num) {
677	*glyph_index = glyph_index_tmp;
678	return(True);
679    }
680
681    return(False);
682}
683
684#define check_string_encoding(codeset)	(codeset->string_encoding)
685
686static void
687output_ulong_value(
688    char *outbufptr,
689    unsigned long code,
690    int length,
691    XlcSide side)
692{
693    int i;
694
695    for (i = (length - 1) * 8; i >= 0; i -= 8) {
696	*outbufptr = ( code >> i) & 0xff;
697
698	if (side == XlcC0 || side == XlcGL) {
699	    *outbufptr = *outbufptr & GL;
700	} else if (side == XlcC1 || side == XlcGR) {
701	    *outbufptr = *outbufptr | GR;
702	}
703
704	outbufptr++;
705    }
706}
707
708/* -------------------------------------------------------------------------- */
709/*				Init                                          */
710/* -------------------------------------------------------------------------- */
711
712static XlcCharSet default_GL_charset = 0;
713static XlcCharSet default_GR_charset = 0;
714
715static void
716init_state(
717    XlcConv conv)
718{
719    State state = (State) conv->state;
720
721    /* for CT */
722    state->charset = NULL;
723    state->GL_charset = default_GL_charset;
724    state->GR_charset = default_GR_charset;
725
726    /* for MB shift state */
727    state->GL_codeset = XLC_GENERIC(state->lcd, initial_state_GL);
728    state->GR_codeset = XLC_GENERIC(state->lcd, initial_state_GR);
729}
730
731/* -------------------------------------------------------------------------- */
732/*				Convert                                       */
733/* -------------------------------------------------------------------------- */
734
735static int
736mbstowcs_org(
737    XlcConv conv,
738    XPointer *from,
739    int *from_left,
740    XPointer *to,
741    int *to_left,
742    XPointer *args,
743    int num_args)
744{
745    State state = (State) conv->state;
746    XLCd lcd = state->lcd;
747
748    unsigned char ch;
749    unsigned long mb = 0;
750    wchar_t wc;
751
752    int length = 0, len_left = 0;
753    int unconv_num = 0;
754    int num;
755
756    CodeSet codeset = NULL;
757
758    const char *inbufptr = *from;
759    wchar_t *outbufptr = (wchar_t *) *to;
760    int from_size = *from_left;
761
762    unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table);
763
764    if (from == NULL || *from == NULL) {
765	_XlcResetConverter(conv);
766        return( 0 );
767    }
768
769    if (*from_left > *to_left)
770        *from_left = *to_left;
771
772    while (*from_left && *to_left) {
773
774	ch = *inbufptr++;
775	(*from_left)--;
776
777	/* null ? */
778	if (!ch) {
779            if (outbufptr) {*outbufptr++ = L'\0';}
780	    (*to_left)--;
781
782	    /* error check */
783            if (len_left) {
784	        unconv_num += (length - len_left);
785		len_left = 0;
786            }
787
788	    continue;
789	}
790
791	/* same mb char data */
792        if (len_left)
793	    goto output_one_wc;
794
795        /* next mb char data for single shift ? */
796	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
797	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
798            if (codeset != NULL) {
799		length = len_left = codeset->length;
800		mb = 0;
801		continue;
802	    }
803        }
804
805	/* next mb char data for byteM ? */
806	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
807	    goto next_mb_char;
808
809	/* next mb char data for GL or GR side ? */
810	if ((codeset = GLGR_parse_codeset(ch)))
811	    goto next_mb_char;
812
813        /* can't find codeset for the ch */
814        unconv_num++;
815        continue;
816
817next_mb_char:
818        length = len_left = codeset->length;
819	mb = 0;
820
821output_one_wc:
822	mb = (mb << 8) | ch;  /* 1 byte left shift */
823	len_left--;
824
825        /* last of one mb char data */
826        if (!len_left) {
827            gi_to_wc(lcd, mb_to_gi(mb, codeset), codeset, &wc);
828            if (outbufptr) {*outbufptr++ = wc;}
829	    (*to_left)--;
830        }
831
832    } /* end of while */
833
834    /* error check on last char */
835    if (len_left) {
836	inbufptr -= (length - len_left);
837	(*from_left) += (length - len_left);
838	unconv_num += (length - len_left);
839    }
840
841    *from = (XPointer) ((const char *) *from + from_size);
842    *from_left = 0;
843    *to = (XPointer) outbufptr;
844
845    return unconv_num;
846}
847
848static int
849stdc_mbstowcs(
850    XlcConv conv,
851    XPointer *from,
852    int *from_left,
853    XPointer *to,
854    int *to_left,
855    XPointer *args,
856    int num_args)
857{
858    const char *src = *((const char **) from);
859    wchar_t *dst = *((wchar_t **) to);
860    int src_left = *from_left;
861    int dst_left = *to_left;
862    int length, unconv_num = 0;
863
864    while (src_left > 0 && dst_left > 0) {
865	length = mbtowc(dst, src, src_left);
866
867	if (length > 0) {
868	    src += length;
869	    src_left -= length;
870	    if (dst)
871	        dst++;
872	    dst_left--;
873	} else if (length < 0) {
874	    src++;
875	    src_left--;
876	    unconv_num++;
877        } else {
878            /* null ? */
879            src++;
880            src_left--;
881            if (dst)
882                *dst++ = L'\0';
883            dst_left--;
884        }
885    }
886
887    *from = (XPointer) src;
888    if (dst)
889	*to = (XPointer) dst;
890    *from_left = src_left;
891    *to_left = dst_left;
892
893    return unconv_num;
894}
895
896static int
897wcstombs_org(
898    XlcConv conv,
899    XPointer *from,
900    int *from_left,
901    XPointer *to,
902    int *to_left,
903    XPointer *args,
904    int num_args)
905{
906    State state = (State) conv->state;
907    XLCd lcd = state->lcd;
908
909    char *encoding;
910    unsigned long mb, glyph_index;
911    wchar_t wc;
912
913    int length;
914    int unconv_num = 0;
915
916    CodeSet codeset;
917
918    const wchar_t *inbufptr = (const wchar_t *) *from;
919    char *outbufptr = *to;
920    int from_size = *from_left;
921
922    const char *default_string = XLC_PUBLIC(lcd, default_string);
923    int defstr_len = strlen(default_string);
924
925
926    if (*from_left > *to_left)
927        *from_left = *to_left;
928
929    while (*from_left && *to_left) {
930
931        wc = *inbufptr++;
932        (*from_left)--;
933
934        /* null ? */
935        if (!wc) {
936            if (outbufptr) {*outbufptr++ = '\0';}
937            (*to_left)--;
938
939            continue;
940        }
941
942        /* convert */
943	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
944
945	    /* output default_string of XDefaultString() */
946            if (*to_left < defstr_len)
947		break;
948	    if (outbufptr) {
949                strncpy((char *)outbufptr, default_string, defstr_len);
950                outbufptr += defstr_len;
951            }
952	    (*to_left) -= defstr_len;
953
954            unconv_num++;
955
956        } else {
957            mb = gi_to_mb(glyph_index, codeset);
958	    if (codeset->parse_info) {
959                Bool need_shift = False;
960                switch (codeset->parse_info->type) {
961                    case E_LSL :
962                        if (codeset != state->GL_codeset) {
963                            need_shift = True;
964                            state->GL_codeset = codeset;
965                        }
966                        break;
967                    case E_LSR :
968                        if (codeset != state->GR_codeset) {
969                            need_shift = True;
970                            state->GR_codeset = codeset;
971                        }
972                        break;
973                    /* case E_SS */
974                    default:
975                        need_shift = True;
976                }
977
978		/* output shift sequence */
979                if (need_shift) {
980		    encoding = codeset->parse_info->encoding;
981                    length = strlen(encoding);
982                    if (*to_left < length)
983		        break;
984	            if (outbufptr) {
985                        strncpy((char *)outbufptr, encoding, length);
986	                outbufptr += length;
987                    }
988	            (*to_left) -= length;
989                }
990            }
991
992            /* output characters */
993	    length = codeset->length;
994            if (*to_left < length)
995		break;
996
997	    if (outbufptr) {
998		output_ulong_value(outbufptr, mb, length, XlcNONE);
999	        outbufptr += length;
1000	    }
1001
1002	    (*to_left) -= length;
1003        }
1004
1005    } /* end of while */
1006
1007    *from = (XPointer) ((const wchar_t *) *from + from_size);
1008    *from_left = 0;
1009    *to = (XPointer) outbufptr;
1010
1011    return unconv_num;
1012}
1013
1014static int
1015stdc_wcstombs(
1016    XlcConv conv,
1017    XPointer *from,
1018    int *from_left,
1019    XPointer *to,
1020    int *to_left,
1021    XPointer *args,
1022    int num_args)
1023{
1024    const wchar_t *src = *((const wchar_t **) from);
1025    char *dst = *((char **) to);
1026    int src_left = *from_left;
1027    int dst_left = *to_left;
1028    int length, unconv_num = 0;
1029
1030    while (src_left > 0 && dst_left >= MB_CUR_MAX) {
1031	length = wctomb(dst, *src);		/* XXX */
1032
1033        if (length > 0) {
1034	    src++;
1035	    src_left--;
1036	    if (dst)
1037		dst += length;
1038	    dst_left -= length;
1039	} else if (length < 0) {
1040	    src++;
1041	    src_left--;
1042	    unconv_num++;
1043	}
1044    }
1045
1046    *from = (XPointer) src;
1047    if (dst)
1048      *to = (XPointer) dst;
1049    *from_left = src_left;
1050    *to_left = dst_left;
1051
1052    return unconv_num;
1053}
1054
1055static int
1056wcstocts(
1057    XlcConv conv,
1058    XPointer *from,
1059    int *from_left,
1060    XPointer *to,
1061    int *to_left,
1062    XPointer *args,
1063    int num_args)
1064{
1065    State state = (State) conv->state;
1066    XLCd lcd = state->lcd;
1067
1068    unsigned long glyph_index;
1069    wchar_t wc;
1070
1071    int total_len, seq_len, name_len;
1072    int unconv_num = 0;
1073    Bool first_flag = True, standard_flag;
1074    XlcSide side;
1075
1076    CodeSet codeset;
1077    XlcCharSet charset, old_charset = NULL;
1078    const char *ct_sequence;
1079
1080    const wchar_t *inbufptr = (const wchar_t *) *from;
1081    char *outbufptr = *to;
1082    int from_size = *from_left;
1083    char *ext_seg_len = NULL;
1084
1085    if (*from_left > *to_left)
1086        *from_left = *to_left;
1087
1088    while (*from_left && *to_left) {
1089
1090        wc = *inbufptr++;
1091        (*from_left)--;
1092
1093        /* null ? */
1094        if (!wc) {
1095            if (outbufptr) {*outbufptr++ = '\0';}
1096            (*to_left)--;
1097
1098            continue;
1099        }
1100
1101        /* convert */
1102	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
1103            unconv_num++;
1104	    continue;
1105        }
1106
1107        /* parse charset */
1108        if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) {
1109            unconv_num++;
1110	    continue;
1111        }
1112
1113        /* Standard Character Set Encoding ? */
1114	standard_flag = charset->source == CSsrcStd ? True : False;
1115
1116        /*
1117         *   Non-Standard Character Set Encoding
1118         *
1119         * +-----+-----+-----+-----+-----+-----+-----+----   ----+-----+-----+
1120         * |     esc sequence      |  M  |  L  |     encoding name     | STX |
1121         * +-----+-----+-----+-----+-----+-----+-----+----   ----+-----+-----+
1122         *           4bytes         1byte 1byte     variable length     1byte
1123         * 	                   |                                         |
1124         * 	                   +-----------------------------------------+
1125         * 	                     name length  = ((M - 128) * 128) + (L - 128)
1126         */
1127
1128        /* make encoding data */
1129	ct_sequence = charset->ct_sequence;
1130	side = charset->side;
1131        seq_len = strlen(ct_sequence);
1132	if (standard_flag) {
1133            name_len = 0;
1134	    total_len = seq_len;
1135	} else {
1136            name_len = strlen(charset->encoding_name) + 1;
1137	    total_len = seq_len + name_len + 2;
1138	}
1139
1140        /* output escape sequence of CT */
1141	if ( (charset != old_charset) &&
1142	    !(first_flag && charset->string_encoding) ){
1143
1144            if ( (ext_seg_len != NULL) && outbufptr) {
1145                int i = (outbufptr - ext_seg_len) - 2;
1146                *ext_seg_len++ = i / 128 + 128;
1147                *ext_seg_len   = i % 128 + 128;
1148                ext_seg_len = NULL;
1149            }
1150
1151	    if (*to_left < total_len + 1) {
1152                unconv_num++;
1153	        break;
1154	    }
1155
1156	    if (outbufptr) {
1157	        strcpy((char *)outbufptr, ct_sequence);
1158		outbufptr += seq_len;
1159
1160                if (!standard_flag) {
1161                    const char *i = charset->encoding_name;
1162                    ext_seg_len = outbufptr;
1163                    outbufptr += 2;
1164	            for (; *i ; i++)
1165                        *outbufptr++ = ((*i >= 'A') && (*i <= 'Z')) ?
1166                                       *i - 'A' + 'a' : *i;
1167		    *outbufptr++ = STX;
1168                }
1169	    }
1170
1171	    (*to_left) -= total_len;
1172
1173	    first_flag = False;
1174	    old_charset = charset;
1175	}
1176
1177        /* output glyph index */
1178	if (codeset->ctconv)
1179            glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
1180        if (*to_left < charset->char_size) {
1181            unconv_num++;
1182	    break;
1183        }
1184
1185	if (outbufptr) {
1186	   output_ulong_value(outbufptr, glyph_index, charset->char_size, side);
1187	   outbufptr += charset->char_size;
1188	}
1189
1190	(*to_left) -= charset->char_size;
1191
1192    } /* end of while */
1193
1194    if ( (ext_seg_len != NULL) && outbufptr) {
1195        int i = (outbufptr - ext_seg_len) - 2;
1196        *ext_seg_len++ = i / 128 + 128;
1197        *ext_seg_len   = i % 128 + 128;
1198    }
1199
1200    *from = (XPointer) ((const wchar_t *) *from + from_size);
1201    *from_left = 0;
1202    *to = (XPointer) outbufptr;
1203
1204    return unconv_num;
1205}
1206
1207static int
1208stdc_wcstocts(
1209    XlcConv conv,
1210    XPointer *from,
1211    int *from_left,
1212    XPointer *to,
1213    int *to_left,
1214    XPointer *args,
1215    int num_args)
1216{
1217    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1218    char *buf_ptr1 = buf;
1219    int buf_left1 = (*from_left) * MB_CUR_MAX;
1220    char *buf_ptr2 = buf_ptr1;
1221    int buf_left2;
1222    int unconv_num1 = 0, unconv_num2 = 0;
1223
1224    unconv_num1 = stdc_wcstombs(conv,
1225		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1226    if (unconv_num1 < 0)
1227        goto ret;
1228
1229    buf_left2 = buf_ptr1 - buf_ptr2;
1230
1231    unconv_num2 = mbstocts(conv,
1232		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1233    if (unconv_num2 < 0)
1234        goto ret;
1235
1236ret:
1237    if (buf)
1238	Xfree((char *)buf);
1239
1240    return (unconv_num1 + unconv_num2);
1241}
1242
1243static int
1244ctstowcs(
1245    XlcConv conv,
1246    XPointer *from,
1247    int *from_left,
1248    XPointer *to,
1249    int *to_left,
1250    XPointer *args,
1251    int num_args)
1252{
1253    State state = (State) conv->state;
1254    XLCd lcd = state->lcd;
1255
1256    unsigned char ch;
1257    unsigned long glyph_index = 0;
1258    wchar_t wc;
1259
1260    int ctr_seq_len = 0, gi_len_left = 0, gi_len = 0;
1261    int unconv_num = 0;
1262
1263    CodeSet codeset = NULL;
1264    XlcCharSet charset_tmp;
1265
1266    const char *inbufptr = *from;
1267    wchar_t *outbufptr = (wchar_t *) *to;
1268    int from_size = *from_left;
1269
1270    _XlcResetConverter(conv); /* ??? */
1271
1272    if (from == NULL || *from == NULL) {
1273	_XlcResetConverter(conv);
1274        return( 0 );
1275    }
1276
1277    if (*from_left > *to_left)
1278        *from_left = *to_left;
1279
1280    while (*from_left && *to_left) {
1281
1282	ch = *inbufptr++;
1283	(*from_left)--;
1284
1285	/* null ? */
1286	if (!ch) {
1287            if (outbufptr) {*outbufptr++ = L'\0';}
1288	    (*to_left)--;
1289
1290	    /* error check */
1291            if (gi_len_left) {
1292	        unconv_num += (gi_len - gi_len_left);
1293		gi_len_left = 0;
1294            }
1295
1296	    continue;
1297	}
1298
1299	/* same glyph_index data */
1300        if (gi_len_left)
1301	    goto output_one_wc;
1302
1303        /* control sequence ? */
1304        if (ch == CSI) {
1305            if ( !ct_parse_csi(inbufptr - 1, &ctr_seq_len) )
1306	        goto skip_the_seg;
1307
1308	    if (*from_left + 1 < ctr_seq_len) {
1309		inbufptr--;
1310		(*from_left)++;
1311		unconv_num += *from_left;
1312		break;
1313	    }
1314
1315            /* skip the control sequence */
1316	    inbufptr += (ctr_seq_len - 1);
1317	    *from_left -= (ctr_seq_len - 1);
1318
1319            continue;
1320	}
1321
1322        /* escape sequence ? */
1323        if (ch == ESC) {
1324	    if ( !ct_parse_charset(lcd,
1325			inbufptr - 1, &state->charset, &ctr_seq_len) )
1326		goto skip_the_seg;
1327
1328	    if (state->charset->side == XlcC0 ||
1329		state->charset->side == XlcGL)
1330	      {
1331		state->GL_charset = state->charset;
1332	      }
1333	    else if (state->charset->side == XlcC1 ||
1334		     state->charset->side == XlcGR)
1335	      {
1336		state->GR_charset = state->charset;
1337	      }
1338	    else if (state->charset->side == XlcGLGR)
1339	      {
1340		state->GL_charset = state->charset;
1341		state->GR_charset = state->charset;
1342	      }
1343
1344	    if (*from_left + 1 < ctr_seq_len) {
1345		inbufptr--;
1346		(*from_left)++;
1347		unconv_num += *from_left;
1348		break;
1349	    }
1350
1351            /* skip the escape sequence */
1352	    inbufptr += (ctr_seq_len - 1);
1353	    *from_left -= (ctr_seq_len - 1);
1354
1355            continue;
1356        }
1357
1358 	/* check current state */
1359	if (isleftside(ch))
1360	  state->charset = state->GL_charset;
1361	else
1362	  state->charset = state->GR_charset;
1363
1364	gi_len = gi_len_left = state->charset->char_size;
1365	glyph_index = 0;
1366
1367output_one_wc:
1368        if (state->charset->side == XlcC1 || state->charset->side == XlcGR)
1369            glyph_index = (glyph_index << 8) | (ch & GL);
1370        else
1371            glyph_index = (glyph_index << 8) | ch;
1372
1373	gi_len_left--;
1374
1375        /* last of one glyph_index data */
1376        if (!gi_len_left) {
1377
1378	    /* segment conversion */
1379	    charset_tmp = state->charset;
1380	    segment_conversion(lcd, &charset_tmp, &glyph_index);
1381
1382            /* get codeset */
1383            if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp,
1384						&codeset, &glyph_index) ) {
1385		unconv_num += gi_len;
1386		continue;
1387            }
1388
1389            /* convert glyph index to wicd char */
1390            gi_to_wc(lcd, glyph_index, codeset, &wc);
1391            if (outbufptr) {*outbufptr++ = wc;}
1392	    (*to_left)--;
1393        }
1394
1395        continue;
1396
1397skip_the_seg:
1398	/* skip until next escape or control sequence */
1399        while ( *from_left ) {
1400	    ch = *inbufptr++;
1401	    (*from_left)--;
1402	    unconv_num++;
1403
1404            if (ch == ESC || ch == CSI) {
1405		inbufptr--;
1406		(*from_left)++;
1407		unconv_num--;
1408		break;
1409	    }
1410        }
1411
1412        if ( !(*from_left) )
1413	    break;
1414
1415    } /* end of while */
1416
1417    /* error check on last char */
1418    if (gi_len_left) {
1419	inbufptr -= (gi_len - gi_len_left);
1420	(*from_left) += (gi_len - gi_len_left);
1421	unconv_num += (gi_len - gi_len_left);
1422    }
1423
1424    *from = (XPointer) ((const char *) *from + from_size);
1425    *from_left = 0;
1426    *to = (XPointer) outbufptr;
1427
1428    return unconv_num;
1429}
1430
1431static int
1432cstowcs(
1433    XlcConv conv,
1434    XPointer *from,
1435    int *from_left,
1436    XPointer *to,
1437    int *to_left,
1438    XPointer *args,
1439    int num_args)
1440{
1441    State state = (State) conv->state;
1442    XLCd lcd = state->lcd;
1443
1444    unsigned char ch;
1445    unsigned long glyph_index = 0;
1446    wchar_t wc;
1447    int gi_len_left = 0, gi_len = 0;
1448
1449    int unconv_num = 0;
1450
1451    CodeSet codeset = NULL;
1452    XlcCharSet charset, charset_tmp;
1453
1454    const char *inbufptr = *from;
1455    wchar_t *outbufptr = (wchar_t *) *to;
1456    int from_size = *from_left;
1457
1458    if (from == NULL || *from == NULL) {
1459        return( 0 );
1460    }
1461
1462    charset = (XlcCharSet) args[0];
1463
1464    while (*from_left && *to_left) {
1465
1466        if (!gi_len_left) {
1467            gi_len_left = gi_len = charset->char_size;
1468            glyph_index = 0;
1469        }
1470
1471	ch = *inbufptr++;
1472	(*from_left)--;
1473
1474	/* null ? */
1475	if (!ch) {
1476            if (outbufptr) {*outbufptr++ = L'\0';}
1477	    (*to_left)--;
1478
1479	    /* error check */
1480            if (gi_len_left) {
1481	        unconv_num += (gi_len - gi_len_left);
1482		gi_len_left = 0;
1483            }
1484	    continue;
1485	}
1486
1487        if (charset->side == XlcC1 || charset->side == XlcGR)
1488            glyph_index = (glyph_index << 8) | (ch & GL);
1489        else
1490            glyph_index = (glyph_index << 8) | ch;
1491
1492	gi_len_left--;
1493
1494        /* last of one glyph_index data */
1495        if (!gi_len_left) {
1496
1497	    /* segment conversion */
1498	    charset_tmp = charset;
1499	    segment_conversion(lcd, &charset_tmp, &glyph_index);
1500
1501            /* get codeset */
1502            if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp,
1503						&codeset, &glyph_index) ) {
1504		unconv_num += gi_len;
1505		continue;
1506            }
1507
1508            /* convert glyph index to wicd char */
1509            gi_to_wc(lcd, glyph_index, codeset, &wc);
1510            if (outbufptr) {*outbufptr++ = wc;}
1511	    (*to_left)--;
1512        }
1513
1514    } /* end of while */
1515
1516    /* error check on last char */
1517    if (gi_len_left) {
1518	inbufptr -= (gi_len - gi_len_left);
1519	(*from_left) += (gi_len - gi_len_left);
1520	unconv_num += (gi_len - gi_len_left);
1521    }
1522
1523    *from = (XPointer) ((const char *) *from + from_size);
1524    *from_left = 0;
1525    *to = (XPointer) outbufptr;
1526
1527    return unconv_num;
1528}
1529
1530static int
1531stdc_ctstowcs(
1532    XlcConv conv,
1533    XPointer *from,
1534    int *from_left,
1535    XPointer *to,
1536    int *to_left,
1537    XPointer *args,
1538    int num_args)
1539{
1540    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1541    char *buf_ptr1 = buf;
1542    int buf_left1 = (*from_left) * MB_CUR_MAX;
1543    char *buf_ptr2 = buf_ptr1;
1544    int buf_left2;
1545    int unconv_num1 = 0, unconv_num2 = 0;
1546
1547    unconv_num1 = ctstombs(conv,
1548		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1549    if (unconv_num1 < 0)
1550        goto ret;
1551
1552    buf_left2 = buf_ptr1 - buf_ptr2;
1553
1554    unconv_num2 = stdc_mbstowcs(conv,
1555		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1556    if (unconv_num2 < 0)
1557        goto ret;
1558
1559ret:
1560    if (buf)
1561	Xfree((char *)buf);
1562
1563    return (unconv_num1 + unconv_num2);
1564}
1565
1566static int
1567stdc_cstowcs(
1568    XlcConv conv,
1569    XPointer *from,
1570    int *from_left,
1571    XPointer *to,
1572    int *to_left,
1573    XPointer *args,
1574    int num_args)
1575{
1576    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1577    char *buf_ptr1 = buf;
1578    int buf_left1 = (*from_left) * MB_CUR_MAX;
1579    char *buf_ptr2 = buf_ptr1;
1580    int buf_left2;
1581    int unconv_num1 = 0, unconv_num2 = 0;
1582
1583    unconv_num1 = cstombs(conv,
1584		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1585    if (unconv_num1 < 0)
1586        goto ret;
1587
1588    buf_left2 = buf_ptr1 - buf_ptr2;
1589
1590    unconv_num2 = stdc_mbstowcs(conv,
1591		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1592    if (unconv_num2 < 0)
1593        goto ret;
1594
1595ret:
1596    if (buf)
1597	Xfree((char *)buf);
1598
1599    return (unconv_num1 + unconv_num2);
1600}
1601
1602static int
1603mbstocts(
1604    XlcConv conv,
1605    XPointer *from,
1606    int *from_left,
1607    XPointer *to,
1608    int *to_left,
1609    XPointer *args,
1610    int num_args)
1611{
1612    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
1613    char *buf_ptr1 = buf;
1614    int buf_left1 = (*from_left);
1615    char *buf_ptr2 = buf_ptr1;
1616    int buf_left2;
1617    int unconv_num1 = 0, unconv_num2 = 0;
1618
1619    unconv_num1 = mbstowcs_org(conv,
1620		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1621    if (unconv_num1 < 0)
1622        goto ret;
1623
1624    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
1625
1626    unconv_num2 += wcstocts(conv,
1627		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1628    if (unconv_num2 < 0)
1629        goto ret;
1630
1631ret:
1632    if (buf)
1633	Xfree((char *)buf);
1634
1635    return (unconv_num1 + unconv_num2);
1636}
1637
1638static int
1639mbstostr(
1640    XlcConv conv,
1641    XPointer *from,
1642    int *from_left,
1643    XPointer *to,
1644    int *to_left,
1645    XPointer *args,
1646    int num_args)
1647{
1648    State state = (State) conv->state;
1649    XLCd lcd = state->lcd;
1650
1651    unsigned char ch;
1652    unsigned long mb = 0;
1653
1654    int length = 0, len_left = 0;
1655    int unconv_num = 0;
1656    int num;
1657
1658    CodeSet codeset = NULL;
1659
1660    const char *inbufptr = *from;
1661    char *outbufptr = *to;
1662    int from_size = *from_left;
1663
1664    unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table);
1665
1666    if (from == NULL || *from == NULL) {
1667	_XlcResetConverter(conv);
1668        return( 0 );
1669    }
1670
1671    if (*from_left > *to_left)
1672        *from_left = *to_left;
1673
1674    while (*from_left && *to_left) {
1675
1676	ch = *inbufptr++;
1677	(*from_left)--;
1678
1679	/* null ? */
1680	if (!ch) {
1681            if (outbufptr) {*outbufptr++ = '\0';}
1682	    (*to_left)--;
1683
1684            /* error check */
1685            if (len_left) {
1686                unconv_num += (length - len_left);
1687                len_left = 0;
1688            }
1689
1690	    continue;
1691	}
1692
1693        /* same mb char data */
1694        if (len_left)
1695            goto output_one_mb;
1696
1697        /* next mb char data for single shift ? */
1698	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
1699	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
1700            if (codeset != NULL) {
1701		length = len_left = codeset->length;
1702		mb = 0;
1703		continue;
1704	    }
1705        }
1706
1707	/* next char data : byteM ? */
1708	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
1709	    goto next_mb_char;
1710
1711	/* next char data : GL or GR side ? */
1712	if ((codeset = GLGR_parse_codeset(ch)))
1713	    goto next_mb_char;
1714
1715        /* can't find codeset for the ch */
1716        unconv_num++;
1717        continue;
1718
1719next_mb_char:
1720        length = len_left = codeset->length;
1721        mb = 0;
1722
1723output_one_mb:
1724        mb = (mb << 8) | ch;  /* 1 byte left shift */
1725        len_left--;
1726
1727        /* last of one mb char data */
1728        if (!len_left) {
1729            if (check_string_encoding(codeset)) {
1730                if (outbufptr) {*outbufptr++ = mb & 0xff;}
1731		(*to_left)--;
1732            } else {
1733	        unconv_num++;
1734            }
1735        }
1736
1737    } /* end of while */
1738
1739    /* error check on last char */
1740    if (len_left) {
1741        inbufptr -= (length - len_left);
1742        (*from_left) += (length - len_left);
1743        unconv_num += (length - len_left);
1744    }
1745
1746    *from = (XPointer) ((const char *) *from + from_size);
1747    *from_left = 0;
1748    *to = (XPointer) outbufptr;
1749
1750    return unconv_num;
1751}
1752
1753static int
1754mbtocs(
1755    XlcConv conv,
1756    XPointer *from,
1757    int *from_left,
1758    XPointer *to,
1759    int *to_left,
1760    XPointer *args,
1761    int num_args)
1762{
1763    State state = (State) conv->state;
1764    XLCd lcd = state->lcd;
1765
1766    unsigned char ch;
1767    unsigned long mb = 0;
1768    unsigned long glyph_index;
1769
1770    int length = 0, len_left = 0, char_len;
1771    int unconv_num = 0;
1772    int num;
1773    XlcSide side;
1774
1775    CodeSet codeset = NULL;
1776    XlcCharSet charset = NULL;
1777
1778    const char *inbufptr = *from;
1779    char *outbufptr = *to;
1780    int from_size = *from_left;
1781
1782    unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table);
1783
1784    if (from == NULL || *from == NULL) {
1785	_XlcResetConverter(conv);
1786        return( 0 );
1787    }
1788
1789    if (*from_left > *to_left)
1790        *from_left = *to_left;
1791
1792    while (*from_left && *to_left) {
1793
1794	ch = *inbufptr++;
1795	(*from_left)--;
1796
1797	/* null ? */
1798	if (!ch) {
1799            unconv_num = 1;
1800            if (len_left)
1801	        unconv_num += (length - len_left);
1802	    break;
1803	}
1804
1805	/* same mb char data */
1806        if (len_left)
1807	    goto output;
1808
1809        /* next mb char data for single shift ? */
1810	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
1811	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
1812            if (codeset != NULL) {
1813		length = len_left = codeset->length;
1814		mb = 0;
1815		continue;
1816	    }
1817        }
1818
1819	/* next mb char data for byteM ? */
1820	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
1821	    goto next_mb_char;
1822
1823	/* next mb char data for GL or GR side ? */
1824	if ((codeset = GLGR_parse_codeset(ch)))
1825	    goto next_mb_char;
1826
1827        /* can't find codeset for the ch */
1828        unconv_num = 1;
1829        break;
1830
1831next_mb_char:
1832        length = len_left = codeset->length;
1833	mb = 0;
1834
1835output:
1836	mb = (mb << 8) | ch;  /* 1 byte left shift */
1837	len_left--;
1838
1839        /* last of one mb char data */
1840        if (!len_left) {
1841            glyph_index = mb_to_gi(mb, codeset);
1842            if (!(charset = gi_parse_charset(glyph_index, codeset))) {
1843                unconv_num = length;
1844                break;
1845            }
1846            char_len = charset->char_size;
1847	    side = charset->side;
1848
1849            /* output glyph index */
1850            if (codeset->ctconv)
1851                glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
1852            if (*to_left < char_len) {
1853                unconv_num = length;
1854                break;
1855            }
1856
1857	    if (outbufptr) {
1858	        output_ulong_value(outbufptr, glyph_index, char_len, side);
1859	        outbufptr += char_len;
1860	    }
1861
1862            (*to_left) -= char_len;
1863
1864            break;
1865        }
1866
1867    } /* end of while */
1868
1869    /* error end */
1870    if (unconv_num) {
1871        *from = (XPointer) ((const char *) *from + from_size);
1872        *from_left = 0;
1873        *to = (XPointer) outbufptr;
1874	return -1;
1875    }
1876
1877    /* nomal end */
1878    *from = (XPointer) inbufptr;
1879    *to = (XPointer) outbufptr;
1880
1881    if (num_args > 0)
1882        *((XlcCharSet *) args[0]) = charset;
1883
1884    return 0;
1885}
1886
1887static int
1888mbstocs(
1889    XlcConv conv,
1890    XPointer *from,
1891    int *from_left,
1892    XPointer *to,
1893    int *to_left,
1894    XPointer *args,
1895    int num_args)
1896{
1897    int ret;
1898    XlcCharSet charset_old, charset = NULL;
1899    XPointer tmp_args[1];
1900
1901    const char *inbufptr;
1902    int	in_left;
1903    char *outbufptr;
1904    int	out_left;
1905    tmp_args[0] = (XPointer) &charset;
1906
1907    ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1908    charset_old = charset;
1909
1910    while ( ret == 0 && *from_left && *to_left) {
1911	inbufptr = *from;
1912	in_left = *from_left;
1913	outbufptr = *to;
1914	out_left = *to_left;
1915        ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1916        if (charset_old != charset) {
1917           *from = (XPointer) inbufptr;
1918           *from_left = in_left;
1919           *to = (XPointer) outbufptr;
1920           *to_left = out_left;
1921           break;
1922        }
1923    }
1924
1925    if (num_args > 0)
1926        *((XlcCharSet *) args[0]) = charset_old;
1927
1928    /* error end */
1929    if (ret != 0)
1930	return( -1 );
1931
1932    return(0);
1933}
1934
1935static int
1936wcstostr(
1937    XlcConv conv,
1938    XPointer *from,
1939    int *from_left,
1940    XPointer *to,
1941    int *to_left,
1942    XPointer *args,
1943    int num_args)
1944{
1945    State state = (State) conv->state;
1946    XLCd lcd = state->lcd;
1947
1948    char *encoding;
1949    unsigned long mb, glyph_index;
1950    wchar_t wc;
1951
1952    int length;
1953    int unconv_num = 0;
1954
1955    CodeSet codeset;
1956
1957    const wchar_t *inbufptr = (const wchar_t *) *from;
1958    char *outbufptr = *to;
1959    int from_size = *from_left;
1960
1961    const char *default_string = XLC_PUBLIC(lcd, default_string);
1962    int defstr_len = strlen(default_string);
1963
1964
1965    if (*from_left > *to_left)
1966        *from_left = *to_left;
1967
1968    while (*from_left && *to_left) {
1969
1970        wc = *inbufptr++;
1971        (*from_left)--;
1972
1973        /* null ? */
1974        if (!wc) {
1975            if (outbufptr) {*outbufptr++ = '\0';}
1976            (*to_left)--;
1977
1978            continue;
1979        }
1980
1981        /* convert */
1982	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
1983
1984	    /* output default_string of XDefaultString() */
1985            if (*to_left < defstr_len)
1986		break;
1987	    if (outbufptr) {
1988                strncpy((char *)outbufptr, default_string, defstr_len);
1989	        outbufptr += defstr_len;
1990            }
1991	    (*to_left) -= defstr_len;
1992
1993            unconv_num++;
1994
1995        } else {
1996            mb = gi_to_mb(glyph_index, codeset);
1997
1998	    if (check_string_encoding(codeset)) {
1999	        if (codeset->parse_info) {
2000                    Bool need_shift = False;
2001                    switch (codeset->parse_info->type) {
2002                        case E_LSL :
2003                            if (codeset != state->GL_codeset) {
2004                                need_shift = True;
2005                                state->GL_codeset = codeset;
2006                            }
2007                            break;
2008                        case E_LSR :
2009                            if (codeset != state->GR_codeset) {
2010                                need_shift = True;
2011                                state->GR_codeset = codeset;
2012                            }
2013                            break;
2014                        /* case E_SS */
2015                        default:
2016                            need_shift = True;
2017                    }
2018
2019		    /* output shift sequence */
2020                    if (need_shift) {
2021		        encoding = codeset->parse_info->encoding;
2022                        length = strlen(encoding);
2023                        if (*to_left < length)
2024		            break;
2025
2026	                if (outbufptr) {
2027                            strncpy((char *)outbufptr, encoding, length);
2028	                    outbufptr += length;
2029                        }
2030	                (*to_left) -= length;
2031                    }
2032                }
2033
2034                /* output characters */
2035	        length = codeset->length;
2036                if (*to_left < length)
2037		    break;
2038
2039	        if (outbufptr) {
2040	            output_ulong_value(outbufptr, mb, length, XlcNONE);
2041	            outbufptr += length;
2042	        }
2043
2044	        (*to_left) -= length;
2045            } else {
2046		unconv_num++;
2047            }
2048        }
2049
2050    } /* end of while */
2051
2052    *from = (XPointer) ((const wchar_t *) *from + from_size);
2053    *from_left = 0;
2054    *to = (XPointer) outbufptr;
2055
2056    return unconv_num;
2057}
2058
2059static int
2060stdc_wcstostr(
2061    XlcConv conv,
2062    XPointer *from,
2063    int *from_left,
2064    XPointer *to,
2065    int *to_left,
2066    XPointer *args,
2067    int num_args)
2068{
2069    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2070    char *buf_ptr1 = buf;
2071    int buf_left1 = (*from_left) * MB_CUR_MAX;
2072    char *buf_ptr2 = buf_ptr1;
2073    int buf_left2;
2074    int unconv_num1 = 0, unconv_num2 = 0;
2075
2076    unconv_num1 = stdc_wcstombs(conv,
2077		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2078    if (unconv_num1 < 0)
2079        goto ret;
2080
2081    buf_left2 = buf_ptr1 - buf_ptr2;
2082
2083    unconv_num2 = mbstostr(conv,
2084		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2085    if (unconv_num2 < 0)
2086        goto ret;
2087
2088ret:
2089    if (buf)
2090	Xfree((char *)buf);
2091
2092    return (unconv_num1 + unconv_num2);
2093}
2094
2095static int
2096wctocs(
2097    XlcConv conv,
2098    XPointer *from,
2099    int *from_left,
2100    XPointer *to,
2101    int *to_left,
2102    XPointer *args,
2103    int num_args)
2104{
2105    State state = (State) conv->state;
2106    XLCd lcd = state->lcd;
2107
2108    wchar_t wc;
2109    unsigned long glyph_index;
2110
2111    int char_len;
2112    int unconv_num = 0;
2113    XlcSide side;
2114
2115    CodeSet codeset;
2116    XlcCharSet charset = NULL;
2117
2118    const wchar_t *inbufptr = (const wchar_t *) *from;
2119    char *outbufptr = *to;
2120    int from_size = *from_left;
2121
2122    if (*from_left > *to_left)
2123        *from_left = *to_left;
2124
2125    if (*from_left && *to_left) {
2126
2127        wc = *inbufptr++;
2128        (*from_left)--;
2129
2130        /* null ? */
2131        if (!wc) {
2132            unconv_num = 1;
2133            goto end;
2134        }
2135
2136        /* convert */
2137	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
2138            unconv_num = 1;
2139	    goto end;
2140        }
2141
2142        if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) {
2143            unconv_num = 1;
2144	    goto end;
2145        }
2146	char_len = charset->char_size;
2147	side = charset->side;
2148
2149        /* output glyph index */
2150	if (codeset->ctconv)
2151            glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
2152        if (*to_left < char_len) {
2153            unconv_num++;
2154	    goto end;
2155        }
2156
2157        if (outbufptr) {
2158            output_ulong_value(outbufptr, glyph_index, char_len, side);
2159            outbufptr += char_len;
2160        }
2161
2162	(*to_left) -= char_len;
2163
2164    }
2165
2166end:
2167
2168     /* error end */
2169    if (unconv_num) {
2170        *from = (XPointer) ((const wchar_t *) *from + from_size);
2171        *from_left = 0;
2172        *to = (XPointer) outbufptr;
2173        return -1;
2174    }
2175
2176    /* nomal end */
2177    *from = (XPointer) inbufptr;
2178    *to = (XPointer) outbufptr;
2179
2180    if (num_args > 0)
2181        *((XlcCharSet *) args[0]) = charset;
2182
2183    return 0;
2184}
2185
2186static int
2187stdc_wctocs(
2188    XlcConv conv,
2189    XPointer *from,
2190    int *from_left,
2191    XPointer *to,
2192    int *to_left,
2193    XPointer *args,
2194    int num_args)
2195{
2196    const wchar_t *src = *((const wchar_t **) from);
2197    wchar_t wch;
2198    XPointer tmp_from, save_from = *from;
2199    char tmp[32];
2200    int length, ret, src_left = *from_left;
2201    int from_size = *from_left;
2202
2203    if (src_left > 0 && *to_left > 0) {
2204	if ((wch = *src)) {
2205	    length = wctomb(tmp, wch);
2206	} else {
2207	    goto end;
2208	}
2209
2210	if (length < 0)
2211	    goto end;
2212
2213	tmp_from = (XPointer) tmp;
2214	ret = mbtocs(conv, &tmp_from, &length, to, to_left, args, num_args);
2215	if (ret < 0)
2216	    goto end;
2217
2218	src++;
2219	src_left--;
2220    }
2221
2222end:
2223     /* error end */
2224    if (save_from == (XPointer) src) {
2225        *from = (XPointer) ((const wchar_t *) *from + from_size);
2226        *from_left = 0;
2227	return -1;
2228    }
2229
2230    /* nomal end */
2231    *from = (XPointer) src;
2232    *from_left = src_left;
2233
2234    return 0;
2235}
2236
2237static int
2238wcstocs(
2239    XlcConv conv,
2240    XPointer *from,
2241    int *from_left,
2242    XPointer *to,
2243    int *to_left,
2244    XPointer *args,
2245    int num_args)
2246{
2247    int ret;
2248    XlcCharSet charset_old, charset = NULL;
2249    XPointer tmp_args[1];
2250
2251    const wchar_t *inbufptr;
2252    int	in_left;
2253    XPointer outbufptr;
2254    int	out_left;
2255    tmp_args[0] = (XPointer) &charset;
2256
2257    ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2258    charset_old = charset;
2259
2260    while ( ret == 0 && *from_left && *to_left) {
2261	inbufptr = (const wchar_t *) *from;
2262	in_left = *from_left;
2263	outbufptr = *to;
2264	out_left = *to_left;
2265        ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2266        if (charset_old != charset) {
2267           *from = (XPointer) inbufptr;
2268           *from_left = in_left;
2269           *to = (XPointer) outbufptr;
2270           *to_left = out_left;
2271           break;
2272        }
2273    }
2274
2275    if (num_args > 0)
2276        *((XlcCharSet *) args[0]) = charset_old;
2277
2278    /* error end */
2279    if (ret != 0)
2280	return( -1 );
2281
2282    return(0);
2283}
2284
2285#ifdef STDCVT
2286
2287static int
2288stdc_wcstocs(
2289    XlcConv conv,
2290    XPointer *from,
2291    int *from_left,
2292    XPointer *to,
2293    int *to_left,
2294    XPointer *args,
2295    int num_args)
2296{
2297    int ret;
2298    XlcCharSet charset_old, charset = NULL;
2299    XPointer tmp_args[1];
2300
2301    const wchar_t *inbufptr;
2302    int	in_left;
2303    XPointer outbufptr;
2304    int	out_left;
2305    tmp_args[0] = (XPointer) &charset;
2306
2307    ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2308    charset_old = charset;
2309
2310    while ( ret == 0 && *from_left && *to_left ) {
2311	inbufptr = (const wchar_t *) *from;
2312	in_left = *from_left;
2313	outbufptr = *to;
2314	out_left = *to_left;
2315        ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2316        if (charset_old != charset) {
2317           *from = (XPointer) inbufptr;
2318           *from_left = in_left;
2319           *to = (XPointer) outbufptr;
2320           *to_left = out_left;
2321           break;
2322        }
2323    }
2324
2325    if (num_args > 0)
2326        *((XlcCharSet *) args[0]) = charset_old;
2327
2328    /* error end */
2329    if (ret != 0)
2330	return( -1 );
2331
2332    return(0);
2333}
2334
2335#endif
2336
2337static int
2338ctstombs(
2339    XlcConv conv,
2340    XPointer *from,
2341    int *from_left,
2342    XPointer *to,
2343    int *to_left,
2344    XPointer *args,
2345    int num_args)
2346{
2347    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2348    char *buf_ptr1 = buf;
2349    int buf_left1 = (*from_left);
2350    char *buf_ptr2 = buf_ptr1;
2351    int buf_left2;
2352    int unconv_num1 = 0, unconv_num2 = 0;
2353
2354    unconv_num1 = ctstowcs(conv,
2355		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2356    if (unconv_num1 < 0)
2357        goto ret;
2358
2359    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2360
2361    unconv_num2 += wcstombs_org(conv,
2362		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2363    if (unconv_num2 < 0)
2364        goto ret;
2365
2366ret:
2367    if (buf)
2368	Xfree((char *)buf);
2369
2370    return (unconv_num1 + unconv_num2);
2371}
2372
2373static int
2374cstombs(
2375    XlcConv conv,
2376    XPointer *from,
2377    int *from_left,
2378    XPointer *to,
2379    int *to_left,
2380    XPointer *args,
2381    int num_args)
2382{
2383    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2384    char *buf_ptr1 = buf;
2385    int buf_left1 = (*from_left);
2386    char *buf_ptr2 = buf_ptr1;
2387    int buf_left2;
2388    int unconv_num1 = 0, unconv_num2 = 0;
2389
2390    unconv_num1 = cstowcs(conv,
2391		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2392    if (unconv_num1 < 0)
2393        goto ret;
2394
2395    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2396
2397    unconv_num2 += wcstombs_org(conv,
2398		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2399    if (unconv_num2 < 0)
2400        goto ret;
2401
2402ret:
2403    if (buf)
2404	Xfree((char *)buf);
2405
2406    return (unconv_num1 + unconv_num2);
2407}
2408
2409static int
2410strtombs(
2411    XlcConv conv,
2412    XPointer *from,
2413    int *from_left,
2414    XPointer *to,
2415    int *to_left,
2416    XPointer *args,
2417    int num_args)
2418{
2419    State state = (State) conv->state;
2420    XLCd lcd = state->lcd;
2421
2422    char *encoding;
2423    unsigned long mb, glyph_index;
2424    unsigned char ch;
2425
2426    int length;
2427    int unconv_num = 0;
2428
2429    CodeSet codeset;
2430
2431    const char *inbufptr = *from;
2432    char *outbufptr = *to;
2433    int from_size = *from_left;
2434
2435    if (*from_left > *to_left)
2436        *from_left = *to_left;
2437
2438    while (*from_left && *to_left) {
2439
2440        ch = *inbufptr++;
2441        (*from_left)--;
2442
2443        /* null ? */
2444        if (!ch) {
2445            if (outbufptr) {*outbufptr++ = '\0';}
2446            (*to_left)--;
2447
2448            continue;
2449        }
2450
2451        /* convert */
2452        if (isleftside(ch)) {
2453	    glyph_index = ch;
2454	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2455	} else {
2456	    glyph_index = ch & GL;
2457	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2458	}
2459
2460        if (!codeset) {
2461	    unconv_num++;
2462	    continue;
2463        }
2464
2465        mb = gi_to_mb(glyph_index, codeset);
2466	if (codeset->parse_info) {
2467            Bool need_shift = False;
2468            switch (codeset->parse_info->type) {
2469                case E_LSL :
2470                    if (codeset != state->GL_codeset) {
2471                        need_shift = True;
2472                        state->GL_codeset = codeset;
2473                    }
2474                    break;
2475                case E_LSR :
2476                    if (codeset != state->GR_codeset) {
2477                        need_shift = True;
2478                        state->GR_codeset = codeset;
2479                    }
2480                    break;
2481                /* case E_SS */
2482                default:
2483                    need_shift = True;
2484            }
2485
2486	    /* output shift sequence */
2487            if (need_shift) {
2488                encoding = codeset->parse_info->encoding;
2489                length = strlen(encoding);
2490                if (*to_left < length)
2491		    break;
2492	        if (outbufptr) {
2493                    strncpy((char *)outbufptr, encoding, length);
2494	            outbufptr += length;
2495                }
2496	        (*to_left) -= length;
2497	    }
2498        }
2499
2500        /* output characters */
2501	length = codeset->length;
2502        if (*to_left < length)
2503	    break;
2504
2505        if (outbufptr) {
2506            output_ulong_value(outbufptr, mb, length, XlcNONE);
2507            outbufptr += length;
2508        }
2509
2510	(*to_left) -= length;
2511
2512    } /* end of while */
2513
2514    *from = (XPointer) ((const char *) *from + from_size);
2515    *from_left = 0;
2516    *to = (XPointer) outbufptr;
2517
2518    return unconv_num;
2519}
2520
2521static int
2522strtowcs(
2523    XlcConv conv,
2524    XPointer *from,
2525    int *from_left,
2526    XPointer *to,
2527    int *to_left,
2528    XPointer *args,
2529    int num_args)
2530{
2531    State state = (State) conv->state;
2532    XLCd lcd = state->lcd;
2533
2534    unsigned char ch;
2535    unsigned long glyph_index;
2536    wchar_t wc;
2537
2538    int unconv_num = 0;
2539    CodeSet codeset;
2540
2541    const char *inbufptr = *from;
2542    wchar_t *outbufptr = (wchar_t *)*to;
2543    int from_size = *from_left;
2544
2545    if (*from_left > *to_left)
2546        *from_left = *to_left;
2547
2548    while (*from_left && *to_left) {
2549
2550        ch = *inbufptr++;
2551        (*from_left)--;
2552
2553        /* null ? */
2554        if (!ch) {
2555            if (outbufptr) {*outbufptr++ = L'\0';}
2556            (*to_left)--;
2557
2558            continue;
2559        }
2560
2561        /* convert */
2562        if (isleftside(ch)) {
2563	    glyph_index = ch;
2564	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2565	} else {
2566	    glyph_index = ch & GL;
2567	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2568	}
2569
2570        if (!codeset) {
2571	    unconv_num++;
2572	    continue;
2573        }
2574
2575        gi_to_wc(lcd, glyph_index, codeset, &wc);
2576	if (outbufptr) {*outbufptr++ = wc;}
2577	(*to_left)--;
2578
2579    } /* end of while */
2580
2581    *from = (XPointer) ((const char *) *from + from_size);
2582    *from_left = 0;
2583    *to = (XPointer) outbufptr;
2584
2585    return unconv_num;
2586}
2587
2588static int
2589stdc_strtowcs(
2590    XlcConv conv,
2591    XPointer *from,
2592    int *from_left,
2593    XPointer *to,
2594    int *to_left,
2595    XPointer *args,
2596    int num_args)
2597{
2598    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2599    char *buf_ptr1 = buf;
2600    int buf_left1 = (*from_left) * MB_CUR_MAX;
2601    char *buf_ptr2 = buf_ptr1;
2602    int buf_left2;
2603    int unconv_num1 = 0, unconv_num2 = 0;
2604
2605    unconv_num1 = strtombs(conv,
2606		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2607    if (unconv_num1 < 0)
2608        goto ret;
2609
2610    buf_left2 = buf_ptr1 - buf_ptr2;
2611
2612    unconv_num2 = stdc_mbstowcs(conv,
2613		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2614    if (unconv_num2 < 0)
2615        goto ret;
2616
2617ret:
2618    if (buf)
2619	Xfree((char *)buf);
2620
2621    return (unconv_num1 + unconv_num2);
2622}
2623
2624/* -------------------------------------------------------------------------- */
2625/*				Close                                         */
2626/* -------------------------------------------------------------------------- */
2627
2628static void
2629close_converter(
2630    XlcConv conv)
2631{
2632    if (conv->state) {
2633	Xfree((char *) conv->state);
2634    }
2635
2636    if (conv->methods) {
2637	Xfree((char *) conv->methods);
2638    }
2639
2640    Xfree((char *) conv);
2641}
2642
2643/* -------------------------------------------------------------------------- */
2644/*				Open                                          */
2645/* -------------------------------------------------------------------------- */
2646
2647static XlcConv
2648create_conv(
2649    XLCd lcd,
2650    XlcConvMethods methods)
2651{
2652    XlcConv conv;
2653    State state;
2654
2655    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
2656    if (conv == NULL)
2657	return (XlcConv) NULL;
2658
2659    conv->methods = (XlcConvMethods) Xmalloc(sizeof(XlcConvMethodsRec));
2660    if (conv->methods == NULL)
2661	goto err;
2662    *conv->methods = *methods;
2663    conv->methods->reset = init_state;
2664
2665    conv->state = (XPointer) Xmalloc(sizeof(StateRec));
2666    if (conv->state == NULL)
2667	goto err;
2668    bzero((char *) conv->state, sizeof(StateRec));
2669
2670    state = (State) conv->state;
2671    state->lcd = lcd;
2672
2673    _XlcResetConverter(conv);
2674
2675    return conv;
2676
2677err:
2678    close_converter(conv);
2679
2680    return (XlcConv) NULL;
2681}
2682
2683static XlcConvMethodsRec mbstocts_methods = {
2684    close_converter,
2685    mbstocts,
2686    NULL
2687};
2688
2689static XlcConv
2690open_mbstocts(
2691    XLCd from_lcd,
2692    const char *from_type,
2693    XLCd to_lcd,
2694    const char *to_type)
2695{
2696    return create_conv(from_lcd, &mbstocts_methods);
2697}
2698
2699static XlcConvMethodsRec mbstostr_methods = {
2700    close_converter,
2701    mbstostr,
2702    NULL
2703};
2704
2705static XlcConv
2706open_mbstostr(
2707    XLCd from_lcd,
2708    const char *from_type,
2709    XLCd to_lcd,
2710    const char *to_type)
2711{
2712    return create_conv(from_lcd, &mbstostr_methods);
2713}
2714
2715static XlcConvMethodsRec mbstocs_methods = {
2716    close_converter,
2717    mbstocs,
2718    NULL
2719};
2720
2721static XlcConv
2722open_mbstocs(
2723    XLCd from_lcd,
2724    const char *from_type,
2725    XLCd to_lcd,
2726    const char *to_type)
2727{
2728    return create_conv(from_lcd, &mbstocs_methods);
2729}
2730
2731static XlcConvMethodsRec mbtocs_methods = {
2732    close_converter,
2733    mbtocs,
2734    NULL
2735};
2736
2737static XlcConv
2738open_mbtocs(
2739    XLCd from_lcd,
2740    const char *from_type,
2741    XLCd to_lcd,
2742    const char *to_type)
2743{
2744    return create_conv(from_lcd, &mbtocs_methods);
2745}
2746
2747static XlcConvMethodsRec ctstombs_methods = {
2748    close_converter,
2749    ctstombs,
2750    NULL
2751};
2752
2753static XlcConv
2754open_ctstombs(
2755    XLCd from_lcd,
2756    const char *from_type,
2757    XLCd to_lcd,
2758    const char *to_type)
2759{
2760    return create_conv(from_lcd, &ctstombs_methods);
2761}
2762
2763static XlcConvMethodsRec cstombs_methods = {
2764    close_converter,
2765    cstombs,
2766    NULL
2767};
2768
2769static XlcConv
2770open_cstombs(
2771    XLCd from_lcd,
2772    const char *from_type,
2773    XLCd to_lcd,
2774    const char *to_type)
2775{
2776    return create_conv(from_lcd, &cstombs_methods);
2777}
2778
2779static XlcConvMethodsRec strtombs_methods = {
2780    close_converter,
2781    strtombs,
2782    NULL
2783};
2784
2785static XlcConv
2786open_strtombs(
2787    XLCd from_lcd,
2788    const char *from_type,
2789    XLCd to_lcd,
2790    const char *to_type)
2791{
2792    return create_conv(from_lcd, &strtombs_methods);
2793}
2794
2795#ifdef STDCVT
2796
2797static XlcConvMethodsRec stdc_mbstowcs_methods = {
2798    close_converter,
2799    stdc_mbstowcs,
2800    NULL
2801};
2802
2803static XlcConv
2804open_stdc_mbstowcs(
2805    XLCd from_lcd,
2806    const char *from_type,
2807    XLCd to_lcd,
2808    const char *to_type)
2809{
2810    return create_conv(from_lcd, &stdc_mbstowcs_methods);
2811}
2812
2813static XlcConvMethodsRec stdc_wcstombs_methods = {
2814    close_converter,
2815    stdc_wcstombs,
2816    NULL
2817};
2818
2819static XlcConv
2820open_stdc_wcstombs(
2821    XLCd from_lcd,
2822    const char *from_type,
2823    XLCd to_lcd,
2824    const char *to_type)
2825{
2826    return create_conv(from_lcd, &stdc_wcstombs_methods);
2827}
2828
2829static XlcConvMethodsRec stdc_wcstocts_methods = {
2830    close_converter,
2831    stdc_wcstocts,
2832    NULL
2833};
2834
2835static XlcConv
2836open_stdc_wcstocts(
2837    XLCd from_lcd,
2838    const char *from_type,
2839    XLCd to_lcd,
2840    const char *to_type)
2841{
2842    return create_conv(from_lcd, &stdc_wcstocts_methods);
2843}
2844
2845static XlcConvMethodsRec stdc_wcstostr_methods = {
2846    close_converter,
2847    stdc_wcstostr,
2848    NULL
2849};
2850
2851static XlcConv
2852open_stdc_wcstostr(
2853    XLCd from_lcd,
2854    const char *from_type,
2855    XLCd to_lcd,
2856    const char *to_type)
2857{
2858    return create_conv(from_lcd, &stdc_wcstostr_methods);
2859}
2860
2861static XlcConvMethodsRec stdc_wcstocs_methods = {
2862    close_converter,
2863    stdc_wcstocs,
2864    NULL
2865};
2866
2867static XlcConv
2868open_stdc_wcstocs(
2869    XLCd from_lcd,
2870    const char *from_type,
2871    XLCd to_lcd,
2872    const char *to_type)
2873{
2874    return create_conv(from_lcd, &stdc_wcstocs_methods);
2875}
2876
2877static XlcConvMethodsRec stdc_wctocs_methods = {
2878    close_converter,
2879    stdc_wctocs,
2880    NULL
2881};
2882
2883static XlcConv
2884open_stdc_wctocs(
2885    XLCd from_lcd,
2886    const char *from_type,
2887    XLCd to_lcd,
2888    const char *to_type)
2889{
2890    return create_conv(from_lcd, &stdc_wctocs_methods);
2891}
2892
2893static XlcConvMethodsRec stdc_ctstowcs_methods = {
2894    close_converter,
2895    stdc_ctstowcs,
2896    NULL
2897};
2898
2899static XlcConv
2900open_stdc_ctstowcs(
2901    XLCd from_lcd,
2902    const char *from_type,
2903    XLCd to_lcd,
2904    const char *to_type)
2905{
2906    return create_conv(from_lcd, &stdc_ctstowcs_methods);
2907}
2908
2909static XlcConvMethodsRec stdc_cstowcs_methods = {
2910    close_converter,
2911    stdc_cstowcs,
2912    NULL
2913};
2914
2915static XlcConv
2916open_stdc_cstowcs(
2917    XLCd from_lcd,
2918    const char *from_type,
2919    XLCd to_lcd,
2920    const char *to_type)
2921{
2922    return create_conv(from_lcd, &stdc_cstowcs_methods);
2923}
2924
2925static XlcConvMethodsRec stdc_strtowcs_methods = {
2926    close_converter,
2927    stdc_strtowcs,
2928    NULL
2929};
2930
2931static XlcConv
2932open_stdc_strtowcs(
2933    XLCd from_lcd,
2934    const char *from_type,
2935    XLCd to_lcd,
2936    const char *to_type)
2937{
2938    return create_conv(from_lcd, &stdc_strtowcs_methods);
2939}
2940
2941#endif /* STDCVT */
2942
2943static XlcConvMethodsRec mbstowcs_methods = {
2944    close_converter,
2945    mbstowcs_org,
2946    NULL
2947};
2948
2949static XlcConv
2950open_mbstowcs(
2951    XLCd from_lcd,
2952    const char *from_type,
2953    XLCd to_lcd,
2954    const char *to_type)
2955{
2956    return create_conv(from_lcd, &mbstowcs_methods);
2957}
2958
2959static XlcConvMethodsRec wcstombs_methods = {
2960    close_converter,
2961    wcstombs_org,
2962    NULL
2963};
2964
2965static XlcConv
2966open_wcstombs(
2967    XLCd from_lcd,
2968    const char *from_type,
2969    XLCd to_lcd,
2970    const char *to_type)
2971{
2972    return create_conv(from_lcd, &wcstombs_methods);
2973}
2974
2975static XlcConvMethodsRec wcstocts_methods = {
2976    close_converter,
2977    wcstocts,
2978    NULL
2979};
2980
2981static XlcConv
2982open_wcstocts(
2983    XLCd from_lcd,
2984    const char *from_type,
2985    XLCd to_lcd,
2986    const char *to_type)
2987{
2988    return create_conv(from_lcd, &wcstocts_methods);
2989}
2990
2991static XlcConvMethodsRec wcstostr_methods = {
2992    close_converter,
2993    wcstostr,
2994    NULL
2995};
2996
2997static XlcConv
2998open_wcstostr(
2999    XLCd from_lcd,
3000    const char *from_type,
3001    XLCd to_lcd,
3002    const char *to_type)
3003{
3004    return create_conv(from_lcd, &wcstostr_methods);
3005}
3006
3007static XlcConvMethodsRec wcstocs_methods = {
3008    close_converter,
3009    wcstocs,
3010    NULL
3011};
3012
3013static XlcConv
3014open_wcstocs(
3015    XLCd from_lcd,
3016    const char *from_type,
3017    XLCd to_lcd,
3018    const char *to_type)
3019{
3020    return create_conv(from_lcd, &wcstocs_methods);
3021}
3022
3023static XlcConvMethodsRec wctocs_methods = {
3024    close_converter,
3025    wctocs,
3026    NULL
3027};
3028
3029static XlcConv
3030open_wctocs(
3031    XLCd from_lcd,
3032    const char *from_type,
3033    XLCd to_lcd,
3034    const char *to_type)
3035{
3036    return create_conv(from_lcd, &wctocs_methods);
3037}
3038
3039static XlcConvMethodsRec ctstowcs_methods = {
3040    close_converter,
3041    ctstowcs,
3042    NULL
3043};
3044
3045static XlcConv
3046open_ctstowcs(
3047    XLCd from_lcd,
3048    const char *from_type,
3049    XLCd to_lcd,
3050    const char *to_type)
3051{
3052    return create_conv(from_lcd, &ctstowcs_methods);
3053}
3054
3055static XlcConvMethodsRec cstowcs_methods = {
3056    close_converter,
3057    cstowcs,
3058    NULL
3059};
3060
3061static XlcConv
3062open_cstowcs(
3063    XLCd from_lcd,
3064    const char *from_type,
3065    XLCd to_lcd,
3066    const char *to_type)
3067{
3068    return create_conv(from_lcd, &cstowcs_methods);
3069}
3070
3071static XlcConvMethodsRec strtowcs_methods = {
3072    close_converter,
3073    strtowcs,
3074    NULL
3075};
3076
3077static XlcConv
3078open_strtowcs(
3079    XLCd from_lcd,
3080    const char *from_type,
3081    XLCd to_lcd,
3082    const char *to_type)
3083{
3084    return create_conv(from_lcd, &strtowcs_methods);
3085}
3086
3087/* -------------------------------------------------------------------------- */
3088/*				Loader                                        */
3089/* -------------------------------------------------------------------------- */
3090
3091XLCd
3092_XlcGenericLoader(
3093    const char *name)
3094{
3095    XLCd lcd;
3096#ifdef STDCVT
3097    XLCdGenericPart *gen;
3098#endif
3099
3100    lcd = _XlcCreateLC(name, _XlcGenericMethods);
3101
3102    if (lcd == NULL)
3103	return lcd;
3104
3105    default_GL_charset = _XlcGetCharSet("ISO8859-1:GL");
3106    default_GR_charset = _XlcGetCharSet("ISO8859-1:GR");
3107
3108    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts);
3109    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString,       open_mbstostr);
3110    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet,      open_mbstocs);
3111    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar,         open_mbtocs);
3112    _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs);
3113    _XlcSetConverter(lcd, XlcNString,    lcd, XlcNMultiByte,    open_strtombs);
3114    _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNMultiByte,    open_cstombs);
3115
3116#ifdef STDCVT
3117     gen = XLC_GENERIC_PART(lcd);
3118
3119     if (gen->use_stdc_env != True) {
3120#endif
3121        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_mbstowcs);
3122        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_wcstombs);
3123        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_wcstocts);
3124        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_wcstostr);
3125        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_wcstocs);
3126        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_wctocs);
3127        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_ctstowcs);
3128        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_strtowcs);
3129        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_cstowcs);
3130#ifdef STDCVT
3131    }
3132#endif
3133
3134#ifdef STDCVT
3135    if (gen->use_stdc_env == True) {
3136        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_stdc_mbstowcs);
3137        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_stdc_wcstombs);
3138        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_stdc_wcstocts);
3139        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_stdc_wcstostr);
3140        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_stdc_wcstocs);
3141        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_stdc_wctocs);
3142        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_stdc_ctstowcs);
3143        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_stdc_strtowcs);
3144        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_stdc_cstowcs);
3145    }
3146#endif
3147
3148    _XlcAddUtf8Converters(lcd);
3149
3150    return lcd;
3151}
3152