lcGenConv.c revision c17aa6b1
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#ifdef notdef
1798    if (*from_left > *to_left)
1799        *from_left = *to_left;
1800#endif
1801
1802    while (*from_left && *to_left) {
1803
1804	ch = *inbufptr++;
1805	(*from_left)--;
1806
1807	/* null ? */
1808	if (!ch) {
1809            unconv_num = 1;
1810            if (len_left)
1811	        unconv_num += (length - len_left);
1812	    break;
1813	}
1814
1815	/* same mb char data */
1816        if (len_left)
1817	    goto output;
1818
1819        /* next mb char data for single shift ? */
1820	if (mb_parse_table && (num = mb_parse_table[ch]) ) {
1821	    codeset = mb_parse_codeset(state, num, &inbufptr, from_left);
1822            if (codeset != NULL) {
1823		length = len_left = codeset->length;
1824		mb = 0;
1825		continue;
1826	    }
1827        }
1828
1829	/* next mb char data for byteM ? */
1830	if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1))))
1831	    goto next_mb_char;
1832
1833	/* next mb char data for GL or GR side ? */
1834	if ((codeset = GLGR_parse_codeset(ch)))
1835	    goto next_mb_char;
1836
1837        /* can't find codeset for the ch */
1838        unconv_num = 1;
1839        break;
1840
1841next_mb_char:
1842        length = len_left = codeset->length;
1843	mb = 0;
1844
1845output:
1846	mb = (mb << 8) | ch;  /* 1 byte left shift */
1847	len_left--;
1848
1849        /* last of one mb char data */
1850        if (!len_left) {
1851            glyph_index = mb_to_gi(mb, codeset);
1852            if (!(charset = gi_parse_charset(glyph_index, codeset))) {
1853                unconv_num = length;
1854                break;
1855            }
1856            char_len = charset->char_size;
1857	    side = charset->side;
1858
1859            /* output glyph index */
1860            if (codeset->ctconv)
1861                glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
1862            if (*to_left < char_len) {
1863                unconv_num = length;
1864                break;
1865            }
1866
1867	    if (outbufptr) {
1868	        output_ulong_value(outbufptr, glyph_index, char_len, side);
1869	        outbufptr += char_len;
1870	    }
1871
1872            (*to_left) -= char_len;
1873
1874            break;
1875        }
1876
1877    } /* end of while */
1878
1879    /* error end */
1880    if (unconv_num) {
1881        *from = (XPointer) ((const char *) *from + from_size);
1882        *from_left = 0;
1883        *to = (XPointer) outbufptr;
1884	return -1;
1885    }
1886
1887    /* nomal end */
1888    *from = (XPointer) inbufptr;
1889    *to = (XPointer) outbufptr;
1890
1891    if (num_args > 0)
1892        *((XlcCharSet *) args[0]) = charset;
1893
1894    return 0;
1895}
1896
1897static int
1898mbstocs(
1899    XlcConv conv,
1900    XPointer *from,
1901    int *from_left,
1902    XPointer *to,
1903    int *to_left,
1904    XPointer *args,
1905    int num_args)
1906{
1907    int ret;
1908    XlcCharSet charset_old, charset = NULL;
1909    XPointer tmp_args[1];
1910
1911    const char *inbufptr;
1912    int	in_left;
1913    char *outbufptr;
1914    int	out_left;
1915    tmp_args[0] = (XPointer) &charset;
1916
1917    ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1918    charset_old = charset;
1919
1920    while ( ret == 0 && *from_left && *to_left) {
1921	inbufptr = *from;
1922	in_left = *from_left;
1923	outbufptr = *to;
1924	out_left = *to_left;
1925        ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1);
1926        if (charset_old != charset) {
1927           *from = (XPointer) inbufptr;
1928           *from_left = in_left;
1929           *to = (XPointer) outbufptr;
1930           *to_left = out_left;
1931           break;
1932        }
1933    }
1934
1935    if (num_args > 0)
1936        *((XlcCharSet *) args[0]) = charset_old;
1937
1938    /* error end */
1939    if (ret != 0)
1940	return( -1 );
1941
1942    return(0);
1943}
1944
1945static int
1946wcstostr(
1947    XlcConv conv,
1948    XPointer *from,
1949    int *from_left,
1950    XPointer *to,
1951    int *to_left,
1952    XPointer *args,
1953    int num_args)
1954{
1955    State state = (State) conv->state;
1956    XLCd lcd = state->lcd;
1957
1958    char *encoding;
1959    unsigned long mb, glyph_index;
1960    wchar_t wc;
1961
1962    int length;
1963    int unconv_num = 0;
1964
1965    CodeSet codeset;
1966
1967    const wchar_t *inbufptr = (const wchar_t *) *from;
1968    char *outbufptr = *to;
1969    int from_size = *from_left;
1970
1971    const char *default_string = XLC_PUBLIC(lcd, default_string);
1972    int defstr_len = strlen(default_string);
1973
1974
1975#ifdef notdef
1976    if (*from_left > *to_left)
1977        *from_left = *to_left;
1978#endif
1979
1980    while (*from_left && *to_left) {
1981
1982        wc = *inbufptr++;
1983        (*from_left)--;
1984
1985        /* null ? */
1986        if (!wc) {
1987            if (outbufptr) {*outbufptr++ = '\0';}
1988            (*to_left)--;
1989
1990            continue;
1991        }
1992
1993        /* convert */
1994	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
1995
1996	    /* output default_string of XDefaultString() */
1997            if (*to_left < defstr_len)
1998		break;
1999	    if (outbufptr) {
2000                strncpy((char *)outbufptr, default_string, defstr_len);
2001	        outbufptr += defstr_len;
2002            }
2003	    (*to_left) -= defstr_len;
2004
2005            unconv_num++;
2006
2007        } else {
2008            mb = gi_to_mb(glyph_index, codeset);
2009
2010	    if (check_string_encoding(codeset)) {
2011	        if (codeset->parse_info) {
2012                    Bool need_shift = False;
2013                    switch (codeset->parse_info->type) {
2014                        case E_LSL :
2015                            if (codeset != state->GL_codeset) {
2016                                need_shift = True;
2017                                state->GL_codeset = codeset;
2018                            }
2019                            break;
2020                        case E_LSR :
2021                            if (codeset != state->GR_codeset) {
2022                                need_shift = True;
2023                                state->GR_codeset = codeset;
2024                            }
2025                            break;
2026                        /* case E_SS */
2027                        default:
2028                            need_shift = True;
2029                    }
2030
2031		    /* output shift sequence */
2032                    if (need_shift) {
2033		        encoding = codeset->parse_info->encoding;
2034                        length = strlen(encoding);
2035                        if (*to_left < length)
2036		            break;
2037
2038	                if (outbufptr) {
2039                            strncpy((char *)outbufptr, encoding, length);
2040	                    outbufptr += length;
2041                        }
2042	                (*to_left) -= length;
2043                    }
2044                }
2045
2046                /* output characters */
2047	        length = codeset->length;
2048                if (*to_left < length)
2049		    break;
2050
2051	        if (outbufptr) {
2052	            output_ulong_value(outbufptr, mb, length, XlcNONE);
2053	            outbufptr += length;
2054	        }
2055
2056	        (*to_left) -= length;
2057            } else {
2058		unconv_num++;
2059            }
2060        }
2061
2062    } /* end of while */
2063
2064    *from = (XPointer) ((const wchar_t *) *from + from_size);
2065    *from_left = 0;
2066    *to = (XPointer) outbufptr;
2067
2068    return unconv_num;
2069}
2070
2071static int
2072stdc_wcstostr(
2073    XlcConv conv,
2074    XPointer *from,
2075    int *from_left,
2076    XPointer *to,
2077    int *to_left,
2078    XPointer *args,
2079    int num_args)
2080{
2081    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2082    char *buf_ptr1 = buf;
2083    int buf_left1 = (*from_left) * MB_CUR_MAX;
2084    char *buf_ptr2 = buf_ptr1;
2085    int buf_left2;
2086    int unconv_num1 = 0, unconv_num2 = 0;
2087
2088    unconv_num1 = stdc_wcstombs(conv,
2089		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2090    if (unconv_num1 < 0)
2091        goto ret;
2092
2093    buf_left2 = buf_ptr1 - buf_ptr2;
2094
2095    unconv_num2 = mbstostr(conv,
2096		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2097    if (unconv_num2 < 0)
2098        goto ret;
2099
2100ret:
2101    if (buf)
2102	Xfree((char *)buf);
2103
2104    return (unconv_num1 + unconv_num2);
2105}
2106
2107static int
2108wctocs(
2109    XlcConv conv,
2110    XPointer *from,
2111    int *from_left,
2112    XPointer *to,
2113    int *to_left,
2114    XPointer *args,
2115    int num_args)
2116{
2117    State state = (State) conv->state;
2118    XLCd lcd = state->lcd;
2119
2120    wchar_t wc;
2121    unsigned long glyph_index;
2122
2123    int char_len;
2124    int unconv_num = 0;
2125    XlcSide side;
2126
2127    CodeSet codeset;
2128    XlcCharSet charset = NULL;
2129
2130    const wchar_t *inbufptr = (const wchar_t *) *from;
2131    char *outbufptr = *to;
2132    int from_size = *from_left;
2133
2134#ifdef notdef
2135    if (*from_left > *to_left)
2136        *from_left = *to_left;
2137#endif
2138
2139    if (*from_left && *to_left) {
2140
2141        wc = *inbufptr++;
2142        (*from_left)--;
2143
2144        /* null ? */
2145        if (!wc) {
2146            unconv_num = 1;
2147            goto end;
2148        }
2149
2150        /* convert */
2151	if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) {
2152            unconv_num = 1;
2153	    goto end;
2154        }
2155
2156        if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) {
2157            unconv_num = 1;
2158	    goto end;
2159        }
2160	char_len = charset->char_size;
2161	side = charset->side;
2162
2163        /* output glyph index */
2164	if (codeset->ctconv)
2165            glyph_index = conv_to_dest(codeset->ctconv, glyph_index);
2166        if (*to_left < char_len) {
2167            unconv_num++;
2168	    goto end;
2169        }
2170
2171        if (outbufptr) {
2172            output_ulong_value(outbufptr, glyph_index, char_len, side);
2173            outbufptr += char_len;
2174        }
2175
2176	(*to_left) -= char_len;
2177
2178    }
2179
2180end:
2181
2182     /* error end */
2183    if (unconv_num) {
2184        *from = (XPointer) ((const wchar_t *) *from + from_size);
2185        *from_left = 0;
2186        *to = (XPointer) outbufptr;
2187        return -1;
2188    }
2189
2190    /* nomal end */
2191    *from = (XPointer) inbufptr;
2192    *to = (XPointer) outbufptr;
2193
2194    if (num_args > 0)
2195        *((XlcCharSet *) args[0]) = charset;
2196
2197    return 0;
2198}
2199
2200static int
2201stdc_wctocs(
2202    XlcConv conv,
2203    XPointer *from,
2204    int *from_left,
2205    XPointer *to,
2206    int *to_left,
2207    XPointer *args,
2208    int num_args)
2209{
2210    const wchar_t *src = *((const wchar_t **) from);
2211    wchar_t wch;
2212    XPointer tmp_from, save_from = *from;
2213    char tmp[32];
2214    int length, ret, src_left = *from_left;
2215    int from_size = *from_left;
2216
2217    if (src_left > 0 && *to_left > 0) {
2218	if ((wch = *src)) {
2219	    length = wctomb(tmp, wch);
2220	} else {
2221	    goto end;
2222	}
2223
2224	if (length < 0)
2225	    goto end;
2226
2227	tmp_from = (XPointer) tmp;
2228	ret = mbtocs(conv, &tmp_from, &length, to, to_left, args, num_args);
2229	if (ret < 0)
2230	    goto end;
2231
2232	src++;
2233	src_left--;
2234    }
2235
2236end:
2237     /* error end */
2238    if (save_from == (XPointer) src) {
2239        *from = (XPointer) ((const wchar_t *) *from + from_size);
2240        *from_left = 0;
2241	return -1;
2242    }
2243
2244    /* nomal end */
2245    *from = (XPointer) src;
2246    *from_left = src_left;
2247
2248    return 0;
2249}
2250
2251static int
2252wcstocs(
2253    XlcConv conv,
2254    XPointer *from,
2255    int *from_left,
2256    XPointer *to,
2257    int *to_left,
2258    XPointer *args,
2259    int num_args)
2260{
2261    int ret;
2262    XlcCharSet charset_old, charset = NULL;
2263    XPointer tmp_args[1];
2264
2265    const wchar_t *inbufptr;
2266    int	in_left;
2267    XPointer outbufptr;
2268    int	out_left;
2269    tmp_args[0] = (XPointer) &charset;
2270
2271    ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2272    charset_old = charset;
2273
2274    while ( ret == 0 && *from_left && *to_left) {
2275	inbufptr = (const wchar_t *) *from;
2276	in_left = *from_left;
2277	outbufptr = *to;
2278	out_left = *to_left;
2279        ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2280        if (charset_old != charset) {
2281           *from = (XPointer) inbufptr;
2282           *from_left = in_left;
2283           *to = (XPointer) outbufptr;
2284           *to_left = out_left;
2285           break;
2286        }
2287    }
2288
2289    if (num_args > 0)
2290        *((XlcCharSet *) args[0]) = charset_old;
2291
2292    /* error end */
2293    if (ret != 0)
2294	return( -1 );
2295
2296    return(0);
2297}
2298
2299#ifdef STDCVT
2300
2301static int
2302stdc_wcstocs(
2303    XlcConv conv,
2304    XPointer *from,
2305    int *from_left,
2306    XPointer *to,
2307    int *to_left,
2308    XPointer *args,
2309    int num_args)
2310{
2311    int ret;
2312    XlcCharSet charset_old, charset = NULL;
2313    XPointer tmp_args[1];
2314
2315    const wchar_t *inbufptr;
2316    int	in_left;
2317    XPointer outbufptr;
2318    int	out_left;
2319    tmp_args[0] = (XPointer) &charset;
2320
2321    ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2322    charset_old = charset;
2323
2324    while ( ret == 0 && *from_left && *to_left ) {
2325	inbufptr = (const wchar_t *) *from;
2326	in_left = *from_left;
2327	outbufptr = *to;
2328	out_left = *to_left;
2329        ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1);
2330        if (charset_old != charset) {
2331           *from = (XPointer) inbufptr;
2332           *from_left = in_left;
2333           *to = (XPointer) outbufptr;
2334           *to_left = out_left;
2335           break;
2336        }
2337    }
2338
2339    if (num_args > 0)
2340        *((XlcCharSet *) args[0]) = charset_old;
2341
2342    /* error end */
2343    if (ret != 0)
2344	return( -1 );
2345
2346    return(0);
2347}
2348
2349#endif
2350
2351static int
2352ctstombs(
2353    XlcConv conv,
2354    XPointer *from,
2355    int *from_left,
2356    XPointer *to,
2357    int *to_left,
2358    XPointer *args,
2359    int num_args)
2360{
2361    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2362    char *buf_ptr1 = buf;
2363    int buf_left1 = (*from_left);
2364    char *buf_ptr2 = buf_ptr1;
2365    int buf_left2;
2366    int unconv_num1 = 0, unconv_num2 = 0;
2367
2368    unconv_num1 = ctstowcs(conv,
2369		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2370    if (unconv_num1 < 0)
2371        goto ret;
2372
2373    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2374
2375    unconv_num2 += wcstombs_org(conv,
2376		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2377    if (unconv_num2 < 0)
2378        goto ret;
2379
2380ret:
2381    if (buf)
2382	Xfree((char *)buf);
2383
2384    return (unconv_num1 + unconv_num2);
2385}
2386
2387static int
2388cstombs(
2389    XlcConv conv,
2390    XPointer *from,
2391    int *from_left,
2392    XPointer *to,
2393    int *to_left,
2394    XPointer *args,
2395    int num_args)
2396{
2397    XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t));
2398    char *buf_ptr1 = buf;
2399    int buf_left1 = (*from_left);
2400    char *buf_ptr2 = buf_ptr1;
2401    int buf_left2;
2402    int unconv_num1 = 0, unconv_num2 = 0;
2403
2404    unconv_num1 = cstowcs(conv,
2405		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2406    if (unconv_num1 < 0)
2407        goto ret;
2408
2409    buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t);
2410
2411    unconv_num2 += wcstombs_org(conv,
2412		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2413    if (unconv_num2 < 0)
2414        goto ret;
2415
2416ret:
2417    if (buf)
2418	Xfree((char *)buf);
2419
2420    return (unconv_num1 + unconv_num2);
2421}
2422
2423static int
2424strtombs(
2425    XlcConv conv,
2426    XPointer *from,
2427    int *from_left,
2428    XPointer *to,
2429    int *to_left,
2430    XPointer *args,
2431    int num_args)
2432{
2433    State state = (State) conv->state;
2434    XLCd lcd = state->lcd;
2435
2436    char *encoding;
2437    unsigned long mb, glyph_index;
2438    unsigned char ch;
2439
2440    int length;
2441    int unconv_num = 0;
2442
2443    CodeSet codeset;
2444
2445    const char *inbufptr = *from;
2446    char *outbufptr = *to;
2447    int from_size = *from_left;
2448
2449#ifdef notdef
2450    if (*from_left > *to_left)
2451        *from_left = *to_left;
2452#endif
2453
2454    while (*from_left && *to_left) {
2455
2456        ch = *inbufptr++;
2457        (*from_left)--;
2458
2459        /* null ? */
2460        if (!ch) {
2461            if (outbufptr) {*outbufptr++ = '\0';}
2462            (*to_left)--;
2463
2464            continue;
2465        }
2466
2467        /* convert */
2468        if (isleftside(ch)) {
2469	    glyph_index = ch;
2470	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2471	} else {
2472	    glyph_index = ch & GL;
2473	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2474	}
2475
2476        if (!codeset) {
2477	    unconv_num++;
2478	    continue;
2479        }
2480
2481        mb = gi_to_mb(glyph_index, codeset);
2482	if (codeset->parse_info) {
2483            Bool need_shift = False;
2484            switch (codeset->parse_info->type) {
2485                case E_LSL :
2486                    if (codeset != state->GL_codeset) {
2487                        need_shift = True;
2488                        state->GL_codeset = codeset;
2489                    }
2490                    break;
2491                case E_LSR :
2492                    if (codeset != state->GR_codeset) {
2493                        need_shift = True;
2494                        state->GR_codeset = codeset;
2495                    }
2496                    break;
2497                /* case E_SS */
2498                default:
2499                    need_shift = True;
2500            }
2501
2502	    /* output shift sequence */
2503            if (need_shift) {
2504                encoding = codeset->parse_info->encoding;
2505                length = strlen(encoding);
2506                if (*to_left < length)
2507		    break;
2508	        if (outbufptr) {
2509                    strncpy((char *)outbufptr, encoding, length);
2510	            outbufptr += length;
2511                }
2512	        (*to_left) -= length;
2513	    }
2514        }
2515
2516        /* output characters */
2517	length = codeset->length;
2518        if (*to_left < length)
2519	    break;
2520
2521        if (outbufptr) {
2522            output_ulong_value(outbufptr, mb, length, XlcNONE);
2523            outbufptr += length;
2524        }
2525
2526	(*to_left) -= length;
2527
2528    } /* end of while */
2529
2530    *from = (XPointer) ((const char *) *from + from_size);
2531    *from_left = 0;
2532    *to = (XPointer) outbufptr;
2533
2534    return unconv_num;
2535}
2536
2537static int
2538strtowcs(
2539    XlcConv conv,
2540    XPointer *from,
2541    int *from_left,
2542    XPointer *to,
2543    int *to_left,
2544    XPointer *args,
2545    int num_args)
2546{
2547    State state = (State) conv->state;
2548    XLCd lcd = state->lcd;
2549
2550    unsigned char ch;
2551    unsigned long glyph_index;
2552    wchar_t wc;
2553
2554    int unconv_num = 0;
2555    CodeSet codeset;
2556
2557    const char *inbufptr = *from;
2558    wchar_t *outbufptr = (wchar_t *)*to;
2559    int from_size = *from_left;
2560
2561#ifdef notdef
2562    if (*from_left > *to_left)
2563        *from_left = *to_left;
2564#endif
2565
2566    while (*from_left && *to_left) {
2567
2568        ch = *inbufptr++;
2569        (*from_left)--;
2570
2571        /* null ? */
2572        if (!ch) {
2573            if (outbufptr) {*outbufptr++ = L'\0';}
2574            (*to_left)--;
2575
2576            continue;
2577        }
2578
2579        /* convert */
2580        if (isleftside(ch)) {
2581	    glyph_index = ch;
2582	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL");
2583	} else {
2584	    glyph_index = ch & GL;
2585	    codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR");
2586	}
2587
2588        if (!codeset) {
2589	    unconv_num++;
2590	    continue;
2591        }
2592
2593        gi_to_wc(lcd, glyph_index, codeset, &wc);
2594	if (outbufptr) {*outbufptr++ = wc;}
2595	(*to_left)--;
2596
2597    } /* end of while */
2598
2599    *from = (XPointer) ((const char *) *from + from_size);
2600    *from_left = 0;
2601    *to = (XPointer) outbufptr;
2602
2603    return unconv_num;
2604}
2605
2606static int
2607stdc_strtowcs(
2608    XlcConv conv,
2609    XPointer *from,
2610    int *from_left,
2611    XPointer *to,
2612    int *to_left,
2613    XPointer *args,
2614    int num_args)
2615{
2616    XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX);
2617    char *buf_ptr1 = buf;
2618    int buf_left1 = (*from_left) * MB_CUR_MAX;
2619    char *buf_ptr2 = buf_ptr1;
2620    int buf_left2;
2621    int unconv_num1 = 0, unconv_num2 = 0;
2622
2623    unconv_num1 = strtombs(conv,
2624		from, from_left, &buf_ptr1, &buf_left1, args, num_args);
2625    if (unconv_num1 < 0)
2626        goto ret;
2627
2628    buf_left2 = buf_ptr1 - buf_ptr2;
2629
2630    unconv_num2 = stdc_mbstowcs(conv,
2631		&buf_ptr2, &buf_left2, to, to_left, args, num_args);
2632    if (unconv_num2 < 0)
2633        goto ret;
2634
2635ret:
2636    if (buf)
2637	Xfree((char *)buf);
2638
2639    return (unconv_num1 + unconv_num2);
2640}
2641
2642/* -------------------------------------------------------------------------- */
2643/*				Close                                         */
2644/* -------------------------------------------------------------------------- */
2645
2646static void
2647close_converter(
2648    XlcConv conv)
2649{
2650    if (conv->state) {
2651	Xfree((char *) conv->state);
2652    }
2653
2654    if (conv->methods) {
2655	Xfree((char *) conv->methods);
2656    }
2657
2658    Xfree((char *) conv);
2659}
2660
2661/* -------------------------------------------------------------------------- */
2662/*				Open                                          */
2663/* -------------------------------------------------------------------------- */
2664
2665static XlcConv
2666create_conv(
2667    XLCd lcd,
2668    XlcConvMethods methods)
2669{
2670    XlcConv conv;
2671    State state;
2672
2673    conv = (XlcConv) Xcalloc(1, sizeof(XlcConvRec));
2674    if (conv == NULL)
2675	return (XlcConv) NULL;
2676
2677    conv->methods = (XlcConvMethods) Xmalloc(sizeof(XlcConvMethodsRec));
2678    if (conv->methods == NULL)
2679	goto err;
2680    *conv->methods = *methods;
2681    conv->methods->reset = init_state;
2682
2683    conv->state = (XPointer) Xmalloc(sizeof(StateRec));
2684    if (conv->state == NULL)
2685	goto err;
2686    bzero((char *) conv->state, sizeof(StateRec));
2687
2688    state = (State) conv->state;
2689    state->lcd = lcd;
2690
2691    _XlcResetConverter(conv);
2692
2693    return conv;
2694
2695err:
2696    close_converter(conv);
2697
2698    return (XlcConv) NULL;
2699}
2700
2701static XlcConvMethodsRec mbstocts_methods = {
2702    close_converter,
2703    mbstocts,
2704    NULL
2705};
2706
2707static XlcConv
2708open_mbstocts(
2709    XLCd from_lcd,
2710    const char *from_type,
2711    XLCd to_lcd,
2712    const char *to_type)
2713{
2714    return create_conv(from_lcd, &mbstocts_methods);
2715}
2716
2717static XlcConvMethodsRec mbstostr_methods = {
2718    close_converter,
2719    mbstostr,
2720    NULL
2721};
2722
2723static XlcConv
2724open_mbstostr(
2725    XLCd from_lcd,
2726    const char *from_type,
2727    XLCd to_lcd,
2728    const char *to_type)
2729{
2730    return create_conv(from_lcd, &mbstostr_methods);
2731}
2732
2733static XlcConvMethodsRec mbstocs_methods = {
2734    close_converter,
2735    mbstocs,
2736    NULL
2737};
2738
2739static XlcConv
2740open_mbstocs(
2741    XLCd from_lcd,
2742    const char *from_type,
2743    XLCd to_lcd,
2744    const char *to_type)
2745{
2746    return create_conv(from_lcd, &mbstocs_methods);
2747}
2748
2749static XlcConvMethodsRec mbtocs_methods = {
2750    close_converter,
2751    mbtocs,
2752    NULL
2753};
2754
2755static XlcConv
2756open_mbtocs(
2757    XLCd from_lcd,
2758    const char *from_type,
2759    XLCd to_lcd,
2760    const char *to_type)
2761{
2762    return create_conv(from_lcd, &mbtocs_methods);
2763}
2764
2765static XlcConvMethodsRec ctstombs_methods = {
2766    close_converter,
2767    ctstombs,
2768    NULL
2769};
2770
2771static XlcConv
2772open_ctstombs(
2773    XLCd from_lcd,
2774    const char *from_type,
2775    XLCd to_lcd,
2776    const char *to_type)
2777{
2778    return create_conv(from_lcd, &ctstombs_methods);
2779}
2780
2781static XlcConvMethodsRec cstombs_methods = {
2782    close_converter,
2783    cstombs,
2784    NULL
2785};
2786
2787static XlcConv
2788open_cstombs(
2789    XLCd from_lcd,
2790    const char *from_type,
2791    XLCd to_lcd,
2792    const char *to_type)
2793{
2794    return create_conv(from_lcd, &cstombs_methods);
2795}
2796
2797static XlcConvMethodsRec strtombs_methods = {
2798    close_converter,
2799    strtombs,
2800    NULL
2801};
2802
2803static XlcConv
2804open_strtombs(
2805    XLCd from_lcd,
2806    const char *from_type,
2807    XLCd to_lcd,
2808    const char *to_type)
2809{
2810    return create_conv(from_lcd, &strtombs_methods);
2811}
2812
2813#ifdef STDCVT
2814
2815static XlcConvMethodsRec stdc_mbstowcs_methods = {
2816    close_converter,
2817    stdc_mbstowcs,
2818    NULL
2819};
2820
2821static XlcConv
2822open_stdc_mbstowcs(
2823    XLCd from_lcd,
2824    const char *from_type,
2825    XLCd to_lcd,
2826    const char *to_type)
2827{
2828    return create_conv(from_lcd, &stdc_mbstowcs_methods);
2829}
2830
2831static XlcConvMethodsRec stdc_wcstombs_methods = {
2832    close_converter,
2833    stdc_wcstombs,
2834    NULL
2835};
2836
2837static XlcConv
2838open_stdc_wcstombs(
2839    XLCd from_lcd,
2840    const char *from_type,
2841    XLCd to_lcd,
2842    const char *to_type)
2843{
2844    return create_conv(from_lcd, &stdc_wcstombs_methods);
2845}
2846
2847static XlcConvMethodsRec stdc_wcstocts_methods = {
2848    close_converter,
2849    stdc_wcstocts,
2850    NULL
2851};
2852
2853static XlcConv
2854open_stdc_wcstocts(
2855    XLCd from_lcd,
2856    const char *from_type,
2857    XLCd to_lcd,
2858    const char *to_type)
2859{
2860    return create_conv(from_lcd, &stdc_wcstocts_methods);
2861}
2862
2863static XlcConvMethodsRec stdc_wcstostr_methods = {
2864    close_converter,
2865    stdc_wcstostr,
2866    NULL
2867};
2868
2869static XlcConv
2870open_stdc_wcstostr(
2871    XLCd from_lcd,
2872    const char *from_type,
2873    XLCd to_lcd,
2874    const char *to_type)
2875{
2876    return create_conv(from_lcd, &stdc_wcstostr_methods);
2877}
2878
2879static XlcConvMethodsRec stdc_wcstocs_methods = {
2880    close_converter,
2881    stdc_wcstocs,
2882    NULL
2883};
2884
2885static XlcConv
2886open_stdc_wcstocs(
2887    XLCd from_lcd,
2888    const char *from_type,
2889    XLCd to_lcd,
2890    const char *to_type)
2891{
2892    return create_conv(from_lcd, &stdc_wcstocs_methods);
2893}
2894
2895static XlcConvMethodsRec stdc_wctocs_methods = {
2896    close_converter,
2897    stdc_wctocs,
2898    NULL
2899};
2900
2901static XlcConv
2902open_stdc_wctocs(
2903    XLCd from_lcd,
2904    const char *from_type,
2905    XLCd to_lcd,
2906    const char *to_type)
2907{
2908    return create_conv(from_lcd, &stdc_wctocs_methods);
2909}
2910
2911static XlcConvMethodsRec stdc_ctstowcs_methods = {
2912    close_converter,
2913    stdc_ctstowcs,
2914    NULL
2915};
2916
2917static XlcConv
2918open_stdc_ctstowcs(
2919    XLCd from_lcd,
2920    const char *from_type,
2921    XLCd to_lcd,
2922    const char *to_type)
2923{
2924    return create_conv(from_lcd, &stdc_ctstowcs_methods);
2925}
2926
2927static XlcConvMethodsRec stdc_cstowcs_methods = {
2928    close_converter,
2929    stdc_cstowcs,
2930    NULL
2931};
2932
2933static XlcConv
2934open_stdc_cstowcs(
2935    XLCd from_lcd,
2936    const char *from_type,
2937    XLCd to_lcd,
2938    const char *to_type)
2939{
2940    return create_conv(from_lcd, &stdc_cstowcs_methods);
2941}
2942
2943static XlcConvMethodsRec stdc_strtowcs_methods = {
2944    close_converter,
2945    stdc_strtowcs,
2946    NULL
2947};
2948
2949static XlcConv
2950open_stdc_strtowcs(
2951    XLCd from_lcd,
2952    const char *from_type,
2953    XLCd to_lcd,
2954    const char *to_type)
2955{
2956    return create_conv(from_lcd, &stdc_strtowcs_methods);
2957}
2958
2959#endif /* STDCVT */
2960
2961static XlcConvMethodsRec mbstowcs_methods = {
2962    close_converter,
2963    mbstowcs_org,
2964    NULL
2965};
2966
2967static XlcConv
2968open_mbstowcs(
2969    XLCd from_lcd,
2970    const char *from_type,
2971    XLCd to_lcd,
2972    const char *to_type)
2973{
2974    return create_conv(from_lcd, &mbstowcs_methods);
2975}
2976
2977static XlcConvMethodsRec wcstombs_methods = {
2978    close_converter,
2979    wcstombs_org,
2980    NULL
2981};
2982
2983static XlcConv
2984open_wcstombs(
2985    XLCd from_lcd,
2986    const char *from_type,
2987    XLCd to_lcd,
2988    const char *to_type)
2989{
2990    return create_conv(from_lcd, &wcstombs_methods);
2991}
2992
2993static XlcConvMethodsRec wcstocts_methods = {
2994    close_converter,
2995    wcstocts,
2996    NULL
2997};
2998
2999static XlcConv
3000open_wcstocts(
3001    XLCd from_lcd,
3002    const char *from_type,
3003    XLCd to_lcd,
3004    const char *to_type)
3005{
3006    return create_conv(from_lcd, &wcstocts_methods);
3007}
3008
3009static XlcConvMethodsRec wcstostr_methods = {
3010    close_converter,
3011    wcstostr,
3012    NULL
3013};
3014
3015static XlcConv
3016open_wcstostr(
3017    XLCd from_lcd,
3018    const char *from_type,
3019    XLCd to_lcd,
3020    const char *to_type)
3021{
3022    return create_conv(from_lcd, &wcstostr_methods);
3023}
3024
3025static XlcConvMethodsRec wcstocs_methods = {
3026    close_converter,
3027    wcstocs,
3028    NULL
3029};
3030
3031static XlcConv
3032open_wcstocs(
3033    XLCd from_lcd,
3034    const char *from_type,
3035    XLCd to_lcd,
3036    const char *to_type)
3037{
3038    return create_conv(from_lcd, &wcstocs_methods);
3039}
3040
3041static XlcConvMethodsRec wctocs_methods = {
3042    close_converter,
3043    wctocs,
3044    NULL
3045};
3046
3047static XlcConv
3048open_wctocs(
3049    XLCd from_lcd,
3050    const char *from_type,
3051    XLCd to_lcd,
3052    const char *to_type)
3053{
3054    return create_conv(from_lcd, &wctocs_methods);
3055}
3056
3057static XlcConvMethodsRec ctstowcs_methods = {
3058    close_converter,
3059    ctstowcs,
3060    NULL
3061};
3062
3063static XlcConv
3064open_ctstowcs(
3065    XLCd from_lcd,
3066    const char *from_type,
3067    XLCd to_lcd,
3068    const char *to_type)
3069{
3070    return create_conv(from_lcd, &ctstowcs_methods);
3071}
3072
3073static XlcConvMethodsRec cstowcs_methods = {
3074    close_converter,
3075    cstowcs,
3076    NULL
3077};
3078
3079static XlcConv
3080open_cstowcs(
3081    XLCd from_lcd,
3082    const char *from_type,
3083    XLCd to_lcd,
3084    const char *to_type)
3085{
3086    return create_conv(from_lcd, &cstowcs_methods);
3087}
3088
3089static XlcConvMethodsRec strtowcs_methods = {
3090    close_converter,
3091    strtowcs,
3092    NULL
3093};
3094
3095static XlcConv
3096open_strtowcs(
3097    XLCd from_lcd,
3098    const char *from_type,
3099    XLCd to_lcd,
3100    const char *to_type)
3101{
3102    return create_conv(from_lcd, &strtowcs_methods);
3103}
3104
3105/* -------------------------------------------------------------------------- */
3106/*				Loader                                        */
3107/* -------------------------------------------------------------------------- */
3108
3109XLCd
3110_XlcGenericLoader(
3111    const char *name)
3112{
3113    XLCd lcd;
3114#ifdef STDCVT
3115    XLCdGenericPart *gen;
3116#endif
3117
3118    lcd = _XlcCreateLC(name, _XlcGenericMethods);
3119
3120    if (lcd == NULL)
3121	return lcd;
3122
3123    default_GL_charset = _XlcGetCharSet("ISO8859-1:GL");
3124    default_GR_charset = _XlcGetCharSet("ISO8859-1:GR");
3125
3126    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts);
3127    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString,       open_mbstostr);
3128    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet,      open_mbstocs);
3129    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar,         open_mbtocs);
3130    _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs);
3131    _XlcSetConverter(lcd, XlcNString,    lcd, XlcNMultiByte,    open_strtombs);
3132    _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNMultiByte,    open_cstombs);
3133
3134#ifdef STDCVT
3135     gen = XLC_GENERIC_PART(lcd);
3136
3137     if (gen->use_stdc_env != True) {
3138#endif
3139        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_mbstowcs);
3140        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_wcstombs);
3141        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_wcstocts);
3142        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_wcstostr);
3143        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_wcstocs);
3144        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_wctocs);
3145        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_ctstowcs);
3146        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_strtowcs);
3147        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_cstowcs);
3148#ifdef STDCVT
3149    }
3150#endif
3151
3152#ifdef STDCVT
3153    if (gen->use_stdc_env == True) {
3154        _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar,     open_stdc_mbstowcs);
3155        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNMultiByte,    open_stdc_wcstombs);
3156        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCompoundText, open_stdc_wcstocts);
3157        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNString,       open_stdc_wcstostr);
3158        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNCharSet,      open_stdc_wcstocs);
3159        _XlcSetConverter(lcd, XlcNWideChar,  lcd, XlcNChar,         open_stdc_wctocs);
3160        _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar,  open_stdc_ctstowcs);
3161        _XlcSetConverter(lcd, XlcNString,    lcd, XlcNWideChar,     open_stdc_strtowcs);
3162        _XlcSetConverter(lcd, XlcNCharSet,   lcd, XlcNWideChar,     open_stdc_cstowcs);
3163    }
3164#endif
3165
3166    _XlcAddUtf8Converters(lcd);
3167
3168    return lcd;
3169}
3170