OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [winduni.c] - Blame information for rev 41

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 khays
/* winduni.c -- unicode support for the windres program.
2
   Copyright 1997, 1998, 2000, 2001, 2003, 2005, 2007, 2009
3
   Free Software Foundation, Inc.
4
   Written by Ian Lance Taylor, Cygnus Support.
5
   Rewritten by Kai Tietz, Onevision.
6
 
7
   This file is part of GNU Binutils.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22
   02110-1301, USA.  */
23
 
24
 
25
/* This file contains unicode support routines for the windres
26
   program.  Ideally, we would have generic unicode support which
27
   would work on all systems.  However, we don't.  Instead, on a
28
   Windows host, we are prepared to call some Windows routines.  This
29
   means that we will generate different output on Windows and Unix
30
   hosts, but that seems better than not really supporting unicode at
31
   all.  */
32
 
33
#include "sysdep.h"
34
#include "bfd.h"
35
#include "libiberty.h" /* for xstrdup */
36
#include "bucomm.h"
37
/* Must be include before windows.h and winnls.h.  */
38
#if defined (_WIN32) || defined (__CYGWIN__)
39
#include <windows.h>
40
#include <winnls.h>
41
#endif
42
#include "winduni.h"
43
#include "safe-ctype.h"
44
 
45
#if HAVE_ICONV
46
#include <iconv.h>
47
#endif
48
 
49
static rc_uint_type wind_WideCharToMultiByte (rc_uint_type, const unichar *, char *, rc_uint_type);
50
static rc_uint_type wind_MultiByteToWideChar (rc_uint_type, const char *, unichar *, rc_uint_type);
51
static int unichar_isascii (const unichar *, rc_uint_type);
52
 
53
/* Convert an ASCII string to a unicode string.  We just copy it,
54
   expanding chars to shorts, rather than doing something intelligent.  */
55
 
56
#if !defined (_WIN32) && !defined (__CYGWIN__)
57
 
58
/* Codepages mapped.  */
59
static local_iconv_map codepages[] =
60
{
61
  { 0, "MS-ANSI" },
62
  { 1, "WINDOWS-1252" },
63
  { 437, "MS-ANSI" },
64
  { 737, "MS-GREEK" },
65
  { 775, "WINBALTRIM" },
66
  { 850, "MS-ANSI" },
67
  { 852, "MS-EE" },
68
  { 857, "MS-TURK" },
69
  { 862, "CP862" },
70
  { 864, "CP864" },
71
  { 866, "MS-CYRL" },
72
  { 874, "WINDOWS-874" },
73
  { 932, "CP932" },
74
  { 936, "CP936" },
75
  { 949, "CP949" },
76
  { 950, "CP950" },
77
  { 1250, "WINDOWS-1250" },
78
  { 1251, "WINDOWS-1251" },
79
  { 1252, "WINDOWS-1252" },
80
  { 1253, "WINDOWS-1253" },
81
  { 1254, "WINDOWS-1254" },
82
  { 1255, "WINDOWS-1255" },
83
  { 1256, "WINDOWS-1256" },
84
  { 1257, "WINDOWS-1257" },
85
  { 1258, "WINDOWS-1258" },
86
  { CP_UTF7, "UTF-7" },
87
  { CP_UTF8, "UTF-8" },
88
  { CP_UTF16, "UTF-16" },
89
  { (rc_uint_type) -1, NULL }
90
};
91
 
