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