winex11: Directly use win32u for user functions in mouse.c.
[wine.git] / tools / winedump / nls.c
blob9fe0d26773c5177d9fbe29a8449c34be3c7e172d
1 /*
2 * Dump a NLS file
4 * Copyright 2020 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
27 #include "windef.h"
28 #include "winedump.h"
30 static const void *read_data( unsigned int *pos, unsigned int size )
32 const void *ret = PRD( *pos, size );
33 *pos += size;
34 return ret;
37 static unsigned short mapchar( const unsigned short *table, unsigned int len, unsigned short ch )
39 unsigned int off = table[ch >> 8] + ((ch >> 4) & 0x0f);
40 if (off >= len) return 0;
41 off = table[off] + (ch & 0x0f);
42 if (off >= len) return 0;
43 return ch + table[off];
46 static void dump_offset_table( const unsigned short *table, unsigned int len )
48 int i, ch;
50 for (i = 0; i < 0x10000; i++)
52 if (!(i % 16)) printf( "\n%04x:", i );
53 ch = mapchar( table, len, i );
54 if (ch == i) printf( " ...." );
55 else printf( " %04x", ch );
59 struct ctype
61 WORD c1, c2, c3;
64 static const char *get_ctype( const struct ctype *ctype )
66 static char buffer[100];
67 static const char *c1[] = { "up ", "lo ", "dg ", "sp ", "pt ", "cl ", "bl ", "xd ", "al " };
68 static const char *c2[] = { " ", "L ", "R ", "EN", "ES", "ET",
69 "AN", "CS", "B ", "S ", "WS", "ON" };
70 static const char *c3[] = { "ns ", "di ", "vo ", "sy ", "ka ", "hi ", "hw ", "fw ",
71 "id ", "ks ", "lx ", "hi ", "lo ", " ", " ", "al " };
72 int i;
73 strcpy( buffer, "| " );
74 for (i = 0; i < ARRAY_SIZE(c1); i++)
75 strcat( buffer, (ctype->c1 & (1 << i)) ? c1[i] : "__ " );
76 strcat( buffer, "| " );
77 strcat( buffer, ctype->c2 < ARRAY_SIZE(c2) ? c2[ctype->c2] : "??" );
78 strcat( buffer, " | " );
79 for (i = 0; i < ARRAY_SIZE(c3); i++)
80 strcat( buffer, (ctype->c3 & (1 << i)) ? c3[i] : "__ " );
81 strcat( buffer, "|" );
82 return buffer;
85 static void dump_ctype_table( const USHORT *ptr )
87 const struct ctype *ctypes = (const struct ctype *)(ptr + 2);
88 const BYTE *types = (const BYTE *)ptr + ptr[1] + 2;
89 int i, len = (ptr[1] - 2) / sizeof(*ctypes);
91 printf( " CTYPE1 CTYPE2 CTYPE3\n" );
92 for (i = 0; i < 0x10000; i++)
94 const BYTE *b = types + ((const WORD *)types)[i >> 8];
95 b = types + ((const WORD *)b)[(i >> 4) & 0x0f] + (i & 0x0f);
96 if (*b < len) printf( "%04x %s\n", i, get_ctype( ctypes + *b ));
97 else printf( "%04x ??? %02x\n", i, *b );
99 printf( "\n" );
102 static void dump_casemap(void)
104 unsigned int pos = 0, upper_len, lower_len;
105 const unsigned short *header, *upper, *lower;
107 if (!(header = read_data( &pos, 2 * sizeof(*header) ))) return;
108 upper_len = header[1];
109 if (!(upper = read_data( &pos, upper_len * sizeof(*upper) )))
111 printf( "Invalid len %04x\n", header[1] );
112 return;
114 lower_len = dump_total_len / sizeof(*lower) - 2 - upper_len;
115 if (!(lower = read_data( &pos, lower_len * sizeof(*lower) ))) return;
117 printf( "Magic: %04x\n", header[0] );
118 printf( "Upper-case table:\n" );
119 dump_offset_table( upper, upper_len );
120 printf( "\n\nLower-case table:\n" );
121 dump_offset_table( lower, lower_len );
122 printf( "\n\n" );
125 static void dump_codepage(void)
127 unsigned int i, j, uni2cp_offset, pos = 0;
128 const unsigned short *header, *ptr;
130 if (!(header = read_data( &pos, 13 * sizeof(*header) ))) return;
131 printf( "Codepage: %03u\n", header[1] );
132 printf( "Char size: %u\n", header[2] );
133 printf( "Default char A: %04x / %04x\n", header[3], header[5] );
134 printf( "Default char W: %04x / %04x\n", header[4], header[6] );
135 if (header[2] == 2)
137 printf( "Lead bytes: " );
138 for (i = 0; i < 12; i++)
140 unsigned char val = ((unsigned char *)(header + 7))[i];
141 if (!val) break;
142 printf( "%c%02x", (i % 2) ? '-' : ' ', val );
144 printf( "\n" );
146 printf( "\nCharacter map:\n" );
147 pos = header[0] * sizeof(*ptr);
148 if (!(ptr = read_data( &pos, sizeof(*ptr) ))) return;
149 uni2cp_offset = pos / sizeof(*ptr) + *ptr;
150 if (!(ptr = read_data( &pos, 256 * sizeof(*ptr) ))) return;
151 for (i = 0; i < 256; i++)
153 if (!(i % 16)) printf( "\n%02x:", i );
154 printf( " %04x", ptr[i] );
156 printf( "\n" );
157 if (!(ptr = read_data( &pos, sizeof(*ptr) ))) return;
158 if (*ptr == 256)
160 if (!(ptr = read_data( &pos, 256 * sizeof(*ptr) ))) return;
161 printf( "\nGlyph table:\n" );
162 for (i = 0; i < 256; i++)
164 if (!(i % 16)) printf( "\n%02x:", i );
165 printf( " %04x", ptr[i] );
167 printf( "\n" );
169 if (!(ptr = read_data( &pos, sizeof(*ptr) ))) return;
170 if (*ptr)
172 if (!(ptr = read_data( &pos, (uni2cp_offset - pos) * sizeof(*ptr) ))) return;
173 for (i = 0; i < 256; i++)
175 if (!ptr[i] || ptr[i] > pos - 256) continue;
176 for (j = 0; j < 256; j++)
178 if (!(j % 16)) printf( "\n%02x%02x:", i, j );
179 printf( " %04x", ptr[ptr[i] + j] );
182 printf( "\n" );
184 printf( "\nUnicode table:\n" );
185 pos = uni2cp_offset * sizeof(*ptr);
186 if (header[2] == 2)
188 if (!(ptr = read_data( &pos, 65536 * sizeof(*ptr) ))) return;
189 for (i = 0; i < 65536; i++)
191 if (!(i % 16)) printf( "\n%04x:", i );
192 printf( " %04x", ptr[i] );
194 printf( "\n" );
196 else
198 const unsigned char *uni2cp;
199 if (!(uni2cp = read_data( &pos, 65536 ))) return;
200 for (i = 0; i < 65536; i++)
202 if (!(i % 16)) printf( "\n%04x:", i );
203 printf( " %02x", uni2cp[i] );
205 printf( "\n" );
207 printf( "\n" );
210 struct norm_table
212 WCHAR name[13]; /* 00 file name */
213 USHORT checksum[3]; /* 1a checksum? */
214 USHORT version[4]; /* 20 Unicode version */
215 USHORT form; /* 28 normalization form */
216 USHORT len_factor; /* 2a factor for length estimates */
217 USHORT unknown1; /* 2c */
218 USHORT decomp_size; /* 2e decomposition hash size */
219 USHORT comp_size; /* 30 composition hash size */
220 USHORT unknown2; /* 32 */
221 USHORT classes; /* 34 combining classes table offset */
222 USHORT props_level1; /* 36 char properties table level 1 offset */
223 USHORT props_level2; /* 38 char properties table level 2 offset */
224 USHORT decomp_hash; /* 3a decomposition hash table offset */
225 USHORT decomp_map; /* 3c decomposition character map table offset */
226 USHORT decomp_seq; /* 3e decomposition character sequences offset */
227 USHORT comp_hash; /* 40 composition hash table offset */
228 USHORT comp_seq; /* 42 composition character sequences offset */
231 static int offset_scale = 1; /* older versions use byte offsets */
233 #define GET_TABLE(info,table) ((const void *)((const BYTE *)info + (info->table * offset_scale)))
235 static unsigned int get_utf16( const WCHAR *str )
237 if (str[0] >= 0xd800 && str[0] <= 0xdbff &&
238 str[1] >= 0xdc00 && str[1] <= 0xdfff)
239 return 0x10000 + ((str[0] & 0x3ff) << 10) + (str[1] & 0x3ff);
240 return str[0];
243 static BYTE rol( BYTE val, BYTE count )
245 return (val << count) | (val >> (8 - count));
248 static unsigned char get_char_props( const struct norm_table *info, unsigned int ch )
250 const BYTE *level1 = GET_TABLE( info, props_level1 );
251 const BYTE *level2 = GET_TABLE( info, props_level2 );
252 BYTE off = level1[ch / 128];
254 if (!off || off >= 0xfb) return rol( off, 5 );
255 return level2[(off - 1) * 128 + ch % 128];
258 static const WCHAR *get_decomposition( const struct norm_table *info,
259 unsigned int ch, unsigned int *ret_len )
261 const USHORT *hash_table = GET_TABLE( info, decomp_hash );
262 const WCHAR *seq = GET_TABLE(info, decomp_seq );
263 const WCHAR *ret;
264 unsigned int i, pos, end, len, hash;
266 *ret_len = 1 + (ch >= 0x10000);
267 if (!info->decomp_size) return NULL;
268 hash = ch % info->decomp_size;
269 pos = hash_table[hash];
270 if (pos >> 13)
272 if (get_char_props( info, ch ) != 0xbf) return NULL;
273 ret = seq + (pos & 0x1fff);
274 len = pos >> 13;
276 else
278 const struct { WCHAR src; USHORT dst; } *pairs = GET_TABLE( info, decomp_map );
280 /* find the end of the hash bucket */
281 for (i = hash + 1; i < info->decomp_size; i++) if (!(hash_table[i] >> 13)) break;
282 if (i < info->decomp_size) end = hash_table[i];
283 else for (end = pos; pairs[end].src; end++) ;
285 for ( ; pos < end; pos++)
287 if (pairs[pos].src != (WCHAR)ch) continue;
288 ret = seq + (pairs[pos].dst & 0x1fff);
289 len = pairs[pos].dst >> 13;
290 break;
292 if (pos >= end) return NULL;
295 if (len == 7) while (ret[len]) len++;
296 *ret_len = len;
297 return ret;
300 static int cmp_compos( const void *a, const void *b )
302 int ret = ((unsigned int *)a)[0] - ((unsigned int *)b)[0];
303 if (!ret) ret = ((unsigned int *)a)[1] - ((unsigned int *)b)[1];
304 return ret;
307 static void dump_norm(void)
309 const struct norm_table *info;
310 const BYTE *classes;
311 unsigned int i;
312 char name[13];
314 if (!(info = PRD( 0, sizeof(*info) ))) return;
315 for (i = 0; i < sizeof(name); i++) name[i] = info->name[i];
316 printf( "Name: %s\n", name );
317 switch (info->form)
319 case 1: printf( "Form: NFC\n" ); break;
320 case 2: printf( "Form: NFD\n" ); break;
321 case 5: printf( "Form: NFKC\n" ); break;
322 case 6: printf( "Form: NFKD\n" ); break;
323 case 13: printf( "Form: IDNA\n" ); break;
324 default: printf( "Form: %u\n", info->form ); break;
326 printf( "Version: %u.%u.%u\n", info->version[0], info->version[1], info->version[2] );
327 printf( "Factor: %u\n", info->len_factor );
329 if (info->classes == sizeof(*info) / 2) offset_scale = 2;
330 classes = GET_TABLE( info, classes );
332 printf( "\nCharacter classes:\n" );
333 for (i = 0; i < 0x110000; i++)
335 BYTE flags = get_char_props( info, i );
337 if (!(i % 16)) printf( "\n%06x:", i );
338 if (!flags || (flags & 0x3f) == 0x3f)
340 static const char *flagstr[4] = { ".....", "Undef", "QC=No", "Inval" };
341 printf( " %s", flagstr[flags >> 6] );
343 else
345 static const char flagschar[4] = ".+*M";
346 BYTE class = classes[flags & 0x3f];
347 printf( " %c.%03u", flagschar[flags >> 6], class );
351 printf( "\n\nDecompositions:\n\n" );
352 for (i = 0; i < 0x110000; i++)
354 unsigned int j, len;
355 const WCHAR *decomp = get_decomposition( info, i, &len );
356 if (!decomp) continue;
357 printf( "%04x ->", i );
358 for (j = 0; j < len; j++)
360 unsigned int ch = get_utf16( decomp + j );
361 printf( " %04x", ch );
362 if (ch >= 0x10000) j++;
364 printf( "\n" );
366 if (info->comp_size)
368 unsigned int pos, len = (dump_total_len - info->comp_seq * offset_scale) / sizeof(WCHAR);
369 const WCHAR *seq = GET_TABLE( info, comp_seq );
370 unsigned int *map = xmalloc( len * sizeof(*map) );
372 printf( "\nCompositions:\n\n" );
374 /* ignore hash table, simply dump all the sequences */
375 for (i = pos = 0; i < len; pos += 3)
377 map[pos] = get_utf16( seq + i );
378 i += 1 + (map[pos] >= 0x10000);
379 map[pos+1] = get_utf16( seq + i );
380 i += 1 + (map[pos+1] >= 0x10000);
381 map[pos+2] = get_utf16( seq + i );
382 i += 1 + (map[pos+2] >= 0x10000);
384 qsort( map, pos / 3, 3 * sizeof(*map), cmp_compos );
385 for (i = 0; i < pos; i += 3) printf( "%04x %04x -> %04x\n", map[i], map[i + 1], map[i + 2] );
386 free( map );
388 printf( "\n" );
392 struct sortguid
394 GUID id; /* sort GUID */
395 DWORD flags; /* flags */
396 DWORD compr; /* offset to compression table */
397 DWORD except; /* exception table offset in sortkey table */
398 DWORD ling_except; /* exception table offset for linguistic casing */
399 DWORD casemap; /* linguistic casemap table offset */
402 #define FLAG_HAS_3_BYTE_WEIGHTS 0x01
403 #define FLAG_REVERSEDIACRITICS 0x10
404 #define FLAG_DOUBLECOMPRESSION 0x20
405 #define FLAG_INVERSECASING 0x40
407 struct language_id
409 DWORD offset;
410 WCHAR name[32];
413 struct compression
415 DWORD offset;
416 WCHAR minchar, maxchar;
417 WORD len[8];
420 struct comprlang
422 struct compression compr;
423 WCHAR name[32];
426 static const char *get_sortkey( DWORD key )
428 static char buffer[16];
429 if (!key) return "....";
430 if ((WORD)key == 0x200)
431 sprintf( buffer, "expand %04x", key >> 16 );
432 else
433 sprintf( buffer, "%u.%u.%u.%u", (BYTE)(key >> 8), (BYTE)key, (BYTE)(key >> 16), (BYTE)(key >> 24) );
434 return buffer;
437 static const void *dump_expansions( const DWORD *ptr )
439 DWORD i, count = *ptr++;
441 printf( "\nExpansions: (count=%04x)\n\n", count );
442 for (i = 0; i < count; i++)
444 const WCHAR *p = (const WCHAR *)(ptr + i);
445 printf( " %04x: %04x %04x\n", i, p[0], p[1] );
447 return ptr + count;
450 static void dump_exceptions( const DWORD *sortkeys, DWORD offset )
452 int i, j;
453 const DWORD *table = sortkeys + offset;
455 for (i = 0; i < 0x100; i++)
457 if (table[i] == i * 0x100) continue;
458 for (j = 0; j < 0x100; j++)
460 if (sortkeys[table[i] + j] == sortkeys[i * 0x100 + j]) continue;
461 printf( " %04x: %s\n", i * 0x100 + j, get_sortkey( sortkeys[table[i] + j] ));
466 static const void *dump_compression( const struct compression *compr, const WCHAR *table )
468 int i, j, k;
469 const WCHAR *p = table + compr->offset;
471 printf( " min=%04x max=%04x counts=%u,%u,%u,%u,%u,%u,%u,%u\n",
472 compr->minchar, compr->maxchar,
473 compr->len[0], compr->len[1], compr->len[2], compr->len[3],
474 compr->len[4], compr->len[5], compr->len[6], compr->len[7] );
475 for (i = 0; i < 8; i++)
477 for (j = 0; j < compr->len[i]; j++)
479 printf( " " );
480 for (k = 0; k < i + 2; k++) printf( " %04x", *p++ );
481 p = (const WCHAR *)(((ULONG_PTR)p + 3) & ~3);
482 printf( " -> %s\n", get_sortkey( *(const DWORD *)p ));
483 p += 2;
486 return p;
489 static const void *dump_multiple_weights( const DWORD *ptr )
491 int i, count = *ptr++;
492 const WCHAR *p;
494 printf( "\nMultiple weights: (count=%u)\n\n", count );
495 p = (const WCHAR *)ptr;
496 for (i = 0; i < count; i++)
498 BYTE weight = p[i];
499 BYTE count = p[i] >> 8;
500 printf( "%u - %u\n", weight, weight + count );
502 return ptr + (count + 1) / 2;
505 static void dump_sort( int old_version )
507 const struct
509 DWORD sortkeys;
510 DWORD casemaps;
511 DWORD ctypes;
512 DWORD sortids;
513 } *header;
515 const struct compression *compr;
516 const struct sortguid *guids;
517 const struct comprlang *comprlangs;
518 const struct language_id *language_ids = NULL;
519 const WORD *casemaps, *map;
520 const DWORD *sortkeys, *ptr;
521 const WCHAR *p = NULL;
522 int i, j, size, len;
523 int nb_casemaps = 0, casemap_offsets[16];
525 if (!(header = PRD( 0, sizeof(*header) ))) return;
527 if (!(sortkeys = PRD( header->sortkeys, header->casemaps - header->sortkeys ))) return;
528 printf( "\nSort keys:\n" );
529 for (i = 0; i < 0x10000; i++)
531 if (!(i % 8)) printf( "\n%04x:", i );
532 printf( " %16s", get_sortkey( sortkeys[i] ));
534 printf( "\n\n" );
536 size = (header->ctypes - header->casemaps) / sizeof(*casemaps);
537 if (!(casemaps = PRD( header->casemaps, size * sizeof(*casemaps) ))) return;
538 len = 0;
539 if (old_version)
541 ptr = (const DWORD *)casemaps;
542 len = *ptr++;
543 language_ids = (const struct language_id *)ptr;
544 casemaps = (const WORD *)(language_ids + len);
546 map = casemaps;
547 while (size)
549 const WORD *upper = map + 2;
550 const WORD *lower = map + 2 + map[1];
551 const WORD *end = map + map[1] + 1 + map[map[1] + 1];
553 if (map[0] != 1) break;
554 printf( "\nCase mapping table %u:\n", nb_casemaps );
555 casemap_offsets[nb_casemaps++] = map - casemaps;
556 for (j = 0; j < len; j++)
558 if (language_ids[j].offset != map - casemaps) continue;
559 printf( "Language: %s\n", get_unicode_str( language_ids[j].name, -1 ));
560 break;
562 printf( "\nUpper-case table:\n" );
563 dump_offset_table( upper, lower - upper );
564 printf( "\n\nLower-case table:\n" );
565 dump_offset_table( lower, end - lower );
566 printf( "\n\n" );
567 size -= (end - map);
568 map = end;
571 if (!(p = PRD( header->ctypes, header->sortids - header->ctypes ))) return;
572 printf( "\nCTYPE table:\n\n" );
573 dump_ctype_table( p );
575 printf( "\nSort tables:\n\n" );
576 size = (dump_total_len - header->sortids) / sizeof(*ptr);
577 if (!(ptr = PRD( header->sortids, size * sizeof(*ptr) ))) return;
579 if (old_version)
581 len = *ptr++;
582 for (i = 0; i < len; i++, ptr += 2) printf( "NLS version: %08x %08x\n", ptr[0], ptr[1] );
583 len = *ptr++;
584 for (i = 0; i < len; i++, ptr += 2) printf( "Defined version: %08x %08x\n", ptr[0], ptr[1] );
585 len = *ptr++;
586 printf( "\nReversed diacritics:\n\n" );
587 for (i = 0; i < len; i++)
589 const WCHAR *name = (const WCHAR *)ptr;
590 printf( "%s\n", get_unicode_str( name, -1 ));
591 ptr += 16;
593 len = *ptr++;
594 printf( "\nDouble compression:\n\n" );
595 for (i = 0; i < len; i++)
597 const WCHAR *name = (const WCHAR *)ptr;
598 printf( "%s\n", get_unicode_str( name, -1 ));
599 ptr += 16;
601 ptr = dump_expansions( ptr );
603 printf( "\nCompressions:\n" );
604 size = *ptr++;
605 comprlangs = (const struct comprlang *)ptr;
606 for (i = 0; i < size; i++)
608 printf( "\n %s\n", get_unicode_str( comprlangs[i].name, -1 ));
609 ptr = dump_compression( &comprlangs[i].compr, (const WCHAR *)(comprlangs + size) );
612 ptr = dump_multiple_weights( ptr );
614 size = *ptr++;
615 printf( "\nJamo sort:\n\n" );
616 for (i = 0; i < size; i++, ptr += 2)
618 const struct jamo { BYTE val[5], off, len; } *jamo = (const struct jamo *)ptr;
619 printf( "%04x: %02x %02x %02x %02x %02x off=%02x len=%02x\n", 0x1100 + i, jamo->val[0],
620 jamo->val[1], jamo->val[2], jamo->val[3], jamo->val[4],
621 jamo->off, jamo->len );
624 size = *ptr++;
625 printf( "\nJamo second chars:\n\n" );
626 for (i = 0; i < size; i++, ptr += 2)
628 const struct jamo { WORD ch; BYTE val[5], len; } *jamo = (const struct jamo *)ptr;
629 printf( "%02x: %04x: %02x %02x %02x %02x %02x len=%02x\n", i, jamo->ch, jamo->val[0],
630 jamo->val[1], jamo->val[2], jamo->val[3], jamo->val[4], jamo->len );
633 size = *ptr++;
634 printf( "\nExceptions:\n" );
635 language_ids = (const struct language_id *)ptr;
636 for (i = 0; i < size; i++)
638 printf( "\n %08x %s\n", language_ids[i].offset, get_unicode_str( language_ids[i].name, -1 ));
639 dump_exceptions( sortkeys, language_ids[i].offset );
642 else
644 int guid_count = ptr[1];
645 printf( "NLS version: %08x\n\n", ptr[0] );
646 printf( "Sort GUIDs:\n\n" );
647 guids = (const struct sortguid *)(ptr + 2);
648 for (i = 0; i < guid_count; i++)
650 for (j = 0; j < nb_casemaps; j++) if (casemap_offsets[j] == guids[i].casemap) break;
651 printf( " %s flags=%08x compr=%08x casemap=%d\n", get_guid_str( &guids[i].id ),
652 guids[i].flags, guids[i].compr, j < nb_casemaps ? j : -1 );
655 ptr = dump_expansions( (const DWORD *)(guids + guid_count) );
657 size = *ptr++;
658 printf( "\nCompressions:\n" );
659 compr = (const struct compression *)ptr;
660 for (i = 0; i < size; i++)
662 printf( "\n" );
663 for (j = 0; j < guid_count; j++)
664 if (guids[j].compr == i) printf( " %s\n", get_guid_str( &guids[j].id ));
665 ptr = dump_compression( compr + i, (const WCHAR *)(compr + size) );
668 ptr = dump_multiple_weights( ptr );
670 size = *ptr++;
671 printf( "\nJamo sort:\n\n" );
672 for (i = 0; i < size; i++)
674 static const WCHAR hangul_chars[] =
676 0xa960, 0xa961, 0xa962, 0xa963, 0xa964, 0xa965, 0xa966, 0xa967,
677 0xa968, 0xa969, 0xa96a, 0xa96b, 0xa96c, 0xa96d, 0xa96e, 0xa96f,
678 0xa970, 0xa971, 0xa972, 0xa973, 0xa974, 0xa975, 0xa976, 0xa977,
679 0xa978, 0xa979, 0xa97a, 0xa97b, 0xa97c,
680 0xd7b0, 0xd7b1, 0xd7b2, 0xd7b3, 0xd7b4, 0xd7b5, 0xd7b6, 0xd7b7,
681 0xd7b8, 0xd7b9, 0xd7ba, 0xd7bb, 0xd7bc, 0xd7bd, 0xd7be, 0xd7bf,
682 0xd7c0, 0xd7c1, 0xd7c2, 0xd7c3, 0xd7c4, 0xd7c5, 0xd7c6,
683 0xd7cb, 0xd7cc, 0xd7cd, 0xd7ce, 0xd7cf,
684 0xd7d0, 0xd7d1, 0xd7d2, 0xd7d3, 0xd7d4, 0xd7d5, 0xd7d6, 0xd7d7,
685 0xd7d8, 0xd7d9, 0xd7da, 0xd7db, 0xd7dc, 0xd7dd, 0xd7de, 0xd7df,
686 0xd7e0, 0xd7e1, 0xd7e2, 0xd7e3, 0xd7e4, 0xd7e5, 0xd7e6, 0xd7e7,
687 0xd7e8, 0xd7e9, 0xd7ea, 0xd7eb, 0xd7ec, 0xd7ed, 0xd7ee, 0xd7ef,
688 0xd7f0, 0xd7f1, 0xd7f2, 0xd7f3, 0xd7f4, 0xd7f5, 0xd7f6, 0xd7f7,
689 0xd7f8, 0xd7f9, 0xd7fa, 0xd7fb
691 const BYTE *b = (const BYTE *)(ptr + 2 * i);
692 WCHAR wc = i < 0x100 ? 0x1100 + i : hangul_chars[i - 0x100];
693 printf( "%04x: %02x %02x %02x %02x %02x\n", wc, b[0], b[1], b[2], b[3], b[4] );
696 printf( "\nExceptions:\n" );
697 for (i = 0; i < guid_count; i++)
699 if (!guids[i].except) continue;
700 printf( "\n %s\n", get_guid_str( &guids[i].id ));
701 dump_exceptions( sortkeys, guids[i].except );
702 if (!guids[i].ling_except) continue;
703 printf( "\n %s LINGUISTIC_CASING\n", get_guid_str( &guids[i].id ));
704 dump_exceptions( sortkeys, guids[i].ling_except );
707 printf( "\n" );
710 void nls_dump(void)
712 const char *name = get_basename( globals.input_name );
713 if (!strcasecmp( name, "l_intl.nls" )) return dump_casemap();
714 if (!strncasecmp( name, "c_", 2 )) return dump_codepage();
715 if (!strncasecmp( name, "norm", 4 )) return dump_norm();
716 if (!strcasecmp( name, "sortdefault.nls" )) return dump_sort( 0 );
717 if (!strncasecmp( name, "sort", 4 )) return dump_sort( 1 );
718 fprintf( stderr, "Unrecognized file name '%s'\n", globals.input_name );
721 enum FileSig get_kind_nls(void)
723 if (strlen( globals.input_name ) < 5) return SIG_UNKNOWN;
724 if (strcasecmp( globals.input_name + strlen(globals.input_name) - 4, ".nls" )) return SIG_UNKNOWN;
725 return SIG_NLS;