92
/* Languages supported.  */
93
static const wind_language_t languages[] =
94
{
95
  { 0x0000, 437, 1252, "Neutral", "Neutral" },
96
  { 0x0401, 864, 1256, "Arabic", "Saudi Arabia" },    { 0x0402, 866, 1251, "Bulgarian", "Bulgaria" },
97
  { 0x0403, 850, 1252, "Catalan", "Spain" },          { 0x0404, 950,  950, "Chinese", "Taiwan" },
98
  { 0x0405, 852, 1250, "Czech", "Czech Republic" },   { 0x0406, 850, 1252, "Danish", "Denmark" },
99
  { 0x0407, 850, 1252, "German", "Germany" },         { 0x0408, 737, 1253, "Greek", "Greece" },
100
  { 0x0409, 437, 1252, "English", "United States" },  { 0x040A, 850, 1252, "Spanish - Traditional Sort", "Spain" },
101
  { 0x040B, 850, 1252, "Finnish", "Finland" },        { 0x040C, 850, 1252, "French", "France" },
102
  { 0x040D, 862, 1255, "Hebrew", "Israel" },          { 0x040E, 852, 1250, "Hungarian", "Hungary" },
103
  { 0x040F, 850, 1252, "Icelandic", "Iceland" },      { 0x0410, 850, 1252, "Italian", "Italy" },
104
  { 0x0411, 932,  932, "Japanese", "Japan" },         { 0x0412, 949,  949, "Korean", "Korea (south)" },
105
  { 0x0413, 850, 1252, "Dutch", "Netherlands" },      { 0x0414, 850, 1252, "Norwegian (Bokmål)", "Norway" },
106
  { 0x0415, 852, 1250, "Polish", "Poland" },          { 0x0416, 850, 1252, "Portuguese", "Brazil" },
107
  { 0x0418, 852, 1250, "Romanian", "Romania" },       { 0x0419, 866, 1251, "Russian", "Russia" },
108
  { 0x041A, 852, 1250, "Croatian", "Croatia" },       { 0x041B, 852, 1250, "Slovak", "Slovakia" },
109
  { 0x041C, 852, 1250, "Albanian", "Albania" },       { 0x041D, 850, 1252, "Swedish", "Sweden" },
110
  { 0x041E, 874,  874, "Thai", "Thailand" },          { 0x041F, 857, 1254, "Turkish", "Turkey" },
111
  { 0x0421, 850, 1252, "Indonesian", "Indonesia" },   { 0x0422, 866, 1251, "Ukrainian", "Ukraine" },
112
  { 0x0423, 866, 1251, "Belarusian", "Belarus" },     { 0x0424, 852, 1250, "Slovene", "Slovenia" },
113
  { 0x0425, 775, 1257, "Estonian", "Estonia" },       { 0x0426, 775, 1257, "Latvian", "Latvia" },
114
  { 0x0427, 775, 1257, "Lithuanian", "Lithuania" },
115
  { 0x0429, 864, 1256, "Arabic", "Farsi" },           { 0x042A,1258, 1258, "Vietnamese", "Vietnam" },
116
  { 0x042D, 850, 1252, "Basque", "Spain" },
117
  { 0x042F, 866, 1251, "Macedonian", "Former Yugoslav Republic of Macedonia" },
118
  { 0x0436, 850, 1252, "Afrikaans", "South Africa" },
119
  { 0x0438, 850, 1252, "Faroese", "Faroe Islands" },
120
  { 0x043C, 437, 1252, "Irish", "Ireland" },
121
  { 0x043E, 850, 1252, "Malay", "Malaysia" },
122
  { 0x0801, 864, 1256, "Arabic", "Iraq" },
123
  { 0x0804, 936,  936, "Chinese (People's republic of China)", "People's republic of China" },
124
  { 0x0807, 850, 1252, "German", "Switzerland" },
125
  { 0x0809, 850, 1252, "English", "United Kingdom" }, { 0x080A, 850, 1252, "Spanish", "Mexico" },
126
  { 0x080C, 850, 1252, "French", "Belgium" },
127
  { 0x0810, 850, 1252, "Italian", "Switzerland" },
128
  { 0x0813, 850, 1252, "Dutch", "Belgium" },          { 0x0814, 850, 1252, "Norwegian (Nynorsk)", "Norway" },
129
  { 0x0816, 850, 1252, "Portuguese", "Portugal" },
130
  { 0x081A, 852, 1252, "Serbian (latin)", "Yugoslavia" },
131
  { 0x081D, 850, 1252, "Swedish (Finland)", "Finland" },
132
  { 0x0C01, 864, 1256, "Arabic", "Egypt" },
133
  { 0x0C04, 950,  950, "Chinese", "Hong Kong" },
134
  { 0x0C07, 850, 1252, "German", "Austria" },
135
  { 0x0C09, 850, 1252, "English", "Australia" },      { 0x0C0A, 850, 1252, "Spanish - International Sort", "Spain" },
136
  { 0x0C0C, 850, 1252, "French", "Canada"},
137
  { 0x0C1A, 855, 1251, "Serbian (Cyrillic)", "Serbia" },
138
  { 0x1001, 864, 1256, "Arabic", "Libya" },
139
  { 0x1004, 936,  936, "Chinese", "Singapore" },
140
  { 0x1007, 850, 1252, "German", "Luxembourg" },
141
  { 0x1009, 850, 1252, "English", "Canada" },
142
  { 0x100A, 850, 1252, "Spanish", "Guatemala" },
143
  { 0x100C, 850, 1252, "French", "Switzerland" },
144
  { 0x1401, 864, 1256, "Arabic", "Algeria" },
145
  { 0x1407, 850, 1252, "German", "Liechtenstein" },
146
  { 0x1409, 850, 1252, "English", "New Zealand" },    { 0x140A, 850, 1252, "Spanish", "Costa Rica" },
147
  { 0x140C, 850, 1252, "French", "Luxembourg" },
148
  { 0x1801, 864, 1256, "Arabic", "Morocco" },
149
  { 0x1809, 850, 1252, "English", "Ireland" },        { 0x180A, 850, 1252, "Spanish", "Panama" },
150
  { 0x180C, 850, 1252, "French", "Monaco" },
151
  { 0x1C01, 864, 1256, "Arabic", "Tunisia" },
152
  { 0x1C09, 437, 1252, "English", "South Africa" },   { 0x1C0A, 850, 1252, "Spanish", "Dominican Republic" },
153
  { 0x2001, 864, 1256, "Arabic", "Oman" },
154
  { 0x2009, 850, 1252, "English", "Jamaica" },        { 0x200A, 850, 1252, "Spanish", "Venezuela" },
155
  { 0x2401, 864, 1256, "Arabic", "Yemen" },
156
  { 0x2409, 850, 1252, "English", "Caribbean" },      { 0x240A, 850, 1252, "Spanish", "Colombia" },
157
  { 0x2801, 864, 1256, "Arabic", "Syria" },
158
  { 0x2809, 850, 1252, "English", "Belize" },         { 0x280A, 850, 1252, "Spanish", "Peru" },
159
  { 0x2C01, 864, 1256, "Arabic", "Jordan" },
160
  { 0x2C09, 437, 1252, "English", "Trinidad & Tobago" },{ 0x2C0A, 850, 1252, "Spanish", "Argentina" },
161
  { 0x3001, 864, 1256, "Arabic", "Lebanon" },
162
  { 0x3009, 437, 1252, "English", "Zimbabwe" },       { 0x300A, 850, 1252, "Spanish", "Ecuador" },
163
  { 0x3401, 864, 1256, "Arabic", "Kuwait" },
164
  { 0x3409, 437, 1252, "English", "Philippines" },    { 0x340A, 850, 1252, "Spanish", "Chile" },
165
  { 0x3801, 864, 1256, "Arabic", "United Arab Emirates" },
166
  { 0x380A, 850, 1252, "Spanish", "Uruguay" },
167
  { 0x3C01, 864, 1256, "Arabic", "Bahrain" },
168
  { 0x3C0A, 850, 1252, "Spanish", "Paraguay" },
169
  { 0x4001, 864, 1256, "Arabic", "Qatar" },
170
  { 0x400A, 850, 1252, "Spanish", "Bolivia" },
171
  { 0x440A, 850, 1252, "Spanish", "El Salvador" },
172
  { 0x480A, 850, 1252, "Spanish", "Honduras" },
173
  { 0x4C0A, 850, 1252, "Spanish", "Nicaragua" },
174
  { 0x500A, 850, 1252, "Spanish", "Puerto Rico" },
175
  { (unsigned) -1,  0,      0, NULL, NULL }
176
};
177
 
