[ROSAPPS] Add NLS to TXT file converter
[reactos.git] / rosapps / applications / devutils / nls2txt / nls.c
1 /*
2 * PROJECT: ReactOS NLS to TXT Converter
3 * LICENSE: GNU General Public License Version 2.0 or any later version
4 * FILE: devutils/nlsedit/nls.c
5 * COPYRIGHT: Copyright 2016 Dmitry Chapyshev <dmitry@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 static VOID
11 NLS_InitCodePageTable(PUSHORT TableBase, PCPTABLEINFO CodePageTable)
12 {
13 PNLS_FILE_HEADER NlsFileHeader;
14
15 NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
16
17 /* Copy header fields first */
18 CodePageTable->CodePage = NlsFileHeader->CodePage;
19 CodePageTable->MaximumCharacterSize = NlsFileHeader->MaximumCharacterSize;
20 CodePageTable->DefaultChar = NlsFileHeader->DefaultChar;
21 CodePageTable->UniDefaultChar = NlsFileHeader->UniDefaultChar;
22 CodePageTable->TransDefaultChar = NlsFileHeader->TransDefaultChar;
23 CodePageTable->TransUniDefaultChar = NlsFileHeader->TransUniDefaultChar;
24
25 CopyMemory(&CodePageTable->LeadByte, &NlsFileHeader->LeadByte, MAXIMUM_LEADBYTES);
26
27 /* Offset to wide char table is after the header */
28 CodePageTable->WideCharTable = TableBase + NlsFileHeader->HeaderSize + 1 +
29 TableBase[NlsFileHeader->HeaderSize];
30
31 /* Then multibyte table (256 wchars) follows */
32 CodePageTable->MultiByteTable = TableBase + NlsFileHeader->HeaderSize + 1;
33
34 /* Check the presence of glyph table (256 wchars) */
35 if (!CodePageTable->MultiByteTable[256])
36 {
37 CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1;
38 }
39 else
40 {
41 CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1 + 256;
42 }
43
44 /* Is this double-byte code page? */
45 if (*CodePageTable->DBCSRanges)
46 {
47 CodePageTable->DBCSCodePage = 1;
48 CodePageTable->DBCSOffsets = CodePageTable->DBCSRanges + 1;
49 }
50 else
51 {
52 CodePageTable->DBCSCodePage = 0;
53 CodePageTable->DBCSOffsets = NULL;
54 }
55 }
56
57 PUSHORT
58 NLS_ReadFile(const WCHAR *pszFile, PCPTABLEINFO CodePageTable)
59 {
60 HANDLE hFile;
61
62 hFile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
63 if (hFile != INVALID_HANDLE_VALUE)
64 {
65 PUSHORT pData = NULL;
66 DWORD dwRead;
67 DWORD dwFileSize;
68
69 dwFileSize = GetFileSize(hFile, NULL);
70 pData = malloc(dwFileSize);
71 if (pData != NULL)
72 {
73 if (ReadFile(hFile, pData, dwFileSize, &dwRead, NULL) != FALSE)
74 {
75 NLS_InitCodePageTable(pData, CodePageTable);
76 CloseHandle(hFile);
77
78 return pData;
79 }
80
81 free(pData);
82 }
83
84 CloseHandle(hFile);
85 }
86
87 return NULL;
88 }
89
90 BOOL
91 NLS_IsDBCSCodePage(PCPTABLEINFO CodePageTable)
92 {
93 return (BOOL)CodePageTable->DBCSCodePage;
94 }
95
96 BOOL
97 NLS_IsGlyphTablePresent(PCPTABLEINFO CodePageTable)
98 {
99 return (CodePageTable->MultiByteTable[256]) ? TRUE : FALSE;
100 }
101
102 BOOL
103 NLS_IsDefaultCharForMB(PCPTABLEINFO CodePageTable, UCHAR Char)
104 {
105 if (CodePageTable->MultiByteTable[Char] != CodePageTable->UniDefaultChar)
106 return FALSE;
107
108 return TRUE;
109 }
110
111 BOOL
112 NLS_IsDefaultCharForUnicode(PCPTABLEINFO CodePageTable, USHORT Char)
113 {
114 USHORT CodePageChar;
115
116 if (NLS_IsDBCSCodePage(CodePageTable))
117 {
118 PUSHORT MultiByteTable = (PUSHORT)CodePageTable->WideCharTable;
119 CodePageChar = MultiByteTable[Char];
120 }
121 else
122 {
123 PUCHAR SingleByteTable = (PUCHAR)CodePageTable->WideCharTable;
124 CodePageChar = SingleByteTable[Char];
125 }
126
127 if (CodePageChar != CodePageTable->DefaultChar)
128 return FALSE;
129
130 return TRUE;
131 }
132
133 USHORT
134 NLS_RecordsCountForMBTable(PCPTABLEINFO CodePageTable)
135 {
136 USHORT CodePageChar;
137 USHORT Count = 0;
138
139 for (CodePageChar = 0; CodePageChar <= 0xFF; CodePageChar++)
140 {
141 if (!NLS_IsDefaultCharForMB(CodePageTable, CodePageChar))
142 Count++;
143 }
144
145 return Count;
146 }
147
148 USHORT
149 NLS_RecordsCountForUnicodeTable(PCPTABLEINFO CodePageTable)
150 {
151 ULONG UnicodeChar;
152 USHORT Count = 0;
153
154 for (UnicodeChar = 0; UnicodeChar <= 0xFFFF; UnicodeChar++)
155 {
156 if (!NLS_IsDefaultCharForUnicode(CodePageTable, UnicodeChar))
157 Count++;
158 }
159
160 return Count;
161 }
162
163 USHORT
164 NLS_RecordsCountForGlyphTable(PCPTABLEINFO CodePageTable)
165 {
166 USHORT Count = 0;
167
168 if (NLS_IsGlyphTablePresent(CodePageTable))
169 {
170 PUSHORT GlyphTable = CodePageTable->MultiByteTable + 256 + 1;
171 USHORT CodePageChar;
172
173 for (CodePageChar = 0; CodePageChar <= 0xFF; CodePageChar++)
174 {
175 USHORT Char = GlyphTable[CodePageChar];
176
177 if (Char != CodePageTable->UniDefaultChar)
178 Count++;
179 }
180 }
181
182 return Count;
183 }
184
185 USHORT
186 NLS_RecordsCountForDBCSTable(PCPTABLEINFO CodePageTable, UCHAR LeadByte)
187 {
188 PUSHORT LeadByteInfo = CodePageTable->DBCSOffsets;
189 USHORT CodePageChar;
190 USHORT Count = 0;
191
192 for (CodePageChar = 0; CodePageChar <= 0xFF; CodePageChar++)
193 {
194 USHORT Info = LeadByteInfo[LeadByte];
195
196 if (Info && LeadByteInfo[Info + CodePageChar] != CodePageTable->UniDefaultChar)
197 {
198 Count++;
199 }
200 }
201
202 return Count;
203 }