~sbeattie/ubuntu/lucid/vnc4/lp556147

« back to all changes in this revision

Viewing changes to unix/xc/lib/X11/lcUTF8.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $TOG:  $ */
 
2
/******************************************************************
 
3
 
 
4
              Copyright 1993 by SunSoft, Inc.
 
5
              Copyright 1999-2000 by Bruno Haible
 
6
 
 
7
Permission to use, copy, modify, distribute, and sell this software
 
8
and its documentation for any purpose is hereby granted without fee,
 
9
provided that the above copyright notice appear in all copies and
 
10
that both that copyright notice and this permission notice appear
 
11
in supporting documentation, and that the names of SunSoft, Inc. and
 
12
Bruno Haible not be used in advertising or publicity pertaining to
 
13
distribution of the software without specific, written prior
 
14
permission.  SunSoft, Inc. and Bruno Haible make no representations
 
15
about the suitability of this software for any purpose.  It is
 
16
provided "as is" without express or implied warranty.
 
17
 
 
18
SunSoft Inc. AND Bruno Haible DISCLAIM ALL WARRANTIES WITH REGARD
 
19
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 
20
AND FITNESS, IN NO EVENT SHALL SunSoft, Inc. OR Bruno Haible BE LIABLE
 
21
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
22
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
23
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 
24
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
25
 
 
26
******************************************************************/
 
27
/* $XFree86: xc/lib/X11/lcUTF8.c,v 1.15 2002/10/08 23:31:36 dawes Exp $ */
 
28
 
 
29
/*
 
30
 * This file contains:
 
31
 *
 
32
 * I. Conversion routines CompoundText/CharSet <--> Unicode/UTF-8.
 
33
 *
 
34
 *    Used for three purposes:
 
35
 *      1. The UTF-8 locales, see below.
 
36
 *      2. Unicode aware applications for which the use of 8-bit character
 
37
 *         sets is an anachronism.
 
38
 *      3. For conversion from keysym to locale encoding.
 
39
 *
 
40
 * II. Conversion files for an UTF-8 locale loader.
 
41
 *     Supports: all locales with codeset UTF-8.
 
42
 *     How: Provides converters for UTF-8.
 
43
 *     Platforms: all systems.
 
44
 *
 
45
 * The loader itself is located in lcUTF8.c.
 
46
 */
 
47
 
 
48
/*
 
49
 * The conversion from UTF-8 to CompoundText is realized in a very
 
50
 * conservative way. Recall that CompoundText data is used for inter-client
 
51
 * communication purposes. We distinguish three classes of clients:
 
52
 * - Clients which accept only those pieces of CompoundText which belong to
 
53
 *   the character set understood by the current locale.
 
54
 *   (Example: clients which are linked to an older X11 library.)
 
55
 * - Clients which accept CompoundText with multiple character sets and parse
 
56
 *   it themselves.
 
57
 *   (Example: emacs, xemacs.)
 
58
 * - Clients which rely entirely on the X{mb,wc}TextPropertyToTextList
 
59
 *   functions for the conversion of CompoundText to their current locale's
 
60
 *   multi-byte/wide-character format.
 
61
 * For best interoperation, the UTF-8 to CompoundText conversion proceeds as
 
62
 * follows. For every character, it first tests whether the character is
 
63
 * representable in the current locale's original (non-UTF-8) character set.
 
64
 * If not, it goes through the list of predefined character sets for
 
65
 * CompoundText and tests if the character is representable in that character
 
66
 * set. If so, it encodes the character using its code within that character
 
67
 * set. If not, it uses an UTF-8-in-CompoundText encapsulation. Since
 
68
 * clients of the first and second kind ignore such encapsulated text,
 
69
 * this encapsulation is kept to a minimum and terminated as early as possible.
 
70
 *
 
71
 * In a distant future, when clients of the first and second kind will have
 
72
 * disappeared, we will be able to stuff UTF-8 data directly in CompoundText
 
73
 * without first going through the list of predefined character sets.
 
74
 */
 
75
 
 
76
#include <stdio.h>
 
77
#include "Xlibint.h"
 
78
#include "XlcPubI.h"
 
79
#include "XlcGeneric.h"
 
80
 
 
81
static XlcConv
 
82
create_conv(
 
83
    XLCd lcd,
 
84
    XlcConvMethods methods)
 
85
{
 
86
    XlcConv conv;
 
87
 
 
88
    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
 
89
    if (conv == (XlcConv) NULL)
 
90
        return (XlcConv) NULL;
 
91
 
 
92
    conv->methods = methods;
 
93
    conv->state = NULL;
 
94
 
 
95
    return conv;
 
96
}
 
97
 
 
98
static void
 
99
close_converter(
 
100
    XlcConv conv)
 
101
{
 
102
    Xfree((char *) conv);
 
103
}
 
104
 
 
105
/* Replacement character for invalid multibyte sequence or wide character. */
 
106
#define BAD_WCHAR ((ucs4_t) 0xfffd)
 
107
#define BAD_CHAR '?'
 
108
 
 
109
/***************************************************************************/
 
110
/* Part I: Conversion routines CompoundText/CharSet <--> Unicode/UTF-8.
 
111
 *
 
112
 * Note that this code works in any locale. We store Unicode values in
 
113
 * `ucs4_t' variables, but don't pass them to the user.
 
114
 *
 
115
 * This code has to support all character sets that are used for CompoundText,
 
116
 * nothing more, nothing less. See the table in lcCT.c.
 
117
 * Since the conversion _to_ CompoundText is likely to need the tables for all
 
118
 * character sets at once, we don't use dynamic loading (of tables or shared
 
119
 * libraries through iconv()). Use a fixed set of tables instead.
 
120
 *
 
121
 * We use statically computed tables, not dynamically allocated arrays,
 
122
 * because it's more memory efficient: Different processes using the same
 
123
 * libX11 shared library share the "text" and read-only "data" sections.
 
124
 */
 
125
 
 
126
typedef unsigned int ucs4_t;
 
127
#define conv_t XlcConv
 
128
 
 
129
typedef struct _Utf8ConvRec {
 
130
    const char *name;
 
131
    XrmQuark xrm_name;
 
132
#if NeedFunctionPrototypes
 
133
    int (* cstowc) (XlcConv, ucs4_t *, unsigned char const *, int);
 
134
#else
 
135
    int (* cstowc) ();
 
136
#endif
 
137
#if NeedFunctionPrototypes
 
138
    int (* wctocs) (XlcConv, unsigned char *, ucs4_t, int);
 
139
#else
 
140
    int (* wctocs) ();
 
141
#endif
 
142
} Utf8ConvRec, *Utf8Conv;
 
143
 
 
144
/*
 
145
 * int xxx_cstowc (XlcConv conv, ucs4_t *pwc, unsigned char const *s, int n)
 
146
 * converts the byte sequence starting at s to a wide character. Up to n bytes
 
147
 * are available at s. n is >= 1.
 
148
 * Result is number of bytes consumed (if a wide character was read),
 
149
 * or 0 if invalid, or -1 if n too small.
 
150
 *
 
151
 * int xxx_wctocs (XlcConv conv, unsigned char *r, ucs4_t wc, int n)
 
152
 * converts the wide character wc to the character set xxx, and stores the
 
153
 * result beginning at r. Up to n bytes may be written at r. n is >= 1.
 
154
 * Result is number of bytes written, or 0 if invalid, or -1 if n too small.
 
155
 */
 
156
 
 
157
/* Return code if invalid. (xxx_mbtowc, xxx_wctomb) */
 
158
#define RET_ILSEQ      0
 
159
/* Return code if only a shift sequence of n bytes was read. (xxx_mbtowc) */
 
160
#define RET_TOOFEW(n)  (-1-(n))
 
161
/* Return code if output buffer is too small. (xxx_wctomb, xxx_reset) */
 
162
#define RET_TOOSMALL   -1
 
163
 
 
164
/*
 
165
 * The tables below are bijective. It would be possible to extend the
 
166
 * xxx_wctocs tables to do some transliteration (e.g. U+201C,U+201D -> 0x22)
 
167
 * but *only* with characters not contained in any other table, and *only*
 
168
 * when the current locale is not an UTF-8 locale.
 
169
 */
 
170
 
 
171
#include "lcUniConv/utf8.h"
 
172
#include "lcUniConv/ucs2be.h"
 
173
#ifdef notused
 
174
#include "lcUniConv/ascii.h"
 
175
#endif
 
176
#include "lcUniConv/iso8859_1.h"
 
177
#include "lcUniConv/iso8859_2.h"
 
178
#include "lcUniConv/iso8859_3.h"
 
179
#include "lcUniConv/iso8859_4.h"
 
180
#include "lcUniConv/iso8859_5.h"
 
181
#include "lcUniConv/iso8859_6.h"
 
182
#include "lcUniConv/iso8859_7.h"
 
183
#include "lcUniConv/iso8859_8.h"
 
184
#include "lcUniConv/iso8859_9.h"
 