178
#endif
179
 
180
/* Specifies the default codepage to be used for unicode
181
   transformations.  By default this is CP_ACP.  */
182
rc_uint_type wind_default_codepage = CP_ACP;
183
 
184
/* Specifies the currently used codepage for unicode
185
   transformations.  By default this is CP_ACP.  */
186
rc_uint_type wind_current_codepage = CP_ACP;
187
 
188
/* Convert an ASCII string to a unicode string.  We just copy it,
189
   expanding chars to shorts, rather than doing something intelligent.  */
190
 
191
void
192
unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
193
{
194
  unicode_from_codepage (length, unicode, ascii, wind_current_codepage);
195
}
196
 
197
/* Convert an unicode string to an ASCII string.  We just copy it,
198
   shrink shorts to chars, rather than doing something intelligent.
199
   Shorts with not within the char range are replaced by '_'.  */
200
 
201
void
202
ascii_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii)
203
{
204
  codepage_from_unicode (length, unicode, ascii, wind_current_codepage);
205
}
206
 
207
/* Print the unicode string UNICODE to the file E.  LENGTH is the
208
   number of characters to print, or -1 if we should print until the
209
   end of the string.  FIXME: On a Windows host, we should be calling
210
   some Windows function, probably WideCharToMultiByte.  */
