[ROSAPPS] Add initial version txt2nls file converter (DBCS codepages not supported...
[reactos.git] / rosapps / applications / devutils / txt2nls / txt.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/txt.c
5 * COPYRIGHT: Copyright 2016 Dmitry Chapyshev <dmitry@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 int
11 txt_get_header(const char *file_path, NLS_FILE_HEADER *header)
12 {
13 FILE *file;
14 char *p;
15 char buf[256];
16 uint32_t line = 0;
17 int res = 0;
18 int found;
19 uint32_t val;
20
21 file = fopen(file_path, "r");
22 if (!file)
23 {
24 printf("Unable to read TXT file.\n");
25 return 0;
26 }
27
28 /* Find CODEPAGE entry */
29 found = 0;
30 while (fgets(buf, sizeof(buf), file))
31 {
32 ++line;
33
34 p = strstr(buf, "CODEPAGE");
35 if (p)
36 {
37 /* Length of CODEPAGE string is 8 chars */
38 p += 8;
39
40 /* Skip all spaces after CODEPAGE */
41 while (isspace(*p)) ++p;
42
43 /* Convert string to uint32_t */
44 val = strtoul(p, &p, 10);
45
46 /* Validate codepage value */
47 if (val > 0xFFFF)
48 {
49 printf("Wrong codepage: %u (line: %u)\n", val, line);
50 goto Cleanup;
51 }
52
53 header->CodePage = (uint16_t)val;
54
55 found = 1;
56 break;
57 }
58 }
59
60 if (!found)
61 {
62 printf("CODEPAGE not found.\n");
63 goto Cleanup;
64 }
65
66 /* Find CPINFO entry */
67 found = 0;
68 while (fgets(buf, sizeof(buf), file))
69 {
70 ++line;
71
72 p = strstr(buf, "CPINFO");
73 if (p)
74 {
75 /* Length of CPINFO string is 6 chars */
76 p += 6;
77
78 /* Skip all spaces after CPINFO */
79 while (isspace(*p)) ++p;
80
81 /* Convert string to uint32_t */
82 val = strtoul(p, &p, 10);
83
84 /* Validate value */
85 if (val != 1 && val != 2)
86 {
87 printf("Wrong character size: %u (line: %u)\n", val, line);
88 goto Cleanup;
89 }
90
91 header->MaximumCharacterSize = (uint16_t)val;
92
93 /* Skip all spaces after character size */
94 while (isspace(*p)) ++p;
95
96 /* Convert string to uint32_t */
97 val = strtoul(p, &p, 16);
98 header->DefaultChar = (uint16_t)val;
99 header->TransDefaultChar = (uint16_t)val;
100
101 /* Skip all spaces after default char */
102 while (isspace(*p)) ++p;
103
104 /* Convert string to uint32_t */
105 val = strtoul(p, &p, 16);
106 header->UniDefaultChar = (uint16_t)val;
107 header->TransUniDefaultChar = (uint16_t)val;
108
109 found = 1;
110 break;
111 }
112 }
113
114 if (!found)
115 {
116 printf("CPINFO not found.\n");
117 goto Cleanup;
118 }
119
120 header->HeaderSize = sizeof(NLS_FILE_HEADER) / sizeof(uint16_t);
121
122 res = 1;
123
124 Cleanup:
125 fclose(file);
126
127 return res;
128 }
129
130 uint16_t*
131 txt_get_mb_table(const char *file_path, uint16_t uni_default_char)
132 {
133 uint16_t *table;
134 char buf[256];
135 char *p;
136 uint32_t count = 0;
137 uint32_t index;
138 uint32_t line = 0;
139 int found;
140 int res = 0;
141 FILE *file;
142
143 table = malloc(0xFF * sizeof(uint16_t));
144 if (!table)
145 {
146 printf("Memory allocation failure\n");
147 return NULL;
148 }
149
150 /* Set default value for all table items */
151 for (index = 0; index <= 0xFF; index++)
152 table[index] = uni_default_char;
153
154 file = fopen(file_path, "r");
155 if (!file)
156 {
157 printf("Unable to read TXT file.\n");
158 goto Cleanup;
159 }
160
161 /* Find MBTABLE entry */
162 found = 0;
163 while (fgets(buf, sizeof(buf), file))
164 {
165 ++line;
166
167 p = strstr(buf, "MBTABLE");
168 if (p)
169 {
170 p += 7;
171
172 /* Skip spaces */
173 while (isspace(*p)) ++p;
174
175 count = strtoul(p, &p, 10);
176 if (count == 0 || count > 256)
177 {
178 printf("Wrong MBTABLE size: %u (line: %u)\n", count, line);
179 goto Cleanup;
180 }
181
182 found = 1;
183 break;
184 }
185 }
186
187 if (!found)
188 {
189 printf("MBTABLE not found.\n");
190 goto Cleanup;
191 }
192
193 /* Parse next line */
194 while (fgets(buf, sizeof(buf), file) && count)
195 {
196 uint32_t cp_char;
197 uint32_t uni_char;
198
199 ++line;
200
201 p = buf;
202
203 /* Skip spaces */
204 while (isspace(*p)) ++p;
205
206 if (!*p || p[0] == ';')
207 continue;
208
209 cp_char = strtoul(p, &p, 16);
210 if (cp_char > 0xFF)
211 {
212 printf("Wrong char value: %u (line: %u)\n", cp_char, line);
213 goto Cleanup;
214 }
215
216 /* Skip spaces */
217 while (isspace(*p)) ++p;
218
219 uni_char = strtoul(p, &p, 16);
220 if (uni_char > 0xFFFF)
221 {
222 printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line);
223 goto Cleanup;
224 }
225
226 table[cp_char] = uni_char;
227 --count;
228 }
229
230 res = 1;
231
232 Cleanup:
233 if (!res)
234 {
235 free(table);
236 table = NULL;
237 }
238
239 fclose(file);
240
241 return table;
242 }
243
244 uint16_t*
245 txt_get_wc_table(const char *file_path, uint16_t default_char, int is_dbcs)
246 {
247 char buf[256];
248 char *p;
249 uint16_t *table;
250 uint32_t index;
251 uint32_t count = 0;
252 uint32_t line = 0;
253 int res = 0;
254 int found;
255 FILE *file;
256
257 table = malloc(0xFFFF * (is_dbcs ? sizeof(uint16_t) : sizeof(uint8_t)));
258 if (!table)
259 {
260 printf("Memory allocation failure\n");
261 return NULL;
262 }
263
264 /* Set default value for all table items */
265 for (index = 0; index <= 0xFFFF; index++)
266 {
267 /* DBCS code page */
268 if (is_dbcs)
269 {
270 uint16_t *tmp = (uint16_t*)table;
271 tmp[index] = default_char;
272 }
273 /* SBCS code page */
274 else
275 {
276 uint8_t *tmp = (uint8_t*)table;
277 tmp[index] = default_char;
278 }
279 }
280
281 file = fopen(file_path, "r");
282 if (!file)
283 {
284 printf("Unable to read TXT file.\n");
285 goto Cleanup;
286 }
287
288 /* Find WCTABLE entry */
289 found = 0;
290 while (fgets(buf, sizeof(buf), file))
291 {
292 ++line;
293
294 p = strstr(buf, "WCTABLE");
295 if (p)
296 {
297 p += 7;
298
299 /* Skip spaces */
300 while (isspace(*p)) ++p;
301
302 count = strtoul(p, &p, 10);
303 if (count == 0 || count > 65536)
304 {
305 printf("Wrong WCTABLE size: %u (line: %u)\n", count, line);
306 goto Cleanup;
307 }
308
309 found = 1;
310 break;
311 }
312 }
313
314 if (!found)
315 {
316 printf("WCTABLE not found.\n");
317 goto Cleanup;
318 }
319
320 /* Parse next line */
321 while (fgets(buf, sizeof(buf), file) && count)
322 {
323 uint32_t cp_char;
324 uint32_t uni_char;
325
326 ++line;
327
328 p = buf;
329
330 /* Skip spaces */
331 while (isspace(*p)) ++p;
332
333 if (!*p || p[0] == ';')
334 continue;
335
336 uni_char = strtoul(p, &p, 16);
337 if (uni_char > 0xFFFF)
338 {
339 printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line);
340 goto Cleanup;
341 }
342
343 /* Skip spaces */
344 while (isspace(*p)) ++p;
345
346 cp_char = strtoul(p, &p, 16);
347 if ((is_dbcs && cp_char > 0xFFFF) || (!is_dbcs && cp_char > 0xFF))
348 {
349 printf("Wrong char value: %u (line: %u)\n", cp_char, line);
350 goto Cleanup;
351 }
352
353 /* DBCS code page */
354 if (is_dbcs)
355 {
356 uint16_t *tmp = (uint16_t*)table;
357 tmp[uni_char] = cp_char;
358 }
359 /* SBCS code page */
360 else
361 {
362 uint8_t *tmp = (uint8_t*)table;
363 tmp[uni_char] = cp_char;
364 }
365
366 --count;
367 }
368
369 res = 1;
370
371 Cleanup:
372 if (!res)
373 {
374 free(table);
375 table = NULL;
376 }
377
378 fclose(file);
379
380 return table;
381 }
382
383 uint16_t*
384 txt_get_glyph_table(const char *file_path, uint16_t uni_default_char)
385 {
386 uint16_t *table;
387 char buf[256];
388 char *p;
389 uint32_t count = 0;
390 uint32_t index;
391 uint32_t line = 0;
392 int found;
393 int res = 0;
394 FILE *file;
395
396 table = malloc(0xFF * sizeof(uint16_t));
397 if (!table)
398 {
399 printf("Memory allocation failure\n");
400 return NULL;
401 }
402
403 /* Set default value for all table items */
404 for (index = 0; index <= 0xFF; index++)
405 table[index] = uni_default_char;
406
407 file = fopen(file_path, "r");
408 if (!file)
409 {
410 printf("Unable to read TXT file.\n");
411 goto Cleanup;
412 }
413
414 /* Find GLYPHTABLE entry */
415 found = 0;
416 while (fgets(buf, sizeof(buf), file))
417 {
418 ++line;
419
420 p = strstr(buf, "GLYPHTABLE");
421 if (p)
422 {
423 p += 10;
424
425 /* Skip spaces */
426 while (isspace(*p)) ++p;
427
428 count = strtoul(p, &p, 10);
429 if (count == 0 || count > 256)
430 {
431 printf("Wrong GLYPHTABLE size: %u (line: %u)\n", count, line);
432 goto Cleanup;
433 }
434
435 found = 1;
436 break;
437 }
438 }
439
440 if (!found)
441 {
442 printf("GLYPHTABLE not found.\n");
443 goto Cleanup;
444 }
445
446 /* Parse next line */
447 while (fgets(buf, sizeof(buf), file) && count)
448 {
449 uint32_t cp_char;
450 uint32_t uni_char;
451
452 ++line;
453
454 p = buf;
455
456 /* Skip spaces */
457 while (isspace(*p)) ++p;
458
459 if (!*p || p[0] == ';')
460 continue;
461
462 cp_char = strtoul(p, &p, 16);
463 if (cp_char > 0xFF)
464 {
465 printf("Wrong char value: %u (line: %u)\n", cp_char, line);
466 goto Cleanup;
467 }
468
469 /* Skip spaces */
470 while (isspace(*p)) ++p;
471
472 uni_char = strtoul(p, &p, 16);
473 if (uni_char > 0xFFFF)
474 {
475 printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line);
476 goto Cleanup;
477 }
478
479 table[cp_char] = uni_char;
480 --count;
481 }
482
483 res = 1;
484
485 Cleanup:
486 if (!res)
487 {
488 free(table);
489 table = NULL;
490 }
491
492 fclose(file);
493
494 return table;
495 }