185
#include "lcUniConv/iso8859_10.h"
 
186
#include "lcUniConv/iso8859_11.h"
 
187
#include "lcUniConv/iso8859_13.h"
 
188
#include "lcUniConv/iso8859_14.h"
 
189
#include "lcUniConv/iso8859_15.h"
 
190
#include "lcUniConv/iso8859_16.h"
 
191
#include "lcUniConv/iso8859_9e.h"
 
192
#include "lcUniConv/jisx0201.h"
 
193
#include "lcUniConv/tis620.h"
 
194
#include "lcUniConv/koi8_r.h"
 
195
#include "lcUniConv/koi8_u.h"
 
196
#include "lcUniConv/koi8_c.h"
 
197
#include "lcUniConv/armscii_8.h"
 
198
#include "lcUniConv/cp1133.h"
 
199
#include "lcUniConv/mulelao.h"
 
200
#include "lcUniConv/viscii.h"
 
201
#include "lcUniConv/tcvn.h"
 
202
#include "lcUniConv/georgian_academy.h"
 
203
#include "lcUniConv/georgian_ps.h"
 
204
#include "lcUniConv/cp1251.h"
 
205
#include "lcUniConv/cp1255.h"
 
206
#include "lcUniConv/cp1256.h"
 
207
#include "lcUniConv/tatar_cyr.h"
 
208
 
 
209
typedef struct {
 
210
    unsigned short indx; /* index into big table */
 
211
    unsigned short used; /* bitmask of used entries */
 
212
} Summary16;
 
213
 
 
214
#include "lcUniConv/gb2312.h"
 
215
#include "lcUniConv/jisx0208.h"
 
216
#include "lcUniConv/jisx0212.h"
 
217
#include "lcUniConv/ksc5601.h"
 
218
#include "lcUniConv/big5.h"
 
219
#include "lcUniConv/big5_emacs.h"
 
220
 
 
221
static Utf8ConvRec all_charsets[] = {
 
222
    /* The ISO10646-1/UTF-8 entry occurs twice, once at the beginning
 
223
       (for lookup speed), once at the end (as a fallback).  */
 
224
    { "ISO10646-1", NULLQUARK,
 
225
        utf8_mbtowc, utf8_wctomb
 
226
    },
 
227
 
 
228
    { "ISO8859-1", NULLQUARK,
 
229
        iso8859_1_mbtowc, iso8859_1_wctomb
 
230
    },
 
231
    { "ISO8859-2", NULLQUARK,
 
232
        iso8859_2_mbtowc, iso8859_2_wctomb
 
233
    },
 
234
    { "ISO8859-3", NULLQUARK,
 
235
        iso8859_3_mbtowc, iso8859_3_wctomb
 
236
    },
 
237
    { "ISO8859-4", NULLQUARK,
 
238
        iso8859_4_mbtowc, iso8859_4_wctomb
 
239
    },
 
240
    { "ISO8859-5", NULLQUARK,
 
241
        iso8859_5_mbtowc, iso8859_5_wctomb
 
242
    },
 
243
    { "ISO8859-6", NULLQUARK,
 
244
        iso8859_6_mbtowc, iso8859_6_wctomb
 
245
    },
 
246
    { "ISO8859-7", NULLQUARK,
 
247
        iso8859_7_mbtowc, iso8859_7_wctomb
 
248
    },
 
249
    { "ISO8859-8", NULLQUARK,
 
250
        iso8859_8_mbtowc, iso8859_8_wctomb
 
251
    },
 
252
    { "ISO8859-9", NULLQUARK,
 
253
        iso8859_9_mbtowc, iso8859_9_wctomb
 
254
    },
 
255
    { "ISO8859-10", NULLQUARK,
 
256
        iso8859_10_mbtowc, iso8859_10_wctomb
 
257
    },
 
258
    { "ISO8859-11", NULLQUARK,
 
259
        iso8859_11_mbtowc, iso8859_11_wctomb
 
260
    },
 
261
    { "ISO8859-13", NULLQUARK,
 
262
        iso8859_13_mbtowc, iso8859_13_wctomb
 
263
    },
 
264
    { "ISO8859-14", NULLQUARK,
 
265
        iso8859_14_mbtowc, iso8859_14_wctomb
 
266
    },
 
267
    { "ISO8859-15", NULLQUARK,
 
268
        iso8859_15_mbtowc, iso8859_15_wctomb
 
269
    },
 
270
    { "ISO8859-16", NULLQUARK,
 
271
        iso8859_16_mbtowc, iso8859_16_wctomb
 
272
    },
 
273
    { "JISX0201.1976-0", NULLQUARK,
 
274
        jisx0201_mbtowc, jisx0201_wctomb
 
275
    },
 
276
    { "TIS620-0", NULLQUARK,
 
277
        tis620_mbtowc, tis620_wctomb
 
278
    },
 
279
    { "GB2312.1980-0", NULLQUARK,
 
280
        gb2312_mbtowc, gb2312_wctomb
 
281
    },
 
282
    { "JISX0208.1983-0", NULLQUARK,
 
283
        jisx0208_mbtowc, jisx0208_wctomb
 
284
    },
 
285
    { "JISX0208.1990-0", NULLQUARK,
 
286
        jisx0208_mbtowc, jisx0208_wctomb
 
287
    },
 
288
    { "JISX0212.1990-0", NULLQUARK,
 
289
        jisx0212_mbtowc, jisx0212_wctomb
 
290
    },
 
291
    { "KSC5601.1987-0", NULLQUARK,
 
292
        ksc5601_mbtowc, ksc5601_wctomb
 
293
    },
 
294
    { "KOI8-R", NULLQUARK,
 
295
        koi8_r_mbtowc, koi8_r_wctomb
 
296
    },
 
297
    { "KOI8-U", NULLQUARK,
 
298
        koi8_u_mbtowc, koi8_u_wctomb
 
299
    },
 
300
    { "KOI8-C", NULLQUARK,
 
301
        koi8_c_mbtowc, koi8_c_wctomb
 
302
    },
 
303
    { "TATAR-CYR", NULLQUARK,
 
304
        tatar_cyr_mbtowc, tatar_cyr_wctomb
 
305
    },
 
306
    { "ARMSCII-8", NULLQUARK,
 
307
        armscii_8_mbtowc, armscii_8_wctomb
 
308
    },
 
309
    { "IBM-CP1133", NULLQUARK,
 
310
        cp1133_mbtowc, cp1133_wctomb
 
311
    },
 
312
    { "MULELAO-1", NULLQUARK,
 
313
        mulelao_mbtowc, mulelao_wctomb
 
314
    },
 
315
    { "VISCII1.1-1", NULLQUARK,
 
316
        viscii_mbtowc, viscii_wctomb
 
317
    },
 
318
    { "TCVN-5712", NULLQUARK,
 
319
        tcvn_mbtowc, tcvn_wctomb
 
320
    },
 
321
    { "GEORGIAN-ACADEMY", NULLQUARK,
 
322
        georgian_academy_mbtowc, georgian_academy_wctomb
 
323
    },
 
324
    { "GEORGIAN-PS", NULLQUARK,
 
325
        georgian_ps_mbtowc, georgian_ps_wctomb
 
326
    },
 
327
    { "ISO8859-9E", NULLQUARK,
 
328
        iso8859_9e_mbtowc, iso8859_9e_wctomb
 
329
    },
 
330
    { "MICROSOFT-CP1251", NULLQUARK,
 
331
        cp1251_mbtowc, cp1251_wctomb
 
332
    },
 
333
    { "MICROSOFT-CP1255", NULLQUARK,
 
334
        cp1255_mbtowc, cp1255_wctomb
 
335
    },
 
336
    { "MICROSOFT-CP1256", NULLQUARK,
 
337
        cp1256_mbtowc, cp1256_wctomb
 
338
    },
 
339
    { "BIG5-0", NULLQUARK,
 
340
    big5_mbtowc, big5_wctomb
 
341
        },
 
342
    { "BIG5-E0", NULLQUARK,
 
343
        big5_0_mbtowc, big5_0_wctomb
 
344
    },
 
345
    { "BIG5-E1", NULLQUARK,
 
346
        big5_1_mbtowc, big5_1_wctomb
 
347
    },
 
348
 
 
349
    /* The ISO10646-1/UTF-8 entry occurs twice, once at the beginning
 
350
       (for lookup speed), once at the end (as a fallback).  */
 
351
    { "ISO10646-1", NULLQUARK,
 
352
        utf8_mbtowc, utf8_wctomb
 
353
    },
 
354
 
 
355
    /* Encoding ISO10646-1 for fonts means UCS2-like encoding
 
356
       so for conversion to FontCharSet we need this record */
 
357
    { "ISO10646-1", NULLQUARK,
 
358
        ucs2be_mbtowc, ucs2be_wctomb
 
359
    }
 
360
};
 
361
 
 
362
#define charsets_table_size (sizeof(all_charsets)/sizeof(all_charsets[0]))
 
363
#define all_charsets_count  (charsets_table_size - 1)
 