211
 
212
void
213
unicode_print (FILE *e, const unichar *unicode, rc_uint_type length)
214
{
215
  while (1)
216
    {
217
      unichar ch;
218
 
219
      if (length == 0)
220
        return;
221
      if ((bfd_signed_vma) length > 0)
222
        --length;
223
 
224
      ch = *unicode;
225
 
226
      if (ch == 0 && (bfd_signed_vma) length < 0)
227
        return;
228
 
229
      ++unicode;
230
 
231
      if ((ch & 0x7f) == ch)
232
        {
233
          if (ch == '\\')
234
            fputs ("\\\\", e);
235
          else if (ch == '"')
236
            fputs ("\"\"", e);
237
          else if (ISPRINT (ch))
238
            putc (ch, e);
239
          else
240
            {
241
              switch (ch)
242
                {
243
                case ESCAPE_A:
244
                  fputs ("\\a", e);
245
                  break;
246
 
247
                case ESCAPE_B:
248
                  fputs ("\\b", e);
249
                  break;
250
 
251
                case ESCAPE_F:
252
                  fputs ("\\f", e);
253
                  break;
254
 
255
                case ESCAPE_N:
256
                  fputs ("\\n", e);
257
                  break;
258
 
259
                case ESCAPE_R:
260
                  fputs ("\\r", e);
261
                  break;
262
 
263
                case ESCAPE_T:
264
                  fputs ("\\t", e);
265
                  break;
266
 
267
                case ESCAPE_V:
268
                  fputs ("\\v", e);
269
                  break;
270
 
271
                default:
272
                  fprintf (e, "\\%03o", (unsigned int) ch);
273
                  break;
274
                }
275
            }
276
        }
277
      else if ((ch & 0xff) == ch)
278
        fprintf (e, "\\%03o", (unsigned int) ch);
279
      else
280
        fprintf (e, "\\x%04x", (unsigned int) ch);
281
    }
282
}
283
 
284
/* Print a unicode string to a file.  */
285
 
