comctl32/tests: Use CRT allocation functions.
[wine.git] / dlls / mlang / mlang.c
blob6b0f2922a7718da8b6ab154b3422e4c68232d90c
1 /*
2 * MLANG Class Factory
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2003,2004 Mike McCormack
6 * Copyright 2004,2005 Dmitry Timoshkov
7 * Copyright 2009 Detlef Riekenberg
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library 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 GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define COBJMACROS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "objbase.h"
36 #include "rpcproxy.h"
37 #include "mlang.h"
38 #include "mimeole.h"
40 #include "wine/debug.h"
41 #include "wine/list.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
45 #include "initguid.h"
47 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
48 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
49 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
51 /* FIXME:
52 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
53 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
56 typedef struct
58 const WCHAR *description;
59 UINT cp;
60 DWORD flags;
61 const WCHAR *web_charset;
62 const WCHAR *header_charset;
63 const WCHAR *body_charset;
64 const WCHAR *alias;
65 } MIME_CP_INFO;
67 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
68 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
70 static const MIME_CP_INFO arabic_cp[] =
72 { L"Arabic (864)",
73 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
74 MIMECONTF_MIME_LATEST,
75 L"ibm864", L"ibm864", L"ibm864" },
76 { L"Arabic (1006)",
77 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
78 MIMECONTF_MIME_LATEST,
79 L"ibm1006", L"ibm1006", L"ibm1006" },
80 { L"Arabic (Windows)",
81 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
82 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
83 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
84 L"windows-1256", L"windows-1256", L"windows-1256" },
85 { L"Arabic (ISO)",
86 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
87 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
88 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
89 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
90 L"iso-8859-6", L"iso-8859-6", L"iso-8859-6" }
92 static const MIME_CP_INFO baltic_cp[] =
94 { L"Baltic (DOS)",
95 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
96 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
97 L"ibm775", L"ibm775", L"ibm775" },
98 { L"Baltic (Windows)",
99 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
100 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
101 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
102 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
103 L"windows-1257", L"windows-1257", L"windows-1257" },
104 { L"Baltic (ISO)",
105 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
106 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
107 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
108 MIMECONTF_MIME_LATEST,
109 L"iso-8859-4", L"iso-8859-4", L"iso-8859-4" },
110 { L"Estonian (ISO)",
111 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
112 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
113 L"iso-8859-13", L"iso-8859-13", L"iso-8859-13" }
115 static const MIME_CP_INFO chinese_simplified_cp[] =
117 { L"Chinese Simplified (Auto-Select)",
118 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
119 MIMECONTF_MIME_LATEST,
120 L"_autodetect_chs", L"_autodetect_chs", L"_autodetect_chs" },
121 { L"Chinese Simplified (GB2312)",
122 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
123 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
124 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
125 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
126 L"gb2312", L"gb2312", L"gb2312" },
127 { L"Chinese Simplified (GB2312-80)",
128 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
129 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
130 L"x-cp20936", L"x-cp20936", L"x-cp20936" },
131 { L"Chinese Simplified (HZ)",
132 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
133 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
134 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
135 MIMECONTF_MIME_LATEST,
136 L"hz-gb-2312", L"hz-gb-2312", L"hz-gb-2312" },
137 { L"Chinese Simplified (GB18030)",
138 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
139 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
140 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
141 MIMECONTF_MIME_LATEST,
142 L"GB18030", L"GB18030", L"GB18030" },
143 { L"Chinese Simplified (GBK)",
144 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
145 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
146 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
147 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
148 L"gbk", L"gbk", L"gbk" }
150 static const MIME_CP_INFO chinese_traditional_cp[] =
152 { L"Chinese Traditional (Auto-Select)",
153 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
154 MIMECONTF_MIME_LATEST,
155 L"_autodetect_cht", L"_autodetect_cht", L"_autodetect_cht" },
156 { L"Chinese Traditional (Big5)",
157 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
158 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
159 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
160 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
161 L"big5", L"big5", L"big5" },
162 { L"Chinese Traditional (CNS)",
163 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
164 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
165 L"x-Chinese-CNS", L"x-Chinese-CNS", L"x-Chinese-CNS" }
167 static const MIME_CP_INFO central_european_cp[] =
169 { L"Central European (DOS)",
170 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
171 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
172 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
173 L"ibm852", L"ibm852", L"ibm852" },
174 { L"Central European (Windows)",
175 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
176 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
177 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
178 MIMECONTF_MIME_LATEST,
179 L"windows-1250", L"windows-1250", L"windows-1250" },
180 { L"Central European (Mac)",
181 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
182 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
183 L"x-mac-ce", L"x-mac-ce", L"x-mac-ce" },
184 { L"Central European (ISO)",
185 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
186 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
187 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
188 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
189 L"iso-8859-2", L"iso-8859-2", L"iso-8859-2" }
191 static const MIME_CP_INFO cyrillic_cp[] =
193 { L"OEM Cyrillic",
194 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
195 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
196 L"ibm855", L"ibm855", L"ibm855" },
197 { L"Cyrillic (DOS)",
198 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
199 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
200 MIMECONTF_MIME_LATEST,
201 L"cp866", L"cp866", L"cp866" },
202 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
203 { L"Cyrillic (KOI8-R)",
204 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
205 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
206 L"koi8-r", L"koi8-r", L"koi8-r" },
207 #endif
208 { L"Cyrillic (Windows)",
209 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
210 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
211 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
212 L"windows-1251", L"windows-1251", L"windows-1251" },
213 { L"Cyrillic (Mac)",
214 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
215 MIMECONTF_MIME_LATEST,
216 L"x-mac-cyrillic", L"x-mac-cyrillic", L"x-mac-cyrillic" },
217 { L"Cyrillic (KOI8-R)",
218 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
219 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
220 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
221 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
222 L"koi8-r", L"koi8-r", L"koi8-r" },
223 { L"Cyrillic (KOI8-U)",
224 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
225 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
226 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
227 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
228 L"koi8-u", L"koi8-u", L"koi8-u" },
229 { L"Cyrillic (ISO)",
230 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
231 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
232 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
233 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
234 L"iso-8859-5", L"iso-8859-5", L"iso-8859-5" }
236 static const MIME_CP_INFO greek_cp[] =
238 { L"Greek (DOS)",
239 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
240 MIMECONTF_MIME_LATEST,
241 L"ibm737", L"ibm737", L"ibm737" },
242 { L"Greek, Modern (DOS)",
243 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
244 MIMECONTF_MIME_LATEST,
245 L"ibm869", L"ibm869", L"ibm869" },
246 { L"IBM EBCDIC (Greek Modern)",
247 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
248 MIMECONTF_MIME_LATEST,
249 L"cp875", L"cp875", L"cp875" },
250 { L"Greek (Windows)",
251 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
252 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
253 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
254 L"windows-1253", L"windows-1253", L"windows-1253" },
255 { L"Greek (Mac)",
256 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
257 MIMECONTF_MIME_LATEST,
258 L"x-mac-greek", L"x-mac-greek", L"x-mac-greek" },
259 { L"Greek (ISO)",
260 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
261 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
262 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
263 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
264 L"iso-8859-7", L"iso-8859-7", L"iso-8859-7" }
266 static const MIME_CP_INFO hebrew_cp[] =
268 { L"Hebrew (424)",
269 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
270 MIMECONTF_MIME_LATEST,
271 L"ibm424", L"ibm424", L"ibm424" },
272 { L"Hebrew (856)",
273 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
274 MIMECONTF_MIME_LATEST,
275 L"cp856", L"cp856", L"cp856" },
276 { L"Hebrew (DOS)",
277 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
278 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
279 MIMECONTF_MIME_LATEST,
280 L"dos-862", L"dos-862", L"dos-862" },
281 { L"Hebrew (Windows)",
282 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
283 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
284 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
285 L"windows-1255", L"windows-1255", L"windows-1255" },
286 { L"Hebrew (ISO-Visual)",
287 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
288 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
289 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
290 L"iso-8859-8", L"iso-8859-8", L"iso-8859-8" }
292 static const MIME_CP_INFO japanese_cp[] =
294 { L"Japanese (Auto-Select)",
295 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
296 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
297 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
298 L"_autodetect", L"_autodetect", L"_autodetect" },
299 { L"Japanese (EUC)",
300 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
301 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
302 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
303 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
304 L"euc-jp", L"euc-jp", L"euc-jp" },
305 { L"Japanese (JIS)",
306 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
307 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
308 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
309 MIMECONTF_MIME_IE4,
310 L"iso-2022-jp", L"iso-2022-jp", L"iso-2022-jp"},
311 { L"Japanese (JIS 0208-1990 and 0212-1990)",
312 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
313 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
314 L"EUC-JP", L"EUC-JP", L"EUC-JP"},
315 { L"Japanese (JIS-Allow 1 byte Kana)",
316 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
317 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
318 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
319 L"csISO2022JP", L"iso-2022-jp", L"iso-2022-jp"},
320 { L"Japanese (JIS-Allow 1 byte Kana - SO/SI)",
321 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
322 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
323 L"iso-2022-jp", L"iso-2022-jp", L"iso-2022-jp"},
324 { L"Japanese (Mac)",
325 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
326 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
327 L"x-mac-japanese", L"x-mac-japanese", L"x-mac-japanese"},
328 { L"Japanese (Shift-JIS)",
329 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
330 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
331 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
332 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
333 L"shift_jis", L"iso-2022-jp", L"iso-2022-jp" }
335 static const MIME_CP_INFO korean_cp[] =
337 { L"Korean",
338 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
339 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
340 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
341 MIMECONTF_MIME_LATEST,
342 L"ks_c_5601-1987", L"ks_c_5601-1987", L"ks_c_5601-1987" }
344 static const MIME_CP_INFO thai_cp[] =
346 { L"Thai (Windows)",
347 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
348 L"ibm-thai", L"ibm-thai", L"ibm-thai" }
350 static const MIME_CP_INFO turkish_cp[] =
352 { L"Turkish (DOS)",
353 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
354 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
355 L"ibm857", L"ibm857", L"ibm857" },
356 { L"IBM EBCDIC (Turkish Latin-5)",
357 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
358 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
359 L"ibm1026", L"ibm1026", L"ibm1026" },
360 { L"Turkish (Windows)",
361 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
362 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
363 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
364 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
365 L"windows-1254", L"windows-1254", L"windows-1254" },
366 { L"Turkish (Mac)",
367 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
368 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
369 L"x-mac-turkish", L"x-mac-turkish", L"x-mac-turkish" },
370 { L"Latin 3 (ISO)",
371 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
372 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
373 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
374 L"iso-8859-3", L"iso-8859-3", L"iso-8859-3" },
375 { L"Turkish (ISO)",
376 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
377 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
378 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
379 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
380 L"iso-8859-9", L"iso-8859-9", L"iso-8859-9" }
382 static const MIME_CP_INFO vietnamese_cp[] =
384 { L"Vietnamese (Windows)",
385 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
386 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
387 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
388 MIMECONTF_MIME_LATEST,
389 L"windows-1258", L"windows-1258", L"windows-1258" }
392 static const MIME_CP_INFO western_cp[] =
394 { L"IBM EBCDIC (US-Canada)",
395 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
396 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
397 L"ibm037", L"ibm037", L"ibm037" },
398 { L"OEM United States",
399 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
400 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
401 L"ibm437", L"ibm437", L"ibm437" },
402 { L"IBM EBCDIC (International)",
403 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
404 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
405 L"ibm500", L"ibm500", L"ibm500" },
406 { L"Western European (DOS)",
407 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
408 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
409 L"ibm850", L"ibm850", L"ibm850" },
410 { L"Portuguese (DOS)",
411 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
412 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
413 L"ibm860", L"ibm860", L"ibm860" },
414 { L"Icelandic (DOS)",
415 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
416 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
417 L"ibm861", L"ibm861", L"ibm861" },
418 { L"French Canadian (DOS)",
419 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
420 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
421 L"ibm863", L"ibm863", L"ibm863" },
422 { L"Nordic (DOS)",
423 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
424 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
425 L"ibm865", L"ibm865", L"ibm865" },
426 { L"Western European (Windows)",
427 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
428 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
429 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
430 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
431 L"windows-1252", L"windows-1252", L"iso-8859-1" },
432 { L"Western European (Mac)",
433 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
434 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
435 L"macintosh", L"macintosh", L"macintosh" },
436 { L"Icelandic (Mac)",
437 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
438 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
439 L"x-mac-icelandic", L"x-mac-icelandic", L"x-mac-icelandic" },
440 { L"US-ASCII",
441 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
442 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
443 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
444 L"us-ascii", L"us-ascii", L"us-ascii", L"ascii" },
445 { L"Western European (ISO)",
446 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
447 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
448 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
449 MIMECONTF_MIME_LATEST,
450 L"iso-8859-1", L"iso-8859-1", L"iso-8859-1" },
451 { L"Latin 9 (ISO)",
452 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
453 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
454 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
455 MIMECONTF_MIME_LATEST,
456 L"iso-8859-15", L"iso-8859-15", L"iso-8859-15" }
458 static const MIME_CP_INFO unicode_cp[] =
460 { L"Unicode",
461 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
462 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
463 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
464 MIMECONTF_MIME_LATEST,
465 L"unicode", L"unicode", L"unicode" },
466 { L"Unicode (UTF-7)",
467 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
468 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
469 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
470 L"utf-7", L"utf-7", L"utf-7" },
471 { L"Unicode (UTF-8)",
472 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
473 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
474 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
475 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
476 L"utf-8", L"utf-8", L"utf-8" }
479 static const struct mlang_data
481 const WCHAR *description;
482 UINT family_codepage;
483 UINT number_of_cp;
484 const MIME_CP_INFO *mime_cp_info;
485 const WCHAR *fixed_font;
486 const WCHAR *proportional_font;
487 SCRIPT_ID sid;
488 } mlang_data[] =
490 { L"Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
491 L"Simplified Arabic Fixed", L"Simplified Arabic", sidArabic },
492 { L"Baltic", 1257, ARRAY_SIZE(baltic_cp), baltic_cp,
493 L"Courier New", L"Arial", sidAsciiLatin },
494 { L"Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
495 L"Simsun", L"Simsun", sidHan },
496 { L"Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
497 L"MingLiu", L"New MingLiu", sidBopomofo },
498 { L"Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
499 L"Courier New", L"Arial", sidAsciiLatin },
500 { L"Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
501 L"Courier New", L"Arial", sidCyrillic },
502 { L"Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
503 L"Courier New", L"Arial", sidGreek },
504 { L"Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
505 L"Miriam Fixed", L"David", sidHebrew },
506 { L"Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
507 L"MS Gothic", L"MS PGothic", sidKana },
508 { L"Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
509 L"GulimChe", L"Gulim", sidHangul },
510 { L"Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
511 L"Tahoma", L"Tahoma", sidThai },
512 { L"Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
513 L"Courier New", L"Arial", sidAsciiLatin },
514 { L"Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
515 L"Courier New", L"Arial", sidAsciiLatin },
516 { L"Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
517 L"Courier New", L"Arial", sidAsciiLatin },
518 { L"Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
519 L"Courier New", L"Arial" }
522 struct font_list
524 struct list list_entry;
525 HFONT base_font;
526 HFONT font;
527 UINT charset;
530 static struct list font_cache = LIST_INIT(font_cache);
531 static CRITICAL_SECTION font_cache_critical;
532 static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
534 0, 0, &font_cache_critical,
535 { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
536 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
538 static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
540 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
542 static LONG dll_count;
545 * Japanese Detection and Conversion Functions
548 #define HANKATA(A) ((A >= 161) && (A <= 223))
549 #define ISEUC(A) ((A >= 161) && (A <= 254))
550 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
551 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
552 #define SJIS2(A) ((A >= 64) && (A <= 252))
553 #define ISMARU(A) ((A >= 202) && (A <= 206))
554 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
556 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
558 UINT code = 0;
559 DWORD i = 0;
560 unsigned char c1,c2;
562 while ((code == 0 || code == 51932) && i < count)
564 c1 = input[i];
565 if (c1 == 0x1b /* ESC */)
567 i++;
568 if (i >= count)
569 return code;
570 c1 = input[i];
571 if (c1 == '$')
573 i++;
574 if (i >= count)
575 return code;
576 c1 = input[i];
577 if (c1 =='B' || c1 == '@')
578 code = 50220;
580 if (c1 == 'K')
581 code = 50220;
583 else if (c1 >= 129)
585 i++;
586 if (i >= count)
587 return code;
588 c2 = input[i];
589 if NOTEUC(c1,c2)
590 code = 932;
591 else if (ISEUC(c1) && ISEUC(c2))
592 code = 51932;
593 else if (((c1 == 142)) && HANKATA(c2))
594 code = 51932;
596 i++;
598 return code;
601 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
603 unsigned char c1 = *p1;
604 unsigned char c2 = *p2;
605 int row = c1 < 95 ? 112 : 176;
606 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
608 *p1 = ((c1 + 1) >> 1) + row;
609 *p2 = c2 + cell;
612 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
614 unsigned char c1 = *p1;
615 unsigned char c2 = *p2;
616 int shift = c2 < 159;
617 int row = c1 < 160 ? 112 : 176;
618 int cell = shift ? (31 + (c2 > 127)): 126;
620 *p1 = ((c1 - row) << 1) - shift;
621 *p2 -= cell;
624 static int han2zen(unsigned char *p1, unsigned char *p2)
626 BOOL maru = FALSE;
627 BOOL nigori = FALSE;
628 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
629 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
630 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
631 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
632 131,129,129 };
633 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
634 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
635 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
636 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
638 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
639 nigori = TRUE;
640 else if ((*p2 == 223) && (ISMARU(*p1)))
641 maru = TRUE;
643 if (*p1 >= 161 && *p1 <= 223)
645 unsigned char index = *p1 - 161;
646 *p1 = char1[index];
647 *p2 = char2[index];
650 if (maru || nigori)
652 if (nigori)
654 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
655 (*p2)++;
656 else if ((*p1 == 131) && (*p2 == 69))
657 *p2 = 148;
659 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
660 *p2+= 2;
662 return 1;
665 return 0;
669 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
671 DWORD i = 0;
672 int j = 0;
673 unsigned char p2,p;
674 BOOL shifted = FALSE;
676 while (i < count)
678 p = input[i];
679 if (p == 0x1b /* ESC */)
681 i++;
682 if (i >= count)
683 return 0;
684 p2 = input[i];
685 if (p2 == '$' || p2 =='(')
686 i++;
687 if (p2 == 'K' || p2 =='$')
688 shifted = TRUE;
689 else
690 shifted = FALSE;
692 else
694 if (shifted)
696 i++;
697 if (i >= count)
698 return 0;
699 p2 = input[i];
700 jis2sjis(&p,&p2);
701 output[j++]=p;
702 output[j++]=p2;
704 else
706 output[j++] = p;
709 i++;
711 return j;
714 static inline int exit_shift(LPSTR out, int c)
716 if (out)
718 out[c] = 0x1b;
719 out[c+1] = '(';
720 out[c+2] = 'B';
722 return 3;
725 static inline int enter_shift(LPSTR out, int c)
727 if (out)
729 out[c] = 0x1b;
730 out[c+1] = '$';
731 out[c+2] = 'B';
733 return 3;
737 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
739 DWORD i = 0;
740 int j = 0;
741 unsigned char p2,p;
742 BOOL shifted = FALSE;
744 while (i < count)
746 p = input[i] & 0xff;
747 if (p == 10 || p == 13) /* NL and CR */
749 if (shifted)
751 shifted = FALSE;
752 j += exit_shift(output,j);
754 if (output)
755 output[j++] = p;
756 else
757 j++;
759 else
761 if (SJIS1(p))
763 i++;
764 if (i >= count)
765 return 0;
766 p2 = input[i] & 0xff;
767 if (SJIS2(p2))
769 sjis2jis(&p,&p2);
770 if (!shifted)
772 shifted = TRUE;
773 j+=enter_shift(output,j);
777 if (output)
779 output[j++]=p;
780 output[j++]=p2;
782 else
783 j+=2;
785 else
787 if (HANKATA(p))
789 if ((i+1) >= count)
790 return 0;
791 p2 = input[i+1] & 0xff;
792 i+=han2zen(&p,&p2);
793 sjis2jis(&p,&p2);
794 if (!shifted)
796 shifted = TRUE;
797 j+=enter_shift(output,j);
799 if (output)
801 output[j++]=p;
802 output[j++]=p2;
804 else
805 j+=2;
807 else
809 if (shifted)
811 shifted = FALSE;
812 j += exit_shift(output,j);
814 if (output)
815 output[j++]=p;
816 else
817 j++;
821 i++;
823 if (shifted)
824 j += exit_shift(output,j);
825 return j;
828 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
829 LPWSTR output, DWORD out_count)
831 CHAR *sjis_string;
832 UINT rc = 0;
833 sjis_string = malloc(count);
834 rc = ConvertJIS2SJIS(input,count,sjis_string);
835 if (rc)
837 TRACE("%s\n",debugstr_an(sjis_string,rc));
838 if (output)
839 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
840 else
841 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
843 free(sjis_string);
844 return rc;
848 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
849 LPWSTR output, DWORD out_count)
851 CHAR *sjis_string;
852 UINT rc = 0;
853 int code = DetectJapaneseCode(input,count);
854 TRACE("Japanese code %i\n",code);
856 switch (code)
858 case 0:
859 if (output)
860 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
861 else
862 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
863 break;
865 case 932:
866 if (output)
867 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
868 else
869 rc = MultiByteToWideChar(932,0,input,count,0,0);
870 break;
872 case 51932:
873 if (output)
874 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
875 else
876 rc = MultiByteToWideChar(20932,0,input,count,0,0);
877 break;
879 case 50220:
880 sjis_string = malloc(count);
881 rc = ConvertJIS2SJIS(input,count,sjis_string);
882 if (rc)
884 TRACE("%s\n",debugstr_an(sjis_string,rc));
885 if (output)
886 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
887 else
888 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
890 free(sjis_string);
891 break;
893 return rc;
896 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
897 LPSTR output, DWORD out_count)
899 CHAR *sjis_string;
900 INT len;
901 UINT rc = 0;
903 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
904 sjis_string = malloc(len);
905 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
906 TRACE("%s\n",debugstr_an(sjis_string,len));
908 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
909 if (out_count >= rc)
911 ConvertSJIS2JIS(sjis_string, len, output);
913 free(sjis_string);
914 return rc;
919 * Dll lifetime tracking declaration
921 static void LockModule(void)
923 InterlockedIncrement(&dll_count);
926 static void UnlockModule(void)
928 InterlockedDecrement(&dll_count);
931 HRESULT WINAPI ConvertINetMultiByteToUnicode(
932 LPDWORD pdwMode,
933 DWORD dwEncoding,
934 LPCSTR pSrcStr,
935 LPINT pcSrcSize,
936 LPWSTR pDstStr,
937 LPINT pcDstSize)
939 INT src_len = -1;
941 TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
942 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
944 if (!pcDstSize)
945 return E_FAIL;
947 if (!pcSrcSize)
948 pcSrcSize = &src_len;
950 if (!*pcSrcSize)
952 *pcDstSize = 0;
953 return S_OK;
956 /* forwarding euc-jp to EUC-JP */
957 if (dwEncoding == 51932)
958 dwEncoding = 20932;
960 switch (dwEncoding)
962 case CP_UNICODE:
963 if (*pcSrcSize == -1)
964 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
965 *pcDstSize = min(*pcSrcSize, *pcDstSize);
966 *pcSrcSize *= sizeof(WCHAR);
967 if (pDstStr)
968 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
969 break;
971 case 50220:
972 case 50221:
973 case 50222:
974 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
975 break;
976 case 50932:
977 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
978 break;
980 default:
981 if (*pcSrcSize == -1)
982 *pcSrcSize = lstrlenA(pSrcStr);
984 if (pDstStr)
985 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
986 else
987 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
988 break;
991 if (!*pcDstSize)
992 return E_FAIL;
994 return S_OK;
997 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
998 LPDWORD pdwMode,
999 DWORD dwEncoding,
1000 LPCWSTR pSrcStr,
1001 LPINT pcSrcSize,
1002 LPSTR pDstStr,
1003 LPINT pcDstSize)
1005 INT destsz, size;
1006 INT src_len = -1;
1008 TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
1009 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1011 if (!pcDstSize)
1012 return S_OK;
1014 if (!pcSrcSize)
1015 pcSrcSize = &src_len;
1017 destsz = (pDstStr) ? *pcDstSize : 0;
1018 *pcDstSize = 0;
1020 if (!pSrcStr || !*pcSrcSize)
1021 return S_OK;
1023 if (*pcSrcSize == -1)
1024 *pcSrcSize = lstrlenW(pSrcStr);
1026 /* forwarding euc-jp to EUC-JP */
1027 if (dwEncoding == 51932)
1028 dwEncoding = 20932;
1030 if (dwEncoding == CP_UNICODE)
1032 if (*pcSrcSize == -1)
1033 *pcSrcSize = lstrlenW(pSrcStr);
1035 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1036 if (pDstStr)
1037 memmove(pDstStr, pSrcStr, size);
1039 if (size >= destsz)
1040 goto fail;
1042 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1044 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1045 if (!size)
1046 goto fail;
1048 if (pDstStr)
1050 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1051 destsz);
1052 if (!size)
1053 goto fail;
1057 else
1059 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1060 NULL, 0, NULL, NULL);
1061 if (!size)
1062 goto fail;
1064 if (pDstStr)
1066 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1067 pDstStr, destsz, NULL, NULL);
1068 if (!size)
1069 goto fail;
1073 *pcDstSize = size;
1074 return S_OK;
1076 fail:
1077 *pcSrcSize = 0;
1078 *pcDstSize = 0;
1079 return E_FAIL;
1082 HRESULT WINAPI ConvertINetString(
1083 LPDWORD pdwMode,
1084 DWORD dwSrcEncoding,
1085 DWORD dwDstEncoding,
1086 LPCSTR pSrcStr,
1087 LPINT pcSrcSize,
1088 LPSTR pDstStr,
1089 LPINT pcDstSize
1092 TRACE("%p %ld %ld %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1093 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1095 if (dwSrcEncoding == CP_UNICODE)
1097 INT cSrcSizeW;
1098 if (pcSrcSize && *pcSrcSize != -1)
1100 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1101 pcSrcSize = &cSrcSizeW;
1103 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1105 else if (dwDstEncoding == CP_UNICODE)
1107 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1108 *pcDstSize *= sizeof(WCHAR);
1109 return hr;
1111 else
1113 INT cDstSizeW;
1114 LPWSTR pDstStrW;
1115 HRESULT hr;
1117 TRACE("convert %s from %ld to %ld\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1119 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1120 if (hr != S_OK)
1121 return hr;
1123 pDstStrW = malloc(cDstSizeW * sizeof(WCHAR));
1124 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1125 if (hr == S_OK)
1126 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1128 free(pDstStrW);
1129 return hr;
1133 static HRESULT GetFamilyCodePage(
1134 UINT uiCodePage,
1135 UINT* puiFamilyCodePage)
1137 UINT i, n;
1139 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1141 if (!puiFamilyCodePage) return S_FALSE;
1143 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1145 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1147 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1149 *puiFamilyCodePage = mlang_data[i].family_codepage;
1150 return S_OK;
1155 return S_FALSE;
1158 HRESULT WINAPI IsConvertINetStringAvailable(
1159 DWORD dwSrcEncoding,
1160 DWORD dwDstEncoding)
1162 UINT src_family, dst_family;
1164 TRACE("%ld %ld\n", dwSrcEncoding, dwDstEncoding);
1166 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1167 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1168 return S_FALSE;
1170 if (src_family == dst_family) return S_OK;
1172 /* we can convert any codepage to/from unicode */
1173 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1175 return S_FALSE;
1178 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1180 CHAR buffer[MAX_RFC1766_NAME];
1181 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1182 INT i;
1184 if (n)
1186 i = PRIMARYLANGID(lcid);
1187 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1188 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1189 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1191 buffer[n - 1] = '-';
1192 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1193 if (!i)
1194 buffer[n - 1] = '\0';
1196 else
1197 i = 0;
1199 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1200 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1202 return E_FAIL;
1205 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1207 WCHAR buffer[MAX_RFC1766_NAME];
1208 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1209 INT i;
1211 if (n)
1213 i = PRIMARYLANGID(lcid);
1214 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1215 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1216 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1218 buffer[n - 1] = '-';
1219 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1220 if (!i)
1221 buffer[n - 1] = '\0';
1223 else
1224 i = 0;
1226 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1227 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1229 return E_FAIL;
1232 HRESULT WINAPI LcidToRfc1766A(
1233 LCID lcid,
1234 LPSTR pszRfc1766,
1235 INT nChar)
1237 TRACE("%04lx %p %u\n", lcid, pszRfc1766, nChar);
1238 if (!pszRfc1766)
1239 return E_INVALIDARG;
1241 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1244 HRESULT WINAPI LcidToRfc1766W(
1245 LCID lcid,
1246 LPWSTR pszRfc1766,
1247 INT nChar)
1249 TRACE("%04lx %p %u\n", lcid, pszRfc1766, nChar);
1250 if (!pszRfc1766)
1251 return E_INVALIDARG;
1253 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1256 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1258 RFC1766INFO info;
1259 ULONG num;
1261 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1263 if (!wcsicmp(info.wszRfc1766, rfc1766))
1265 *lcid = info.lcid;
1266 return S_OK;
1268 if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1270 *lcid = PRIMARYLANGID(info.lcid);
1271 return S_OK;
1275 return E_FAIL;
1278 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1280 IEnumRfc1766 *enumrfc1766;
1281 HRESULT hr;
1283 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1285 if (!pLocale || !pszRfc1766)
1286 return E_INVALIDARG;
1288 hr = EnumRfc1766_create(0, &enumrfc1766);
1289 if (FAILED(hr))
1290 return hr;
1292 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1293 IEnumRfc1766_Release(enumrfc1766);
1295 return hr;
1298 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1300 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1302 if (!rfc1766A)
1303 return E_INVALIDARG;
1305 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1306 rfc1766W[MAX_RFC1766_NAME] = 0;
1308 return Rfc1766ToLcidW(lcid, rfc1766W);
1311 static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
1313 struct font_list *font_list_entry;
1314 CHARSETINFO charset_info;
1315 HFONT new_font, old_font;
1316 LOGFONTW font_attr;
1317 DWORD mask, Csb[2];
1318 BOOL found_cached;
1319 UINT charset;
1320 BOOL ret;
1321 UINT i;
1323 if (hdc == NULL || src_font == NULL) return E_FAIL;
1325 for (i = 0; i < 32; i++)
1327 mask = (DWORD)(1 << i);
1328 if (codepages & mask)
1330 Csb[0] = mask;
1331 Csb[1] = 0x0;
1332 ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
1333 if (!ret) continue;
1335 /* use cached font if possible */
1336 found_cached = FALSE;
1337 EnterCriticalSection(&font_cache_critical);
1338 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1340 if (font_list_entry->charset == charset_info.ciCharset &&
1341 font_list_entry->base_font == src_font)
1343 if (dst_font != NULL)
1344 *dst_font = font_list_entry->font;
1345 found_cached = TRUE;
1348 LeaveCriticalSection(&font_cache_critical);
1349 if (found_cached) return S_OK;
1351 GetObjectW(src_font, sizeof(font_attr), &font_attr);
1352 font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
1353 font_attr.lfWidth = 0;
1354 font_attr.lfFaceName[0] = 0;
1355 new_font = CreateFontIndirectW(&font_attr);
1356 if (new_font == NULL) continue;
1358 old_font = SelectObject(hdc, new_font);
1359 charset = GetTextCharset(hdc);
1360 SelectObject(hdc, old_font);
1361 if (charset == charset_info.ciCharset)
1363 font_list_entry = malloc(sizeof(*font_list_entry));
1364 if (font_list_entry == NULL) return E_OUTOFMEMORY;
1366 font_list_entry->base_font = src_font;
1367 font_list_entry->font = new_font;
1368 font_list_entry->charset = charset;
1370 EnterCriticalSection(&font_cache_critical);
1371 list_add_tail(&font_cache, &font_list_entry->list_entry);
1372 LeaveCriticalSection(&font_cache_critical);
1374 if (dst_font != NULL)
1375 *dst_font = new_font;
1376 return S_OK;
1381 return E_FAIL;
1384 static HRESULT release_font(HFONT font)
1386 struct font_list *font_list_entry;
1387 HRESULT hr;
1389 hr = E_FAIL;
1390 EnterCriticalSection(&font_cache_critical);
1391 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1393 if (font_list_entry->font == font)
1395 list_remove(&font_list_entry->list_entry);
1396 DeleteObject(font);
1397 free(font_list_entry);
1398 hr = S_OK;
1399 break;
1402 LeaveCriticalSection(&font_cache_critical);
1404 return hr;
1407 static HRESULT clear_font_cache(void)
1409 struct font_list *font_list_entry;
1410 struct font_list *font_list_entry2;
1412 EnterCriticalSection(&font_cache_critical);
1413 LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
1415 list_remove(&font_list_entry->list_entry);
1416 DeleteObject(font_list_entry->font);
1417 free(font_list_entry);
1419 LeaveCriticalSection(&font_cache_critical);
1421 return S_OK;
1424 /******************************************************************************
1425 * MLANG ClassFactory
1427 typedef struct {
1428 IClassFactory IClassFactory_iface;
1429 LONG ref;
1430 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1431 } IClassFactoryImpl;
1433 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1435 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1438 struct object_creation_info
1440 const CLSID *clsid;
1441 LPCSTR szClassName;
1442 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1445 static const struct object_creation_info object_creation[] =
1447 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1448 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1451 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1453 TRACE("%s\n", debugstr_guid(riid) );
1455 if (IsEqualGUID(riid, &IID_IUnknown)
1456 || IsEqualGUID(riid, &IID_IClassFactory))
1458 IClassFactory_AddRef(iface);
1459 *ppobj = iface;
1460 return S_OK;
1463 *ppobj = NULL;
1464 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1465 return E_NOINTERFACE;
1468 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1470 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1471 return InterlockedIncrement(&This->ref);
1474 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1476 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1477 ULONG ref = InterlockedDecrement(&This->ref);
1479 if (ref == 0)
1481 TRACE("Destroying %p\n", This);
1482 free(This);
1485 return ref;
1488 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1489 REFIID riid, void **ppobj)
1491 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1492 HRESULT hres;
1493 LPUNKNOWN punk;
1495 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1497 *ppobj = NULL;
1498 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1499 if (SUCCEEDED(hres)) {
1500 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1501 IUnknown_Release(punk);
1503 TRACE("returning (%p) -> %lx\n", *ppobj, hres);
1504 return hres;
1507 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1509 if (dolock)
1510 LockModule();
1511 else
1512 UnlockModule();
1514 return S_OK;
1517 static const IClassFactoryVtbl MLANGCF_Vtbl =
1519 MLANGCF_QueryInterface,
1520 MLANGCF_AddRef,
1521 MLANGCF_Release,
1522 MLANGCF_CreateInstance,
1523 MLANGCF_LockServer
1526 /******************************************************************
1527 * DllGetClassObject (MLANG.@)
1529 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1531 unsigned int i;
1532 IClassFactoryImpl *factory;
1534 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1536 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1537 && ! IsEqualGUID( &IID_IUnknown, iid) )
1538 return E_NOINTERFACE;
1540 for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1542 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1543 break;
1546 if (i == ARRAY_SIZE(object_creation))
1548 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1549 return CLASS_E_CLASSNOTAVAILABLE;
1552 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1554 factory = malloc(sizeof(*factory));
1555 if (factory == NULL) return E_OUTOFMEMORY;
1557 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1558 factory->ref = 1;
1560 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1562 *ppv = &factory->IClassFactory_iface;
1564 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1566 return S_OK;
1570 /******************************************************************************/
1572 typedef struct tagMLang_impl
1574 IMLangFontLink IMLangFontLink_iface;
1575 IMultiLanguage IMultiLanguage_iface;
1576 IMultiLanguage3 IMultiLanguage3_iface;
1577 IMLangFontLink2 IMLangFontLink2_iface;
1578 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1579 LONG ref;
1580 DWORD total_cp, total_scripts;
1581 } MLang_impl;
1583 /******************************************************************************/
1585 typedef struct tagEnumCodePage_impl
1587 IEnumCodePage IEnumCodePage_iface;
1588 LONG ref;
1589 MIMECPINFO *cpinfo;
1590 DWORD total, pos;
1591 } EnumCodePage_impl;
1593 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1595 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1598 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1599 IEnumCodePage* iface,
1600 REFIID riid,
1601 void** ppvObject)
1603 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1605 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1607 if (IsEqualGUID(riid, &IID_IUnknown)
1608 || IsEqualGUID(riid, &IID_IEnumCodePage))
1610 IEnumCodePage_AddRef(iface);
1611 TRACE("Returning IID_IEnumCodePage %p ref = %ld\n", This, This->ref);
1612 *ppvObject = &This->IEnumCodePage_iface;
1613 return S_OK;
1616 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1617 return E_NOINTERFACE;
1620 static ULONG WINAPI fnIEnumCodePage_AddRef(
1621 IEnumCodePage* iface)
1623 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1624 return InterlockedIncrement(&This->ref);
1627 static ULONG WINAPI fnIEnumCodePage_Release(
1628 IEnumCodePage* iface)
1630 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1631 ULONG ref = InterlockedDecrement(&This->ref);
1633 TRACE("%p ref = %ld\n", This, ref);
1634 if (ref == 0)
1636 TRACE("Destroying %p\n", This);
1637 free(This->cpinfo);
1638 free(This);
1641 return ref;
1644 static HRESULT WINAPI fnIEnumCodePage_Clone(
1645 IEnumCodePage* iface,
1646 IEnumCodePage** ppEnum)
1648 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1649 FIXME("%p %p\n", This, ppEnum);
1650 return E_NOTIMPL;
1653 static HRESULT WINAPI fnIEnumCodePage_Next(
1654 IEnumCodePage* iface,
1655 ULONG celt,
1656 PMIMECPINFO rgelt,
1657 ULONG* pceltFetched)
1659 ULONG i;
1660 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1662 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
1664 if (!pceltFetched) return S_FALSE;
1665 *pceltFetched = 0;
1667 if (!rgelt) return S_FALSE;
1669 if (This->pos + celt > This->total)
1670 celt = This->total - This->pos;
1672 if (!celt) return S_FALSE;
1674 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1675 *pceltFetched = celt;
1676 This->pos += celt;
1678 for (i = 0; i < celt; i++)
1680 TRACE("#%lu: %08lx %u %u %s %s %s %s %s %s %d\n",
1681 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1682 rgelt[i].uiFamilyCodePage,
1683 wine_dbgstr_w(rgelt[i].wszDescription),
1684 wine_dbgstr_w(rgelt[i].wszWebCharset),
1685 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1686 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1687 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1688 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1689 rgelt[i].bGDICharset);
1691 return S_OK;
1694 static HRESULT WINAPI fnIEnumCodePage_Reset(
1695 IEnumCodePage* iface)
1697 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1699 TRACE("%p\n", This);
1701 This->pos = 0;
1702 return S_OK;
1705 static HRESULT WINAPI fnIEnumCodePage_Skip(
1706 IEnumCodePage* iface,
1707 ULONG celt)
1709 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1711 TRACE("%p %lu\n", This, celt);
1713 if (celt >= This->total) return S_FALSE;
1715 This->pos += celt;
1716 return S_OK;
1719 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1721 fnIEnumCodePage_QueryInterface,
1722 fnIEnumCodePage_AddRef,
1723 fnIEnumCodePage_Release,
1724 fnIEnumCodePage_Clone,
1725 fnIEnumCodePage_Next,
1726 fnIEnumCodePage_Reset,
1727 fnIEnumCodePage_Skip
1730 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1731 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1733 EnumCodePage_impl *ecp;
1734 MIMECPINFO *cpinfo;
1735 UINT i, n;
1737 TRACE("%p, %08lx, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1739 if (!grfFlags) /* enumerate internal data base of encodings */
1740 grfFlags = MIMECONTF_MIME_LATEST;
1742 ecp = malloc(sizeof(EnumCodePage_impl));
1743 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1744 ecp->ref = 1;
1745 ecp->pos = 0;
1746 ecp->total = 0;
1747 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1749 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1751 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1752 ecp->total++;
1756 ecp->cpinfo = malloc(sizeof(MIMECPINFO) * ecp->total);
1757 cpinfo = ecp->cpinfo;
1759 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1761 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1763 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1764 fill_cp_info(&mlang_data[i], n, cpinfo++);
1768 TRACE("enumerated %ld codepages with flags %08lx\n", ecp->total, grfFlags);
1770 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1772 return S_OK;
1775 /******************************************************************************/
1777 typedef struct tagEnumScript_impl
1779 IEnumScript IEnumScript_iface;
1780 LONG ref;
1781 SCRIPTINFO *script_info;
1782 DWORD total, pos;
1783 } EnumScript_impl;
1785 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1787 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1790 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1791 IEnumScript* iface,
1792 REFIID riid,
1793 void** ppvObject)
1795 EnumScript_impl *This = impl_from_IEnumScript( iface );
1797 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1799 if (IsEqualGUID(riid, &IID_IUnknown)
1800 || IsEqualGUID(riid, &IID_IEnumScript))
1802 IEnumScript_AddRef(iface);
1803 TRACE("Returning IID_IEnumScript %p ref = %ld\n", This, This->ref);
1804 *ppvObject = &This->IEnumScript_iface;
1805 return S_OK;
1808 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1809 return E_NOINTERFACE;
1812 static ULONG WINAPI fnIEnumScript_AddRef(
1813 IEnumScript* iface)
1815 EnumScript_impl *This = impl_from_IEnumScript( iface );
1816 return InterlockedIncrement(&This->ref);
1819 static ULONG WINAPI fnIEnumScript_Release(
1820 IEnumScript* iface)
1822 EnumScript_impl *This = impl_from_IEnumScript( iface );
1823 ULONG ref = InterlockedDecrement(&This->ref);
1825 TRACE("%p ref = %ld\n", This, ref);
1826 if (ref == 0)
1828 TRACE("Destroying %p\n", This);
1829 free(This->script_info);
1830 free(This);
1833 return ref;
1836 static HRESULT WINAPI fnIEnumScript_Clone(
1837 IEnumScript* iface,
1838 IEnumScript** ppEnum)
1840 EnumScript_impl *This = impl_from_IEnumScript( iface );
1841 FIXME("%p %p: stub!\n", This, ppEnum);
1842 return E_NOTIMPL;
1845 static HRESULT WINAPI fnIEnumScript_Next(
1846 IEnumScript* iface,
1847 ULONG celt,
1848 PSCRIPTINFO rgelt,
1849 ULONG* pceltFetched)
1851 EnumScript_impl *This = impl_from_IEnumScript( iface );
1853 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
1855 if (!pceltFetched || !rgelt) return E_FAIL;
1857 *pceltFetched = 0;
1859 if (This->pos + celt > This->total)
1860 celt = This->total - This->pos;
1862 if (!celt) return S_FALSE;
1864 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1865 *pceltFetched = celt;
1866 This->pos += celt;
1868 return S_OK;
1871 static HRESULT WINAPI fnIEnumScript_Reset(
1872 IEnumScript* iface)
1874 EnumScript_impl *This = impl_from_IEnumScript( iface );
1876 TRACE("%p\n", This);
1878 This->pos = 0;
1879 return S_OK;
1882 static HRESULT WINAPI fnIEnumScript_Skip(
1883 IEnumScript* iface,
1884 ULONG celt)
1886 EnumScript_impl *This = impl_from_IEnumScript( iface );
1888 TRACE("%p %lu\n", This, celt);
1890 if (celt >= This->total) return S_FALSE;
1892 This->pos += celt;
1893 return S_OK;
1896 static const IEnumScriptVtbl IEnumScript_vtbl =
1898 fnIEnumScript_QueryInterface,
1899 fnIEnumScript_AddRef,
1900 fnIEnumScript_Release,
1901 fnIEnumScript_Clone,
1902 fnIEnumScript_Next,
1903 fnIEnumScript_Reset,
1904 fnIEnumScript_Skip
1907 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1908 LANGID LangId, IEnumScript** ppEnumScript )
1910 EnumScript_impl *es;
1911 UINT i;
1913 TRACE("%p, %08lx, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1915 if (!dwFlags) /* enumerate all available scripts */
1916 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1918 es = malloc(sizeof(EnumScript_impl));
1919 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1920 es->ref = 1;
1921 es->pos = 0;
1922 /* do not enumerate unicode flavours */
1923 es->total = ARRAY_SIZE(mlang_data) - 1;
1924 es->script_info = malloc(sizeof(SCRIPTINFO) * es->total);
1926 for (i = 0; i < es->total; i++)
1928 es->script_info[i].ScriptId = i;
1929 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1930 wcscpy( es->script_info[i].wszDescription, mlang_data[i].description );
1931 wcscpy( es->script_info[i].wszFixedWidthFont, mlang_data[i].fixed_font );
1932 wcscpy( es->script_info[i].wszProportionalFont, mlang_data[i].proportional_font );
1935 TRACE("enumerated %ld scripts with flags %08lx\n", es->total, dwFlags);
1937 *ppEnumScript = &es->IEnumScript_iface;
1939 return S_OK;
1942 /******************************************************************************/
1944 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1946 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1949 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1950 IMLangFontLink* iface,
1951 REFIID riid,
1952 void** ppvObject)
1954 MLang_impl *This = impl_from_IMLangFontLink( iface );
1955 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1958 static ULONG WINAPI fnIMLangFontLink_AddRef(
1959 IMLangFontLink* iface)
1961 MLang_impl *This = impl_from_IMLangFontLink( iface );
1962 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1965 static ULONG WINAPI fnIMLangFontLink_Release(
1966 IMLangFontLink* iface)
1968 MLang_impl *This = impl_from_IMLangFontLink( iface );
1969 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1972 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1973 IMLangFontLink* iface,
1974 WCHAR ch_src,
1975 DWORD* codepages)
1977 MLang_impl *This = impl_from_IMLangFontLink( iface );
1978 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
1981 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1982 IMLangFontLink* iface,
1983 const WCHAR* src,
1984 LONG src_len,
1985 DWORD priority_cp,
1986 DWORD* codepages,
1987 LONG* ret_len)
1989 MLang_impl *This = impl_from_IMLangFontLink( iface );
1990 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
1991 codepages, ret_len);
1994 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1995 IMLangFontLink* iface,
1996 UINT codepage,
1997 DWORD* codepages)
1999 MLang_impl *This = impl_from_IMLangFontLink( iface );
2000 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2003 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2004 IMLangFontLink* iface,
2005 DWORD codepages,
2006 UINT def_codepage,
2007 UINT* codepage)
2009 MLang_impl *This = impl_from_IMLangFontLink(iface);
2010 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2011 def_codepage, codepage);
2014 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2015 IMLangFontLink* iface,
2016 HDC hdc,
2017 HFONT hfont,
2018 DWORD* codepages)
2020 MLang_impl *This = impl_from_IMLangFontLink(iface);
2021 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2024 static HRESULT WINAPI fnIMLangFontLink_MapFont(
2025 IMLangFontLink* iface,
2026 HDC hDC,
2027 DWORD dwCodePages,
2028 HFONT hSrcFont,
2029 HFONT* phDestFont)
2031 TRACE("(%p)->%p %08lx %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
2033 return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2036 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2037 IMLangFontLink* iface,
2038 HFONT hFont)
2040 TRACE("(%p)->%p\n",iface, hFont);
2042 return release_font(hFont);
2045 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2046 IMLangFontLink* iface)
2048 TRACE("(%p)\n",iface);
2050 return clear_font_cache();
2054 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2056 fnIMLangFontLink_QueryInterface,
2057 fnIMLangFontLink_AddRef,
2058 fnIMLangFontLink_Release,
2059 fnIMLangFontLink_GetCharCodePages,
2060 fnIMLangFontLink_GetStrCodePages,
2061 fnIMLangFontLink_CodePageToCodePages,
2062 fnIMLangFontLink_CodePagesToCodePage,
2063 fnIMLangFontLink_GetFontCodePages,
2064 fnIMLangFontLink_MapFont,
2065 fnIMLangFontLink_ReleaseFont,
2066 fnIMLangFontLink_ResetFontMapping,
2069 /******************************************************************************/
2071 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2073 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2076 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2077 IMultiLanguage* iface,
2078 REFIID riid,
2079 void** obj)
2081 MLang_impl *This = impl_from_IMultiLanguage( iface );
2082 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2085 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2087 MLang_impl *This = impl_from_IMultiLanguage( iface );
2088 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2091 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2093 MLang_impl *This = impl_from_IMultiLanguage( iface );
2094 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2097 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2098 IMultiLanguage* iface,
2099 UINT* cp)
2101 MLang_impl *This = impl_from_IMultiLanguage( iface );
2102 TRACE("(%p, %p)\n", This, cp);
2103 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2106 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2107 IMultiLanguage* iface,
2108 UINT uiCodePage,
2109 PMIMECPINFO pCodePageInfo)
2111 UINT i, n;
2112 MLang_impl *This = impl_from_IMultiLanguage( iface );
2114 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2116 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2118 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2120 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2122 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2123 return S_OK;
2128 return S_FALSE;
2131 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2132 IMultiLanguage* iface,
2133 UINT cp,
2134 UINT* family_cp)
2136 MLang_impl *This = impl_from_IMultiLanguage( iface );
2137 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2140 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2141 IMultiLanguage* iface,
2142 DWORD grfFlags,
2143 IEnumCodePage** ppEnumCodePage)
2145 MLang_impl *This = impl_from_IMultiLanguage( iface );
2147 TRACE("%p %08lx %p\n", This, grfFlags, ppEnumCodePage);
2149 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2152 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2153 IMultiLanguage* iface,
2154 BSTR Charset,
2155 PMIMECSETINFO pCharsetInfo)
2157 MLang_impl *This = impl_from_IMultiLanguage( iface );
2158 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2161 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2162 IMultiLanguage* iface,
2163 DWORD src_enc,
2164 DWORD dst_enc)
2166 MLang_impl *This = impl_from_IMultiLanguage( iface );
2167 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2170 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2171 IMultiLanguage* iface,
2172 DWORD* mode,
2173 DWORD src_enc,
2174 DWORD dst_enc,
2175 BYTE* src,
2176 UINT* src_size,
2177 BYTE* dest,
2178 UINT* dest_size)
2180 MLang_impl *This = impl_from_IMultiLanguage( iface );
2181 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2182 dst_enc, src, src_size, dest, dest_size);
2185 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2186 IMultiLanguage* iface,
2187 DWORD* mode,
2188 DWORD src_enc,
2189 CHAR* src,
2190 UINT* src_size,
2191 WCHAR* dest,
2192 UINT* dest_size)
2194 MLang_impl *This = impl_from_IMultiLanguage( iface );
2195 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2196 mode, src_enc, src, src_size, dest, dest_size);
2199 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2200 IMultiLanguage* iface,
2201 DWORD* mode,
2202 DWORD encoding,
2203 WCHAR* src,
2204 UINT* src_size,
2205 CHAR* dest,
2206 UINT* dest_size)
2208 MLang_impl *This = impl_from_IMultiLanguage(iface);
2209 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2210 mode, encoding, src, src_size, dest, dest_size);
2213 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2214 IMultiLanguage* iface)
2216 MLang_impl *This = impl_from_IMultiLanguage( iface );
2217 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2220 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2221 IMultiLanguage* iface,
2222 LCID lcid,
2223 BSTR* pbstrRfc1766)
2225 MLang_impl *This = impl_from_IMultiLanguage(iface);
2226 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2229 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2230 IMultiLanguage* iface,
2231 LCID* locale,
2232 BSTR rfc1766)
2234 MLang_impl *This = impl_from_IMultiLanguage(iface);
2235 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2238 /******************************************************************************/
2240 typedef struct tagEnumRfc1766_impl
2242 IEnumRfc1766 IEnumRfc1766_iface;
2243 LONG ref;
2244 RFC1766INFO *info;
2245 DWORD total, pos;
2246 } EnumRfc1766_impl;
2248 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2250 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2253 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2254 IEnumRfc1766 *iface,
2255 REFIID riid,
2256 void** ppvObject)
2258 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2260 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2262 if (IsEqualGUID(riid, &IID_IUnknown)
2263 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2265 IEnumRfc1766_AddRef(iface);
2266 TRACE("Returning IID_IEnumRfc1766 %p ref = %ld\n", This, This->ref);
2267 *ppvObject = &This->IEnumRfc1766_iface;
2268 return S_OK;
2271 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2272 return E_NOINTERFACE;
2275 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2276 IEnumRfc1766 *iface)
2278 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2279 return InterlockedIncrement(&This->ref);
2282 static ULONG WINAPI fnIEnumRfc1766_Release(
2283 IEnumRfc1766 *iface)
2285 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2286 ULONG ref = InterlockedDecrement(&This->ref);
2288 TRACE("%p ref = %ld\n", This, ref);
2289 if (ref == 0)
2291 TRACE("Destroying %p\n", This);
2292 free(This->info);
2293 free(This);
2295 return ref;
2298 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2299 IEnumRfc1766 *iface,
2300 IEnumRfc1766 **ppEnum)
2302 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2304 FIXME("%p %p\n", This, ppEnum);
2305 return E_NOTIMPL;
2308 static HRESULT WINAPI fnIEnumRfc1766_Next(
2309 IEnumRfc1766 *iface,
2310 ULONG celt,
2311 PRFC1766INFO rgelt,
2312 ULONG *pceltFetched)
2314 ULONG i;
2315 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2317 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
2319 if (!pceltFetched) return S_FALSE;
2320 *pceltFetched = 0;
2322 if (!rgelt) return S_FALSE;
2324 if (This->pos + celt > This->total)
2325 celt = This->total - This->pos;
2327 if (!celt) return S_FALSE;
2329 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2330 *pceltFetched = celt;
2331 This->pos += celt;
2333 for (i = 0; i < celt; i++)
2335 TRACE("#%lu: %08lx %s %s\n",
2336 i, rgelt[i].lcid,
2337 wine_dbgstr_w(rgelt[i].wszRfc1766),
2338 wine_dbgstr_w(rgelt[i].wszLocaleName));
2340 return S_OK;
2343 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2344 IEnumRfc1766 *iface)
2346 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2348 TRACE("%p\n", This);
2350 This->pos = 0;
2351 return S_OK;
2354 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2355 IEnumRfc1766 *iface,
2356 ULONG celt)
2358 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2360 TRACE("%p %lu\n", This, celt);
2362 if (celt >= This->total) return S_FALSE;
2364 This->pos += celt;
2365 return S_OK;
2368 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2370 fnIEnumRfc1766_QueryInterface,
2371 fnIEnumRfc1766_AddRef,
2372 fnIEnumRfc1766_Release,
2373 fnIEnumRfc1766_Clone,
2374 fnIEnumRfc1766_Next,
2375 fnIEnumRfc1766_Reset,
2376 fnIEnumRfc1766_Skip
2379 struct enum_locales_data
2381 RFC1766INFO *info;
2382 DWORD total, allocated;
2385 static BOOL CALLBACK enum_locales_proc(LPWSTR locale, DWORD flags, LPARAM lparam)
2387 struct enum_locales_data *data = (struct enum_locales_data *)lparam;
2388 RFC1766INFO *info;
2390 TRACE("%s\n", debugstr_w(locale));
2392 if (data->total >= data->allocated)
2394 data->allocated *= 2;
2395 data->info = realloc(data->info, data->allocated * sizeof(RFC1766INFO));
2396 if (!data->info) return FALSE;
2399 info = &data->info[data->total];
2401 info->lcid = LocaleNameToLCID( locale, 0 );
2402 if (info->lcid == LOCALE_CUSTOM_UNSPECIFIED) return TRUE;
2404 info->wszRfc1766[0] = 0;
2405 if (FAILED( lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME ))) return TRUE;
2407 info->wszLocaleName[0] = 0;
2408 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2409 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2411 data->total++;
2413 return TRUE;
2416 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2418 EnumRfc1766_impl *rfc;
2419 struct enum_locales_data data;
2421 TRACE("%04x, %p\n", LangId, ppEnum);
2423 rfc = malloc(sizeof(EnumRfc1766_impl));
2424 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2425 rfc->ref = 1;
2426 rfc->pos = 0;
2427 rfc->total = 0;
2429 data.total = 0;
2430 data.allocated = 160;
2431 data.info = malloc(data.allocated * sizeof(RFC1766INFO));
2432 if (!data.info)
2434 free(rfc);
2435 return E_OUTOFMEMORY;
2438 EnumSystemLocalesEx(enum_locales_proc, LOCALE_WINDOWS, (LPARAM)&data, NULL);
2440 TRACE("enumerated %ld rfc1766 structures\n", data.total);
2442 if (!data.total)
2444 free(data.info);
2445 free(rfc);
2446 return E_FAIL;
2449 rfc->info = data.info;
2450 rfc->total = data.total;
2452 *ppEnum = &rfc->IEnumRfc1766_iface;
2453 return S_OK;
2456 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2457 IMultiLanguage *iface,
2458 IEnumRfc1766 **ppEnumRfc1766)
2460 MLang_impl *This = impl_from_IMultiLanguage( iface );
2462 TRACE("%p %p\n", This, ppEnumRfc1766);
2464 return EnumRfc1766_create(0, ppEnumRfc1766);
2467 /******************************************************************************/
2469 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2470 IMultiLanguage* iface,
2471 LCID Locale,
2472 PRFC1766INFO pRfc1766Info)
2474 LCTYPE type = LOCALE_SLANGUAGE;
2476 TRACE("(%p, 0x%04lx, %p)\n", iface, Locale, pRfc1766Info);
2478 if (!pRfc1766Info)
2479 return E_INVALIDARG;
2481 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2482 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2483 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2485 if (!SUBLANGID(Locale))
2486 type = LOCALE_SENGLANGUAGE; /* suppress country */
2488 else
2490 if (!SUBLANGID(Locale)) {
2491 TRACE("SUBLANGID missing in 0x%04lx\n", Locale);
2492 return E_FAIL;
2496 pRfc1766Info->lcid = Locale;
2497 pRfc1766Info->wszRfc1766[0] = 0;
2498 pRfc1766Info->wszLocaleName[0] = 0;
2500 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2501 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2502 return S_OK;
2504 /* Locale not supported */
2505 return E_INVALIDARG;
2508 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2509 IMultiLanguage* iface,
2510 UINT src_cp,
2511 UINT dst_cp,
2512 DWORD prop,
2513 IMLangConvertCharset** convert_charset)
2515 MLang_impl *This = impl_from_IMultiLanguage(iface);
2516 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2519 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2521 fnIMultiLanguage_QueryInterface,
2522 fnIMultiLanguage_AddRef,
2523 fnIMultiLanguage_Release,
2524 fnIMultiLanguage_GetNumberOfCodePageInfo,
2525 fnIMultiLanguage_GetCodePageInfo,
2526 fnIMultiLanguage_GetFamilyCodePage,
2527 fnIMultiLanguage_EnumCodePages,
2528 fnIMultiLanguage_GetCharsetInfo,
2529 fnIMultiLanguage_IsConvertible,
2530 fnIMultiLanguage_ConvertString,
2531 fnIMultiLanguage_ConvertStringToUnicode,
2532 fnIMultiLanguage_ConvertStringFromUnicode,
2533 fnIMultiLanguage_ConvertStringReset,
2534 fnIMultiLanguage_GetRfc1766FromLcid,
2535 fnIMultiLanguage_GetLcidFromRfc1766,
2536 fnIMultiLanguage_EnumRfc1766,
2537 fnIMultiLanguage_GetRfc1766Info,
2538 fnIMultiLanguage_CreateConvertCharset,
2542 /******************************************************************************/
2544 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2546 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2549 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2550 IMultiLanguage3* iface,
2551 REFIID riid,
2552 void** obj)
2554 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2556 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2558 if (IsEqualGUID(riid, &IID_IUnknown) ||
2559 IsEqualGUID(riid, &IID_IMultiLanguage))
2561 *obj = &This->IMultiLanguage_iface;
2563 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2564 IsEqualGUID(riid, &IID_IMLangFontLink))
2566 *obj = &This->IMLangFontLink_iface;
2568 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2570 *obj = &This->IMLangFontLink2_iface;
2572 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2573 IsEqualGUID(riid, &IID_IMultiLanguage3))
2575 *obj = &This->IMultiLanguage3_iface;
2577 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2579 *obj = &This->IMLangLineBreakConsole_iface;
2581 else
2583 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2584 *obj = NULL;
2585 return E_NOINTERFACE;
2588 IMultiLanguage3_AddRef(iface);
2589 return S_OK;
2592 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2594 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2595 return InterlockedIncrement(&This->ref);
2598 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2600 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2601 ULONG ref = InterlockedDecrement(&This->ref);
2603 TRACE("(%p)->(%ld)\n", This, ref);
2604 if (ref == 0)
2606 free(This);
2607 UnlockModule();
2610 return ref;
2613 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2614 IMultiLanguage3* iface,
2615 UINT* pcCodePage)
2617 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2619 TRACE("%p, %p\n", This, pcCodePage);
2621 if (!pcCodePage) return E_INVALIDARG;
2623 *pcCodePage = This->total_cp;
2624 return S_OK;
2627 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2629 CHARSETINFO csi;
2631 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2632 TCI_SRCCODEPAGE))
2633 mime_cp_info->bGDICharset = csi.ciCharset;
2634 else
2635 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2637 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2638 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2639 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2640 wcscpy( mime_cp_info->wszDescription, ml_data->mime_cp_info[index].description );
2641 wcscpy( mime_cp_info->wszWebCharset, ml_data->mime_cp_info[index].web_charset );
2642 wcscpy( mime_cp_info->wszHeaderCharset, ml_data->mime_cp_info[index].header_charset );
2643 wcscpy( mime_cp_info->wszBodyCharset, ml_data->mime_cp_info[index].body_charset );
2644 wcscpy( mime_cp_info->wszFixedWidthFont, ml_data->fixed_font );
2645 wcscpy( mime_cp_info->wszProportionalFont, ml_data->proportional_font );
2647 TRACE("%08lx %u %u %s %s %s %s %s %s %d\n",
2648 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2649 mime_cp_info->uiFamilyCodePage,
2650 wine_dbgstr_w(mime_cp_info->wszDescription),
2651 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2652 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2653 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2654 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2655 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2656 mime_cp_info->bGDICharset);
2659 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2660 IMultiLanguage3* iface,
2661 UINT uiCodePage,
2662 LANGID LangId,
2663 PMIMECPINFO pCodePageInfo)
2665 UINT i, n;
2666 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2668 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2670 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2672 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2674 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2676 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2677 return S_OK;
2682 return S_FALSE;
2685 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2686 IMultiLanguage3* iface,
2687 UINT uiCodePage,
2688 UINT* puiFamilyCodePage)
2690 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2693 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2694 IMultiLanguage3* iface,
2695 DWORD grfFlags,
2696 LANGID LangId,
2697 IEnumCodePage** ppEnumCodePage)
2699 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2701 TRACE("%p %08lx %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2703 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2706 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2707 IMultiLanguage3* iface,
2708 BSTR Charset,
2709 PMIMECSETINFO pCharsetInfo)
2711 UINT i, n;
2712 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2714 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2716 if (!pCharsetInfo) return E_FAIL;
2718 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2720 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2722 if (!lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].web_charset))
2724 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2725 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2726 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].web_charset);
2727 return S_OK;
2729 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2731 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2732 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2733 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2734 return S_OK;
2739 /* FIXME:
2740 * Since we do not support charsets like iso-2022-jp and do not have
2741 * them in our database as a primary (web_charset) encoding this loop
2742 * does an attempt to 'approximate' charset name by header_charset.
2744 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2746 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2748 if (!lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].header_charset))
2750 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2751 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2752 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].header_charset);
2753 return S_OK;
2758 return E_FAIL;
2761 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2762 IMultiLanguage3* iface,
2763 DWORD dwSrcEncoding,
2764 DWORD dwDstEncoding)
2766 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2769 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2770 IMultiLanguage3* iface,
2771 DWORD* pdwMode,
2772 DWORD dwSrcEncoding,
2773 DWORD dwDstEncoding,
2774 BYTE* pSrcStr,
2775 UINT* pcSrcSize,
2776 BYTE* pDstStr,
2777 UINT* pcDstSize)
2779 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2780 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2783 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2784 IMultiLanguage3* iface,
2785 DWORD* pdwMode,
2786 DWORD dwEncoding,
2787 CHAR* pSrcStr,
2788 UINT* pcSrcSize,
2789 WCHAR* pDstStr,
2790 UINT* pcDstSize)
2792 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2793 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2796 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2797 IMultiLanguage3* iface,
2798 DWORD* pdwMode,
2799 DWORD dwEncoding,
2800 WCHAR* pSrcStr,
2801 UINT* pcSrcSize,
2802 CHAR* pDstStr,
2803 UINT* pcDstSize)
2805 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2806 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2809 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2810 IMultiLanguage3* iface)
2812 FIXME("\n");
2813 return E_NOTIMPL;
2816 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2817 IMultiLanguage3* iface,
2818 LCID lcid,
2819 BSTR* pbstrRfc1766)
2821 WCHAR buf[MAX_RFC1766_NAME];
2823 TRACE("%p %04lx %p\n", iface, lcid, pbstrRfc1766);
2824 if (!pbstrRfc1766)
2825 return E_INVALIDARG;
2827 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2829 *pbstrRfc1766 = SysAllocString( buf );
2830 return S_OK;
2832 return E_FAIL;
2835 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2836 IMultiLanguage3* iface,
2837 LCID* pLocale,
2838 BSTR bstrRfc1766)
2840 HRESULT hr;
2841 IEnumRfc1766 *rfc1766;
2843 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2845 if (!pLocale || !bstrRfc1766)
2846 return E_INVALIDARG;
2848 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2849 if (FAILED(hr))
2850 return hr;
2852 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2854 IEnumRfc1766_Release(rfc1766);
2855 return hr;
2858 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2859 IMultiLanguage3* iface,
2860 LANGID LangId,
2861 IEnumRfc1766** ppEnumRfc1766)
2863 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2865 TRACE("%p %p\n", This, ppEnumRfc1766);
2867 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2870 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2871 IMultiLanguage3* iface,
2872 LCID Locale,
2873 LANGID LangId,
2874 PRFC1766INFO pRfc1766Info)
2876 static LANGID last_lang = -1;
2877 LCTYPE type = LOCALE_SLANGUAGE;
2879 TRACE("(%p, 0x%04lx, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2881 if (!pRfc1766Info)
2882 return E_INVALIDARG;
2884 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2885 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2886 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2888 if (!SUBLANGID(Locale))
2889 type = LOCALE_SENGLANGUAGE; /* suppress country */
2891 else
2893 if (!SUBLANGID(Locale)) {
2894 TRACE("SUBLANGID missing in 0x%04lx\n", Locale);
2895 return E_FAIL;
2899 pRfc1766Info->lcid = Locale;
2900 pRfc1766Info->wszRfc1766[0] = 0;
2901 pRfc1766Info->wszLocaleName[0] = 0;
2903 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2904 (last_lang != LangId)) {
2905 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2906 last_lang = LangId;
2909 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2910 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2911 return S_OK;
2913 /* Locale not supported */
2914 return E_INVALIDARG;
2917 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2918 IMultiLanguage3* iface,
2919 UINT src_cp,
2920 UINT dst_cp,
2921 DWORD prop,
2922 IMLangConvertCharset** convert_charset)
2924 HRESULT hr;
2926 TRACE("(%u %u 0x%08lx %p)\n", src_cp, dst_cp, prop, convert_charset);
2928 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2929 if (FAILED(hr)) return hr;
2931 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2934 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2935 IMultiLanguage3* iface,
2936 DWORD* pdwMode,
2937 DWORD dwFlag,
2938 WCHAR* lpFallBack,
2939 DWORD dwSrcEncoding,
2940 DWORD dwDstEncoding,
2941 IStream* pstmIn,
2942 IStream* pstmOut)
2944 char *src, *dst = NULL;
2945 INT srclen, dstlen;
2946 STATSTG stat;
2947 HRESULT hr;
2949 TRACE("%p %0lx8 %s %lu %lu %p %p\n",
2950 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2952 FIXME("dwFlag and lpFallBack not handled\n");
2954 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2955 if (FAILED(hr)) return hr;
2957 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2958 if (!(src = malloc(stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2960 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2961 if (FAILED(hr)) goto exit;
2963 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
2964 if (FAILED(hr)) goto exit;
2966 if (!(dst = malloc(dstlen)))
2968 hr = E_OUTOFMEMORY;
2969 goto exit;
2971 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
2972 if (FAILED(hr)) goto exit;
2974 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
2976 exit:
2977 free(src);
2978 free(dst);
2979 return hr;
2982 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
2983 IMultiLanguage3* iface,
2984 DWORD* pdwMode,
2985 DWORD dwEncoding,
2986 CHAR* pSrcStr,
2987 UINT* pcSrcSize,
2988 WCHAR* pDstStr,
2989 UINT* pcDstSize,
2990 DWORD dwFlag,
2991 WCHAR* lpFallBack)
2993 if (dwFlag || lpFallBack)
2994 FIXME("Ignoring dwFlag (0x%lx/%ld) and lpFallBack (%p)\n",
2995 dwFlag, dwFlag, lpFallBack);
2997 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2998 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3001 /*****************************************************************************
3002 * MultiLanguage2::ConvertStringToUnicodeEx
3004 * Translates the multibyte string from the specified code page to Unicode.
3006 * PARAMS
3007 * see ConvertStringToUnicode
3008 * dwFlag
3009 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3010 * instead unconvertible characters.
3012 * RETURNS
3013 * S_OK Success.
3014 * S_FALSE The conversion is not supported.
3015 * E_FAIL Some error has occurred.
3017 * TODO: handle dwFlag and lpFallBack
3019 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3020 IMultiLanguage3* This,
3021 DWORD* pdwMode,
3022 DWORD dwEncoding,
3023 WCHAR* pSrcStr,
3024 UINT* pcSrcSize,
3025 CHAR* pDstStr,
3026 UINT* pcDstSize,
3027 DWORD dwFlag,
3028 WCHAR* lpFallBack)
3030 FIXME("\n");
3031 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3032 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3035 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3036 IMultiLanguage3* iface,
3037 DWORD dwFlag,
3038 DWORD dwPrefWinCodePage,
3039 IStream* pstmIn,
3040 DetectEncodingInfo* lpEncoding,
3041 INT* pnScores)
3043 FIXME("\n");
3044 return E_NOTIMPL;
3047 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3048 IMultiLanguage3* iface,
3049 DWORD dwFlag,
3050 DWORD dwPrefWinCodePage,
3051 CHAR* pSrcStr,
3052 INT* pcSrcSize,
3053 DetectEncodingInfo* lpEncoding,
3054 INT* pnScores)
3056 FIXME("\n");
3057 return E_NOTIMPL;
3060 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3061 IMultiLanguage3* iface,
3062 UINT uiCodePage,
3063 HWND hwnd)
3065 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3068 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3069 IMultiLanguage3* iface,
3070 UINT uiCodePage,
3071 LCID lcid,
3072 LPWSTR lpWideCharStr,
3073 int cchWideChar)
3075 /* Find first instance */
3076 unsigned int i,n;
3078 TRACE ("%u, %04lx, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3079 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3081 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3083 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3085 lstrcpynW( lpWideCharStr, mlang_data[i].mime_cp_info[n].description, cchWideChar);
3086 return S_OK;
3091 return S_FALSE;
3094 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3095 IMultiLanguage3* iface,
3096 UINT uiCodePage)
3098 TRACE("%u\n", uiCodePage);
3100 /* FIXME: the installable set is usually larger than the set of valid codepages */
3101 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3104 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3105 IMultiLanguage3* iface,
3106 MIMECONTF dwSource)
3108 FIXME("0x%08x\n", dwSource);
3109 return S_OK;
3112 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3113 IMultiLanguage3* iface,
3114 UINT* pnScripts)
3116 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3118 TRACE("%p %p\n", This, pnScripts);
3120 if (!pnScripts) return S_FALSE;
3122 *pnScripts = This->total_scripts;
3123 return S_OK;
3126 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3127 IMultiLanguage3* iface,
3128 DWORD dwFlags,
3129 LANGID LangId,
3130 IEnumScript** ppEnumScript)
3132 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3134 TRACE("%p %08lx %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3136 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3139 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3140 IMultiLanguage3* iface,
3141 UINT uiCodePage,
3142 HWND hwnd,
3143 DWORD dwfIODControl)
3145 unsigned int i;
3146 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3148 TRACE("%p %u %p %08lx\n", This, uiCodePage, hwnd, dwfIODControl);
3150 /* quick check for kernel32 supported code pages */
3151 if (IsValidCodePage(uiCodePage))
3152 return S_OK;
3154 /* check for mlang supported code pages */
3155 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3157 UINT n;
3158 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3160 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3161 return S_OK;
3165 if (dwfIODControl != CPIOD_PEEK)
3166 FIXME("Request to install codepage language pack not handled\n");
3168 return S_FALSE;
3171 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3172 IMultiLanguage3 *iface,
3173 DWORD dwFlags,
3174 LPCWSTR lpWideCharStr,
3175 UINT cchWideChar,
3176 UINT *puiPreferredCodePages,
3177 UINT nPreferredCodePages,
3178 UINT *puiDetectedCodePages,
3179 UINT *pnDetectedCodePages,
3180 WCHAR *lpSpecialChar)
3182 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3184 FIXME("(%p)->(%08lx %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3185 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3186 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3187 debugstr_w(lpSpecialChar));
3189 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3190 return E_INVALIDARG;
3192 puiDetectedCodePages[0] = CP_UTF8;
3193 *pnDetectedCodePages = 1;
3194 return S_OK;
3197 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3198 IMultiLanguage3 *iface,
3199 DWORD dwFlags,
3200 IStream *pStrIn,
3201 UINT *puiPreferredCodePages,
3202 UINT nPreferredCodePages,
3203 UINT *puiDetectedCodePages,
3204 UINT *pnDetectedCodePages,
3205 WCHAR *lpSpecialChar)
3207 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3209 FIXME("(%p)->(%08lx %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3210 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3211 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3212 debugstr_w(lpSpecialChar));
3214 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3215 return E_INVALIDARG;
3217 puiDetectedCodePages[0] = CP_UTF8;
3218 *pnDetectedCodePages = 1;
3219 return S_OK;
3222 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3224 fnIMultiLanguage3_QueryInterface,
3225 fnIMultiLanguage3_AddRef,
3226 fnIMultiLanguage3_Release,
3227 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3228 fnIMultiLanguage3_GetCodePageInfo,
3229 fnIMultiLanguage3_GetFamilyCodePage,
3230 fnIMultiLanguage3_EnumCodePages,
3231 fnIMultiLanguage3_GetCharsetInfo,
3232 fnIMultiLanguage3_IsConvertible,
3233 fnIMultiLanguage3_ConvertString,
3234 fnIMultiLanguage3_ConvertStringToUnicode,
3235 fnIMultiLanguage3_ConvertStringFromUnicode,
3236 fnIMultiLanguage3_ConvertStringReset,
3237 fnIMultiLanguage3_GetRfc1766FromLcid,
3238 fnIMultiLanguage3_GetLcidFromRfc1766,
3239 fnIMultiLanguage3_EnumRfc1766,
3240 fnIMultiLanguage3_GetRfc1766Info,
3241 fnIMultiLanguage3_CreateConvertCharset,
3242 fnIMultiLanguage3_ConvertStringInIStream,
3243 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3244 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3245 fnIMultiLanguage3_DetectCodepageInIStream,
3246 fnIMultiLanguage3_DetectInputCodepage,
3247 fnIMultiLanguage3_ValidateCodePage,
3248 fnIMultiLanguage3_GetCodePageDescription,
3249 fnIMultiLanguage3_IsCodePageInstallable,
3250 fnIMultiLanguage3_SetMimeDBSource,
3251 fnIMultiLanguage3_GetNumberOfScripts,
3252 fnIMultiLanguage3_EnumScripts,
3253 fnIMultiLanguage3_ValidateCodePageEx,
3254 fnIMultiLanguage3_DetectOutboundCodePage,
3255 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3258 /******************************************************************************/
3260 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3262 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3265 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3266 IMLangFontLink2 * iface,
3267 REFIID riid,
3268 void** ppvObject)
3270 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3271 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3274 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3276 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3277 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3280 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3282 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3283 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3286 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3287 WCHAR ch_src, DWORD *ret_codepages)
3289 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3290 unsigned int i;
3292 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3294 *ret_codepages = 0;
3296 for (i = 0; i < ARRAY_SIZE(mlang_data) - 1 /* skip unicode codepages */; i++)
3298 BOOL used_dc;
3299 CHAR buf;
3301 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3302 &ch_src, 1, &buf, 1, NULL, &used_dc);
3304 /* If default char is not used, current codepage include the given symbol */
3305 if (!used_dc)
3307 DWORD codepages;
3309 IMLangFontLink2_CodePageToCodePages(iface,
3310 mlang_data[i].family_codepage, &codepages);
3311 *ret_codepages |= codepages;
3314 return S_OK;
3317 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3318 const WCHAR *src, LONG src_len, DWORD priority_cp,
3319 DWORD *codepages, LONG *ret_len)
3321 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3322 LONG i;
3323 DWORD cps = 0;
3325 TRACE("(%p)->(%s:%ld %lx %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3326 codepages, ret_len);
3328 if (codepages) *codepages = 0;
3329 if (ret_len) *ret_len = 0;
3331 if (!src || !src_len || src_len < 0)
3332 return E_INVALIDARG;
3334 for (i = 0; i < src_len; i++)
3336 DWORD cp;
3337 HRESULT ret;
3339 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3340 if (ret != S_OK) return E_FAIL;
3342 if (!cps) cps = cp;
3343 else if ((cps & cp) != 0) cps &= cp;
3344 else
3346 i--;
3347 break;
3350 /* FIXME: not tested */
3351 if (priority_cp & cps) break;
3354 if (codepages) *codepages = cps;
3355 if (ret_len) *ret_len = min( i + 1, src_len );
3356 return S_OK;
3359 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3360 UINT codepage,
3361 DWORD *codepages)
3363 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3364 CHARSETINFO cs;
3365 BOOL rc;
3367 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3369 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3370 if (rc)
3372 *codepages = cs.fs.fsCsb[0];
3373 TRACE("resulting codepages 0x%lx\n", *codepages);
3374 return S_OK;
3377 TRACE("codepage not found\n");
3378 *codepages = 0;
3379 return E_FAIL;
3382 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3383 DWORD codepages, UINT def_codepage, UINT *codepage)
3385 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3386 DWORD mask = 0;
3387 CHARSETINFO cs;
3388 BOOL rc;
3389 UINT i;
3391 TRACE("(%p)->(0x%lx %u %p)\n", This, codepages, def_codepage, codepage);
3393 *codepage = 0;
3395 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3396 if (rc && (codepages & cs.fs.fsCsb[0]))
3398 TRACE("Found Default Codepage\n");
3399 *codepage = def_codepage;
3400 return S_OK;
3403 for (i = 0; i < 32; i++)
3405 mask = 1 << i;
3406 if (codepages & mask)
3408 DWORD Csb[2];
3409 Csb[0] = mask;
3410 Csb[1] = 0x0;
3411 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3412 if (!rc)
3413 continue;
3415 TRACE("Falling back to least significant found CodePage %u\n",
3416 cs.ciACP);
3417 *codepage = cs.ciACP;
3418 return S_OK;
3422 TRACE("no codepage found\n");
3423 return E_FAIL;
3426 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3427 HDC hdc, HFONT hfont, DWORD *codepages)
3429 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3430 FONTSIGNATURE fontsig;
3431 HFONT old_font;
3433 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3435 old_font = SelectObject(hdc, hfont);
3436 GetTextCharsetInfo(hdc, &fontsig, 0);
3437 SelectObject(hdc, old_font);
3439 *codepages = fontsig.fsCsb[0];
3440 TRACE("ret 0x%lx\n", fontsig.fsCsb[0]);
3442 return S_OK;
3445 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3446 HFONT hFont)
3448 TRACE("(%p)->%p\n",This, hFont);
3450 return release_font(hFont);
3453 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3455 TRACE("(%p)\n",This);
3457 return clear_font_cache();
3460 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3461 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3463 HFONT old_font;
3465 TRACE("(%p)->%p %08lx %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
3467 if (!hDC) return E_FAIL;
3469 if (dwCodePages != 0)
3471 old_font = GetCurrentObject(hDC, OBJ_FONT);
3472 return map_font(hDC, dwCodePages, old_font, pFont);
3474 else
3476 if (pFont == NULL) return E_INVALIDARG;
3477 FIXME("the situation where dwCodepages is set to zero is not implemented\n");
3478 return E_FAIL;
3482 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3483 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3485 DWORD size;
3486 GLYPHSET *gs;
3488 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3490 if (!puiRanges) return E_INVALIDARG;
3491 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3492 if (!(gs = malloc(size))) return E_OUTOFMEMORY;
3494 GetFontUnicodeRanges(hDC, gs);
3495 *puiRanges = gs->cRanges;
3496 if (pUranges)
3498 UINT i;
3499 for (i = 0; i < gs->cRanges; i++)
3501 if (i >= *puiRanges) break;
3502 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3503 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3505 *puiRanges = i;
3507 free(gs);
3508 return S_OK;
3511 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3512 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3513 SCRIPTFONTINFO *pScriptFont)
3515 UINT i, j;
3517 TRACE("(%p)->%u %lx %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3519 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3521 for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3523 if (sid == mlang_data[i].sid)
3525 if (pScriptFont)
3527 if (j >= *puiFonts) break;
3529 pScriptFont[j].scripts = (SCRIPT_IDS)1 << mlang_data[i].sid;
3530 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3531 wcscpy( pScriptFont[j].wszFont, mlang_data[i].fixed_font );
3532 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3533 wcscpy( pScriptFont[j].wszFont, mlang_data[i].proportional_font );
3535 j++;
3538 *puiFonts = j;
3539 return S_OK;
3542 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3543 UINT uiCodePage, SCRIPT_ID *pSid)
3545 UINT i;
3547 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3549 if (uiCodePage == CP_UNICODE) return E_FAIL;
3551 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3553 if (uiCodePage == mlang_data[i].family_codepage)
3555 if (pSid) *pSid = mlang_data[i].sid;
3556 return S_OK;
3559 return E_FAIL;
3562 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3564 fnIMLangFontLink2_QueryInterface,
3565 fnIMLangFontLink2_AddRef,
3566 fnIMLangFontLink2_Release,
3567 fnIMLangFontLink2_GetCharCodePages,
3568 fnIMLangFontLink2_GetStrCodePages,
3569 fnIMLangFontLink2_CodePageToCodePages,
3570 fnIMLangFontLink2_CodePagesToCodePage,
3571 fnIMLangFontLink2_GetFontCodePages,
3572 fnIMLangFontLink2_ReleaseFont,
3573 fnIMLangFontLink2_ResetFontMapping,
3574 fnIMLangFontLink2_MapFont,
3575 fnIMLangFontLink2_GetFontUnicodeRanges,
3576 fnIMLangFontLink2_GetScriptFontInfo,
3577 fnIMLangFontLink2_CodePageToScriptID
3580 /******************************************************************************/
3582 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3584 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3587 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3588 IMLangLineBreakConsole* iface,
3589 REFIID riid,
3590 void** ppvObject)
3592 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3593 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3596 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3597 IMLangLineBreakConsole* iface )
3599 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3600 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3603 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3604 IMLangLineBreakConsole* iface )
3606 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3607 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3610 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3611 IMLangLineBreakConsole* iface,
3612 IMLangString* pSrcMLStr,
3613 LONG lSrcPos,
3614 LONG lSrcLen,
3615 LONG cMinColumns,
3616 LONG cMaxColumns,
3617 LONG* plLineLen,
3618 LONG* plSkipLen)
3620 FIXME("(%p)->%p %li %li %li %li %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3621 return E_NOTIMPL;
3624 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3625 IMLangLineBreakConsole* iface,
3626 LCID locale,
3627 const WCHAR* pszSrc,
3628 LONG cchSrc,
3629 LONG cMaxColumns,
3630 LONG* pcchLine,
3631 LONG* pcchSkip )
3633 FIXME("(%p)->%li %s %li %li %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3635 *pcchLine = cchSrc;
3636 *pcchSkip = 0;
3637 return S_OK;
3640 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3641 IMLangLineBreakConsole* iface,
3642 LCID locale,
3643 UINT uCodePage,
3644 const CHAR* pszSrc,
3645 LONG cchSrc,
3646 LONG cMaxColumns,
3647 LONG* pcchLine,
3648 LONG* pcchSkip)
3650 LONG i, line = cchSrc, skip = 0;
3652 FIXME("(%p)->%li %i %s %li %li %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3654 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3656 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3658 if (pszSrc[i] == ' ')
3660 while (i >= 0 && pszSrc[i] == ' ')
3662 i--;
3663 line--;
3664 skip++;
3666 break;
3670 *pcchLine = line;
3671 *pcchSkip = skip;
3672 return S_OK;
3675 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3677 fnIMLangLineBreakConsole_QueryInterface,
3678 fnIMLangLineBreakConsole_AddRef,
3679 fnIMLangLineBreakConsole_Release,
3680 fnIMLangLineBreakConsole_BreakLineML,
3681 fnIMLangLineBreakConsole_BreakLineW,
3682 fnIMLangLineBreakConsole_BreakLineA
3685 struct convert_charset {
3686 IMLangConvertCharset IMLangConvertCharset_iface;
3687 LONG ref;
3689 UINT src_cp;
3690 UINT dst_cp;
3693 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3695 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3698 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3700 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3702 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3704 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3706 *obj = &This->IMLangConvertCharset_iface;
3707 IMLangConvertCharset_AddRef(iface);
3708 return S_OK;
3711 *obj = NULL;
3712 return E_NOINTERFACE;
3715 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3717 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3718 ULONG ref = InterlockedIncrement(&This->ref);
3719 TRACE("(%p)->(%lu)\n", This, ref);
3720 return ref;
3723 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3725 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3726 ULONG ref = InterlockedDecrement(&This->ref);
3728 TRACE("(%p)->(%lu)\n", This, ref);
3729 if (!ref)
3731 free(This);
3732 UnlockModule();
3735 return ref;
3738 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3739 UINT src_cp, UINT dst_cp, DWORD prop)
3741 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3743 TRACE("(%p)->(%u %u 0x%08lx)\n", This, src_cp, dst_cp, prop);
3745 prop &= ~MLCONVCHARF_USEDEFCHAR;
3746 if (prop)
3747 FIXME("property 0x%08lx not supported\n", prop);
3749 This->src_cp = src_cp;
3750 This->dst_cp = dst_cp;
3752 return S_OK;
3755 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3757 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3759 TRACE("(%p)->(%p)\n", This, src_cp);
3761 if (!src_cp) return E_INVALIDARG;
3762 *src_cp = This->src_cp;
3763 return S_OK;
3766 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3768 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3770 TRACE("(%p)->(%p)\n", This, dst_cp);
3772 if (!dst_cp) return E_INVALIDARG;
3773 *dst_cp = This->dst_cp;
3774 return S_OK;
3777 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3779 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3780 FIXME("(%p)->(%p): stub\n", This, prop);
3781 return E_NOTIMPL;
3784 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3785 UINT *src_size, BYTE *dest, UINT *dest_size)
3787 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3788 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3789 return E_NOTIMPL;
3792 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3793 UINT *src_size, WCHAR *dest, UINT *dest_size)
3795 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3796 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3797 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3800 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3801 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3803 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3804 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3805 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3808 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3810 MLangConvertCharset_QueryInterface,
3811 MLangConvertCharset_AddRef,
3812 MLangConvertCharset_Release,
3813 MLangConvertCharset_Initialize,
3814 MLangConvertCharset_GetSourceCodePage,
3815 MLangConvertCharset_GetDestinationCodePage,
3816 MLangConvertCharset_GetProperty,
3817 MLangConvertCharset_DoConversion,
3818 MLangConvertCharset_DoConversionToUnicode,
3819 MLangConvertCharset_DoConversionFromUnicode
3822 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3824 MLang_impl *mlang;
3825 UINT i;
3827 TRACE("Creating MultiLanguage object\n");
3829 if( pUnkOuter )
3830 return CLASS_E_NOAGGREGATION;
3832 mlang = malloc(sizeof(MLang_impl));
3833 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3834 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3835 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3836 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3837 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3839 mlang->total_cp = 0;
3840 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3841 mlang->total_cp += mlang_data[i].number_of_cp;
3843 /* do not enumerate unicode flavours */
3844 mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3846 mlang->ref = 1;
3847 *ppObj = &mlang->IMultiLanguage_iface;
3848 TRACE("returning %p\n", mlang);
3850 LockModule();
3852 return S_OK;
3855 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3857 struct convert_charset *convert;
3859 if (outer)
3860 return CLASS_E_NOAGGREGATION;
3862 *obj = NULL;
3864 convert = malloc(sizeof(struct convert_charset));
3865 if (!convert) return E_OUTOFMEMORY;
3867 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3868 convert->ref = 1;
3870 *obj = &convert->IMLangConvertCharset_iface;
3872 LockModule();
3874 return S_OK;
3877 /******************************************************************************/
3879 HRESULT WINAPI DllCanUnloadNow(void)
3881 return dll_count == 0 ? S_OK : S_FALSE;
3884 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3886 if (!unknown) return E_INVALIDARG;
3888 FIXME("%p: stub\n", unknown);
3890 return S_FALSE;