364
#define ucs2_conv_index     (charsets_table_size - 1)
 
365
 
 
366
static void
 
367
init_all_charsets (void)
 
368
{
 
369
    Utf8Conv convptr;
 
370
    int i;
 
371
 
 
372
    for (convptr = all_charsets, i = charsets_table_size; i > 0; convptr++, i--)
 
373
        convptr->xrm_name = XrmStringToQuark(convptr->name);
 
374
}
 
375
 
 
376
#define lazy_init_all_charsets()                                        \
 
377
    do {                                                                \
 
378
        if (all_charsets[0].xrm_name == NULLQUARK)                      \
 
379
            init_all_charsets();                                        \
 
380
    } while (0)
 
381
 
 
382
/* from XlcNCharSet to XlcNUtf8String */
 
383
 
 
384
static int
 
385
cstoutf8(
 
386
    XlcConv conv,
 
387
    XPointer *from,
 
388
    int *from_left,
 
389
    XPointer *to,
 
390
    int *to_left,
 
391
    XPointer *args,
 
392
    int num_args)
 
393
{
 
394
    XlcCharSet charset;
 
395
    const char *name;
 
396
    Utf8Conv convptr;
 
397
    int i;
 
398
    unsigned char const *src;
 
399
    unsigned char const *srcend;
 
400
    unsigned char *dst;
 
401
    unsigned char *dstend;
 
402
    int unconv_num;
 
403
 
 
404
    if (from == NULL || *from == NULL)
 
405
        return 0;
 
406
 
 
407
    if (num_args < 1)
 
408
        return -1;
 
409
 
 
410
    charset = (XlcCharSet) args[0];
 
411
    name = charset->encoding_name;
 
412
    /* not charset->name because the latter has a ":GL"/":GR" suffix */
 
413
 
 
414
    for (convptr = all_charsets, i = all_charsets_count-1; i > 0; convptr++, i--)
 
415
        if (!strcmp(convptr->name, name))
 
416
            break;
 
417
    if (i == 0)
 
418
        return -1;
 
419
 
 
420
    src = (unsigned char const *) *from;
 
421
    srcend = src + *from_left;
 
422
    dst = (unsigned char *) *to;
 
423
    dstend = dst + *to_left;
 
424
    unconv_num = 0;
 
425
 
 
426
    while (src < srcend) {
 
427
        ucs4_t wc;
 
428
        int consumed;
 
429
        int count;
 
430
 
 
431
        consumed = convptr->cstowc(conv, &wc, src, srcend-src);
 
432
        if (consumed == RET_ILSEQ)
 
433
            return -1;
 
434
        if (consumed == RET_TOOFEW(0))
 
435
            break;
 
436
 
 
437
        count = utf8_wctomb(NULL, dst, wc, dstend-dst);
 
438
        if (count == RET_TOOSMALL)
 
439
            break;
 
440
        if (count == RET_ILSEQ) {
 
441
            count = utf8_wctomb(NULL, dst, BAD_WCHAR, dstend-dst);
 
442
            if (count == RET_TOOSMALL)
 
443
                break;
 
444
            unconv_num++;
 
445
        }
 
446
        src += consumed;
 
447
        dst += count;
 
448
    }
 
449
 
 
450
    *from = (XPointer) src;
 
451
    *from_left = srcend - src;
 
452
    *to = (XPointer) dst;
 
453
    *to_left = dstend - dst;
 
454
 
 
455
    return unconv_num;
 
456
}
 
457
 
 
458
static XlcConvMethodsRec methods_cstoutf8 = {
 
459
    close_converter,
 
460
    cstoutf8,
 
461
    NULL
 
462
};
 
463
 
 
464
static XlcConv
 
465
open_cstoutf8(
 
466
    XLCd from_lcd,
 
467
    const char *from_type,
 
468
    XLCd to_lcd,
 
469
    const char *to_type)
 
470
{
 
471
    lazy_init_all_charsets();
 
472
    return create_conv(from_lcd, &methods_cstoutf8);
 
473
}
 
474
 
 
475
/* from XlcNUtf8String to XlcNCharSet */
 
476
 
 
477
static XlcConv
 
478
create_tocs_conv(
 
479
    XLCd lcd,
 
480
    XlcConvMethods methods)
 
481
{
 
482
    XlcConv conv;
 
483
    CodeSet *codeset_list;
 
484
    int codeset_num;
 
485
    int charset_num;
 
486
    int i, j, k;
 
487
    Utf8Conv *preferred;
 
488
 
 
489
    lazy_init_all_charsets();
 
490
 
 
491
    codeset_list = XLC_GENERIC(lcd, codeset_list);
 
492
    codeset_num = XLC_GENERIC(lcd, codeset_num);
 
493
 
 
494
    charset_num = 0;
 
495
    for (i = 0; i < codeset_num; i++)
 
496
        charset_num += codeset_list[i]->num_charsets;
 
497
    if (charset_num > all_charsets_count-1)
 
498
        charset_num = all_charsets_count-1;
 
499
 
 
500
    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec)
 
501
                             + (charset_num + 1) * sizeof(Utf8Conv));
 
502
    if (conv == (XlcConv) NULL)
 
503
        return (XlcConv) NULL;
 
504
    preferred = (Utf8Conv *) ((char *) conv + sizeof(XlcConvRec));
 
505
 
 
506
    /* Loop through all codesets mentioned in the locale. */
 
507
    charset_num = 0;
 
508
    for (i = 0; i < codeset_num; i++) {
 
509
        XlcCharSet *charsets = codeset_list[i]->charset_list;
 
510
        int num_charsets = codeset_list[i]->num_charsets;
 
511
        for (j = 0; j < num_charsets; j++) {
 
512
            const char *name = charsets[j]->encoding_name;
 
513
            /* If it wasn't already encountered... */
 
514
            for (k = charset_num-1; k >= 0; k--)
 
515
                if (!strcmp(preferred[k]->name, name))
 
516
                    break;
 
517
            if (k < 0) {
 
518
                /* Look it up in all_charsets[]. */
 
519
                for (k = 0; k < all_charsets_count-1; k++)
 
520
                    if (!strcmp(all_charsets[k].name, name)) {
 
521
                        /* Add it to the preferred set. */
 
522
                        preferred[charset_num++] = &all_charsets[k];
 
523
                        break;
 
524
                    }
 
525
            }
 
526
        }
 
527
    }
 
528
    preferred[charset_num] = (Utf8Conv) NULL;
 
529
 
 
530
    conv->methods = methods;
 
531
    conv->state = (XPointer) preferred;
 
532
 
 
533
    return conv;
 
534
}
 
535
 
 
536
static void
 
537
close_tocs_converter(
 
538
    XlcConv conv)
 
539
{
 
540
    /* conv->state is allocated together with conv, free both at once.  */
 
541
    Xfree((char *) conv);
 
542
}
 
543
 
 
544
/*
 
545
 * Converts a Unicode character to an appropriate character set. The NULL
 
546
 * terminated array of preferred character sets is passed as first argument.
 
547
 * If successful, *charsetp is set to the character set that was used, and
 
548
 * *sidep is set to the character set side (XlcGL or XlcGR).
 
549
 */
 
550
static int
 
551
charset_wctocs(
 
552
    Utf8Conv *preferred,
 
553
    Utf8Conv *charsetp,
 
554
    XlcSide *sidep,
 
555
    XlcConv conv,
 
556
    unsigned char *r,
 
557
    ucs4_t wc,
 
558
    int n)
 
559
{
 
560
    int count;
 
561
    Utf8Conv convptr;
 
562
    int i;
 
563
 
 
564
    for (; *preferred != (Utf8Conv) NULL; preferred++) {
 
565
        convptr = *preferred;
 
566
        count = convptr->wctocs(conv, r, wc, n);
 
567
        if (count == RET_TOOSMALL)
 
568
            return RET_TOOSMALL;
 
569
        if (count != RET_ILSEQ) {
 
570
            *charsetp = convptr;
 
571
            *sidep = (*r < 0x80 ? XlcGL : XlcGR);
 
572
            return count;
 
573
        }
 
574
    }
 
575
    for (convptr = all_charsets+1, i = all_charsets_count-1; i > 0; convptr++, i--) {
 
576
        count = convptr->wctocs(conv, r, wc, n);
 
577
        if (count == RET_TOOSMALL)
 
578
            return RET_TOOSMALL;
 
579
        if (count != RET_ILSEQ) {
 
580
            *charsetp = convptr;
 
581
            *sidep = (*r < 0x80 ? XlcGL : XlcGR);
 
582
            return count;
 
583
        }
 
584
    }
 
585
    return RET_ILSEQ;
 
586
}
 
587
 
 
588
static int
 
589
utf8tocs(
 
590
    XlcConv conv,
 
591
    XPointer *from,
 
592
    int *from_left,
 
593
    XPointer *to,
 
594
    int *to_left,
 
595
    XPointer *args,
 
596
    int num_args)
 
