[TXT2NLS] TransUniDefaultChar has to be received from WideCharTable. TransDefaultChar...
[reactos.git] / rosapps / applications / devutils / txt2nls / nls.c
1 /*
2 * PROJECT: ReactOS TXT to NLS Converter
3 * LICENSE: GNU General Public License Version 2.0 or any later version
4 * FILE: devutils/txt2nls/nls.c
5 * COPYRIGHT: Copyright 2016 Dmitry Chapyshev <dmitry@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 #define _NLS_DEBUG_PRINT
11
12 #ifdef _NLS_DEBUG_PRINT
13
14 static void
15 nls_print_header(NLS_FILE_HEADER *header)
16 {
17 uint32_t i;
18
19 printf("HEADER:\n");
20 printf("CodePage: %u\n", header->CodePage);
21 printf("Character size: %u\n", header->MaximumCharacterSize);
22 printf("Default char: 0x%02X\n", header->DefaultChar);
23 printf("Default unicode char: 0x%04X\n", header->UniDefaultChar);
24 printf("Trans default char: 0x%02X\n", header->TransUniDefaultChar);
25 printf("Trans default unicode char: 0x%04X\n", header->TransUniDefaultChar);
26
27 for (i = 0; i < MAXIMUM_LEADBYTES; i++)
28 {
29 printf("LeadByte[%u] = 0x%02X\n", i, header->LeadByte[i]);
30 }
31
32 printf("\n");
33 }
34
35 static void
36 nls_print_mb_table(uint16_t *mb_table, uint16_t uni_default_char)
37 {
38 uint32_t ch;
39
40 printf("MBTABLE:\n");
41
42 for (ch = 0; ch <= 0xFF; ch++)
43 {
44 if (mb_table[ch] != uni_default_char)
45 {
46 printf("0x%02X 0x%04X\n", (unsigned int)ch, (unsigned int)mb_table[ch]);
47 }
48 }
49
50 printf("\n");
51 }
52
53 static void
54 nls_print_wc_table(uint16_t *wc_table, uint16_t default_char, int is_dbcs)
55 {
56 uint32_t ch;
57
58 printf("WCTABLE:\n");
59
60 for (ch = 0; ch <= 0xFFFF; ch++)
61 {
62 /* DBCS code page */
63 if (is_dbcs)
64 {
65 uint16_t *table = (uint16_t*)wc_table;
66
67 if (table[ch] != default_char)
68 printf("0x%04X 0x%04X\n", (unsigned int)ch, (unsigned int)table[ch]);
69 }
70 /* SBCS code page */
71 else
72 {
73 uint8_t *table = (uint8_t*)wc_table;
74
75 if (table[ch] != default_char)
76 printf("0x%04X 0x%02X\n", (unsigned int)ch, (unsigned int)table[ch]);
77 }
78 }
79
80 printf("\n");
81 }
82
83 static void
84 nls_print_glyph_table(uint16_t *glyph_table, uint16_t uni_default_char)
85 {
86 uint32_t ch;
87
88 printf("GLYPHTABLE:\n");
89
90 for (ch = 0; ch <= 0xFF; ch++)
91 {
92 if (glyph_table[ch] != uni_default_char)
93 {
94 printf("0x%02X 0x%04X\n", (unsigned int)ch, (unsigned int)glyph_table[ch]);
95 }
96 }
97
98 printf("\n");
99 }
100
101 #endif /* _NLS_DEBUG_PRINT */
102
103 int
104 nls_from_txt(const char *txt_file_path, const char *nls_file_path)
105 {
106 NLS_FILE_HEADER header;
107 FILE *file = NULL;
108 uint16_t *mb_table = NULL;
109 uint16_t *wc_table = NULL;
110 uint16_t *glyph_table = NULL;
111 uint16_t number_of_lb_ranges;
112 uint16_t size;
113 int is_dbcs;
114 int res = 0;
115
116 memset(&header, 0, sizeof(header));
117
118 if (!txt_get_header(txt_file_path, &header))
119 goto Cleanup;
120
121 is_dbcs = (header.MaximumCharacterSize == 2) ? 1 : 0;
122
123 mb_table = txt_get_mb_table(txt_file_path, header.UniDefaultChar);
124 if (!mb_table)
125 goto Cleanup;
126
127 wc_table = txt_get_wc_table(txt_file_path, header.DefaultChar, is_dbcs);
128 if (!wc_table)
129 goto Cleanup;
130
131 /* GLYPHTABLE optionally. We do not leave if it is absent */
132 glyph_table = txt_get_glyph_table(txt_file_path, header.UniDefaultChar);
133
134 if (is_dbcs)
135 {
136 /* DBCS codepage */
137 uint16_t *table = (uint16_t*)wc_table;
138 header.TransUniDefaultChar = table[header.UniDefaultChar];
139 /* TODO: TransDefaultChar for DBCS codepages */
140 }
141 else
142 {
143 /* SBCS codepage */
144 uint8_t *table = (uint8_t*)wc_table;
145 header.TransUniDefaultChar = table[header.UniDefaultChar];
146 header.TransDefaultChar = mb_table[LOBYTE(header.DefaultChar)];
147 }
148
149 #ifdef _NLS_DEBUG_PRINT
150 nls_print_header(&header);
151 nls_print_mb_table(mb_table, header.UniDefaultChar);
152 if (glyph_table)
153 nls_print_glyph_table(glyph_table, header.UniDefaultChar);
154 nls_print_wc_table(wc_table, header.DefaultChar, is_dbcs);
155 #endif /* _NLS_DEBUG_PRINT */
156
157 /* Create binary file with write access */
158 file = fopen(nls_file_path, "wb");
159 if (!file)
160 {
161 printf("Unable to create NLS file.\n");
162 goto Cleanup;
163 }
164
165 /* Write NLS file header */
166 if (fwrite(&header, 1, sizeof(header), file) != sizeof(header))
167 {
168 printf("Unable to write NLS file.\n");
169 goto Cleanup;
170 }
171
172 size = (256 * sizeof(uint16_t)) + /* Primary CP to Unicode table */
173 sizeof(uint16_t) + /* optional OEM glyph table size in words */
174 (glyph_table ? (256 * sizeof(uint16_t)) : 0) + /* OEM glyph table size in words * sizeof(uint16_t) */
175 sizeof(uint16_t) + /* Number of DBCS LeadByte ranges */
176 0 + /* offsets of lead byte sub tables */
177 0 + /* LeadByte sub tables */
178 sizeof(uint16_t); /* Unknown flag */
179
180 size /= sizeof(uint16_t);
181
182 if (fwrite(&size, 1, sizeof(size), file) != sizeof(size))
183 {
184 printf("Unable to write NLS file.\n");
185 goto Cleanup;
186 }
187
188 /* Write multibyte table */
189 if (fwrite(mb_table, 1, (256 * sizeof(uint16_t)), file) != (256 * sizeof(uint16_t)))
190 {
191 printf("Unable to write NLS file.\n");
192 goto Cleanup;
193 }
194
195 /* OEM glyph table size in words */
196 size = (glyph_table ? 256 : 0);
197
198 if (fwrite(&size, 1, sizeof(size), file) != sizeof(size))
199 {
200 printf("Unable to write NLS file.\n");
201 goto Cleanup;
202 }
203
204 if (glyph_table)
205 {
206 /* Write OEM glyph table */
207 if (fwrite(glyph_table, 1, (256 * sizeof(uint16_t)), file) != (256 * sizeof(uint16_t)))
208 {
209 printf("Unable to write NLS file.\n");
210 goto Cleanup;
211 }
212 }
213
214 /* Number of DBCS LeadByte ranges */
215 number_of_lb_ranges = 0;
216 if (fwrite(&number_of_lb_ranges, 1, sizeof(number_of_lb_ranges), file) != sizeof(number_of_lb_ranges))
217 {
218 printf("Unable to write NLS file.\n");
219 goto Cleanup;
220 }
221
222 /* Unknown flag */
223 size = 0;
224 if (fwrite(&size, 1, sizeof(size), file) != sizeof(size))
225 {
226 printf("Unable to write NLS file.\n");
227 goto Cleanup;
228 }
229
230 /* Write wide char table */
231 if (fwrite(wc_table, 1, (65536 * header.MaximumCharacterSize), file) != (65536 * header.MaximumCharacterSize))
232 {
233 printf("Unable to write NLS file.\n");
234 goto Cleanup;
235 }
236
237 res = 1;
238
239 Cleanup:
240 if (file) fclose(file);
241 free(mb_table);
242 free(wc_table);
243 free(glyph_table);
244
245 return res;
246 }