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