597
{
 
598
    Utf8Conv *preferred_charsets;
 
599
    XlcCharSet last_charset = NULL;
 
600
    unsigned char const *src;
 
601
    unsigned char const *srcend;
 
602
    unsigned char *dst;
 
603
    unsigned char *dstend;
 
604
    int unconv_num;
 
605
 
 
606
    if (from == NULL || *from == NULL)
 
607
        return 0;
 
608
 
 
609
    preferred_charsets = (Utf8Conv *) conv->state;
 
610
    src = (unsigned char const *) *from;
 
611
    srcend = src + *from_left;
 
612
    dst = (unsigned char *) *to;
 
613
    dstend = dst + *to_left;
 
614
    unconv_num = 0;
 
615
 
 
616
    while (src < srcend && dst < dstend) {
 
617
        Utf8Conv chosen_charset = NULL;
 
618
        XlcSide chosen_side = XlcNONE;
 
619
        ucs4_t wc;
 
620
        int consumed;
 
621
        int count;
 
622
 
 
623
        consumed = utf8_mbtowc(NULL, &wc, src, srcend-src);
 
624
        if (consumed == RET_TOOFEW(0))
 
625
            break;
 
626
        if (consumed == RET_ILSEQ) {
 
627
            src++;
 
628
            unconv_num++;
 
629
            continue;
 
630
        }
 
631
 
 
632
        count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst);
 
633
        if (count == RET_TOOSMALL)
 
634
            break;
 
635
        if (count == RET_ILSEQ) {
 
636
            src += consumed;
 
637
            unconv_num++;
 
638
            continue;
 
639
        }
 
640
 
 
641
        if (last_charset == NULL) {
 
642
            last_charset =
 
643
                _XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
 
644
            if (last_charset == NULL) {
 
645
                src += consumed;
 
646
                unconv_num++;
 
647
                continue;
 
648
            }
 
649
        } else {
 
650
            if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name
 
651
                  && (last_charset->side == XlcGLGR
 
652
                      || last_charset->side == chosen_side)))
 
653
                break;
 
654
        }
 
655
        src += consumed;
 
656
        dst += count;
 
657
    }
 
658
 
 
659
    if (last_charset == NULL)
 
660
        return -1;
 
661
 
 
662
    *from = (XPointer) src;
 
663
    *from_left = srcend - src;
 
664
    *to = (XPointer) dst;
 
665
    *to_left = dstend - dst;
 
666
 
 
667
    if (num_args >= 1)
 
668
        *((XlcCharSet *)args[0]) = last_charset;
 
669
 
 
670
    return unconv_num;
 
671
}
 
672
 
 
673
static XlcConvMethodsRec methods_utf8tocs = {
 
674
    close_tocs_converter,
 
675
    utf8tocs,
 
676
    NULL
 
677
};
 
678
 
 
679
static XlcConv
 
680
open_utf8tocs(
 
681
    XLCd from_lcd,
 
682
    const char *from_type,
 
683
    XLCd to_lcd,
 
684
    const char *to_type)
 
685
{
 
686
    return create_tocs_conv(from_lcd, &methods_utf8tocs);
 
687
}
 
688
 
 
689
/* from XlcNUtf8String to XlcNChar */
 
690
 
 
691
static int
 
692
utf8tocs1(
 
693
    XlcConv conv,
 
694
    XPointer *from,
 
695
    int *from_left,
 
696
    XPointer *to,
 
697
    int *to_left,
 
698
    XPointer *args,
 
699
    int num_args)
 
700
{
 
701
    Utf8Conv *preferred_charsets;
 
702
    XlcCharSet last_charset = NULL;
 
703
    unsigned char const *src;
 
704
    unsigned char const *srcend;
 
705
    unsigned char *dst;
 
706
    unsigned char *dstend;
 
707
    int unconv_num;
 
708
 
 
709
    if (from == NULL || *from == NULL)
 
710
        return 0;
 
711
 
 
712
    preferred_charsets = (Utf8Conv *) conv->state;
 
713
    src = (unsigned char const *) *from;
 
714
    srcend = src + *from_left;
 
715
    dst = (unsigned char *) *to;
 
716
    dstend = dst + *to_left;
 
717
    unconv_num = 0;
 
718
 
 
719
    while (src < srcend && dst < dstend) {
 
720
        Utf8Conv chosen_charset = NULL;
 
721
        XlcSide chosen_side = XlcNONE;
 
722
        ucs4_t wc;
 
723
        int consumed;
 
724
        int count;
 
725
 
 
726
        consumed = utf8_mbtowc(NULL, &wc, src, srcend-src);
 
727
        if (consumed == RET_TOOFEW(0))
 
728
            break;
 
729
        if (consumed == RET_ILSEQ) {
 
730
            src++;
 
731
            unconv_num++;
 
732
            continue;
 
733
        }
 
734
 
 
735
        count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst);
 
736
        if (count == RET_TOOSMALL)
 
737
            break;
 
738
        if (count == RET_ILSEQ) {
 
739
            src += consumed;
 
740
            unconv_num++;
 
741
            continue;
 
742
        }
 
743
 
 
744
        if (last_charset == NULL) {
 
745
            last_charset =
 
746
                _XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
 
747
            if (last_charset == NULL) {
 
748
                src += consumed;
 
749
                unconv_num++;
 
750
                continue;
 
751
            }
 
752
        } else {
 
753
            if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name
 
754
                  && (last_charset->side == XlcGLGR
 
755
                      || last_charset->side == chosen_side)))
 
756
                break;
 
757
        }
 
758
        src += consumed;
 
759
        dst += count;
 
760
        break;
 
761
    }
 
762
 
 
763
    if (last_charset == NULL)
 
764
        return -1;
 
765
 
 
766
    *from = (XPointer) src;
 
767
    *from_left = srcend - src;
 
768
    *to = (XPointer) dst;
 
769
    *to_left = dstend - dst;
 
770
 
 
771
    if (num_args >= 1)
 
772
        *((XlcCharSet *)args[0]) = last_charset;
 
773
 
 
774
    return unconv_num;
 
775
}
 
776
 
 
777
static XlcConvMethodsRec methods_utf8tocs1 = {
 
778
    close_tocs_converter,
 
779
    utf8tocs1,
 
780
    NULL
 
781
};
 
782
 
 
783
static XlcConv
 
784
open_utf8tocs1(
 
785
    XLCd from_lcd,
 
786
    const char *from_type,
 
787
    XLCd to_lcd,
 
788
    const char *to_type)
 
789
{
 
790
    return create_tocs_conv(from_lcd, &methods_utf8tocs1);
 
791
}
 
792
 
 
793
/* from XlcNUtf8String to XlcNString */
 
794
 
 
795
static int
 
796
utf8tostr(
 
797
    XlcConv conv,
 
798
    XPointer *from,
 
799
    int *from_left,
 
800
    XPointer *to,
 
801
    int *to_left,
 
802
    XPointer *args,
 
803
    int num_args)
 
804
{
 
805
    unsigned char const *src;
 
806
    unsigned char const *srcend;
 
807
    unsigned char *dst;
 
808
    unsigned char *dstend;
 
809
    int unconv_num;
 
810
 
 
811
    if (from == NULL || *from == NULL)
 
812
        return 0;
 
813
 
 
814
    src = (unsigned char const *) *from;
 
815
    srcend = src + *from_left;
 
816
    dst = (unsigned char *) *to;
 
817
    dstend = dst + *to_left;
 
818
    unconv_num = 0;
 
819
 
 
820
    while (src < srcend) {
 
821
        unsigned char c;
 
822
        ucs4_t wc;
 
823
        int consumed;
 
824
 
 
825
        consumed = utf8_mbtowc(NULL, &wc, src, srcend-src);
 
826
        if (consumed == RET_TOOFEW(0))
 
827
            break;
 
828
        if (dst == dstend)
 
829
            break;
 
830
        if (consumed == RET_ILSEQ) {
 
831
            consumed = 1;
 
832
            c = BAD_CHAR;
 
833
            unconv_num++;
 
834
        } else {
 
835
            if ((wc & ~(ucs4_t)0xff) != 0) {
 
836
                c = BAD_CHAR;
 
837
                unconv_num++;
 
838
            } else
 
839
                c = (unsigned char) wc;
 
840
        }
 
841
        *dst++ = c;
 
842
        src += consumed;
 
843
    }
 
844
 
 
845
    *from = (XPointer) src;
 
846
    *from_left = srcend - src;
 
847
    *to = (XPointer) dst;
 
848
    *to_left = dstend - dst;
 
849
 
 
850
    return unconv_num;
 
851
}
 
852
 
 
853
static XlcConvMethodsRec methods_utf8tostr = {
 
854
    close_converter,
 
855
    utf8tostr,
 
856
    NULL
 
857
};
 
858
 
 
859
static XlcConv
 
860
open_utf8tostr(
 
861
    XLCd from_lcd,
 
862
    const char *from_type,
 
863
    XLCd to_lcd,
 
864
    const char *to_type)
 