286
void
287
ascii_print (FILE *e, const char *s, rc_uint_type length)
288
{
289
  while (1)
290
    {
291
      char ch;
292
 
293
      if (length == 0)
294
        return;
295
      if ((bfd_signed_vma) length > 0)
296
        --length;
297
 
298
      ch = *s;
299
 
300
      if (ch == 0 && (bfd_signed_vma) length < 0)
301
        return;
302
 
303
      ++s;
304
 
305
      if ((ch & 0x7f) == ch)
306
        {
307
          if (ch == '\\')
308
            fputs ("\\\\", e);
309
          else if (ch == '"')
310
            fputs ("\"\"", e);
311
          else if (ISPRINT (ch))
312
            putc (ch, e);
313
          else
314
            {
315
              switch (ch)
316
                {
317
                case ESCAPE_A:
318
                  fputs ("\\a", e);
319
                  break;
320
 
321
                case ESCAPE_B:
322
                  fputs ("\\b", e);
323
                  break;
324
 
325
                case ESCAPE_F:
326
                  fputs ("\\f", e);
327
                  break;
328
 
329
                case ESCAPE_N:
330
                  fputs ("\\n", e);
331
                  break;
332
 
333
                case ESCAPE_R:
334
                  fputs ("\\r", e);
335
                  break;
336
 
337
                case ESCAPE_T:
338
                  fputs ("\\t", e);
339
                  break;
340
 
341
                case ESCAPE_V:
342
                  fputs ("\\v", e);
343
                  break;
344
 
345
                default:
346
                  fprintf (e, "\\%03o", (unsigned int) ch);
347
                  break;
348
                }
349
            }
350
        }
351
      else
352
        fprintf (e, "\\%03o", (unsigned int) ch & 0xff);
353
    }
354
}
355
 
356
rc_uint_type
357
unichar_len (const unichar *unicode)
358
{
359
  rc_uint_type r = 0;
360
 
361
  if (unicode)
362
    while (unicode[r] != 0)
363
      r++;
364
  else
365
    --r;
366
  return r;
367
}
368
 
369
unichar *
370
unichar_dup (const unichar *unicode)
371
{
372
  unichar *r;
373
  int len;
374
 
375
  if (! unicode)
376
    return NULL;
377
  for (len = 0; unicode[len] != 0; ++len)
378
    ;
379
  ++len;
380
  r = ((unichar *) res_alloc (len * sizeof (unichar)));
381
  memcpy (r, unicode, len * sizeof (unichar));
382
  return r;
383
}
384
 
385
unichar *
386
unichar_dup_uppercase (const unichar *u)
387
{
388
  unichar *r = unichar_dup (u);
389
  int i;
390
 
391
  if (! r)
392
    return NULL;
393
 
394
  for (i = 0; r[i] != 0; ++i)
395
    {
396
      if (r[i] >= 'a' && r[i] <= 'z')
397
        r[i] &= 0xdf;
398
    }
399
  return r;
400
}
401
 
402
static int
403
unichar_isascii (const unichar *u, rc_uint_type len)
404
{
405
  rc_uint_type i;
406
 
407
  if ((bfd_signed_vma) len < 0)
408
    {
409
      if (u)
410
        len = (rc_uint_type) unichar_len (u);
411
      else
412
        len = 0;
413
    }
414
 
415
  for (i = 0; i < len; i++)
416
    if ((u[i] & 0xff80) != 0)
417
      return 0;
418
  return 1;
419
}
420
 
421
void
422
unicode_print_quoted (FILE *e, const unichar *u, rc_uint_type len)
423
{
424
  if (! unichar_isascii (u, len))
425
    fputc ('L', e);
426
  fputc ('"', e);
427
  unicode_print (e, u, len);
428
  fputc ('"', e);
429
}
430
 
431
int
432
unicode_is_valid_codepage (rc_uint_type cp)
433
{
434
  if ((cp & 0xffff) != cp)
435
    return 0;
436
  if (cp == CP_UTF16 || cp == CP_ACP)
437
    return 1;
438
 
439
#if !defined (_WIN32) && !defined (__CYGWIN__)
440
  if (! wind_find_codepage_info (cp))
441
    return 0;
442
  return 1;
443
#else
444
  return !! IsValidCodePage ((UINT) cp);
445
#endif
446
}
447
 
448
#if defined (_WIN32) || defined (__CYGWIN__)
449
 
450
#define max_cp_string_len 6
451
 
