lcGenConv.c revision cf2acdde
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;
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    inbufptr = *from;
768
769    while (*from_left && *to_left) {
770
771	ch = *inbufptr++;
772	(*from_left)--;
773
774	/* null ? */
775	if (!ch) {
776            if (outbufptr) {*outbufptr++ = L'\0';}
777	    (*to_left)--;
778
779	    /* error check */
780            if (len_left) {
781	        unconv_num += (length - len_left);
782		len_left = 0;
783            }
784
785	    continue;
786	}
787
788	/* same mb char data */
789        if (len_left)
790	    goto output_one_wc;
791
792        /* next mb char data for single shift ? */
793	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
794	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
795            if (codeset != NULL) {
796		length = len_left = codeset->length;
797		mb = 0;
798		continue;
799	    }
800        }
801
802	/* next mb char data for byteM ? */
803	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
804	    goto next_mb_char;
805
806	/* next mb char data for GL or GR side ? */
807	if ((codeset = GLGR_parse_codeset(ch)))
808	    goto next_mb_char;
809
810        /* can't find codeset for the ch */
811        unconv_num++;
812        continue;
813
814next_mb_char:
815        length = len_left = codeset->length;
816	mb = 0;
817
818output_one_wc:
819	mb = (mb << 8) | ch;  /* 1 byte left shift */
820	len_left--;
821
822        /* last of one mb char data */
823        if (!len_left) {
824            gi_to_wc(lcd, mb_to_gi(mb, codeset), codeset, &wc);
825            if (outbufptr) {*outbufptr++ = wc;}
826	    (*to_left)--;
827        }
828
829    } /* end of while */
830
831    /* error check on last char */
832    if (len_left) {
833	inbufptr -= (length - len_left);
834	(*from_left) += (length - len_left);
835	unconv_num += (length - len_left);
836    }
837
838    *from = (XPointer) ((const char *) *from + from_size);
839    *from_left = 0;
840    *to = (XPointer) outbufptr;
841
842    return unconv_num;
843}
844
845static int
846stdc_mbstowcs(
847    XlcConv conv,
848    XPointer *from,
849    int *from_left,
850    XPointer *to,
851    int *to_left,
852    XPointer *args,
853    int num_args)
854{
855    const char *src = *((const char **) from);
856    wchar_t *dst = *((wchar_t **) to);
857    int src_left = *from_left;
858    int dst_left = *to_left;
859    int length, unconv_num = 0;
860
861    while (src_left > 0 && dst_left > 0) {
862	length = mbtowc(dst, src, src_left);
863
864	if (length > 0) {
865	    src += length;
866	    src_left -= length;
867	    if (dst)
868	        dst++;
869	    dst_left--;
870	} else if (length < 0) {
871	    src++;
872	    src_left--;
873	    unconv_num++;
874        } else {
875            /* null ? */
876            src++;
877            src_left--;
878            if (dst)
879                *dst++ = L'\0';
880            dst_left--;
881        }
882    }
883
884    *from = (XPointer) src;
885    if (dst)
886	*to = (XPointer) dst;
887    *from_left = src_left;
888    *to_left = dst_left;
889
890    return unconv_num;
891}
892
893static int
894wcstombs_org(
895    XlcConv conv,
896    XPointer *from,
897    int *from_left,
898    XPointer *to,
899    int *to_left,
900    XPointer *args,
901    int num_args)
902{
903    State state = (State) conv->state;
904    XLCd lcd = state->lcd;
905
906    char *encoding;
907    unsigned long mb, glyph_index;
908    wchar_t wc;
909
910    int length;
911    int unconv_num = 0;
912
913    CodeSet codeset;
914
915    const wchar_t *inbufptr = (const wchar_t *) *from;
916    char *outbufptr = *to;
917    int from_size = *from_left;
918
919    const char *default_string = XLC_PUBLIC(lcd, default_string);
920    int defstr_len = strlen(default_string);
921
922
923    while (*from_left && *to_left) {
924
925        wc = *inbufptr++;
926        (*from_left)--;
927
928        /* null ? */
929        if (!wc) {
930            if (outbufptr) {*outbufptr++ = '\0';}
931            (*to_left)--;
932
933            continue;
934        }
935
936        /* convert */
937	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
938
939	    /* output default_string of XDefaultString() */
940            if (*to_left < defstr_len)
941		break;
942	    if (outbufptr) {
943                strncpy((char *)outbufptr, default_string, defstr_len);
944                outbufptr += defstr_len;
945            }
946	    (*to_left) -= defstr_len;
947
948            unconv_num++;
949
950        } else {
951            mb = gi_to_mb(glyph_index, codeset);
952	    if (codeset->parse_info) {
953                Bool need_shift = False;
954                switch (codeset->parse_info->type) {
955                    case E_LSL :
956                        if (codeset != state->GL_codeset) {
957                            need_shift = True;
958                            state->GL_codeset = codeset;
959                        }
960                        break;
961                    case E_LSR :
962                        if (codeset != state->GR_codeset) {
963                            need_shift = True;
964                            state->GR_codeset = codeset;
965                        }
966                        break;
967                    /* case E_SS */
968                    default:
969                        need_shift = True;
970                }
971
972		/* output shift sequence */
973                if (need_shift) {
974		    encoding = codeset->parse_info->encoding;
975                    length = strlen(encoding);
976                    if (*to_left < length)
977		        break;
978	            if (outbufptr) {
979                        strncpy((char *)outbufptr, encoding, length);
980	                outbufptr += length;
981                    }
982	            (*to_left) -= length;
983                }
984            }
985
986            /* output characters */
987	    length = codeset->length;
988            if (*to_left < length)
989		break;
990
991	    if (outbufptr) {
992		output_ulong_value(outbufptr, mb, length, XlcNONE);
993	        outbufptr += length;
994	    }
995
996	    (*to_left) -= length;
997        }
998
999    } /* end of while */
1000
1001    *from = (XPointer) ((const wchar_t *) *from + from_size);
1002    *from_left = 0;
1003    *to = (XPointer) outbufptr;
1004
1005    return unconv_num;
1006}
1007
1008static int
1009stdc_wcstombs(
1010    XlcConv conv,
1011    XPointer *from,
1012    int *from_left,
1013    XPointer *to,
1014    int *to_left,
1015    XPointer *args,
1016    int num_args)
1017{
1018    const wchar_t *src = *((const wchar_t **) from);
1019    char *dst = *((char **) to);
1020    int src_left = *from_left;
1021    int dst_left = *to_left;
1022    int length, unconv_num = 0;
1023
1024    while (src_left > 0 && dst_left >= MB_CUR_MAX) {
1025	length = wctomb(dst, *src);		/* XXX */
1026
1027        if (length > 0) {
1028	    src++;
1029	    src_left--;
1030	    if (dst)
1031		dst += length;
1032	    dst_left -= length;
1033	} else if (length < 0) {
1034	    src++;
1035	    src_left--;
1036	    unconv_num++;
1037	}
1038    }
1039
1040    *from = (XPointer) src;
1041    if (dst)
1042      *to = (XPointer) dst;
1043    *from_left = src_left;
1044    *to_left = dst_left;
1045
1046    return unconv_num;
1047}
1048
1049static int
1050wcstocts(
1051    XlcConv conv,
1052    XPointer *from,
1053    int *from_left,
1054    XPointer *to,
1055    int *to_left,
1056    XPointer *args,
1057    int num_args)
1058{
1059    State state = (State) conv->state;
1060    XLCd lcd = state->lcd;
1061
1062    unsigned long glyph_index;
1063    wchar_t wc;
1064
1065    int total_len, seq_len, name_len;
1066    int unconv_num = 0;
1067    Bool first_flag = True, standard_flag;
1068    XlcSide side;
1069
1070    CodeSet codeset;
1071    XlcCharSet charset, old_charset = NULL;
1072    const char *ct_sequence;
1073
1074    const wchar_t *inbufptr = (const wchar_t *) *from;
1075    char *outbufptr = *to;
1076    int from_size = *from_left;
1077    char *ext_seg_len = NULL;
1078
1079    while (*from_left && *to_left) {
1080
1081        wc = *inbufptr++;
1082        (*from_left)--;
1083
1084        /* null ? */
1085        if (!wc) {
1086            if (outbufptr) {*outbufptr++ = '\0';}
1087            (*to_left)--;
1088
1089            continue;
1090        }
1091
1092        /* convert */
1093	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
1094            unconv_num++;
1095	    continue;
1096        }
1097
1098        /* parse charset */
1099        if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) {
1100            unconv_num++;
1101	    continue;
1102        }
1103
1104        /* Standard Character Set Encoding ? */
1105	standard_flag = charset->source == CSsrcStd ? True : False;
1106
1107        /*
1108         *   Non-Standard Character Set Encoding
1109         *
1110         * +-----+-----+-----+-----+-----+-----+-----+----   ----+-----+-----+
1111         * |     esc sequence      |  M  |  L  |     encoding name     | STX |
1112         * +-----+-----+-----+-----+-----+-----+-----+----   ----+-----+-----+
1113         *           4bytes         1byte 1byte     variable length     1byte
1114         * 	                   |                                         |
1115         * 	                   +-----------------------------------------+
1116         * 	                     name length  = ((M - 128) * 128) + (L - 128)
1117         */
1118
1119        /* make encoding data */
1120	ct_sequence = charset->ct_sequence;
1121	side = charset->side;
1122        seq_len = strlen(ct_sequence);
1123	if (standard_flag) {
1124            name_len = 0;
1125	    total_len = seq_len;
1126	} else {
1127            name_len = strlen(charset->encoding_name) + 1;
1128	    total_len = seq_len + name_len + 2;
1129	}
1130
1131        /* output escape sequence of CT */
1132	if ( (charset != old_charset) &&
1133	    !(first_flag && charset->string_encoding) ){
1134
1135            if ( (ext_seg_len != NULL) && outbufptr) {
1136                int i = (outbufptr - ext_seg_len) - 2;
1137                *ext_seg_len++ = i / 128 + 128;
1138                *ext_seg_len   = i % 128 + 128;
1139                ext_seg_len = NULL;
1140            }
1141
1142	    if (*to_left < total_len + 1) {
1143                unconv_num++;
1144	        break;
1145	    }
1146
1147	    if (outbufptr) {
1148	        strcpy((char *)outbufptr, ct_sequence);
1149		outbufptr += seq_len;
1150
1151                if (!standard_flag) {
1152                    const char *i = charset->encoding_name;
1153                    ext_seg_len = outbufptr;
1154                    outbufptr += 2;
1155	            for (; *i ; i++)
1156                        *outbufptr++ = ((*i >= 'A') && (*i <= 'Z')) ?
1157                                       *i - 'A' + 'a' : *i;
1158		    *outbufptr++ = STX;
1159                }
1160	    }
1161
1162	    (*to_left) -= total_len;
1163
1164	    first_flag = False;
1165	    old_charset = charset;
1166	}
1167
1168        /* output glyph index */
1169	if (codeset->ctconv)
1170            glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
1171        if (*to_left < charset->char_size) {
1172            unconv_num++;
1173	    break;
1174        }
1175
1176	if (outbufptr) {
1177	   output_ulong_value(outbufptr, glyph_index, charset->char_size, side);
1178	   outbufptr += charset->char_size;
1179	}
1180
1181	(*to_left) -= charset->char_size;
1182
1183    } /* end of while */
1184
1185    if ( (ext_seg_len != NULL) && outbufptr) {
1186        int i = (outbufptr - ext_seg_len) - 2;
1187        *ext_seg_len++ = i / 128 + 128;
1188        *ext_seg_len   = i % 128 + 128;
1189    }
1190
1191    *from = (XPointer) ((const wchar_t *) *from + from_size);
1192    *from_left = 0;
1193    *to = (XPointer) outbufptr;
1194
1195    return unconv_num;
1196}
1197
1198static int
1199stdc_wcstocts(
1200    XlcConv conv,
1201    XPointer *from,
1202    int *from_left,
1203    XPointer *to,
1204    int *to_left,
1205    XPointer *args,
1206    int num_args)
1207{
1208    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1209    char *buf_ptr1 = buf;
1210    int buf_left1 = (*from_left) * MB_CUR_MAX;
1211    char *buf_ptr2 = buf_ptr1;
1212    int buf_left2;
1213    int unconv_num1 = 0, unconv_num2 = 0;
1214
1215    unconv_num1 = stdc_wcstombs(conv,
1216		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1217    if (unconv_num1 < 0)
1218        goto ret;
1219
1220    buf_left2 = buf_ptr1 - buf_ptr2;
1221
1222    unconv_num2 = mbstocts(conv,
1223		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1224    if (unconv_num2 < 0)
1225        goto ret;
1226
1227ret:
1228    Xfree(buf);
1229
1230    return (unconv_num1 + unconv_num2);
1231}
1232
1233static int
1234ctstowcs(
1235    XlcConv conv,
1236    XPointer *from,
1237    int *from_left,
1238    XPointer *to,
1239    int *to_left,
1240    XPointer *args,
1241    int num_args)
1242{
1243    State state = (State) conv->state;
1244    XLCd lcd = state->lcd;
1245
1246    unsigned char ch;
1247    unsigned long glyph_index = 0;
1248    wchar_t wc;
1249
1250    int ctr_seq_len = 0, gi_len_left = 0, gi_len = 0;
1251    int unconv_num = 0;
1252
1253    CodeSet codeset = NULL;
1254    XlcCharSet charset_tmp;
1255
1256    const char *inbufptr;
1257    wchar_t *outbufptr = (wchar_t *) *to;
1258    int from_size = *from_left;
1259
1260    _XlcResetConverter(conv); /* ??? */
1261
1262    if (from == NULL || *from == NULL) {
1263	_XlcResetConverter(conv);
1264        return( 0 );
1265    }
1266    inbufptr = *from;
1267
1268    while (*from_left && *to_left) {
1269
1270	ch = *inbufptr++;
1271	(*from_left)--;
1272
1273	/* null ? */
1274	if (!ch) {
1275            if (outbufptr) {*outbufptr++ = L'\0';}
1276	    (*to_left)--;
1277
1278	    /* error check */
1279            if (gi_len_left) {
1280	        unconv_num += (gi_len - gi_len_left);
1281		gi_len_left = 0;
1282            }
1283
1284	    continue;
1285	}
1286
1287	/* same glyph_index data */
1288        if (gi_len_left)
1289	    goto output_one_wc;
1290
1291        /* control sequence ? */
1292        if (ch == CSI) {
1293            if ( !ct_parse_csi(inbufptr - 1, &ctr_seq_len) )
1294	        goto skip_the_seg;
1295
1296	    if (*from_left + 1 < ctr_seq_len) {
1297		inbufptr--;
1298		(*from_left)++;
1299		unconv_num += *from_left;
1300		break;
1301	    }
1302
1303            /* skip the control sequence */
1304	    inbufptr += (ctr_seq_len - 1);
1305	    *from_left -= (ctr_seq_len - 1);
1306
1307            continue;
1308	}
1309
1310        /* escape sequence ? */
1311        if (ch == ESC) {
1312	    if ( !ct_parse_charset(lcd,
1313			inbufptr - 1, &state->charset, &ctr_seq_len) )
1314		goto skip_the_seg;
1315
1316	    if (state->charset->side == XlcC0 ||
1317		state->charset->side == XlcGL)
1318	      {
1319		state->GL_charset = state->charset;
1320	      }
1321	    else if (state->charset->side == XlcC1 ||
1322		     state->charset->side == XlcGR)
1323	      {
1324		state->GR_charset = state->charset;
1325	      }
1326	    else if (state->charset->side == XlcGLGR)
1327	      {
1328		state->GL_charset = state->charset;
1329		state->GR_charset = state->charset;
1330	      }
1331
1332	    if (*from_left + 1 < ctr_seq_len) {
1333		inbufptr--;
1334		(*from_left)++;
1335		unconv_num += *from_left;
1336		break;
1337	    }
1338
1339            /* skip the escape sequence */
1340	    inbufptr += (ctr_seq_len - 1);
1341	    *from_left -= (ctr_seq_len - 1);
1342
1343            continue;
1344        }
1345
1346 	/* check current state */
1347	if (isleftside(ch))
1348	  state->charset = state->GL_charset;
1349	else
1350	  state->charset = state->GR_charset;
1351
1352	gi_len = gi_len_left = state->charset->char_size;
1353	glyph_index = 0;
1354
1355output_one_wc:
1356        if (state->charset->side == XlcC1 || state->charset->side == XlcGR)
1357            glyph_index = (glyph_index << 8) | (ch & GL);
1358        else
1359            glyph_index = (glyph_index << 8) | ch;
1360
1361	gi_len_left--;
1362
1363        /* last of one glyph_index data */
1364        if (!gi_len_left) {
1365
1366	    /* segment conversion */
1367	    charset_tmp = state->charset;
1368	    segment_conversion(lcd, &charset_tmp, &glyph_index);
1369
1370            /* get codeset */
1371            if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp,
1372						&codeset, &glyph_index) ) {
1373		unconv_num += gi_len;
1374		continue;
1375            }
1376
1377            /* convert glyph index to wicd char */
1378            gi_to_wc(lcd, glyph_index, codeset, &wc);
1379            if (outbufptr) {*outbufptr++ = wc;}
1380	    (*to_left)--;
1381        }
1382
1383        continue;
1384
1385skip_the_seg:
1386	/* skip until next escape or control sequence */
1387        while ( *from_left ) {
1388	    ch = *inbufptr++;
1389	    (*from_left)--;
1390	    unconv_num++;
1391
1392            if (ch == ESC || ch == CSI) {
1393		inbufptr--;
1394		(*from_left)++;
1395		unconv_num--;
1396		break;
1397	    }
1398        }
1399
1400        if ( !(*from_left) )
1401	    break;
1402
1403    } /* end of while */
1404
1405    /* error check on last char */
1406    if (gi_len_left) {
1407	inbufptr -= (gi_len - gi_len_left);
1408	(*from_left) += (gi_len - gi_len_left);
1409	unconv_num += (gi_len - gi_len_left);
1410    }
1411
1412    *from = (XPointer) ((const char *) *from + from_size);
1413    *from_left = 0;
1414    *to = (XPointer) outbufptr;
1415
1416    return unconv_num;
1417}
1418
1419static int
1420cstowcs(
1421    XlcConv conv,
1422    XPointer *from,
1423    int *from_left,
1424    XPointer *to,
1425    int *to_left,
1426    XPointer *args,
1427    int num_args)
1428{
1429    State state = (State) conv->state;
1430    XLCd lcd = state->lcd;
1431
1432    unsigned char ch;
1433    unsigned long glyph_index = 0;
1434    wchar_t wc;
1435    int gi_len_left = 0, gi_len = 0;
1436
1437    int unconv_num = 0;
1438
1439    CodeSet codeset = NULL;
1440    XlcCharSet charset, charset_tmp;
1441
1442    const char *inbufptr;
1443    wchar_t *outbufptr = (wchar_t *) *to;
1444    int from_size = *from_left;
1445
1446    if (from == NULL || *from == NULL) {
1447        return( 0 );
1448    }
1449
1450    inbufptr = *from;
1451
1452    charset = (XlcCharSet) args[0];
1453
1454    while (*from_left && *to_left) {
1455
1456        if (!gi_len_left) {
1457            gi_len_left = gi_len = charset->char_size;
1458            glyph_index = 0;
1459        }
1460
1461	ch = *inbufptr++;
1462	(*from_left)--;
1463
1464	/* null ? */
1465	if (!ch) {
1466            if (outbufptr) {*outbufptr++ = L'\0';}
1467	    (*to_left)--;
1468
1469	    /* error check */
1470            if (gi_len_left) {
1471	        unconv_num += (gi_len - gi_len_left);
1472		gi_len_left = 0;
1473            }
1474	    continue;
1475	}
1476
1477        if (charset->side == XlcC1 || charset->side == XlcGR)
1478            glyph_index = (glyph_index << 8) | (ch & GL);
1479        else
1480            glyph_index = (glyph_index << 8) | ch;
1481
1482	gi_len_left--;
1483
1484        /* last of one glyph_index data */
1485        if (!gi_len_left) {
1486
1487	    /* segment conversion */
1488	    charset_tmp = charset;
1489	    segment_conversion(lcd, &charset_tmp, &glyph_index);
1490
1491            /* get codeset */
1492            if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp,
1493						&codeset, &glyph_index) ) {
1494		unconv_num += gi_len;
1495		continue;
1496            }
1497
1498            /* convert glyph index to wicd char */
1499            gi_to_wc(lcd, glyph_index, codeset, &wc);
1500            if (outbufptr) {*outbufptr++ = wc;}
1501	    (*to_left)--;
1502        }
1503
1504    } /* end of while */
1505
1506    /* error check on last char */
1507    if (gi_len_left) {
1508	inbufptr -= (gi_len - gi_len_left);
1509	(*from_left) += (gi_len - gi_len_left);
1510	unconv_num += (gi_len - gi_len_left);
1511    }
1512
1513    *from = (XPointer) ((const char *) *from + from_size);
1514    *from_left = 0;
1515    *to = (XPointer) outbufptr;
1516
1517    return unconv_num;
1518}
1519
1520static int
1521stdc_ctstowcs(
1522    XlcConv conv,
1523    XPointer *from,
1524    int *from_left,
1525    XPointer *to,
1526    int *to_left,
1527    XPointer *args,
1528    int num_args)
1529{
1530    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1531    char *buf_ptr1 = buf;
1532    int buf_left1 = (*from_left) * MB_CUR_MAX;
1533    char *buf_ptr2 = buf_ptr1;
1534    int buf_left2;
1535    int unconv_num1 = 0, unconv_num2 = 0;
1536
1537    unconv_num1 = ctstombs(conv,
1538		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1539    if (unconv_num1 < 0)
1540        goto ret;
1541
1542    buf_left2 = buf_ptr1 - buf_ptr2;
1543
1544    unconv_num2 = stdc_mbstowcs(conv,
1545		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1546    if (unconv_num2 < 0)
1547        goto ret;
1548
1549ret:
1550    Xfree(buf);
1551
1552    return (unconv_num1 + unconv_num2);
1553}
1554
1555static int
1556stdc_cstowcs(
1557    XlcConv conv,
1558    XPointer *from,
1559    int *from_left,
1560    XPointer *to,
1561    int *to_left,
1562    XPointer *args,
1563    int num_args)
1564{
1565    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
1566    char *buf_ptr1 = buf;
1567    int buf_left1 = (*from_left) * MB_CUR_MAX;
1568    char *buf_ptr2 = buf_ptr1;
1569    int buf_left2;
1570    int unconv_num1 = 0, unconv_num2 = 0;
1571
1572    unconv_num1 = cstombs(conv,
1573		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1574    if (unconv_num1 < 0)
1575        goto ret;
1576
1577    buf_left2 = buf_ptr1 - buf_ptr2;
1578
1579    unconv_num2 = stdc_mbstowcs(conv,
1580		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1581    if (unconv_num2 < 0)
1582        goto ret;
1583
1584ret:
1585    Xfree(buf);
1586
1587    return (unconv_num1 + unconv_num2);
1588}
1589
1590static int
1591mbstocts(
1592    XlcConv conv,
1593    XPointer *from,
1594    int *from_left,
1595    XPointer *to,
1596    int *to_left,
1597    XPointer *args,
1598    int num_args)
1599{
1600    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
1601    char *buf_ptr1 = buf;
1602    int buf_left1 = (*from_left);
1603    char *buf_ptr2 = buf_ptr1;
1604    int buf_left2;
1605    int unconv_num1 = 0, unconv_num2 = 0;
1606
1607    unconv_num1 = mbstowcs_org(conv,
1608		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
1609    if (unconv_num1 < 0)
1610        goto ret;
1611
1612    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
1613
1614    unconv_num2 += wcstocts(conv,
1615		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
1616    if (unconv_num2 < 0)
1617        goto ret;
1618
1619ret:
1620    Xfree(buf);
1621
1622    return (unconv_num1 + unconv_num2);
1623}
1624
1625static int
1626mbstostr(
1627    XlcConv conv,
1628    XPointer *from,
1629    int *from_left,
1630    XPointer *to,
1631    int *to_left,
1632    XPointer *args,
1633    int num_args)
1634{
1635    State state = (State) conv->state;
1636    XLCd lcd = state->lcd;
1637
1638    unsigned char ch;
1639    unsigned long mb = 0;
1640
1641    int length = 0, len_left = 0;
1642    int unconv_num = 0;
1643    int num;
1644
1645    CodeSet codeset = NULL;
1646
1647    const char *inbufptr;
1648    char *outbufptr = *to;
1649    int from_size = *from_left;
1650
1651    unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table);
1652
1653    if (from == NULL || *from == NULL) {
1654	_XlcResetConverter(conv);
1655        return( 0 );
1656    }
1657
1658    inbufptr = *from;
1659
1660    while (*from_left && *to_left) {
1661
1662	ch = *inbufptr++;
1663	(*from_left)--;
1664
1665	/* null ? */
1666	if (!ch) {
1667            if (outbufptr) {*outbufptr++ = '\0';}
1668	    (*to_left)--;
1669
1670            /* error check */
1671            if (len_left) {
1672                unconv_num += (length - len_left);
1673                len_left = 0;
1674            }
1675
1676	    continue;
1677	}
1678
1679        /* same mb char data */
1680        if (len_left)
1681            goto output_one_mb;
1682
1683        /* next mb char data for single shift ? */
1684	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
1685	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
1686            if (codeset != NULL) {
1687		length = len_left = codeset->length;
1688		mb = 0;
1689		continue;
1690	    }
1691        }
1692
1693	/* next char data : byteM ? */
1694	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
1695	    goto next_mb_char;
1696
1697	/* next char data : GL or GR side ? */
1698	if ((codeset = GLGR_parse_codeset(ch)))
1699	    goto next_mb_char;
1700
1701        /* can't find codeset for the ch */
1702        unconv_num++;
1703        continue;
1704
1705next_mb_char:
1706        length = len_left = codeset->length;
1707        mb = 0;
1708
1709output_one_mb:
1710        mb = (mb << 8) | ch;  /* 1 byte left shift */
1711        len_left--;
1712
1713        /* last of one mb char data */
1714        if (!len_left) {
1715            if (check_string_encoding(codeset)) {
1716                if (outbufptr) {*outbufptr++ = mb & 0xff;}
1717		(*to_left)--;
1718            } else {
1719	        unconv_num++;
1720            }
1721        }
1722
1723    } /* end of while */
1724
1725    /* error check on last char */
1726    if (len_left) {
1727        inbufptr -= (length - len_left);
1728        (*from_left) += (length - len_left);
1729        unconv_num += (length - len_left);
1730    }
1731
1732    *from = (XPointer) ((const char *) *from + from_size);
1733    *from_left = 0;
1734    *to = (XPointer) outbufptr;
1735
1736    return unconv_num;
1737}
1738
1739static int
1740mbtocs(
1741    XlcConv conv,
1742    XPointer *from,
1743    int *from_left,
1744    XPointer *to,
1745    int *to_left,
1746    XPointer *args,
1747    int num_args)
1748{
1749    State state = (State) conv->state;
1750    XLCd lcd = state->lcd;
1751
1752    unsigned char ch;
1753    unsigned long mb = 0;
1754    unsigned long glyph_index;
1755
1756    int length = 0, len_left = 0, char_len;
1757    int unconv_num = 0;
1758    int num;
1759    XlcSide side;
1760
1761    CodeSet codeset = NULL;
1762    XlcCharSet charset = NULL;
1763
1764    const char *inbufptr;
1765    char *outbufptr = *to;
1766    int from_size = *from_left;
1767
1768    unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table);
1769
1770    if (from == NULL || *from == NULL) {
1771	_XlcResetConverter(conv);
1772        return( 0 );
1773    }
1774
1775    inbufptr = *from;
1776
1777    while (*from_left && *to_left) {
1778
1779	ch = *inbufptr++;
1780	(*from_left)--;
1781
1782	/* null ? */
1783	if (!ch) {
1784            unconv_num = 1;
1785            if (len_left)
1786	        unconv_num += (length - len_left);
1787	    break;
1788	}
1789
1790	/* same mb char data */
1791        if (len_left)
1792	    goto output;
1793
1794        /* next mb char data for single shift ? */
1795	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
1796	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
1797            if (codeset != NULL) {
1798		length = len_left = codeset->length;
1799		mb = 0;
1800		continue;
1801	    }
1802        }
1803
1804	/* next mb char data for byteM ? */
1805	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
1806	    goto next_mb_char;
1807
1808	/* next mb char data for GL or GR side ? */
1809	if ((codeset = GLGR_parse_codeset(ch)))
1810	    goto next_mb_char;
1811
1812        /* can't find codeset for the ch */
1813        unconv_num = 1;
1814        break;
1815
1816next_mb_char:
1817        length = len_left = codeset->length;
1818	mb = 0;
1819
1820output:
1821	mb = (mb << 8) | ch;  /* 1 byte left shift */
1822	len_left--;
1823
1824        /* last of one mb char data */
1825        if (!len_left) {
1826            glyph_index = mb_to_gi(mb, codeset);
1827            if (!(charset = gi_parse_charset(glyph_index, codeset))) {
1828                unconv_num = length;
1829                break;
1830            }
1831            char_len = charset->char_size;
1832	    side = charset->side;
1833
1834            /* output glyph index */
1835            if (codeset->ctconv)
1836                glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
1837            if (*to_left < char_len) {
1838                unconv_num = length;
1839                break;
1840            }
1841
1842	    if (outbufptr) {
1843	        output_ulong_value(outbufptr, glyph_index, char_len, side);
1844	        outbufptr += char_len;
1845	    }
1846
1847            (*to_left) -= char_len;
1848
1849            break;
1850        }
1851
1852    } /* end of while */
1853
1854    /* error end */
1855    if (unconv_num) {
1856        *from = (XPointer) ((const char *) *from + from_size);
1857        *from_left = 0;
1858        *to = (XPointer) outbufptr;
1859	return -1;
1860    }
1861
1862    /* normal end */
1863    *from = (XPointer) inbufptr;
1864    *to = (XPointer) outbufptr;
1865
1866    if (num_args > 0)
1867        *((XlcCharSet *) args[0]) = charset;
1868
1869    return 0;
1870}
1871
1872static int
1873mbstocs(
1874    XlcConv conv,
1875    XPointer *from,
1876    int *from_left,
1877    XPointer *to,
1878    int *to_left,
1879    XPointer *args,
1880    int num_args)
1881{
1882    int ret;
1883    XlcCharSet charset_old, charset = NULL;
1884    XPointer tmp_args[1];
1885
1886    const char *inbufptr;
1887    int	in_left;
1888    char *outbufptr;
1889    int	out_left;
1890    tmp_args[0] = (XPointer) &charset;
1891
1892    ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1893    charset_old = charset;
1894
1895    while ( ret == 0 && *from_left && *to_left) {
1896	inbufptr = *from;
1897	in_left = *from_left;
1898	outbufptr = *to;
1899	out_left = *to_left;
1900        ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1901        if (charset_old != charset) {
1902           *from = (XPointer) inbufptr;
1903           *from_left = in_left;
1904           *to = (XPointer) outbufptr;
1905           *to_left = out_left;
1906           break;
1907        }
1908    }
1909
1910    if (num_args > 0)
1911        *((XlcCharSet *) args[0]) = charset_old;
1912
1913    /* error end */
1914    if (ret != 0)
1915	return( -1 );
1916
1917    return(0);
1918}
1919
1920static int
1921wcstostr(
1922    XlcConv conv,
1923    XPointer *from,
1924    int *from_left,
1925    XPointer *to,
1926    int *to_left,
1927    XPointer *args,
1928    int num_args)
1929{
1930    State state = (State) conv->state;
1931    XLCd lcd = state->lcd;
1932
1933    char *encoding;
1934    unsigned long mb, glyph_index;
1935    wchar_t wc;
1936
1937    int length;
1938    int unconv_num = 0;
1939
1940    CodeSet codeset;
1941
1942    const wchar_t *inbufptr = (const wchar_t *) *from;
1943    char *outbufptr = *to;
1944    int from_size = *from_left;
1945
1946    const char *default_string = XLC_PUBLIC(lcd, default_string);
1947    int defstr_len = strlen(default_string);
1948
1949    while (*from_left && *to_left) {
1950
1951        wc = *inbufptr++;
1952        (*from_left)--;
1953
1954        /* null ? */
1955        if (!wc) {
1956            if (outbufptr) {*outbufptr++ = '\0';}
1957            (*to_left)--;
1958
1959            continue;
1960        }
1961
1962        /* convert */
1963	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
1964
1965	    /* output default_string of XDefaultString() */
1966            if (*to_left < defstr_len)
1967		break;
1968	    if (outbufptr) {
1969                strncpy((char *)outbufptr, default_string, defstr_len);
1970	        outbufptr += defstr_len;
1971            }
1972	    (*to_left) -= defstr_len;
1973
1974            unconv_num++;
1975
1976        } else {
1977            mb = gi_to_mb(glyph_index, codeset);
1978
1979	    if (check_string_encoding(codeset)) {
1980	        if (codeset->parse_info) {
1981                    Bool need_shift = False;
1982                    switch (codeset->parse_info->type) {
1983                        case E_LSL :
1984                            if (codeset != state->GL_codeset) {
1985                                need_shift = True;
1986                                state->GL_codeset = codeset;
1987                            }
1988                            break;
1989                        case E_LSR :
1990                            if (codeset != state->GR_codeset) {
1991                                need_shift = True;
1992                                state->GR_codeset = codeset;
1993                            }
1994                            break;
1995                        /* case E_SS */
1996                        default:
1997                            need_shift = True;
1998                    }
1999
2000		    /* output shift sequence */
2001                    if (need_shift) {
2002		        encoding = codeset->parse_info->encoding;
2003                        length = strlen(encoding);
2004                        if (*to_left < length)
2005		            break;
2006
2007	                if (outbufptr) {
2008                            strncpy((char *)outbufptr, encoding, length);
2009	                    outbufptr += length;
2010                        }
2011	                (*to_left) -= length;
2012                    }
2013                }
2014
2015                /* output characters */
2016	        length = codeset->length;
2017                if (*to_left < length)
2018		    break;
2019
2020	        if (outbufptr) {
2021	            output_ulong_value(outbufptr, mb, length, XlcNONE);
2022	            outbufptr += length;
2023	        }
2024
2025	        (*to_left) -= length;
2026            } else {
2027		unconv_num++;
2028            }
2029        }
2030
2031    } /* end of while */
2032
2033    *from = (XPointer) ((const wchar_t *) *from + from_size);
2034    *from_left = 0;
2035    *to = (XPointer) outbufptr;
2036
2037    return unconv_num;
2038}
2039
2040static int
2041stdc_wcstostr(
2042    XlcConv conv,
2043    XPointer *from,
2044    int *from_left,
2045    XPointer *to,
2046    int *to_left,
2047    XPointer *args,
2048    int num_args)
2049{
2050    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2051    char *buf_ptr1 = buf;
2052    int buf_left1 = (*from_left) * MB_CUR_MAX;
2053    char *buf_ptr2 = buf_ptr1;
2054    int buf_left2;
2055    int unconv_num1 = 0, unconv_num2 = 0;
2056
2057    unconv_num1 = stdc_wcstombs(conv,
2058		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2059    if (unconv_num1 < 0)
2060        goto ret;
2061
2062    buf_left2 = buf_ptr1 - buf_ptr2;
2063
2064    unconv_num2 = mbstostr(conv,
2065		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2066    if (unconv_num2 < 0)
2067        goto ret;
2068
2069ret:
2070    Xfree(buf);
2071
2072    return (unconv_num1 + unconv_num2);
2073}
2074
2075static int
2076wctocs(
2077    XlcConv conv,
2078    XPointer *from,
2079    int *from_left,
2080    XPointer *to,
2081    int *to_left,
2082    XPointer *args,
2083    int num_args)
2084{
2085    State state = (State) conv->state;
2086    XLCd lcd = state->lcd;
2087
2088    wchar_t wc;
2089    unsigned long glyph_index;
2090
2091    int char_len;
2092    int unconv_num = 0;
2093    XlcSide side;
2094
2095    CodeSet codeset;
2096    XlcCharSet charset = NULL;
2097
2098    const wchar_t *inbufptr = (const wchar_t *) *from;
2099    char *outbufptr = *to;
2100    int from_size = *from_left;
2101
2102    if (*from_left && *to_left) {
2103
2104        wc = *inbufptr++;
2105        (*from_left)--;
2106
2107        /* null ? */
2108        if (!wc) {
2109            unconv_num = 1;
2110            goto end;
2111        }
2112
2113        /* convert */
2114	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
2115            unconv_num = 1;
2116	    goto end;
2117        }
2118
2119        if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) {
2120            unconv_num = 1;
2121	    goto end;
2122        }
2123	char_len = charset->char_size;
2124	side = charset->side;
2125
2126        /* output glyph index */
2127	if (codeset->ctconv)
2128            glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
2129        if (*to_left < char_len) {
2130            unconv_num++;
2131	    goto end;
2132        }
2133
2134        if (outbufptr) {
2135            output_ulong_value(outbufptr, glyph_index, char_len, side);
2136            outbufptr += char_len;
2137        }
2138
2139	(*to_left) -= char_len;
2140
2141    }
2142
2143end:
2144
2145     /* error end */
2146    if (unconv_num) {
2147        *from = (XPointer) ((const wchar_t *) *from + from_size);
2148        *from_left = 0;
2149        *to = (XPointer) outbufptr;
2150        return -1;
2151    }
2152
2153    /* normal end */
2154    *from = (XPointer) inbufptr;
2155    *to = (XPointer) outbufptr;
2156
2157    if (num_args > 0)
2158        *((XlcCharSet *) args[0]) = charset;
2159
2160    return 0;
2161}
2162
2163static int
2164stdc_wctocs(
2165    XlcConv conv,
2166    XPointer *from,
2167    int *from_left,
2168    XPointer *to,
2169    int *to_left,
2170    XPointer *args,
2171    int num_args)
2172{
2173    const wchar_t *src = *((const wchar_t **) from);
2174    wchar_t wch;
2175    XPointer tmp_from, save_from = *from;
2176    char tmp[32];
2177    int length, ret, src_left = *from_left;
2178    int from_size = *from_left;
2179
2180    if (src_left > 0 && *to_left > 0) {
2181	if ((wch = *src)) {
2182	    length = wctomb(tmp, wch);
2183	} else {
2184	    goto end;
2185	}
2186
2187	if (length < 0)
2188	    goto end;
2189
2190	tmp_from = (XPointer) tmp;
2191	ret = mbtocs(conv, &tmp_from, &length, to, to_left, args, num_args);
2192	if (ret < 0)
2193	    goto end;
2194
2195	src++;
2196	src_left--;
2197    }
2198
2199end:
2200     /* error end */
2201    if (save_from == (XPointer) src) {
2202        *from = (XPointer) ((const wchar_t *) *from + from_size);
2203        *from_left = 0;
2204	return -1;
2205    }
2206
2207    /* normal end */
2208    *from = (XPointer) src;
2209    *from_left = src_left;
2210
2211    return 0;
2212}
2213
2214static int
2215wcstocs(
2216    XlcConv conv,
2217    XPointer *from,
2218    int *from_left,
2219    XPointer *to,
2220    int *to_left,
2221    XPointer *args,
2222    int num_args)
2223{
2224    int ret;
2225    XlcCharSet charset_old, charset = NULL;
2226    XPointer tmp_args[1];
2227
2228    const wchar_t *inbufptr;
2229    int	in_left;
2230    XPointer outbufptr;
2231    int	out_left;
2232    tmp_args[0] = (XPointer) &charset;
2233
2234    ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2235    charset_old = charset;
2236
2237    while ( ret == 0 && *from_left && *to_left) {
2238	inbufptr = (const wchar_t *) *from;
2239	in_left = *from_left;
2240	outbufptr = *to;
2241	out_left = *to_left;
2242        ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2243        if (charset_old != charset) {
2244           *from = (XPointer) inbufptr;
2245           *from_left = in_left;
2246           *to = (XPointer) outbufptr;
2247           *to_left = out_left;
2248           break;
2249        }
2250    }
2251
2252    if (num_args > 0)
2253        *((XlcCharSet *) args[0]) = charset_old;
2254
2255    /* error end */
2256    if (ret != 0)
2257	return( -1 );
2258
2259    return(0);
2260}
2261
2262#ifdef STDCVT
2263
2264static int
2265stdc_wcstocs(
2266    XlcConv conv,
2267    XPointer *from,
2268    int *from_left,
2269    XPointer *to,
2270    int *to_left,
2271    XPointer *args,
2272    int num_args)
2273{
2274    int ret;
2275    XlcCharSet charset_old, charset = NULL;
2276    XPointer tmp_args[1];
2277
2278    const wchar_t *inbufptr;
2279    int	in_left;
2280    XPointer outbufptr;
2281    int	out_left;
2282    tmp_args[0] = (XPointer) &charset;
2283
2284    ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2285    charset_old = charset;
2286
2287    while ( ret == 0 && *from_left && *to_left ) {
2288	inbufptr = (const wchar_t *) *from;
2289	in_left = *from_left;
2290	outbufptr = *to;
2291	out_left = *to_left;
2292        ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2293        if (charset_old != charset) {
2294           *from = (XPointer) inbufptr;
2295           *from_left = in_left;
2296           *to = (XPointer) outbufptr;
2297           *to_left = out_left;
2298           break;
2299        }
2300    }
2301
2302    if (num_args > 0)
2303        *((XlcCharSet *) args[0]) = charset_old;
2304
2305    /* error end */
2306    if (ret != 0)
2307	return( -1 );
2308
2309    return(0);
2310}
2311
2312#endif
2313
2314static int
2315ctstombs(
2316    XlcConv conv,
2317    XPointer *from,
2318    int *from_left,
2319    XPointer *to,
2320    int *to_left,
2321    XPointer *args,
2322    int num_args)
2323{
2324    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2325    char *buf_ptr1 = buf;
2326    int buf_left1 = (*from_left);
2327    char *buf_ptr2 = buf_ptr1;
2328    int buf_left2;
2329    int unconv_num1 = 0, unconv_num2 = 0;
2330
2331    unconv_num1 = ctstowcs(conv,
2332		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2333    if (unconv_num1 < 0)
2334        goto ret;
2335
2336    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2337
2338    unconv_num2 += wcstombs_org(conv,
2339		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2340    if (unconv_num2 < 0)
2341        goto ret;
2342
2343ret:
2344    Xfree(buf);
2345
2346    return (unconv_num1 + unconv_num2);
2347}
2348
2349static int
2350cstombs(
2351    XlcConv conv,
2352    XPointer *from,
2353    int *from_left,
2354    XPointer *to,
2355    int *to_left,
2356    XPointer *args,
2357    int num_args)
2358{
2359    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2360    char *buf_ptr1 = buf;
2361    int buf_left1 = (*from_left);
2362    char *buf_ptr2 = buf_ptr1;
2363    int buf_left2;
2364    int unconv_num1 = 0, unconv_num2 = 0;
2365
2366    unconv_num1 = cstowcs(conv,
2367		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2368    if (unconv_num1 < 0)
2369        goto ret;
2370
2371    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2372
2373    unconv_num2 += wcstombs_org(conv,
2374		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2375    if (unconv_num2 < 0)
2376        goto ret;
2377
2378ret:
2379    Xfree(buf);
2380
2381    return (unconv_num1 + unconv_num2);
2382}
2383
2384static int
2385strtombs(
2386    XlcConv conv,
2387    XPointer *from,
2388    int *from_left,
2389    XPointer *to,
2390    int *to_left,
2391    XPointer *args,
2392    int num_args)
2393{
2394    State state = (State) conv->state;
2395    XLCd lcd = state->lcd;
2396
2397    char *encoding;
2398    unsigned long mb, glyph_index;
2399    unsigned char ch;
2400
2401    int length;
2402    int unconv_num = 0;
2403
2404    CodeSet codeset;
2405
2406    const char *inbufptr = *from;
2407    char *outbufptr = *to;
2408    int from_size = *from_left;
2409
2410    while (*from_left && *to_left) {
2411
2412        ch = *inbufptr++;
2413        (*from_left)--;
2414
2415        /* null ? */
2416        if (!ch) {
2417            if (outbufptr) {*outbufptr++ = '\0';}
2418            (*to_left)--;
2419
2420            continue;
2421        }
2422
2423        /* convert */
2424        if (isleftside(ch)) {
2425	    glyph_index = ch;
2426	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2427	} else {
2428	    glyph_index = ch & GL;
2429	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2430	}
2431
2432        if (!codeset) {
2433	    unconv_num++;
2434	    continue;
2435        }
2436
2437        mb = gi_to_mb(glyph_index, codeset);
2438	if (codeset->parse_info) {
2439            Bool need_shift = False;
2440            switch (codeset->parse_info->type) {
2441                case E_LSL :
2442                    if (codeset != state->GL_codeset) {
2443                        need_shift = True;
2444                        state->GL_codeset = codeset;
2445                    }
2446                    break;
2447                case E_LSR :
2448                    if (codeset != state->GR_codeset) {
2449                        need_shift = True;
2450                        state->GR_codeset = codeset;
2451                    }
2452                    break;
2453                /* case E_SS */
2454                default:
2455                    need_shift = True;
2456            }
2457
2458	    /* output shift sequence */
2459            if (need_shift) {
2460                encoding = codeset->parse_info->encoding;
2461                length = strlen(encoding);
2462                if (*to_left < length)
2463		    break;
2464	        if (outbufptr) {
2465                    strncpy((char *)outbufptr, encoding, length);
2466	            outbufptr += length;
2467                }
2468	        (*to_left) -= length;
2469	    }
2470        }
2471
2472        /* output characters */
2473	length = codeset->length;
2474        if (*to_left < length)
2475	    break;
2476
2477        if (outbufptr) {
2478            output_ulong_value(outbufptr, mb, length, XlcNONE);
2479            outbufptr += length;
2480        }
2481
2482	(*to_left) -= length;
2483
2484    } /* end of while */
2485
2486    *from = (XPointer) ((const char *) *from + from_size);
2487    *from_left = 0;
2488    *to = (XPointer) outbufptr;
2489
2490    return unconv_num;
2491}
2492
2493static int
2494strtowcs(
2495    XlcConv conv,
2496    XPointer *from,
2497    int *from_left,
2498    XPointer *to,
2499    int *to_left,
2500    XPointer *args,
2501    int num_args)
2502{
2503    State state = (State) conv->state;
2504    XLCd lcd = state->lcd;
2505
2506    unsigned char ch;
2507    unsigned long glyph_index;
2508    wchar_t wc;
2509
2510    int unconv_num = 0;
2511    CodeSet codeset;
2512
2513    const char *inbufptr = *from;
2514    wchar_t *outbufptr = (wchar_t *)*to;
2515    int from_size = *from_left;
2516
2517    while (*from_left && *to_left) {
2518
2519        ch = *inbufptr++;
2520        (*from_left)--;
2521
2522        /* null ? */
2523        if (!ch) {
2524            if (outbufptr) {*outbufptr++ = L'\0';}
2525            (*to_left)--;
2526
2527            continue;
2528        }
2529
2530        /* convert */
2531        if (isleftside(ch)) {
2532	    glyph_index = ch;
2533	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2534	} else {
2535	    glyph_index = ch & GL;
2536	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2537	}
2538
2539        if (!codeset) {
2540	    unconv_num++;
2541	    continue;
2542        }
2543
2544        gi_to_wc(lcd, glyph_index, codeset, &wc);
2545	if (outbufptr) {*outbufptr++ = wc;}
2546	(*to_left)--;
2547
2548    } /* end of while */
2549
2550    *from = (XPointer) ((const char *) *from + from_size);
2551    *from_left = 0;
2552    *to = (XPointer) outbufptr;
2553
2554    return unconv_num;
2555}
2556
2557static int
2558stdc_strtowcs(
2559    XlcConv conv,
2560    XPointer *from,
2561    int *from_left,
2562    XPointer *to,
2563    int *to_left,
2564    XPointer *args,
2565    int num_args)
2566{
2567    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2568    char *buf_ptr1 = buf;
2569    int buf_left1 = (*from_left) * MB_CUR_MAX;
2570    char *buf_ptr2 = buf_ptr1;
2571    int buf_left2;
2572    int unconv_num1 = 0, unconv_num2 = 0;
2573
2574    unconv_num1 = strtombs(conv,
2575		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2576    if (unconv_num1 < 0)
2577        goto ret;
2578
2579    buf_left2 = buf_ptr1 - buf_ptr2;
2580
2581    unconv_num2 = stdc_mbstowcs(conv,
2582		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2583    if (unconv_num2 < 0)
2584        goto ret;
2585
2586ret:
2587    Xfree(buf);
2588
2589    return (unconv_num1 + unconv_num2);
2590}
2591
2592/* -------------------------------------------------------------------------- */
2593/*				Close                                         */
2594/* -------------------------------------------------------------------------- */
2595
2596static void
2597close_converter(
2598    XlcConv conv)
2599{
2600    Xfree(conv->state);
2601    Xfree(conv->methods);
2602    Xfree(conv);
2603}
2604
2605/* -------------------------------------------------------------------------- */
2606/*				Open                                          */
2607/* -------------------------------------------------------------------------- */
2608
2609static XlcConv
2610create_conv(
2611    XLCd lcd,
2612    XlcConvMethods methods)
2613{
2614    XlcConv conv;
2615    State state;
2616
2617    conv = Xcalloc(1, sizeof(XlcConvRec));
2618    if (conv == NULL)
2619	return (XlcConv) NULL;
2620
2621    conv->methods = Xmalloc(sizeof(XlcConvMethodsRec));
2622    if (conv->methods == NULL)
2623	goto err;
2624    *conv->methods = *methods;
2625    conv->methods->reset = init_state;
2626
2627    conv->state = Xcalloc(1, sizeof(StateRec));
2628    if (conv->state == NULL)
2629	goto err;
2630
2631    state = (State) conv->state;
2632    state->lcd = lcd;
2633
2634    _XlcResetConverter(conv);
2635
2636    return conv;
2637
2638err:
2639    close_converter(conv);
2640
2641    return (XlcConv) NULL;
2642}
2643
2644static XlcConvMethodsRec mbstocts_methods = {
2645    close_converter,
2646    mbstocts,
2647    NULL
2648};
2649
2650static XlcConv
2651open_mbstocts(
2652    XLCd from_lcd,
2653    const char *from_type,
2654    XLCd to_lcd,
2655    const char *to_type)
2656{
2657    return create_conv(from_lcd, &mbstocts_methods);
2658}
2659
2660static XlcConvMethodsRec mbstostr_methods = {
2661    close_converter,
2662    mbstostr,
2663    NULL
2664};
2665
2666static XlcConv
2667open_mbstostr(
2668    XLCd from_lcd,
2669    const char *from_type,
2670    XLCd to_lcd,
2671    const char *to_type)
2672{
2673    return create_conv(from_lcd, &mbstostr_methods);
2674}
2675
2676static XlcConvMethodsRec mbstocs_methods = {
2677    close_converter,
2678    mbstocs,
2679    NULL
2680};
2681
2682static XlcConv
2683open_mbstocs(
2684    XLCd from_lcd,
2685    const char *from_type,
2686    XLCd to_lcd,
2687    const char *to_type)
2688{
2689    return create_conv(from_lcd, &mbstocs_methods);
2690}
2691
2692static XlcConvMethodsRec mbtocs_methods = {
2693    close_converter,
2694    mbtocs,
2695    NULL
2696};
2697
2698static XlcConv
2699open_mbtocs(
2700    XLCd from_lcd,
2701    const char *from_type,
2702    XLCd to_lcd,
2703    const char *to_type)
2704{
2705    return create_conv(from_lcd, &mbtocs_methods);
2706}
2707
2708static XlcConvMethodsRec ctstombs_methods = {
2709    close_converter,
2710    ctstombs,
2711    NULL
2712};
2713
2714static XlcConv
2715open_ctstombs(
2716    XLCd from_lcd,
2717    const char *from_type,
2718    XLCd to_lcd,
2719    const char *to_type)
2720{
2721    return create_conv(from_lcd, &ctstombs_methods);
2722}
2723
2724static XlcConvMethodsRec cstombs_methods = {
2725    close_converter,
2726    cstombs,
2727    NULL
2728};
2729
2730static XlcConv
2731open_cstombs(
2732    XLCd from_lcd,
2733    const char *from_type,
2734    XLCd to_lcd,
2735    const char *to_type)
2736{
2737    return create_conv(from_lcd, &cstombs_methods);
2738}
2739
2740static XlcConvMethodsRec strtombs_methods = {
2741    close_converter,
2742    strtombs,
2743    NULL
2744};
2745
2746static XlcConv
2747open_strtombs(
2748    XLCd from_lcd,
2749    const char *from_type,
2750    XLCd to_lcd,
2751    const char *to_type)
2752{
2753    return create_conv(from_lcd, &strtombs_methods);
2754}
2755
2756#ifdef STDCVT
2757
2758static XlcConvMethodsRec stdc_mbstowcs_methods = {
2759    close_converter,
2760    stdc_mbstowcs,
2761    NULL
2762};
2763
2764static XlcConv
2765open_stdc_mbstowcs(
2766    XLCd from_lcd,
2767    const char *from_type,
2768    XLCd to_lcd,
2769    const char *to_type)
2770{
2771    return create_conv(from_lcd, &stdc_mbstowcs_methods);
2772}
2773
2774static XlcConvMethodsRec stdc_wcstombs_methods = {
2775    close_converter,
2776    stdc_wcstombs,
2777    NULL
2778};
2779
2780static XlcConv
2781open_stdc_wcstombs(
2782    XLCd from_lcd,
2783    const char *from_type,
2784    XLCd to_lcd,
2785    const char *to_type)
2786{
2787    return create_conv(from_lcd, &stdc_wcstombs_methods);
2788}
2789
2790static XlcConvMethodsRec stdc_wcstocts_methods = {
2791    close_converter,
2792    stdc_wcstocts,
2793    NULL
2794};
2795
2796static XlcConv
2797open_stdc_wcstocts(
2798    XLCd from_lcd,
2799    const char *from_type,
2800    XLCd to_lcd,
2801    const char *to_type)
2802{
2803    return create_conv(from_lcd, &stdc_wcstocts_methods);
2804}
2805
2806static XlcConvMethodsRec stdc_wcstostr_methods = {
2807    close_converter,
2808    stdc_wcstostr,
2809    NULL
2810};
2811
2812static XlcConv
2813open_stdc_wcstostr(
2814    XLCd from_lcd,
2815    const char *from_type,
2816    XLCd to_lcd,
2817    const char *to_type)
2818{
2819    return create_conv(from_lcd, &stdc_wcstostr_methods);
2820}
2821
2822static XlcConvMethodsRec stdc_wcstocs_methods = {
2823    close_converter,
2824    stdc_wcstocs,
2825    NULL
2826};
2827
2828static XlcConv
2829open_stdc_wcstocs(
2830    XLCd from_lcd,
2831    const char *from_type,
2832    XLCd to_lcd,
2833    const char *to_type)
2834{
2835    return create_conv(from_lcd, &stdc_wcstocs_methods);
2836}
2837
2838static XlcConvMethodsRec stdc_wctocs_methods = {
2839    close_converter,
2840    stdc_wctocs,
2841    NULL
2842};
2843
2844static XlcConv
2845open_stdc_wctocs(
2846    XLCd from_lcd,
2847    const char *from_type,
2848    XLCd to_lcd,
2849    const char *to_type)
2850{
2851    return create_conv(from_lcd, &stdc_wctocs_methods);
2852}
2853
2854static XlcConvMethodsRec stdc_ctstowcs_methods = {
2855    close_converter,
2856    stdc_ctstowcs,
2857    NULL
2858};
2859
2860static XlcConv
2861open_stdc_ctstowcs(
2862    XLCd from_lcd,
2863    const char *from_type,
2864    XLCd to_lcd,
2865    const char *to_type)
2866{
2867    return create_conv(from_lcd, &stdc_ctstowcs_methods);
2868}
2869
2870static XlcConvMethodsRec stdc_cstowcs_methods = {
2871    close_converter,
2872    stdc_cstowcs,
2873    NULL
2874};
2875
2876static XlcConv
2877open_stdc_cstowcs(
2878    XLCd from_lcd,
2879    const char *from_type,
2880    XLCd to_lcd,
2881    const char *to_type)
2882{
2883    return create_conv(from_lcd, &stdc_cstowcs_methods);
2884}
2885
2886static XlcConvMethodsRec stdc_strtowcs_methods = {
2887    close_converter,
2888    stdc_strtowcs,
2889    NULL
2890};
2891
2892static XlcConv
2893open_stdc_strtowcs(
2894    XLCd from_lcd,
2895    const char *from_type,
2896    XLCd to_lcd,
2897    const char *to_type)
2898{
2899    return create_conv(from_lcd, &stdc_strtowcs_methods);
2900}
2901
2902#endif /* STDCVT */
2903
2904static XlcConvMethodsRec mbstowcs_methods = {
2905    close_converter,
2906    mbstowcs_org,
2907    NULL
2908};
2909
2910static XlcConv
2911open_mbstowcs(
2912    XLCd from_lcd,
2913    const char *from_type,
2914    XLCd to_lcd,
2915    const char *to_type)
2916{
2917    return create_conv(from_lcd, &mbstowcs_methods);
2918}
2919
2920static XlcConvMethodsRec wcstombs_methods = {
2921    close_converter,
2922    wcstombs_org,
2923    NULL
2924};
2925
2926static XlcConv
2927open_wcstombs(
2928    XLCd from_lcd,
2929    const char *from_type,
2930    XLCd to_lcd,
2931    const char *to_type)
2932{
2933    return create_conv(from_lcd, &wcstombs_methods);
2934}
2935
2936static XlcConvMethodsRec wcstocts_methods = {
2937    close_converter,
2938    wcstocts,
2939    NULL
2940};
2941
2942static XlcConv
2943open_wcstocts(
2944    XLCd from_lcd,
2945    const char *from_type,
2946    XLCd to_lcd,
2947    const char *to_type)
2948{
2949    return create_conv(from_lcd, &wcstocts_methods);
2950}
2951
2952static XlcConvMethodsRec wcstostr_methods = {
2953    close_converter,
2954    wcstostr,
2955    NULL
2956};
2957
2958static XlcConv
2959open_wcstostr(
2960    XLCd from_lcd,
2961    const char *from_type,
2962    XLCd to_lcd,
2963    const char *to_type)
2964{
2965    return create_conv(from_lcd, &wcstostr_methods);
2966}
2967
2968static XlcConvMethodsRec wcstocs_methods = {
2969    close_converter,
2970    wcstocs,
2971    NULL
2972};
2973
2974static XlcConv
2975open_wcstocs(
2976    XLCd from_lcd,
2977    const char *from_type,
2978    XLCd to_lcd,
2979    const char *to_type)
2980{
2981    return create_conv(from_lcd, &wcstocs_methods);
2982}
2983
2984static XlcConvMethodsRec wctocs_methods = {
2985    close_converter,
2986    wctocs,
2987    NULL
2988};
2989
2990static XlcConv
2991open_wctocs(
2992    XLCd from_lcd,
2993    const char *from_type,
2994    XLCd to_lcd,
2995    const char *to_type)
2996{
2997    return create_conv(from_lcd, &wctocs_methods);
2998}
2999
3000static XlcConvMethodsRec ctstowcs_methods = {
3001    close_converter,
3002    ctstowcs,
3003    NULL
3004};
3005
3006static XlcConv
3007open_ctstowcs(
3008    XLCd from_lcd,
3009    const char *from_type,
3010    XLCd to_lcd,
3011    const char *to_type)
3012{
3013    return create_conv(from_lcd, &ctstowcs_methods);
3014}
3015
3016static XlcConvMethodsRec cstowcs_methods = {
3017    close_converter,
3018    cstowcs,
3019    NULL
3020};
3021
3022static XlcConv
3023open_cstowcs(
3024    XLCd from_lcd,
3025    const char *from_type,
3026    XLCd to_lcd,
3027    const char *to_type)
3028{
3029    return create_conv(from_lcd, &cstowcs_methods);
3030}
3031
3032static XlcConvMethodsRec strtowcs_methods = {
3033    close_converter,
3034    strtowcs,
3035    NULL
3036};
3037
3038static XlcConv
3039open_strtowcs(
3040    XLCd from_lcd,
3041    const char *from_type,
3042    XLCd to_lcd,
3043    const char *to_type)
3044{
3045    return create_conv(from_lcd, &strtowcs_methods);
3046}
3047
3048/* -------------------------------------------------------------------------- */
3049/*				Loader                                        */
3050/* -------------------------------------------------------------------------- */
3051
3052XLCd
3053_XlcGenericLoader(
3054    const char *name)
3055{
3056    XLCd lcd;
3057#ifdef STDCVT
3058    XLCdGenericPart *gen;
3059#endif
3060
3061    lcd = _XlcCreateLC(name, _XlcGenericMethods);
3062
3063    if (lcd == NULL)
3064	return lcd;
3065
3066    default_GL_charset = _XlcGetCharSet("ISO8859-1:GL");
3067    default_GR_charset = _XlcGetCharSet("ISO8859-1:GR");
3068
3069    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts);
3070    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString,       open_mbstostr);
3071    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet,      open_mbstocs);
3072    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar,         open_mbtocs);
3073    _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs);
3074    _XlcSetConverter(lcd, XlcNString,    lcd, XlcNMultiByte,    open_strtombs);
3075    _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNMultiByte,    open_cstombs);
3076
3077#ifdef STDCVT
3078     gen = XLC_GENERIC_PART(lcd);
3079
3080     if (gen->use_stdc_env != True) {
3081#endif
3082        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_mbstowcs);
3083        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_wcstombs);
3084        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_wcstocts);
3085        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_wcstostr);
3086        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_wcstocs);
3087        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_wctocs);
3088        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_ctstowcs);
3089        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_strtowcs);
3090        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_cstowcs);
3091#ifdef STDCVT
3092    }
3093#endif
3094
3095#ifdef STDCVT
3096    if (gen->use_stdc_env == True) {
3097        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_stdc_mbstowcs);
3098        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_stdc_wcstombs);
3099        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_stdc_wcstocts);
3100        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_stdc_wcstostr);
3101        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_stdc_wcstocs);
3102        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_stdc_wctocs);
3103        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_stdc_ctstowcs);
3104        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_stdc_strtowcs);
3105        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_stdc_cstowcs);
3106    }
3107#endif
3108
3109    _XlcAddUtf8Converters(lcd);
3110
3111    return lcd;
3112}
3113