865
{
 
866
    return create_conv(from_lcd, &methods_utf8tostr);
 
867
}
 
868
 
 
869
/* from XlcNString to XlcNUtf8String */
 
870
 
 
871
static int
 
872
strtoutf8(
 
873
    XlcConv conv,
 
874
    XPointer *from,
 
875
    int *from_left,
 
876
    XPointer *to,
 
877
    int *to_left,
 
878
    XPointer *args,
 
879
    int num_args)
 
880
{
 
881
    unsigned char const *src;
 
882
    unsigned char const *srcend;
 
883
    unsigned char *dst;
 
884
    unsigned char *dstend;
 
885
 
 
886
    if (from == NULL || *from == NULL)
 
887
        return 0;
 
888
 
 
889
    src = (unsigned char const *) *from;
 
890
    srcend = src + *from_left;
 
891
    dst = (unsigned char *) *to;
 
892
    dstend = dst + *to_left;
 
893
 
 
894
    while (src < srcend) {
 
895
        int count = utf8_wctomb(NULL, dst, *src, dstend-dst);
 
896
        if (count == RET_TOOSMALL)
 
897
            break;
 
898
        dst += count;
 
899
        src++;
 
900
    }
 
901
 
 
902
    *from = (XPointer) src;
 
903
    *from_left = srcend - src;
 
904
    *to = (XPointer) dst;
 
905
    *to_left = dstend - dst;
 
906
 
 
907
    return 0;
 
908
}
 
909
 
 
910
static XlcConvMethodsRec methods_strtoutf8 = {
 
911
    close_converter,
 
912
    strtoutf8,
 
913
    NULL
 
914
};
 
915
 
 
916
static XlcConv
 
917
open_strtoutf8(
 
918
    XLCd from_lcd,
 
919
    const char *from_type,
 
920
    XLCd to_lcd,
 
921
    const char *to_type)
 
922
{
 
923
    return create_conv(from_lcd, &methods_strtoutf8);
 
924
}
 
925
 
 
926
/* Support for the input methods. */
 
927
 
 
928
XPointer
 
929
_Utf8GetConvByName(
 
930
    const char *name)
 
931
{
 
932
    XrmQuark xrm_name;
 
933
    Utf8Conv convptr;
 
934
    int i;
 
935
 
 
936
    if (name == NULL)
 
937
        return (XPointer) NULL;
 
938
 
 
939
    lazy_init_all_charsets();
 
940
    xrm_name = XrmStringToQuark(name);
 
941
 
 
942
    for (convptr = all_charsets, i = all_charsets_count-1; i > 0; convptr++, i--)
 
943
        if (convptr->xrm_name == xrm_name)
 
944
            return (XPointer) convptr->wctocs;
 
945
    return (XPointer) NULL;
 
946
}
 
947
 
 
948
/* from XlcNUcsChar to XlcNChar, needed for input methods */
 
949
 
 
950
static XlcConv
 
951
create_ucstocs_conv(
 
952
    XLCd lcd,
 
953
    XlcConvMethods methods)
 
954
{
 
955
 
 
956
    if (XLC_PUBLIC_PART(lcd)->codeset
 
957
        && _XlcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "UTF-8") == 0) {
 
958
        XlcConv conv;
 
959
        Utf8Conv *preferred;
 
960
 
 
961
        lazy_init_all_charsets();
 
962
 
 
963
        conv = (XlcConv) Xmalloc(sizeof(XlcConvRec) + 2 * sizeof(Utf8Conv));
 
964
        if (conv == (XlcConv) NULL)
 
965
            return (XlcConv) NULL;
 
966
        preferred = (Utf8Conv *) ((char *) conv + sizeof(XlcConvRec));
 
967
 
 
968
        preferred[0] = &all_charsets[0]; /* ISO10646 */
 
969
        preferred[1] = (Utf8Conv) NULL;
 
970
 
 
971
        conv->methods = methods;
 
972
        conv->state = (XPointer) preferred;
 
973
 
 
974
        return conv;
 
975
    } else {
 
976
        return create_tocs_conv(lcd, methods);
 
977
    }
 
978
}
 
979
 
 
980
static int
 
981
charset_wctocs_exactly(
 
982
    Utf8Conv *preferred,
 
983
    Utf8Conv *charsetp,
 
984
    XlcSide *sidep,
 
985
    XlcConv conv,
 
986
    unsigned char *r,
 
987
    ucs4_t wc,
 
988
    int n)
 
989
{
 
990
    int count;
 
991
    Utf8Conv convptr;
 
992
 
 
993
    for (; *preferred != (Utf8Conv) NULL; preferred++) {
 
994
        convptr = *preferred;
 
995
        count = convptr->wctocs(conv, r, wc, n);
 
996
        if (count == RET_TOOSMALL)
 
997
            return RET_TOOSMALL;
 
998
        if (count != RET_ILSEQ) {
 
999
            *charsetp = convptr;
 
1000
            *sidep = (*r < 0x80 ? XlcGL : XlcGR);
 
1001
            return count;
 
1002
        }
 
1003
    }
 
1004
    return RET_ILSEQ;
 
1005
}
 
1006
 
 
1007
static int
 
1008
ucstocs1(
 
1009
    XlcConv conv,
 
1010
    XPointer *from,
 
1011
    int *from_left,
 
1012
    XPointer *to,
 
1013
    int *to_left,
 
1014
    XPointer *args,
 
1015
    int num_args)
 
1016
{
 
1017
    ucs4_t const *src = (ucs4_t const *) *from;
 
1018
    unsigned char *dst = (unsigned char *) *to;
 
1019
    int unconv_num = 0;
 
1020
    Utf8Conv *preferred_charsets = (Utf8Conv *) conv->state;
 
1021
    Utf8Conv chosen_charset = NULL;
 
1022
    XlcSide chosen_side = XlcNONE;
 
1023
    XlcCharSet charset = NULL;
 
1024
    int count;
 
1025
 
 
1026
    if (from == NULL || *from == NULL)
 
1027
        return 0;
 
1028
 
 
1029
    count = charset_wctocs_exactly(preferred_charsets, &chosen_charset,
 
1030
                                   &chosen_side, conv, dst, *src, *to_left);
 
1031
    if (count < 1) {
 
1032
        unconv_num++;
 
1033
        count = 0;
 
1034
    } else {
 
1035
        charset = _XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
 
1036
    }
 
1037
    if (charset == NULL)
 
1038
        return -1;
 
1039
 
 
1040
    *from = (XPointer) ++src;
 
1041
    (*from_left)--;
 
1042
    *to = (XPointer) dst;
 
1043
    *to_left -= count;
 
1044
 
 
1045
    if (num_args >= 1)
 
1046
        *((XlcCharSet *)args[0]) = charset;
 
1047
 
 
1048
    return unconv_num;
 
1049
}
 
1050
 
 
1051
static XlcConvMethodsRec methods_ucstocs1 = {
 
1052
    close_tocs_converter,
 
1053
    ucstocs1,
 
1054
    NULL
 
1055
};
 
1056
 
 
1057
static XlcConv
 
1058
open_ucstocs1(
 
1059
    XLCd from_lcd,
 
1060
    const char *from_type,
 
1061
    XLCd to_lcd,
 
1062
    const char *to_type)
 
1063
{
 
1064
    return create_ucstocs_conv(from_lcd, &methods_ucstocs1);
 
1065
}
 
1066
 
 
1067
/* from XlcNUcsChar to XlcNUtf8String, needed for input methods */
 
1068
 
 
1069
static int
 
1070
ucstoutf8(
 
1071
    XlcConv conv,
 
1072
    XPointer *from,
 
1073
    int *from_left,
 
1074
    XPointer *to,
 
1075
    int *to_left,
 
1076
    XPointer *args,
 
1077
    int num_args)
 
1078
{
 
1079
    const ucs4_t *src;
 
1080
    const ucs4_t *srcend;
 
1081
    unsigned char *dst;
 
1082
    unsigned char *dstend;
 
1083
    int unconv_num;
 
1084
 
 
1085
    if (from == NULL || *from == NULL)
 
1086
        return 0;
 
1087
 
 
1088
    src = (const ucs4_t *) *from;
 
1089
    srcend = src + *from_left;
 
1090
    dst = (unsigned char *) *to;
 
1091
    dstend = dst + *to_left;
 
1092
    unconv_num = 0;
 
1093
 
 
1094
    while (src < srcend) {
 
1095
        int count = utf8_wctomb(NULL, dst, *src, dstend-dst);
 
1096
        if (count == RET_TOOSMALL)
 
1097
            break;
 
1098
        if (count == RET_ILSEQ)
 
1099
            unconv_num++;
 
1100
        src++;
 
1101
        dst += count;
 
1102
    }
 
1103
 
 
1104
    *from = (XPointer) src;
 
1105
    *from_left = srcend - src;
 
1106
    *to = (XPointer) dst;
 
1107
    *to_left = dstend - dst;
 
1108
 
 
1109
    return unconv_num;
 
1110
}
 