452
static unsigned int
453
codepage_from_langid (unsigned short langid)
454
{
455
  char cp_string [max_cp_string_len];
456
  int c;
457
 
458
  memset (cp_string, 0, max_cp_string_len);
459
  /* LOCALE_RETURN_NUMBER flag would avoid strtoul conversion,
460
     but is unavailable on Win95.  */
461
  c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
462
                      LOCALE_IDEFAULTANSICODEPAGE,
463
                      cp_string, max_cp_string_len);
464
  /* If codepage data for an LCID is not installed on users's system,
465
     GetLocaleInfo returns an empty string.  Fall back to system ANSI
466
     default. */
467
  if (c == 0)
468
    return CP_ACP;
469
  return strtoul (cp_string, 0, 10);
470
}
471
 
472
static unsigned int
473
wincodepage_from_langid (unsigned short langid)
474
{
475
  char cp_string [max_cp_string_len];
476
  int c;
477
 
478
  memset (cp_string, 0, max_cp_string_len);
479
  /* LOCALE_RETURN_NUMBER flag would avoid strtoul conversion,
480
     but is unavailable on Win95.  */
481
  c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
482
                      LOCALE_IDEFAULTCODEPAGE,
483
                      cp_string, max_cp_string_len);
484
  /* If codepage data for an LCID is not installed on users's system,
485
     GetLocaleInfo returns an empty string.  Fall back to system ANSI
486
     default. */
487
  if (c == 0)
488
    return CP_OEM;
489
  return strtoul (cp_string, 0, 10);
490
}
491
 
492
static char *
493
lang_from_langid (unsigned short langid)
494
{
495
  char cp_string[261];
496
  int c;
497
 
498
  memset (cp_string, 0, 261);
499
  c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
500
                      LOCALE_SENGLANGUAGE,
501
                      cp_string, 260);
502
  /* If codepage data for an LCID is not installed on users's system,
503
     GetLocaleInfo returns an empty string.  Fall back to system ANSI
504
     default. */
505
  if (c == 0)
506
    strcpy (cp_string, "Neutral");
507
  return xstrdup (cp_string);
508
}
509
 
510
static char *
511
country_from_langid (unsigned short langid)
512
{
513
  char cp_string[261];
514
  int c;
515
 
516
  memset (cp_string, 0, 261);
517
  c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
518
                      LOCALE_SENGCOUNTRY,
519
                      cp_string, 260);
520
  /* If codepage data for an LCID is not installed on users's system,
521
     GetLocaleInfo returns an empty string.  Fall back to system ANSI
522
     default. */
523
  if (c == 0)
524
    strcpy (cp_string, "Neutral");
525
  return xstrdup (cp_string);
526
}
527
 
528
#endif
529
 
530
const wind_language_t *
531
wind_find_language_by_id (unsigned id)
532
{
533
#if !defined (_WIN32) && !defined (__CYGWIN__)
534
  int i;
535
 
536
  if (! id)
537
    return NULL;
538
  for (i = 0; languages[i].id != (unsigned) -1 && languages[i].id != id; i++)
539
    ;
540
  if (languages[i].id == id)
541
    return &languages[i];
542
  return NULL;
543
#else
544
  static wind_language_t wl;
545
 
546
  wl.id = id;
547
  wl.doscp = codepage_from_langid ((unsigned short) id);
548
  wl.wincp = wincodepage_from_langid ((unsigned short) id);
549
  wl.name = lang_from_langid ((unsigned short) id);
550
  wl.country = country_from_langid ((unsigned short) id);
551
 
552
  return & wl;
553
#endif
554
}
555
 
556
const local_iconv_map *
557
wind_find_codepage_info (unsigned cp)
558
{
559
#if !defined (_WIN32) && !defined (__CYGWIN__)
560
  int i;
561
 
562
  for (i = 0; codepages[i].codepage != (rc_uint_type) -1 && codepages[i].codepage != cp; i++)
563
    ;
564
  if (codepages[i].codepage == (rc_uint_type) -1)
565
    return NULL;
566
  return &codepages[i];
567
#else
568
  static local_iconv_map lim;
569
  if (!unicode_is_valid_codepage (cp))
570
        return NULL;
571
  lim.codepage = cp;
572
  lim.iconv_name = "";
573
  return & lim;
574
#endif
575
}
576
 