1111
 
 
1112
static XlcConvMethodsRec methods_ucstoutf8 = {
 
1113
    close_converter,
 
1114
    ucstoutf8,
 
1115
    NULL
 
1116
};
 
1117
 
 
1118
static XlcConv
 
1119
open_ucstoutf8(
 
1120
    XLCd from_lcd,
 
1121
    const char *from_type,
 
1122
    XLCd to_lcd,
 
1123
    const char *to_type)
 
1124
{
 
1125
    return create_conv(from_lcd, &methods_ucstoutf8);
 
1126
}
 
1127
 
 
1128
/* Registers UTF-8 converters for a non-UTF-8 locale. */
 
1129
void
 
1130
_XlcAddUtf8Converters(
 
1131
    XLCd lcd)
 
1132
{
 
1133
    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String, open_cstoutf8);
 
1134
    _XlcSetConverter(lcd, XlcNUtf8String, lcd, XlcNCharSet, open_utf8tocs);
 
1135
    _XlcSetConverter(lcd, XlcNUtf8String, lcd, XlcNChar, open_utf8tocs1);
 
1136
    _XlcSetConverter(lcd, XlcNString, lcd, XlcNUtf8String, open_strtoutf8);
 
1137
    _XlcSetConverter(lcd, XlcNUtf8String, lcd, XlcNString, open_utf8tostr);
 
1138
    _XlcSetConverter(lcd, XlcNUcsChar,    lcd, XlcNChar, open_ucstocs1);
 
1139
    _XlcSetConverter(lcd, XlcNUcsChar,    lcd, XlcNUtf8String, open_ucstoutf8);
 
1140
}
 
1141
 
 
1142
/***************************************************************************/
 
1143
/* Part II: UTF-8 locale loader conversion files
 
1144
 *
 
1145
 * Here we can assume that "multi-byte" is UTF-8 and that `wchar_t' is Unicode.
 
1146
 */
 
1147
 
 
1148
/* from XlcNMultiByte to XlcNWideChar */
 
1149
 
 
1150
static int
 
1151
utf8towcs(
 
1152
    XlcConv conv,
 
1153
    XPointer *from,
 
1154
    int *from_left,
 
1155
    XPointer *to,
 
1156
    int *to_left,
 
1157
    XPointer *args,
 
1158
    int num_args)
 
1159
{
 
1160
    unsigned char const *src;
 
1161
    unsigned char const *srcend;
 
1162
    wchar_t *dst;
 
1163
    wchar_t *dstend;
 
1164
    int unconv_num;
 
1165
 
 
1166
    if (from == NULL || *from == NULL)
 
1167
        return 0;
 
1168
 
 
1169
    src = (unsigned char const *) *from;
 
1170
    srcend = src + *from_left;
 
1171
    dst = (wchar_t *) *to;
 
1172
    dstend = dst + *to_left;
 
1173
    unconv_num = 0;
 
1174
 
 
1175
    while (src < srcend && dst < dstend) {
 
1176
        ucs4_t wc;
 
1177
        int consumed = utf8_mbtowc(NULL, &wc, src, srcend-src);
 
1178
        if (consumed == RET_TOOFEW(0))
 
1179
            break;
 
1180
        if (consumed == RET_ILSEQ) {
 
1181
            src++;
 
1182
            *dst = BAD_WCHAR;
 
1183
            unconv_num++;
 
1184
        } else {
 
1185
            src += consumed;
 
1186
            *dst = wc;
 
1187
        }
 
1188
        dst++;
 
1189
    }
 
1190
 
 
1191
    *from = (XPointer) src;
 
1192
    *from_left = srcend - src;
 
1193
    *to = (XPointer) dst;
 
1194
    *to_left = dstend - dst;
 
1195
 
 
1196
    return unconv_num;
 
1197
}
 
1198
 
 
1199
static XlcConvMethodsRec methods_utf8towcs = {
 
1200
    close_converter,
 
1201
    utf8towcs,
 
1202
    NULL
 
1203
};
 
1204
 
 
1205
static XlcConv
 
1206
open_utf8towcs(
 
1207
    XLCd from_lcd,
 
1208
    const char *from_type,
 
1209
    XLCd to_lcd,
 
1210
    const char *to_type)
 
1211
{
 
1212
    return create_conv(from_lcd, &methods_utf8towcs);
 
1213
}
 
1214
 
 
1215
/* from XlcNWideChar to XlcNMultiByte */
 
1216
 
 
1217
static int
 
1218
wcstoutf8(
 
1219
    XlcConv conv,
 
1220
    XPointer *from,
 
1221
    int *from_left,
 
1222
    XPointer *to,
 
1223
    int *to_left,
 
1224
    XPointer *args,
 
1225
    int num_args)
 
1226
{
 
1227
    wchar_t const *src;
 
1228
    wchar_t const *srcend;
 
1229
    unsigned char *dst;
 
1230
    unsigned char *dstend;
 
1231
    int unconv_num;
 
1232
 
 
1233
    if (from == NULL || *from == NULL)
 
1234
        return 0;
 
1235
 
 
1236
    src = (wchar_t const *) *from;
 
1237
    srcend = src + *from_left;
 
1238
    dst = (unsigned char *) *to;
 
1239
    dstend = dst + *to_left;
 
1240
    unconv_num = 0;
 
1241
 
 
1242
    while (src < srcend) {
 
1243
        int count = utf8_wctomb(NULL, dst, *src, dstend-dst);
 
1244
        if (count == RET_TOOSMALL)
 
1245
            break;
 
1246
        if (count == RET_ILSEQ) {
 
1247
            count = utf8_wctomb(NULL, dst, BAD_WCHAR, dstend-dst);
 
1248
            if (count == RET_TOOSMALL)
 
1249
                break;
 
1250
            unconv_num++;
 
1251
        }
 
1252
        dst += count;
 
1253
        src++;
 
1254
    }
 
1255
 
 
1256
    *from = (XPointer) src;
 
1257
    *from_left = srcend - src;
 
1258
    *to = (XPointer) dst;
 
1259
    *to_left = dstend - dst;
 
1260
 
 
1261
    return unconv_num;
 
1262
}
 
1263
 
 
1264
static XlcConvMethodsRec methods_wcstoutf8 = {
 
1265
    close_converter,
 
1266
    wcstoutf8,
 
1267
    NULL
 
1268
};
 
1269
 
 
1270
static XlcConv
 
1271
open_wcstoutf8(
 
1272
    XLCd from_lcd,
 
1273
    const char *from_type,
 
1274
    XLCd to_lcd,
 
1275
    const char *to_type)
 
1276
{
 
1277
    return create_conv(from_lcd, &methods_wcstoutf8);
 
1278
}
 
1279
 
 
1280
/* from XlcNString to XlcNWideChar */
 
1281
 
 
1282
static int
 
1283
our_strtowcs(
 
1284
    XlcConv conv,
 
1285
    XPointer *from,
 
1286
    int *from_left,
 
1287
    XPointer *to,
 
1288
    int *to_left,
 
1289
    XPointer *args,
 
1290
    int num_args)
 
1291
{
 
1292
    unsigned char const *src;
 
1293
    unsigned char const *srcend;
 
1294
    wchar_t *dst;
 
1295
    wchar_t *dstend;
 
1296
 
 
1297
    if (from == NULL || *from == NULL)
 
1298
        return 0;
 
1299
 
 
1300
    src = (unsigned char const *) *from;
 
1301
    srcend = src + *from_left;
 
1302
    dst = (wchar_t *) *to;
 
1303
    dstend = dst + *to_left;
 
1304
 
 
1305
    while (src < srcend && dst < dstend)
 
1306
        *dst++ = (wchar_t) *src++;
 
1307
 
 
1308
    *from = (XPointer) src;
 
1309
    *from_left = srcend - src;
 
1310
    *to = (XPointer) dst;
 
1311
    *to_left = dstend - dst;
 
1312
 
 
1313
    return 0;
 
1314
}
 
1315
 
 
1316
static XlcConvMethodsRec methods_strtowcs = {
 
1317
    close_converter,
 
1318
    our_strtowcs,
 
1319
    NULL
 
1320
};
 
1321
 
 
1322
static XlcConv
 
1323
open_strtowcs(
 
1324
    XLCd from_lcd,
 
1325
    const char *from_type,
 
1326
    XLCd to_lcd,
 
1327
    const char *to_type)
 
1328
{
 
1329
    return create_conv(from_lcd, &methods_strtowcs);
 
1330
}
 
1331
 
 
1332
/* from XlcNWideChar to XlcNString */
 
1333
 
 
1334
static int
 
1335
our_wcstostr(
 
1336
    XlcConv conv,
 
1337
    XPointer *from,
 
1338
    int *from_left,
 
1339
    XPointer *to,
 
1340
    int *to_left,
 
1341
    XPointer *args,
 
1342
    int num_args)
 
1343
{
 
1344
    wchar_t const *src;
 
1345
    wchar_t const *srcend;
 
1346
    unsigned char *dst;
 
1347
    unsigned char *dstend;
 
1348
    int unconv_num;
 
1349
 
 
1350
    if (from == NULL || *from == NULL)
 
1351
        return 0;
 
1352
 
 
1353
    src = (wchar_t const *) *from;
 
1354
    srcend = src + *from_left;
 
1355
    dst = (unsigned char *) *to;
 
1356
    dstend = dst + *to_left;
 
1357
    unconv_num = 0;
 
1358
 
 
1359
    while (src < srcend && dst < dstend) {
 
1360
        unsigned int wc = *src++;
 
1361
        if (wc < 0x80)
 
1362
            *dst = wc;
 
1363
        else {
 
1364
            *dst = BAD_CHAR;
 
1365
            unconv_num++;
 
1366
        }
 
1367
        dst++;
 
1368
    }
 
1369
 
 
1370
    *from = (XPointer) src;
 
1371
    *from_left = srcend - src;
 
1372
    *to = (XPointer) dst;
 
1373
    *to_left = dstend - dst;
 
1374
 
 
1375
    return unconv_num;
 
1376
}
 
1377
 
 
1378
static XlcConvMethodsRec methods_wcstostr = {
 
1379
    close_converter,
 
1380
    our_wcstostr,
 
1381
    NULL
 
1382
};
 
1383
 
 
1384
static XlcConv
 
1385
open_wcstostr(
 
1386
    XLCd from_lcd,
 
1387
    const char *from_type,
 
1388
    XLCd to_lcd,
 
1389
    const char *to_type)
 
1390
{
 
1391
    return create_conv(from_lcd, &methods_wcstostr);
 
1392
}
 
1393
 
 
1394
/* from XlcNCharSet to XlcNWideChar */
 
1395
 
 
1396
static int
 
1397
cstowcs(
 
1398
    XlcConv conv,
 
1399
    XPointer *from,
 
1400
    int *from_left,
 
1401
    XPointer *to,
 
1402
    int *to_left,
 
1403
    XPointer *args,
 
1404
    int num_args)
 
1405
{
 
1406
    XlcCharSet charset;
 
1407
    const char *name;
 
1408
    Utf8Conv convptr;
 
1409
    int i;
 
1410
    unsigned char const *src;
 
1411
    unsigned char const *srcend;
 
1412
    wchar_t *dst;
 
1413
    wchar_t *dstend;
 
1414
    int unconv_num;
 
1415
 
 
1416
    if (from == NULL || *from == NULL)
 
1417
        return 0;
 
1418
 
 
1419
    if (num_args < 1)
 
1420
        return -1;
 
1421
 
 
1422
    charset = (XlcCharSet) args[0];
 
1423
    name = charset->encoding_name;
 
1424
    /* not charset->name because the latter has a ":GL"/":GR" suffix */
 
1425
 
 
1426
    for (convptr = all_charsets, i = all_charsets_count-1; i > 0; convptr++, i--)
 
1427
        if (!strcmp(convptr->name, name))
 
1428
            break;
 
1429
    if (i == 0)
 
1430
        return -1;
 
1431
 
 
1432
    src = (unsigned char const *) *from;
 
1433
    srcend = src + *from_left;
 
1434
    dst = (wchar_t *) *to;
 
1435
    dstend = dst + *to_left;
 
1436
    unconv_num = 0;
 
1437
 
 
1438
    while (src < srcend && dst < dstend) {
 
1439
        unsigned int wc;
 
1440
        int consumed;
 
1441
 
 
1442
        consumed = convptr->cstowc(conv, &wc, src, srcend-src);
 
1443
        if (consumed == RET_ILSEQ)
 
1444
            return -1;
 
1445
        if (consumed == RET_TOOFEW(0))
 
1446
            break;
 
1447
 
 
1448
        *dst++ = wc;
 
1449
        src += consumed;
 
1450
    }
 
1451
 
 
1452
    *from = (XPointer) src;
 
1453
    *from_left = srcend - src;
 
1454
    *to = (XPointer) dst;
 
1455
    *to_left = dstend - dst;
 
1456
 
 
1457
    return unconv_num;
 
1458
}
 
1459
 
 
1460
static XlcConvMethodsRec methods_cstowcs = {
 
1461
    close_converter,
 
1462
    cstowcs,
 
1463
    NULL
 
1464
};
 
1465
 
 
1466
static XlcConv
 
1467
open_cstowcs(
 
1468
    XLCd from_lcd,
 
1469
    const char *from_type,
 
1470
    XLCd to_lcd,
 
1471
    const char *to_type)
 
1472
{
 
1473
    lazy_init_all_charsets();
 
1474
    return create_conv(from_lcd, &methods_cstowcs);
 
1475
}
 
1476
 
 
1477
/* from XlcNWideChar to XlcNCharSet */
 
1478
 
 
1479
static int
 
1480
wcstocs(
 
1481
    XlcConv conv,
 
1482
    XPointer *from,
 
1483
    int *from_left,
 
1484
    XPointer *to,
 
1485
    int *to_left,
 
1486
    XPointer *args,
 
1487
    int num_args)
 
1488
{
 
1489
    Utf8Conv *preferred_charsets;
 
1490
    XlcCharSet last_charset = NULL;
 
1491
    wchar_t const *src;
 
1492
    wchar_t const *srcend;
 
1493
    unsigned char *dst;
 
1494
    unsigned char *dstend;
 
1495
    int unconv_num;
 
1496
 
 
1497
    if (from == NULL || *from == NULL)
 
1498
        return 0;
 
1499
 
 
1500
    preferred_charsets = (Utf8Conv *) conv->state;
 
1501
    src = (wchar_t const *) *from;
 
1502
    srcend = src + *from_left;
 
1503
    dst = (unsigned char *) *to;
 
1504
    dstend = dst + *to_left;
 
1505
    unconv_num = 0;
 
1506
 
 
1507
    while (src < srcend && dst < dstend) {
 
1508
        Utf8Conv chosen_charset = NULL;
 
1509
        XlcSide chosen_side = XlcNONE;
 
1510
        wchar_t wc = *src;
 
1511
        int count;
 
1512
 
 
1513
        count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst);
 
1514
        if (count == RET_TOOSMALL)
 
1515
            break;
 
1516
        if (count == RET_ILSEQ) {
 
1517
            src++;
 
1518
            unconv_num++;
 
1519
            continue;
 
1520
        }
 
1521
 
 
1522
        if (last_charset == NULL) {
 
1523
            last_charset =
 
1524
                _XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
 
1525
            if (last_charset == NULL) {
 
1526
                src++;
 
1527
                unconv_num++;
 
1528
                continue;
 
1529
            }
 
1530
        } else {
 
1531
            if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name
 
1532
                  && (last_charset->side == XlcGLGR
 
1533
                      || last_charset->side == chosen_side)))
 
1534
                break;
 
1535
        }
 
1536
        src++;
 
1537
        dst += count;
 
1538
    }
 
1539
 
 
1540
    if (last_charset == NULL)
 
1541
        return -1;
 
1542
 
 
1543
    *from = (XPointer) src;
 
1544
    *from_left = srcend - src;
 
1545
    *to = (XPointer) dst;
 
1546
    *to_left = dstend - dst;
 
1547
 
 
1548
    if (num_args >= 1)
 
1549
        *((XlcCharSet *)args[0]) = last_charset;
 
1550
 
 
1551
    return unconv_num;
 
1552
}
 
1553
 
 
1554
static XlcConvMethodsRec methods_wcstocs = {
 
1555
    close_tocs_converter,
 
1556
    wcstocs,
 
1557
    NULL
 
1558
};
 
1559
 
 
1560
static XlcConv
 
1561
open_wcstocs(
 
1562
    XLCd from_lcd,
 
1563
    const char *from_type,
 
1564
    XLCd to_lcd,
 
1565
    const char *to_type)
 
1566
{
 
1567
    return create_tocs_conv(from_lcd, &methods_wcstocs);
 
1568
}
 
1569
 
 
1570
/* from XlcNWideChar to XlcNChar */
 
1571
 
 
1572
static int
 
1573
wcstocs1(
 
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
    Utf8Conv *preferred_charsets;
 
1583
    XlcCharSet last_charset = NULL;
 
1584
    wchar_t const *src;
 
1585
    wchar_t const *srcend;
 
1586
    unsigned char *dst;
 
1587
    unsigned char *dstend;
 
1588
    int unconv_num;
 
1589
 
 
1590
    if (from == NULL || *from == NULL)
 
1591
        return 0;
 
1592
 
 
1593
    preferred_charsets = (Utf8Conv *) conv->state;
 
1594
    src = (wchar_t const *) *from;
 
1595
    srcend = src + *from_left;
 
1596
    dst = (unsigned char *) *to;
 
1597
    dstend = dst + *to_left;
 
1598
    unconv_num = 0;
 
1599
 
 
1600
    while (src < srcend && dst < dstend) {
 
1601
        Utf8Conv chosen_charset = NULL;
 
1602
        XlcSide chosen_side = XlcNONE;
 
1603
        wchar_t wc = *src;
 
1604
        int count;
 
1605
 
 
1606
        count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst);
 
1607
        if (count == RET_TOOSMALL)
 
1608
            break;
 
1609
        if (count == RET_ILSEQ) {
 
1610
            src++;
 
1611
            unconv_num++;
 
1612
            continue;
 
1613
        }
 
1614
 
 
1615
        if (last_charset == NULL) {
 
1616
            last_charset =
 
1617
                _XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
 
1618
            if (last_charset == NULL) {
 
1619
                src++;
 
1620
                unconv_num++;
 
1621
                continue;
 
1622
            }
 
1623
        } else {
 
1624
            if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name
 
1625
                  && (last_charset->side == XlcGLGR
 
1626
                      || last_charset->side == chosen_side)))
 