577
/* Convert an Codepage string to a unicode string.  */
578
 
579
void
580
unicode_from_codepage (rc_uint_type *length, unichar **u, const char *src, rc_uint_type cp)
581
{
582
  rc_uint_type len;
583
 
584
  len = wind_MultiByteToWideChar (cp, src, NULL, 0);
585
  if (len)
586
    {
587
      *u = ((unichar *) res_alloc (len));
588
      wind_MultiByteToWideChar (cp, src, *u, len);
589
    }
590
  /* Discount the trailing '/0'.  If MultiByteToWideChar failed,
591
     this will set *length to -1.  */
592
  len -= sizeof (unichar);
593
 
594
  if (length != NULL)
595
    *length = len / sizeof (unichar);
596
}
597
 
598
/* Convert an unicode string to an codepage string.  */
599
 
600
void
601
codepage_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii, rc_uint_type cp)
602
{
603
  rc_uint_type len;
604
 
605
  len = wind_WideCharToMultiByte (cp, unicode, NULL, 0);
606
  if (len)
607
    {
608
      *ascii = (char *) res_alloc (len * sizeof (char));
609
      wind_WideCharToMultiByte (cp, unicode, *ascii, len);
610
    }
611
  /* Discount the trailing '/0'.  If MultiByteToWideChar failed,
612
     this will set *length to -1.  */
613
  len--;
614
 
615
  if (length != NULL)
616
    *length = len;
617
}
618
 
619
#if defined (HAVE_ICONV) && !defined (_WIN32) && !defined (__CYGWIN__)
620
static int
621
iconv_onechar (iconv_t cd, ICONV_CONST char *s, char *d, int d_len, const char **n_s, char **n_d)
622
{
623
  int i;
624
 
625
  for (i = 1; i <= 32; i++)
626
    {
627
      char *tmp_d = d;
628
      ICONV_CONST char *tmp_s = s;
629
      size_t ret;
630
      size_t s_left = (size_t) i;
631
      size_t d_left = (size_t) d_len;
632
 
633
      ret = iconv (cd, & tmp_s, & s_left, & tmp_d, & d_left);
634
 
635
      if (ret != (size_t) -1)
636
        {
637
          *n_s = tmp_s;
638
          *n_d = tmp_d;
639
          return 0;
640
        }
641
    }
642
 
643
  return 1;
644
}
645
 
646
static const char *
647
wind_iconv_cp (rc_uint_type cp)
648
{
649
  const local_iconv_map *lim = wind_find_codepage_info (cp);
650
 
651
  if (!lim)
652
    return NULL;
653
  return lim->iconv_name;
654
}
655
#endif /* HAVE_ICONV */
656
 
657
static rc_uint_type
658
wind_MultiByteToWideChar (rc_uint_type cp, const char *mb,
659
                          unichar *u, rc_uint_type u_len)