1627
                break;
 
1628
        }
 
1629
        src++;
 
1630
        dst += count;
 
1631
        break;
 
1632
    }
 
1633
 
 
1634
    if (last_charset == NULL)
 
1635
        return -1;
 
1636
 
 
1637
    *from = (XPointer) src;
 
1638
    *from_left = srcend - src;
 
1639
    *to = (XPointer) dst;
 
1640
    *to_left = dstend - dst;
 
1641
 
 
1642
    if (num_args >= 1)
 
1643
        *((XlcCharSet *)args[0]) = last_charset;
 
1644
 
 
1645
    return unconv_num;
 
1646
}
 
1647
 
 
1648
static XlcConvMethodsRec methods_wcstocs1 = {
 
1649
    close_tocs_converter,
 
1650
    wcstocs1,
 
1651
    NULL
 
1652
};
 
1653
 
 
1654
static XlcConv
 
1655
open_wcstocs1(
 
1656
    XLCd from_lcd,
 
1657
    const char *from_type,
 
1658
    XLCd to_lcd,
 
1659
    const char *to_type)
 
1660
{
 
1661
    return create_tocs_conv(from_lcd, &methods_wcstocs1);
 
1662
}
 
1663
 
 
1664
/* trivial, no conversion */
 
1665
 
 
1666
static int
 
1667
identity(
 
1668
    XlcConv conv,
 
1669
    XPointer *from,
 
1670
    int *from_left,
 
1671
    XPointer *to,
 
1672
    int *to_left,
 
1673
    XPointer *args,
 
1674
    int num_args)
 
1675
{
 
1676
    unsigned char const *src;
 
1677
    unsigned char const *srcend;
 
1678
    unsigned char *dst;
 
1679
    unsigned char *dstend;
 
1680
 
 
1681
    if (from == NULL || *from == NULL)
 
1682
        return 0;
 
1683
 
 
1684
    src = (unsigned char const *) *from;
 
1685
    srcend = src + *from_left;
 
1686
    dst = (unsigned char *) *to;
 
1687
    dstend = dst + *to_left;
 
1688
 
 
1689
    while (src < srcend && dst < dstend)
 
1690
        *dst++ = *src++;
 
1691
 
 
1692
    *from = (XPointer) src;
 
1693
    *from_left = srcend - src;
 
1694
    *to = (XPointer) dst;
 
1695
    *to_left = dstend - dst;
 
1696
 
 
1697
    return 0;
 
1698
}
 
1699
 
 
1700
static XlcConvMethodsRec methods_identity = {
 
1701
    close_converter,
 
1702
    identity,
 
1703
    NULL
 
1704
};
 
1705
 
 
1706
static XlcConv
 
1707
open_identity(
 
1708
    XLCd from_lcd,
 
1709
    const char *from_type,
 
1710
    XLCd to_lcd,
 
1711
    const char *to_type)
 
1712
{
 
1713
    return create_conv(from_lcd, &methods_identity);
 
1714
}
 
1715
 
 
1716
/* from MultiByte/WideChar to FontCharSet. */
 
1717
/* They really use converters to CharSet
 
1718
 * but with different create_conv procedure. */
 
1719
 
 
1720
static XlcConv
 
1721
create_tofontcs_conv(
 
1722
    XLCd lcd,
 
1723
    XlcConvMethods methods)
 
1724
{
 
1725
    XlcConv conv;
 
1726
    int i, num, k, count;
 
1727
    char **value, buf[20];
 
1728
    Utf8Conv *preferred;
 
1729
 
 
1730
    lazy_init_all_charsets();
 
1731
 
 
1732
    for (i = 0, num = 0;; i++) {
 
1733
        sprintf(buf, "fs%d.charset.name", i);
 
1734
        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
 
1735
        if (count < 1) {
 
1736
            sprintf(buf, "fs%d.charset", i);
 
1737
            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
 
1738
            if (count < 1)
 
1739
                break;
 
1740
        }
 
1741
        num += count;
 
1742
    }
 
1743
 
 
1744
    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec) + (num + 1) * sizeof(Utf8Conv));
 
1745
    if (conv == (XlcConv) NULL)
 
1746
        return (XlcConv) NULL;
 
1747
    preferred = (Utf8Conv *) ((char *) conv + sizeof(XlcConvRec));
 
1748
 
 
1749
    /* Loop through all fontsets mentioned in the locale. */
 
1750
    for (i = 0, num = 0;; i++) {
 
1751
        sprintf(buf, "fs%d.charset.name", i);
 
1752
        _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
 
1753
        if (count < 1) {
 
1754
            sprintf(buf, "fs%d.charset", i);
 
1755
            _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
 
1756
            if (count < 1)
 
1757
                break;
 
1758
        }
 
1759
        while (count-- > 0) {
 
1760
            XlcCharSet charset = _XlcGetCharSet(*value++);
 
1761
            const char *name = charset->encoding_name;
 
1762
            /* If it wasn't already encountered... */
 
1763
            for (k = num - 1; k >= 0; k--)
 
1764
                if (!strcmp(preferred[k]->name, name))
 
1765
                    break;
 
1766
            if (k < 0) {
 
1767
                /* For fonts "ISO10646-1" means not utf8 but ucs2.*/
 
1768
                if (!strcmp("ISO10646-1", name)) {
 
1769
                    preferred[num++] = &all_charsets[ucs2_conv_index];
 
1770
                    continue;
 
1771
                }
 
1772
                /* Look it up in all_charsets[]. */
 
1773
                for (k = 0; k < all_charsets_count-1; k++)
 
1774
                    if (!strcmp(all_charsets[k].name, name)) {
 
1775
                        /* Add it to the preferred set. */
 
1776
                        preferred[num++] = &all_charsets[k];
 
1777
                        break;
 
1778
                    }
 
1779
            }
 
1780
        }
 
1781
    }
 
1782
    preferred[num] = (Utf8Conv) NULL;
 
1783
 
 
1784
    conv->methods = methods;
 
1785
    conv->state = (XPointer) preferred;
 
1786
 
 
1787
    return conv;
 
1788
}
 
1789
 
 
1790
static XlcConv
 
1791
open_wcstofcs(
 
1792
    XLCd from_lcd,
 
1793
    const char *from_type,
 
1794
    XLCd to_lcd,
 
1795
    const char *to_type)
 
1796
{
 
1797
    return create_tofontcs_conv(from_lcd, &methods_wcstocs);
 
1798
}
 
1799
 
 
1800
static XlcConv
 
1801
open_utf8tofcs(
 
1802
    XLCd from_lcd,
 
1803
    const char *from_type,
 
1804
    XLCd to_lcd,
 
1805
    const char *to_type)
 
1806
{
 
1807
    return create_tofontcs_conv(from_lcd, &methods_utf8tocs);
 
1808
}
 
1809
 
 
1810
/* Registers UTF-8 converters for a UTF-8 locale. */
 
1811
 
 
1812
void
 
1813
_XlcAddUtf8LocaleConverters(
 
1814
    XLCd lcd)
 
1815
{
 
1816
    /* Register elementary converters. */
 
1817
 
 
1818
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_utf8towcs);
 
1819
 
 
1820
    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstoutf8);
 
1821
    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr);
 
1822
 
 
1823
    _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_strtowcs);
 
1824
 
 
1825
    /* Register converters for XlcNCharSet. This implicitly provides
 
1826
     * converters from and to XlcNCompoundText. */
 
1827
 
 
1828
    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstoutf8);
 
1829
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_utf8tocs);
 
1830
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_utf8tocs1);
 
1831
 
 
1832
    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
 
1833
    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
 
1834
    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNChar, open_wcstocs1);
 
1835
 
 
1836
    _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtoutf8);
 
1837
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_utf8tostr);
 
1838
    _XlcSetConverter(lcd, XlcNUtf8String, lcd, XlcNMultiByte, open_identity);
 
1839
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNUtf8String, open_identity);
 
1840
 
 
1841
    /* Register converters for XlcNFontCharSet */
 
1842
    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNFontCharSet, open_utf8tofcs);
 
1843
    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNFontCharSet, open_wcstofcs);
 
1844
}