660
{
661
  rc_uint_type ret = 0;
662
 
663
#if defined (_WIN32) || defined (__CYGWIN__)
664
  rc_uint_type conv_flags = MB_PRECOMPOSED;
665
 
666
  /* MB_PRECOMPOSED is not allowed for UTF-7 or UTF-8.
667
     MultiByteToWideChar will set the last error to
668
     ERROR_INVALID_FLAGS if we do. */
669
  if (cp == CP_UTF8 || cp == CP_UTF7)
670
    conv_flags = 0;
671
 
672
  ret = (rc_uint_type) MultiByteToWideChar (cp, conv_flags,
673
                                            mb, -1, u, u_len);
674
  /* Convert to bytes. */
675
  ret *= sizeof (unichar);
676
 
677
#elif defined (HAVE_ICONV)
678
  int first = 1;
679
  char tmp[32];
680
  char *p_tmp;
681
  const char *iconv_name = wind_iconv_cp (cp);
682
 
683
  if (!mb || !iconv_name)
684
    return 0;
685
  iconv_t cd = iconv_open ("UTF-16", iconv_name);
686
 
687
  while (1)
688
    {
689
      int iret;
690
      const char *n_mb = "";
691
      char *n_tmp = "";
692
 
693
      p_tmp = tmp;
694
      iret = iconv_onechar (cd, (ICONV_CONST char *) mb, p_tmp, 32, & n_mb, & n_tmp);
695
      if (first)
696
        {
697
          first = 0;
698
          continue;
699
        }
700
      if (!iret)
701
        {
702
          size_t l_tmp = (size_t) (n_tmp - p_tmp);
703
 
704
          if (u)
705
            {
706
              if ((size_t) u_len < l_tmp)
707
                break;
708
              memcpy (u, tmp, l_tmp);
709
              u += l_tmp/2;
710
              u_len -= l_tmp;
711
            }
712
          ret += l_tmp;
713
        }
714
      else
715
        break;
716
      if (tmp[0] == 0 && tmp[1] == 0)
717
        break;
718
      mb = n_mb;
719
    }
720
  iconv_close (cd);
721
#else
722
  if (cp)
723
    ret = 0;
724
  ret = strlen (mb) + 1;
725
  ret *= sizeof (unichar);
726
  if (u != NULL && u_len != 0)
727
    {
728
      do
729
        {
730
          *u++ = ((unichar) *mb) & 0xff;
731
          --u_len; mb++;
732
        }
733
      while (u_len != 0 && mb[-1] != 0);
734
    }
735
  if (u != NULL && u_len != 0)
736
    *u = 0;
737
#endif
738
  return ret;
739
}
740
 
741
static rc_uint_type
742
wind_WideCharToMultiByte (rc_uint_type cp, const unichar *u, char *mb, rc_uint_type mb_len)
743
{
744
  rc_uint_type ret = 0;
745
#if defined (_WIN32) || defined (__CYGWIN__)
746
  WINBOOL used_def = FALSE;
747
 
748
  ret = (rc_uint_type) WideCharToMultiByte (cp, 0, u, -1, mb, mb_len,
749
                                            NULL, & used_def);
750
#elif defined (HAVE_ICONV)
751
  int first = 1;
752
  char tmp[32];
753
  char *p_tmp;
754
  const char *iconv_name = wind_iconv_cp (cp);
755
 
756
  if (!u || !iconv_name)
757
    return 0;
758
  iconv_t cd = iconv_open (iconv_name, "UTF-16");
759
 
760
  while (1)
761
    {
762
      int iret;
763
      const char *n_u = "";
764
      char *n_tmp = "";
765
 
766
      p_tmp = tmp;
767
      iret = iconv_onechar (cd, (ICONV_CONST char *) u, p_tmp, 32, &n_u, & n_tmp);
768
      if (first)
769
        {
770
          first = 0;
771
          continue;
772
        }
773
      if (!iret)
774
        {
775
          size_t l_tmp = (size_t) (n_tmp - p_tmp);
776
 
777
          if (mb)
778
            {
779
              if ((size_t) mb_len < l_tmp)
780
                break;
781
              memcpy (mb, tmp, l_tmp);
782
              mb += l_tmp;
783
              mb_len -= l_tmp;
784
            }
785
          ret += l_tmp;
786
        }
787
      else
788
        break;
789
      if (u[0] == 0)
790
        break;
791
      u = (const unichar *) n_u;
792
    }
793
  iconv_close (cd);
794
#else
795
  if (cp)
796
    ret = 0;
797
 
798
  while (u[ret] != 0)
799
    ++ret;
800
 
801
  ++ret;
802
 
803
  if (mb)
804
    {
805
      while (*u != 0 && mb_len != 0)
806
        {
807
          if (u[0] == (u[0] & 0x7f))
808
            *mb++ = (char) u[0];
809
          else
810
            *mb++ = '_';
811
          ++u; --mb_len;
812
        }
813
      if (mb_len != 0)
814
        *mb = 0;
815
    }
816
#endif
817
  return ret;
818
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.