wined3d: Avoid accessing gl_info in wined3d_buffer_init().
[wine.git] / dlls / mlang / mlang.c
blob1b1aed370e2c37885c3652908d68d8c6dbfd0628
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 static HINSTANCE instance;
52 static DWORD MLANG_tls_index; /* to store various per thead data */
54 /* FIXME:
55 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
56 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
59 typedef struct
61 const char *description;
62 UINT cp;
63 DWORD flags;
64 const char *web_charset;
65 const char *header_charset;
66 const char *body_charset;
67 const WCHAR *alias;
68 } MIME_CP_INFO;
70 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
71 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
73 static const MIME_CP_INFO arabic_cp[] =
75 { "Arabic (864)",
76 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
77 MIMECONTF_MIME_LATEST,
78 "ibm864", "ibm864", "ibm864" },
79 { "Arabic (1006)",
80 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
81 MIMECONTF_MIME_LATEST,
82 "ibm1006", "ibm1006", "ibm1006" },
83 { "Arabic (Windows)",
84 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
85 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
86 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
87 "windows-1256", "windows-1256", "windows-1256" },
88 { "Arabic (ISO)",
89 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
90 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
91 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
92 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
93 "iso-8859-6", "iso-8859-6", "iso-8859-6" }
95 static const MIME_CP_INFO baltic_cp[] =
97 { "Baltic (DOS)",
98 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
99 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
100 "ibm775", "ibm775", "ibm775" },
101 { "Baltic (Windows)",
102 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
103 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
104 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
105 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
106 "windows-1257", "windows-1257", "windows-1257" },
107 { "Baltic (ISO)",
108 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
109 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
110 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
111 MIMECONTF_MIME_LATEST,
112 "iso-8859-4", "iso-8859-4", "iso-8859-4" },
113 { "Estonian (ISO)",
114 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
115 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
116 "iso-8859-13", "iso-8859-13", "iso-8859-13" }
118 static const MIME_CP_INFO chinese_simplified_cp[] =
120 { "Chinese Simplified (Auto-Select)",
121 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
122 MIMECONTF_MIME_LATEST,
123 "_autodetect_chs", "_autodetect_chs", "_autodetect_chs" },
124 { "Chinese Simplified (GB2312)",
125 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
126 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
127 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
128 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
129 "gb2312", "gb2312", "gb2312" },
130 { "Chinese Simplified (GB2312-80)",
131 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
132 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
133 "x-cp20936", "x-cp20936", "x-cp20936" },
134 { "Chinese Simplified (HZ)",
135 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
136 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
137 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
138 MIMECONTF_MIME_LATEST,
139 "hz-gb-2312", "hz-gb-2312", "hz-gb-2312" },
140 { "Chinese Simplified (GB18030)",
141 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
142 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
143 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
144 MIMECONTF_MIME_LATEST,
145 "GB18030", "GB18030", "GB18030" },
146 { "Chinese Simplified (GBK)",
147 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
148 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
149 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
150 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
151 "gbk", "gbk", "gbk" }
153 static const MIME_CP_INFO chinese_traditional_cp[] =
155 { "Chinese Traditional (Auto-Select)",
156 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
157 MIMECONTF_MIME_LATEST,
158 "_autodetect_cht", "_autodetect_cht", "_autodetect_cht" },
159 { "Chinese Traditional (Big5)",
160 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
161 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
162 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
163 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
164 "big5", "big5", "big5" },
165 { "Chinese Traditional (CNS)",
166 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
167 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
168 "x-Chinese-CNS", "x-Chinese-CNS", "x-Chinese-CNS" }
170 static const MIME_CP_INFO central_european_cp[] =
172 { "Central European (DOS)",
173 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
174 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
175 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
176 "ibm852", "ibm852", "ibm852" },
177 { "Central European (Windows)",
178 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
179 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
180 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
181 MIMECONTF_MIME_LATEST,
182 "windows-1250", "windows-1250", "windows-1250" },
183 { "Central European (Mac)",
184 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
185 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
186 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
187 { "Central European (ISO)",
188 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
189 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
190 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
191 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
192 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
194 static const MIME_CP_INFO cyrillic_cp[] =
196 { "OEM Cyrillic",
197 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
198 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
199 "ibm855", "ibm855", "ibm855" },
200 { "Cyrillic (DOS)",
201 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
202 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
203 MIMECONTF_MIME_LATEST,
204 "cp866", "cp866", "cp866" },
205 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
206 { "Cyrillic (KOI8-R)",
207 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
208 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
209 "koi8-r", "koi8-r", "koi8-r" },
210 #endif
211 { "Cyrillic (Windows)",
212 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
213 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
214 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
215 "windows-1251", "windows-1251", "windows-1251" },
216 { "Cyrillic (Mac)",
217 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
218 MIMECONTF_MIME_LATEST,
219 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
220 { "Cyrillic (KOI8-R)",
221 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
222 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
223 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
224 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
225 "koi8-r", "koi8-r", "koi8-r" },
226 { "Cyrillic (KOI8-U)",
227 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
228 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
229 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
230 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
231 "koi8-u", "koi8-u", "koi8-u" },
232 { "Cyrillic (ISO)",
233 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
234 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
235 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
236 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
237 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
239 static const MIME_CP_INFO greek_cp[] =
241 { "Greek (DOS)",
242 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
243 MIMECONTF_MIME_LATEST,
244 "ibm737", "ibm737", "ibm737" },
245 { "Greek, Modern (DOS)",
246 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
247 MIMECONTF_MIME_LATEST,
248 "ibm869", "ibm869", "ibm869" },
249 { "IBM EBCDIC (Greek Modern)",
250 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
251 MIMECONTF_MIME_LATEST,
252 "cp875", "cp875", "cp875" },
253 { "Greek (Windows)",
254 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
255 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
256 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
257 "windows-1253", "windows-1253", "windows-1253" },
258 { "Greek (Mac)",
259 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
260 MIMECONTF_MIME_LATEST,
261 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
262 { "Greek (ISO)",
263 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
264 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
265 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
266 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
267 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
269 static const MIME_CP_INFO hebrew_cp[] =
271 { "Hebrew (424)",
272 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
273 MIMECONTF_MIME_LATEST,
274 "ibm424", "ibm424", "ibm424" },
275 { "Hebrew (856)",
276 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
277 MIMECONTF_MIME_LATEST,
278 "cp856", "cp856", "cp856" },
279 { "Hebrew (DOS)",
280 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
281 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
282 MIMECONTF_MIME_LATEST,
283 "dos-862", "dos-862", "dos-862" },
284 { "Hebrew (Windows)",
285 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
286 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
287 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
288 "windows-1255", "windows-1255", "windows-1255" },
289 { "Hebrew (ISO-Visual)",
290 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
291 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
292 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
293 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
295 static const MIME_CP_INFO japanese_cp[] =
297 { "Japanese (Auto-Select)",
298 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
299 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
300 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
301 "_autodetect", "_autodetect", "_autodetect" },
302 { "Japanese (EUC)",
303 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
304 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
305 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
306 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
307 "euc-jp", "euc-jp", "euc-jp" },
308 { "Japanese (JIS)",
309 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
310 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
311 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
312 MIMECONTF_MIME_IE4,
313 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
314 { "Japanese (JIS 0208-1990 and 0212-1990)",
315 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
316 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
317 "EUC-JP","EUC-JP","EUC-JP"},
318 { "Japanese (JIS-Allow 1 byte Kana)",
319 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
320 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
321 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
322 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
323 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
324 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
325 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
326 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
327 { "Japanese (Mac)",
328 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
329 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
330 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
331 { "Japanese (Shift-JIS)",
332 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
333 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
334 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
335 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
336 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
338 static const MIME_CP_INFO korean_cp[] =
340 { "Korean",
341 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
342 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
343 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
344 MIMECONTF_MIME_LATEST,
345 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
347 static const MIME_CP_INFO thai_cp[] =
349 { "Thai (Windows)",
350 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
351 "ibm-thai", "ibm-thai", "ibm-thai" }
353 static const MIME_CP_INFO turkish_cp[] =
355 { "Turkish (DOS)",
356 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
357 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
358 "ibm857", "ibm857", "ibm857" },
359 { "IBM EBCDIC (Turkish Latin-5)",
360 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
361 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
362 "ibm1026", "ibm1026", "ibm1026" },
363 { "Turkish (Windows)",
364 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
365 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
366 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
367 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
368 "windows-1254", "windows-1254", "windows-1254" },
369 { "Turkish (Mac)",
370 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
371 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
372 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
373 { "Latin 3 (ISO)",
374 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
375 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
376 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
377 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
378 { "Turkish (ISO)",
379 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
380 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
381 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
382 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
383 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
385 static const MIME_CP_INFO vietnamese_cp[] =
387 { "Vietnamese (Windows)",
388 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
389 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
390 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
391 MIMECONTF_MIME_LATEST,
392 "windows-1258", "windows-1258", "windows-1258" }
395 static const WCHAR asciiW[] = {'a','s','c','i','i',0};
397 static const MIME_CP_INFO western_cp[] =
399 { "IBM EBCDIC (US-Canada)",
400 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
401 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
402 "ibm037", "ibm037", "ibm037" },
403 { "OEM United States",
404 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
405 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
406 "ibm437", "ibm437", "ibm437" },
407 { "IBM EBCDIC (International)",
408 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
409 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
410 "ibm500", "ibm500", "ibm500" },
411 { "Western European (DOS)",
412 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
413 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
414 "ibm850", "ibm850", "ibm850" },
415 { "Portuguese (DOS)",
416 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
417 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
418 "ibm860", "ibm860", "ibm860" },
419 { "Icelandic (DOS)",
420 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
421 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
422 "ibm861", "ibm861", "ibm861" },
423 { "French Canadian (DOS)",
424 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
425 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
426 "ibm863", "ibm863", "ibm863" },
427 { "Nordic (DOS)",
428 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
429 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
430 "ibm865", "ibm865", "ibm865" },
431 { "Western European (Windows)",
432 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
433 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
434 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
435 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
436 "windows-1252", "windows-1252", "iso-8859-1" },
437 { "Western European (Mac)",
438 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
439 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
440 "macintosh", "macintosh", "macintosh" },
441 { "Icelandic (Mac)",
442 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
443 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
444 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
445 { "US-ASCII",
446 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
447 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
448 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
449 "us-ascii", "us-ascii", "us-ascii", asciiW },
450 { "Western European (ISO)",
451 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
452 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
453 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
454 MIMECONTF_MIME_LATEST,
455 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
456 { "Latin 9 (ISO)",
457 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
458 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
459 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
460 MIMECONTF_MIME_LATEST,
461 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
463 static const MIME_CP_INFO unicode_cp[] =
465 { "Unicode",
466 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
467 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
468 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
469 MIMECONTF_MIME_LATEST,
470 "unicode", "unicode", "unicode" },
471 { "Unicode (UTF-7)",
472 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
473 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
474 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
475 "utf-7", "utf-7", "utf-7" },
476 { "Unicode (UTF-8)",
477 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
478 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
479 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
480 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
481 "utf-8", "utf-8", "utf-8" }
484 static const struct mlang_data
486 const char *description;
487 UINT family_codepage;
488 UINT number_of_cp;
489 const MIME_CP_INFO *mime_cp_info;
490 const char *fixed_font;
491 const char *proportional_font;
492 SCRIPT_ID sid;
493 } mlang_data[] =
495 { "Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
496 "Simplified Arabic Fixed","Simplified Arabic", sidArabic },
497 { "Baltic", 1257, ARRAY_SIZE(baltic_cp), baltic_cp,
498 "Courier New","Arial", sidAsciiLatin },
499 { "Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
500 "Simsun","Simsun", sidHan },
501 { "Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
502 "MingLiu","New MingLiu", sidBopomofo },
503 { "Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
504 "Courier New","Arial", sidAsciiLatin },
505 { "Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
506 "Courier New","Arial", sidCyrillic },
507 { "Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
508 "Courier New","Arial", sidGreek },
509 { "Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
510 "Miriam Fixed","David", sidHebrew },
511 { "Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
512 "MS Gothic","MS PGothic", sidKana },
513 { "Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
514 "GulimChe","Gulim", sidHangul },
515 { "Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
516 "Tahoma","Tahoma", sidThai },
517 { "Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
518 "Courier New","Arial", sidAsciiLatin },
519 { "Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
520 "Courier New","Arial", sidAsciiLatin },
521 { "Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
522 "Courier New","Arial", sidAsciiLatin },
523 { "Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
524 "Courier New","Arial" }
527 struct font_list
529 struct list list_entry;
530 HFONT base_font;
531 HFONT font;
532 UINT charset;
535 static struct list font_cache = LIST_INIT(font_cache);
536 static CRITICAL_SECTION font_cache_critical;
537 static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
539 0, 0, &font_cache_critical,
540 { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
541 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
543 static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
545 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
547 static LONG dll_count;
550 * Japanese Detection and Conversion Functions
553 #define HANKATA(A) ((A >= 161) && (A <= 223))
554 #define ISEUC(A) ((A >= 161) && (A <= 254))
555 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
556 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
557 #define SJIS2(A) ((A >= 64) && (A <= 252))
558 #define ISMARU(A) ((A >= 202) && (A <= 206))
559 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
561 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
563 UINT code = 0;
564 DWORD i = 0;
565 unsigned char c1,c2;
567 while ((code == 0 || code == 51932) && i < count)
569 c1 = input[i];
570 if (c1 == 0x1b /* ESC */)
572 i++;
573 if (i >= count)
574 return code;
575 c1 = input[i];
576 if (c1 == '$')
578 i++;
579 if (i >= count)
580 return code;
581 c1 = input[i];
582 if (c1 =='B' || c1 == '@')
583 code = 50220;
585 if (c1 == 'K')
586 code = 50220;
588 else if (c1 >= 129)
590 i++;
591 if (i >= count)
592 return code;
593 c2 = input[i];
594 if NOTEUC(c1,c2)
595 code = 932;
596 else if (ISEUC(c1) && ISEUC(c2))
597 code = 51932;
598 else if (((c1 == 142)) && HANKATA(c2))
599 code = 51932;
601 i++;
603 return code;
606 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
608 unsigned char c1 = *p1;
609 unsigned char c2 = *p2;
610 int row = c1 < 95 ? 112 : 176;
611 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
613 *p1 = ((c1 + 1) >> 1) + row;
614 *p2 = c2 + cell;
617 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
619 unsigned char c1 = *p1;
620 unsigned char c2 = *p2;
621 int shift = c2 < 159;
622 int row = c1 < 160 ? 112 : 176;
623 int cell = shift ? (31 + (c2 > 127)): 126;
625 *p1 = ((c1 - row) << 1) - shift;
626 *p2 -= cell;
629 static int han2zen(unsigned char *p1, unsigned char *p2)
631 BOOL maru = FALSE;
632 BOOL nigori = FALSE;
633 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
634 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
635 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
636 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
637 131,129,129 };
638 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
639 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
640 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
641 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
643 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
644 nigori = TRUE;
645 else if ((*p2 == 223) && (ISMARU(*p1)))
646 maru = TRUE;
648 if (*p1 >= 161 && *p1 <= 223)
650 unsigned char index = *p1 - 161;
651 *p1 = char1[index];
652 *p2 = char2[index];
655 if (maru || nigori)
657 if (nigori)
659 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
660 (*p2)++;
661 else if ((*p1 == 131) && (*p2 == 69))
662 *p2 = 148;
664 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
665 *p2+= 2;
667 return 1;
670 return 0;
674 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
676 DWORD i = 0;
677 int j = 0;
678 unsigned char p2,p;
679 BOOL shifted = FALSE;
681 while (i < count)
683 p = input[i];
684 if (p == 0x1b /* ESC */)
686 i++;
687 if (i >= count)
688 return 0;
689 p2 = input[i];
690 if (p2 == '$' || p2 =='(')
691 i++;
692 if (p2 == 'K' || p2 =='$')
693 shifted = TRUE;
694 else
695 shifted = FALSE;
697 else
699 if (shifted)
701 i++;
702 if (i >= count)
703 return 0;
704 p2 = input[i];
705 jis2sjis(&p,&p2);
706 output[j++]=p;
707 output[j++]=p2;
709 else
711 output[j++] = p;
714 i++;
716 return j;
719 static inline int exit_shift(LPSTR out, int c)
721 if (out)
723 out[c] = 0x1b;
724 out[c+1] = '(';
725 out[c+2] = 'B';
727 return 3;
730 static inline int enter_shift(LPSTR out, int c)
732 if (out)
734 out[c] = 0x1b;
735 out[c+1] = '$';
736 out[c+2] = 'B';
738 return 3;
742 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
744 DWORD i = 0;
745 int j = 0;
746 unsigned char p2,p;
747 BOOL shifted = FALSE;
749 while (i < count)
751 p = input[i] & 0xff;
752 if (p == 10 || p == 13) /* NL and CR */
754 if (shifted)
756 shifted = FALSE;
757 j += exit_shift(output,j);
759 if (output)
760 output[j++] = p;
761 else
762 j++;
764 else
766 if (SJIS1(p))
768 i++;
769 if (i >= count)
770 return 0;
771 p2 = input[i] & 0xff;
772 if (SJIS2(p2))
774 sjis2jis(&p,&p2);
775 if (!shifted)
777 shifted = TRUE;
778 j+=enter_shift(output,j);
782 if (output)
784 output[j++]=p;
785 output[j++]=p2;
787 else
788 j+=2;
790 else
792 if (HANKATA(p))
794 if ((i+1) >= count)
795 return 0;
796 p2 = input[i+1] & 0xff;
797 i+=han2zen(&p,&p2);
798 sjis2jis(&p,&p2);
799 if (!shifted)
801 shifted = TRUE;
802 j+=enter_shift(output,j);
804 if (output)
806 output[j++]=p;
807 output[j++]=p2;
809 else
810 j+=2;
812 else
814 if (shifted)
816 shifted = FALSE;
817 j += exit_shift(output,j);
819 if (output)
820 output[j++]=p;
821 else
822 j++;
826 i++;
828 if (shifted)
829 j += exit_shift(output,j);
830 return j;
833 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
834 LPWSTR output, DWORD out_count)
836 CHAR *sjis_string;
837 UINT rc = 0;
838 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
839 rc = ConvertJIS2SJIS(input,count,sjis_string);
840 if (rc)
842 TRACE("%s\n",debugstr_an(sjis_string,rc));
843 if (output)
844 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
845 else
846 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
848 HeapFree(GetProcessHeap(),0,sjis_string);
849 return rc;
853 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
854 LPWSTR output, DWORD out_count)
856 CHAR *sjis_string;
857 UINT rc = 0;
858 int code = DetectJapaneseCode(input,count);
859 TRACE("Japanese code %i\n",code);
861 switch (code)
863 case 0:
864 if (output)
865 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
866 else
867 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
868 break;
870 case 932:
871 if (output)
872 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
873 else
874 rc = MultiByteToWideChar(932,0,input,count,0,0);
875 break;
877 case 51932:
878 if (output)
879 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
880 else
881 rc = MultiByteToWideChar(20932,0,input,count,0,0);
882 break;
884 case 50220:
885 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
886 rc = ConvertJIS2SJIS(input,count,sjis_string);
887 if (rc)
889 TRACE("%s\n",debugstr_an(sjis_string,rc));
890 if (output)
891 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
892 else
893 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
895 HeapFree(GetProcessHeap(),0,sjis_string);
896 break;
898 return rc;
901 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
902 LPSTR output, DWORD out_count)
904 CHAR *sjis_string;
905 INT len;
906 UINT rc = 0;
908 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
909 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
910 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
911 TRACE("%s\n",debugstr_an(sjis_string,len));
913 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
914 if (out_count >= rc)
916 ConvertSJIS2JIS(sjis_string, len, output);
918 HeapFree(GetProcessHeap(),0,sjis_string);
919 return rc;
924 * Dll lifetime tracking declaration
926 static void LockModule(void)
928 InterlockedIncrement(&dll_count);
931 static void UnlockModule(void)
933 InterlockedDecrement(&dll_count);
936 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
938 switch(fdwReason) {
939 case DLL_PROCESS_ATTACH:
940 instance = hInstDLL;
941 MLANG_tls_index = TlsAlloc();
942 DisableThreadLibraryCalls(hInstDLL);
943 break;
944 case DLL_PROCESS_DETACH:
945 if (lpv) break;
946 TlsFree(MLANG_tls_index);
947 break;
949 return TRUE;
952 HRESULT WINAPI ConvertINetMultiByteToUnicode(
953 LPDWORD pdwMode,
954 DWORD dwEncoding,
955 LPCSTR pSrcStr,
956 LPINT pcSrcSize,
957 LPWSTR pDstStr,
958 LPINT pcDstSize)
960 INT src_len = -1;
962 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
963 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
965 if (!pcDstSize)
966 return E_FAIL;
968 if (!pcSrcSize)
969 pcSrcSize = &src_len;
971 if (!*pcSrcSize)
973 *pcDstSize = 0;
974 return S_OK;
977 /* forwarding euc-jp to EUC-JP */
978 if (dwEncoding == 51932)
979 dwEncoding = 20932;
981 switch (dwEncoding)
983 case CP_UNICODE:
984 if (*pcSrcSize == -1)
985 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
986 *pcDstSize = min(*pcSrcSize, *pcDstSize);
987 *pcSrcSize *= sizeof(WCHAR);
988 if (pDstStr)
989 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
990 break;
992 case 50220:
993 case 50221:
994 case 50222:
995 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
996 break;
997 case 50932:
998 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
999 break;
1001 default:
1002 if (*pcSrcSize == -1)
1003 *pcSrcSize = lstrlenA(pSrcStr);
1005 if (pDstStr)
1006 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
1007 else
1008 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
1009 break;
1012 if (!*pcDstSize)
1013 return E_FAIL;
1015 return S_OK;
1018 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
1019 LPDWORD pdwMode,
1020 DWORD dwEncoding,
1021 LPCWSTR pSrcStr,
1022 LPINT pcSrcSize,
1023 LPSTR pDstStr,
1024 LPINT pcDstSize)
1026 INT destsz, size;
1027 INT src_len = -1;
1029 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
1030 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1032 if (!pcDstSize)
1033 return S_OK;
1035 if (!pcSrcSize)
1036 pcSrcSize = &src_len;
1038 destsz = (pDstStr) ? *pcDstSize : 0;
1039 *pcDstSize = 0;
1041 if (!pSrcStr || !*pcSrcSize)
1042 return S_OK;
1044 if (*pcSrcSize == -1)
1045 *pcSrcSize = lstrlenW(pSrcStr);
1047 /* forwarding euc-jp to EUC-JP */
1048 if (dwEncoding == 51932)
1049 dwEncoding = 20932;
1051 if (dwEncoding == CP_UNICODE)
1053 if (*pcSrcSize == -1)
1054 *pcSrcSize = lstrlenW(pSrcStr);
1056 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1057 if (pDstStr)
1058 memmove(pDstStr, pSrcStr, size);
1060 if (size >= destsz)
1061 goto fail;
1063 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1065 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1066 if (!size)
1067 goto fail;
1069 if (pDstStr)
1071 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1072 destsz);
1073 if (!size)
1074 goto fail;
1078 else
1080 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1081 NULL, 0, NULL, NULL);
1082 if (!size)
1083 goto fail;
1085 if (pDstStr)
1087 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1088 pDstStr, destsz, NULL, NULL);
1089 if (!size)
1090 goto fail;
1094 *pcDstSize = size;
1095 return S_OK;
1097 fail:
1098 *pcSrcSize = 0;
1099 *pcDstSize = 0;
1100 return E_FAIL;
1103 HRESULT WINAPI ConvertINetString(
1104 LPDWORD pdwMode,
1105 DWORD dwSrcEncoding,
1106 DWORD dwDstEncoding,
1107 LPCSTR pSrcStr,
1108 LPINT pcSrcSize,
1109 LPSTR pDstStr,
1110 LPINT pcDstSize
1113 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1114 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1116 if (dwSrcEncoding == CP_UNICODE)
1118 INT cSrcSizeW;
1119 if (pcSrcSize && *pcSrcSize != -1)
1121 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1122 pcSrcSize = &cSrcSizeW;
1124 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1126 else if (dwDstEncoding == CP_UNICODE)
1128 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1129 *pcDstSize *= sizeof(WCHAR);
1130 return hr;
1132 else
1134 INT cDstSizeW;
1135 LPWSTR pDstStrW;
1136 HRESULT hr;
1138 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1140 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1141 if (hr != S_OK)
1142 return hr;
1144 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1145 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1146 if (hr == S_OK)
1147 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1149 HeapFree(GetProcessHeap(), 0, pDstStrW);
1150 return hr;
1154 static HRESULT GetFamilyCodePage(
1155 UINT uiCodePage,
1156 UINT* puiFamilyCodePage)
1158 UINT i, n;
1160 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1162 if (!puiFamilyCodePage) return S_FALSE;
1164 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1166 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1168 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1170 *puiFamilyCodePage = mlang_data[i].family_codepage;
1171 return S_OK;
1176 return S_FALSE;
1179 HRESULT WINAPI IsConvertINetStringAvailable(
1180 DWORD dwSrcEncoding,
1181 DWORD dwDstEncoding)
1183 UINT src_family, dst_family;
1185 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1187 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1188 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1189 return S_FALSE;
1191 if (src_family == dst_family) return S_OK;
1193 /* we can convert any codepage to/from unicode */
1194 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1196 return S_FALSE;
1199 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1201 CHAR buffer[MAX_RFC1766_NAME];
1202 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1203 INT i;
1205 if (n)
1207 i = PRIMARYLANGID(lcid);
1208 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1209 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1210 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1212 buffer[n - 1] = '-';
1213 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1214 if (!i)
1215 buffer[n - 1] = '\0';
1217 else
1218 i = 0;
1220 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1221 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1223 return E_FAIL;
1226 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1228 WCHAR buffer[MAX_RFC1766_NAME];
1229 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1230 INT i;
1232 if (n)
1234 i = PRIMARYLANGID(lcid);
1235 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1236 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1237 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1239 buffer[n - 1] = '-';
1240 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1241 if (!i)
1242 buffer[n - 1] = '\0';
1244 else
1245 i = 0;
1247 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1248 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1250 return E_FAIL;
1253 HRESULT WINAPI LcidToRfc1766A(
1254 LCID lcid,
1255 LPSTR pszRfc1766,
1256 INT nChar)
1258 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1259 if (!pszRfc1766)
1260 return E_INVALIDARG;
1262 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1265 HRESULT WINAPI LcidToRfc1766W(
1266 LCID lcid,
1267 LPWSTR pszRfc1766,
1268 INT nChar)
1270 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1271 if (!pszRfc1766)
1272 return E_INVALIDARG;
1274 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1277 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1279 RFC1766INFO info;
1280 ULONG num;
1282 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1284 if (!wcsicmp(info.wszRfc1766, rfc1766))
1286 *lcid = info.lcid;
1287 return S_OK;
1289 if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1291 *lcid = PRIMARYLANGID(info.lcid);
1292 return S_OK;
1296 return E_FAIL;
1299 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1301 IEnumRfc1766 *enumrfc1766;
1302 HRESULT hr;
1304 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1306 if (!pLocale || !pszRfc1766)
1307 return E_INVALIDARG;
1309 hr = EnumRfc1766_create(0, &enumrfc1766);
1310 if (FAILED(hr))
1311 return hr;
1313 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1314 IEnumRfc1766_Release(enumrfc1766);
1316 return hr;
1319 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1321 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1323 if (!rfc1766A)
1324 return E_INVALIDARG;
1326 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1327 rfc1766W[MAX_RFC1766_NAME] = 0;
1329 return Rfc1766ToLcidW(lcid, rfc1766W);
1332 static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
1334 struct font_list *font_list_entry;
1335 CHARSETINFO charset_info;
1336 HFONT new_font, old_font;
1337 LOGFONTW font_attr;
1338 DWORD mask, Csb[2];
1339 BOOL found_cached;
1340 UINT charset;
1341 BOOL ret;
1342 UINT i;
1344 if (hdc == NULL || src_font == NULL) return E_FAIL;
1346 for (i = 0; i < 32; i++)
1348 mask = (DWORD)(1 << i);
1349 if (codepages & mask)
1351 Csb[0] = mask;
1352 Csb[1] = 0x0;
1353 ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
1354 if (!ret) continue;
1356 /* use cached font if possible */
1357 found_cached = FALSE;
1358 EnterCriticalSection(&font_cache_critical);
1359 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1361 if (font_list_entry->charset == charset_info.ciCharset &&
1362 font_list_entry->base_font == src_font)
1364 if (dst_font != NULL)
1365 *dst_font = font_list_entry->font;
1366 found_cached = TRUE;
1369 LeaveCriticalSection(&font_cache_critical);
1370 if (found_cached) return S_OK;
1372 GetObjectW(src_font, sizeof(font_attr), &font_attr);
1373 font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
1374 font_attr.lfWidth = 0;
1375 font_attr.lfFaceName[0] = 0;
1376 new_font = CreateFontIndirectW(&font_attr);
1377 if (new_font == NULL) continue;
1379 old_font = SelectObject(hdc, new_font);
1380 charset = GetTextCharset(hdc);
1381 SelectObject(hdc, old_font);
1382 if (charset == charset_info.ciCharset)
1384 font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
1385 if (font_list_entry == NULL) return E_OUTOFMEMORY;
1387 font_list_entry->base_font = src_font;
1388 font_list_entry->font = new_font;
1389 font_list_entry->charset = charset;
1391 EnterCriticalSection(&font_cache_critical);
1392 list_add_tail(&font_cache, &font_list_entry->list_entry);
1393 LeaveCriticalSection(&font_cache_critical);
1395 if (dst_font != NULL)
1396 *dst_font = new_font;
1397 return S_OK;
1402 return E_FAIL;
1405 static HRESULT release_font(HFONT font)
1407 struct font_list *font_list_entry;
1408 HRESULT hr;
1410 hr = E_FAIL;
1411 EnterCriticalSection(&font_cache_critical);
1412 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1414 if (font_list_entry->font == font)
1416 list_remove(&font_list_entry->list_entry);
1417 DeleteObject(font);
1418 HeapFree(GetProcessHeap(), 0, font_list_entry);
1419 hr = S_OK;
1420 break;
1423 LeaveCriticalSection(&font_cache_critical);
1425 return hr;
1428 static HRESULT clear_font_cache(void)
1430 struct font_list *font_list_entry;
1431 struct font_list *font_list_entry2;
1433 EnterCriticalSection(&font_cache_critical);
1434 LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
1436 list_remove(&font_list_entry->list_entry);
1437 DeleteObject(font_list_entry->font);
1438 HeapFree(GetProcessHeap(), 0, font_list_entry);
1440 LeaveCriticalSection(&font_cache_critical);
1442 return S_OK;
1445 /******************************************************************************
1446 * MLANG ClassFactory
1448 typedef struct {
1449 IClassFactory IClassFactory_iface;
1450 LONG ref;
1451 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1452 } IClassFactoryImpl;
1454 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1456 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1459 struct object_creation_info
1461 const CLSID *clsid;
1462 LPCSTR szClassName;
1463 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1466 static const struct object_creation_info object_creation[] =
1468 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1469 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1472 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1474 TRACE("%s\n", debugstr_guid(riid) );
1476 if (IsEqualGUID(riid, &IID_IUnknown)
1477 || IsEqualGUID(riid, &IID_IClassFactory))
1479 IClassFactory_AddRef(iface);
1480 *ppobj = iface;
1481 return S_OK;
1484 *ppobj = NULL;
1485 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1486 return E_NOINTERFACE;
1489 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1491 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1492 return InterlockedIncrement(&This->ref);
1495 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1497 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1498 ULONG ref = InterlockedDecrement(&This->ref);
1500 if (ref == 0)
1502 TRACE("Destroying %p\n", This);
1503 HeapFree(GetProcessHeap(), 0, This);
1506 return ref;
1509 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1510 REFIID riid, void **ppobj)
1512 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1513 HRESULT hres;
1514 LPUNKNOWN punk;
1516 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1518 *ppobj = NULL;
1519 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1520 if (SUCCEEDED(hres)) {
1521 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1522 IUnknown_Release(punk);
1524 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1525 return hres;
1528 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1530 if (dolock)
1531 LockModule();
1532 else
1533 UnlockModule();
1535 return S_OK;
1538 static const IClassFactoryVtbl MLANGCF_Vtbl =
1540 MLANGCF_QueryInterface,
1541 MLANGCF_AddRef,
1542 MLANGCF_Release,
1543 MLANGCF_CreateInstance,
1544 MLANGCF_LockServer
1547 /******************************************************************
1548 * DllGetClassObject (MLANG.@)
1550 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1552 unsigned int i;
1553 IClassFactoryImpl *factory;
1555 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1557 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1558 && ! IsEqualGUID( &IID_IUnknown, iid) )
1559 return E_NOINTERFACE;
1561 for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1563 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1564 break;
1567 if (i == ARRAY_SIZE(object_creation))
1569 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1570 return CLASS_E_CLASSNOTAVAILABLE;
1573 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1575 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1576 if (factory == NULL) return E_OUTOFMEMORY;
1578 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1579 factory->ref = 1;
1581 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1583 *ppv = &factory->IClassFactory_iface;
1585 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1587 return S_OK;
1591 /******************************************************************************/
1593 typedef struct tagMLang_impl
1595 IMLangFontLink IMLangFontLink_iface;
1596 IMultiLanguage IMultiLanguage_iface;
1597 IMultiLanguage3 IMultiLanguage3_iface;
1598 IMLangFontLink2 IMLangFontLink2_iface;
1599 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1600 LONG ref;
1601 DWORD total_cp, total_scripts;
1602 } MLang_impl;
1604 /******************************************************************************/
1606 typedef struct tagEnumCodePage_impl
1608 IEnumCodePage IEnumCodePage_iface;
1609 LONG ref;
1610 MIMECPINFO *cpinfo;
1611 DWORD total, pos;
1612 } EnumCodePage_impl;
1614 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1616 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1619 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1620 IEnumCodePage* iface,
1621 REFIID riid,
1622 void** ppvObject)
1624 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1626 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1628 if (IsEqualGUID(riid, &IID_IUnknown)
1629 || IsEqualGUID(riid, &IID_IEnumCodePage))
1631 IEnumCodePage_AddRef(iface);
1632 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1633 *ppvObject = &This->IEnumCodePage_iface;
1634 return S_OK;
1637 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1638 return E_NOINTERFACE;
1641 static ULONG WINAPI fnIEnumCodePage_AddRef(
1642 IEnumCodePage* iface)
1644 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1645 return InterlockedIncrement(&This->ref);
1648 static ULONG WINAPI fnIEnumCodePage_Release(
1649 IEnumCodePage* iface)
1651 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1652 ULONG ref = InterlockedDecrement(&This->ref);
1654 TRACE("%p ref = %d\n", This, ref);
1655 if (ref == 0)
1657 TRACE("Destroying %p\n", This);
1658 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1659 HeapFree(GetProcessHeap(), 0, This);
1662 return ref;
1665 static HRESULT WINAPI fnIEnumCodePage_Clone(
1666 IEnumCodePage* iface,
1667 IEnumCodePage** ppEnum)
1669 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1670 FIXME("%p %p\n", This, ppEnum);
1671 return E_NOTIMPL;
1674 static HRESULT WINAPI fnIEnumCodePage_Next(
1675 IEnumCodePage* iface,
1676 ULONG celt,
1677 PMIMECPINFO rgelt,
1678 ULONG* pceltFetched)
1680 ULONG i;
1681 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1683 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1685 if (!pceltFetched) return S_FALSE;
1686 *pceltFetched = 0;
1688 if (!rgelt) return S_FALSE;
1690 if (This->pos + celt > This->total)
1691 celt = This->total - This->pos;
1693 if (!celt) return S_FALSE;
1695 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1696 *pceltFetched = celt;
1697 This->pos += celt;
1699 for (i = 0; i < celt; i++)
1701 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1702 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1703 rgelt[i].uiFamilyCodePage,
1704 wine_dbgstr_w(rgelt[i].wszDescription),
1705 wine_dbgstr_w(rgelt[i].wszWebCharset),
1706 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1707 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1708 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1709 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1710 rgelt[i].bGDICharset);
1712 return S_OK;
1715 static HRESULT WINAPI fnIEnumCodePage_Reset(
1716 IEnumCodePage* iface)
1718 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1720 TRACE("%p\n", This);
1722 This->pos = 0;
1723 return S_OK;
1726 static HRESULT WINAPI fnIEnumCodePage_Skip(
1727 IEnumCodePage* iface,
1728 ULONG celt)
1730 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1732 TRACE("%p %u\n", This, celt);
1734 if (celt >= This->total) return S_FALSE;
1736 This->pos += celt;
1737 return S_OK;
1740 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1742 fnIEnumCodePage_QueryInterface,
1743 fnIEnumCodePage_AddRef,
1744 fnIEnumCodePage_Release,
1745 fnIEnumCodePage_Clone,
1746 fnIEnumCodePage_Next,
1747 fnIEnumCodePage_Reset,
1748 fnIEnumCodePage_Skip
1751 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1752 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1754 EnumCodePage_impl *ecp;
1755 MIMECPINFO *cpinfo;
1756 UINT i, n;
1758 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1760 if (!grfFlags) /* enumerate internal data base of encodings */
1761 grfFlags = MIMECONTF_MIME_LATEST;
1763 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1764 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1765 ecp->ref = 1;
1766 ecp->pos = 0;
1767 ecp->total = 0;
1768 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1770 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1772 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1773 ecp->total++;
1777 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1778 sizeof(MIMECPINFO) * ecp->total);
1779 cpinfo = ecp->cpinfo;
1781 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1783 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1785 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1786 fill_cp_info(&mlang_data[i], n, cpinfo++);
1790 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1792 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1794 return S_OK;
1797 /******************************************************************************/
1799 typedef struct tagEnumScript_impl
1801 IEnumScript IEnumScript_iface;
1802 LONG ref;
1803 SCRIPTINFO *script_info;
1804 DWORD total, pos;
1805 } EnumScript_impl;
1807 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1809 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1812 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1813 IEnumScript* iface,
1814 REFIID riid,
1815 void** ppvObject)
1817 EnumScript_impl *This = impl_from_IEnumScript( iface );
1819 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1821 if (IsEqualGUID(riid, &IID_IUnknown)
1822 || IsEqualGUID(riid, &IID_IEnumScript))
1824 IEnumScript_AddRef(iface);
1825 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1826 *ppvObject = &This->IEnumScript_iface;
1827 return S_OK;
1830 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1831 return E_NOINTERFACE;
1834 static ULONG WINAPI fnIEnumScript_AddRef(
1835 IEnumScript* iface)
1837 EnumScript_impl *This = impl_from_IEnumScript( iface );
1838 return InterlockedIncrement(&This->ref);
1841 static ULONG WINAPI fnIEnumScript_Release(
1842 IEnumScript* iface)
1844 EnumScript_impl *This = impl_from_IEnumScript( iface );
1845 ULONG ref = InterlockedDecrement(&This->ref);
1847 TRACE("%p ref = %d\n", This, ref);
1848 if (ref == 0)
1850 TRACE("Destroying %p\n", This);
1851 HeapFree(GetProcessHeap(), 0, This->script_info);
1852 HeapFree(GetProcessHeap(), 0, This);
1855 return ref;
1858 static HRESULT WINAPI fnIEnumScript_Clone(
1859 IEnumScript* iface,
1860 IEnumScript** ppEnum)
1862 EnumScript_impl *This = impl_from_IEnumScript( iface );
1863 FIXME("%p %p: stub!\n", This, ppEnum);
1864 return E_NOTIMPL;
1867 static HRESULT WINAPI fnIEnumScript_Next(
1868 IEnumScript* iface,
1869 ULONG celt,
1870 PSCRIPTINFO rgelt,
1871 ULONG* pceltFetched)
1873 EnumScript_impl *This = impl_from_IEnumScript( iface );
1875 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1877 if (!pceltFetched || !rgelt) return E_FAIL;
1879 *pceltFetched = 0;
1881 if (This->pos + celt > This->total)
1882 celt = This->total - This->pos;
1884 if (!celt) return S_FALSE;
1886 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1887 *pceltFetched = celt;
1888 This->pos += celt;
1890 return S_OK;
1893 static HRESULT WINAPI fnIEnumScript_Reset(
1894 IEnumScript* iface)
1896 EnumScript_impl *This = impl_from_IEnumScript( iface );
1898 TRACE("%p\n", This);
1900 This->pos = 0;
1901 return S_OK;
1904 static HRESULT WINAPI fnIEnumScript_Skip(
1905 IEnumScript* iface,
1906 ULONG celt)
1908 EnumScript_impl *This = impl_from_IEnumScript( iface );
1910 TRACE("%p %u\n", This, celt);
1912 if (celt >= This->total) return S_FALSE;
1914 This->pos += celt;
1915 return S_OK;
1918 static const IEnumScriptVtbl IEnumScript_vtbl =
1920 fnIEnumScript_QueryInterface,
1921 fnIEnumScript_AddRef,
1922 fnIEnumScript_Release,
1923 fnIEnumScript_Clone,
1924 fnIEnumScript_Next,
1925 fnIEnumScript_Reset,
1926 fnIEnumScript_Skip
1929 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1930 LANGID LangId, IEnumScript** ppEnumScript )
1932 EnumScript_impl *es;
1933 UINT i;
1935 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1937 if (!dwFlags) /* enumerate all available scripts */
1938 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1940 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1941 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1942 es->ref = 1;
1943 es->pos = 0;
1944 /* do not enumerate unicode flavours */
1945 es->total = ARRAY_SIZE(mlang_data) - 1;
1946 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1948 for (i = 0; i < es->total; i++)
1950 es->script_info[i].ScriptId = i;
1951 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1952 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1953 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1954 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1955 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1956 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1957 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1960 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1962 *ppEnumScript = &es->IEnumScript_iface;
1964 return S_OK;
1967 /******************************************************************************/
1969 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1971 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1974 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1975 IMLangFontLink* iface,
1976 REFIID riid,
1977 void** ppvObject)
1979 MLang_impl *This = impl_from_IMLangFontLink( iface );
1980 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1983 static ULONG WINAPI fnIMLangFontLink_AddRef(
1984 IMLangFontLink* iface)
1986 MLang_impl *This = impl_from_IMLangFontLink( iface );
1987 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1990 static ULONG WINAPI fnIMLangFontLink_Release(
1991 IMLangFontLink* iface)
1993 MLang_impl *This = impl_from_IMLangFontLink( iface );
1994 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1997 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1998 IMLangFontLink* iface,
1999 WCHAR ch_src,
2000 DWORD* codepages)
2002 MLang_impl *This = impl_from_IMLangFontLink( iface );
2003 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
2006 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
2007 IMLangFontLink* iface,
2008 const WCHAR* src,
2009 LONG src_len,
2010 DWORD priority_cp,
2011 DWORD* codepages,
2012 LONG* ret_len)
2014 MLang_impl *This = impl_from_IMLangFontLink( iface );
2015 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
2016 codepages, ret_len);
2019 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
2020 IMLangFontLink* iface,
2021 UINT codepage,
2022 DWORD* codepages)
2024 MLang_impl *This = impl_from_IMLangFontLink( iface );
2025 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2028 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2029 IMLangFontLink* iface,
2030 DWORD codepages,
2031 UINT def_codepage,
2032 UINT* codepage)
2034 MLang_impl *This = impl_from_IMLangFontLink(iface);
2035 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2036 def_codepage, codepage);
2039 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2040 IMLangFontLink* iface,
2041 HDC hdc,
2042 HFONT hfont,
2043 DWORD* codepages)
2045 MLang_impl *This = impl_from_IMLangFontLink(iface);
2046 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2049 static HRESULT WINAPI fnIMLangFontLink_MapFont(
2050 IMLangFontLink* iface,
2051 HDC hDC,
2052 DWORD dwCodePages,
2053 HFONT hSrcFont,
2054 HFONT* phDestFont)
2056 TRACE("(%p)->%p %08x %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
2058 return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2061 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2062 IMLangFontLink* iface,
2063 HFONT hFont)
2065 TRACE("(%p)->%p\n",iface, hFont);
2067 return release_font(hFont);
2070 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2071 IMLangFontLink* iface)
2073 TRACE("(%p)\n",iface);
2075 return clear_font_cache();
2079 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2081 fnIMLangFontLink_QueryInterface,
2082 fnIMLangFontLink_AddRef,
2083 fnIMLangFontLink_Release,
2084 fnIMLangFontLink_GetCharCodePages,
2085 fnIMLangFontLink_GetStrCodePages,
2086 fnIMLangFontLink_CodePageToCodePages,
2087 fnIMLangFontLink_CodePagesToCodePage,
2088 fnIMLangFontLink_GetFontCodePages,
2089 fnIMLangFontLink_MapFont,
2090 fnIMLangFontLink_ReleaseFont,
2091 fnIMLangFontLink_ResetFontMapping,
2094 /******************************************************************************/
2096 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2098 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2101 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2102 IMultiLanguage* iface,
2103 REFIID riid,
2104 void** obj)
2106 MLang_impl *This = impl_from_IMultiLanguage( iface );
2107 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2110 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2112 MLang_impl *This = impl_from_IMultiLanguage( iface );
2113 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2116 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2118 MLang_impl *This = impl_from_IMultiLanguage( iface );
2119 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2122 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2123 IMultiLanguage* iface,
2124 UINT* cp)
2126 MLang_impl *This = impl_from_IMultiLanguage( iface );
2127 TRACE("(%p, %p)\n", This, cp);
2128 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2131 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2132 IMultiLanguage* iface,
2133 UINT uiCodePage,
2134 PMIMECPINFO pCodePageInfo)
2136 UINT i, n;
2137 MLang_impl *This = impl_from_IMultiLanguage( iface );
2139 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2141 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2143 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2145 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2147 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2148 return S_OK;
2153 return S_FALSE;
2156 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2157 IMultiLanguage* iface,
2158 UINT cp,
2159 UINT* family_cp)
2161 MLang_impl *This = impl_from_IMultiLanguage( iface );
2162 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2165 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2166 IMultiLanguage* iface,
2167 DWORD grfFlags,
2168 IEnumCodePage** ppEnumCodePage)
2170 MLang_impl *This = impl_from_IMultiLanguage( iface );
2172 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2174 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2177 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2178 IMultiLanguage* iface,
2179 BSTR Charset,
2180 PMIMECSETINFO pCharsetInfo)
2182 MLang_impl *This = impl_from_IMultiLanguage( iface );
2183 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2186 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2187 IMultiLanguage* iface,
2188 DWORD src_enc,
2189 DWORD dst_enc)
2191 MLang_impl *This = impl_from_IMultiLanguage( iface );
2192 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2195 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2196 IMultiLanguage* iface,
2197 DWORD* mode,
2198 DWORD src_enc,
2199 DWORD dst_enc,
2200 BYTE* src,
2201 UINT* src_size,
2202 BYTE* dest,
2203 UINT* dest_size)
2205 MLang_impl *This = impl_from_IMultiLanguage( iface );
2206 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2207 dst_enc, src, src_size, dest, dest_size);
2210 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2211 IMultiLanguage* iface,
2212 DWORD* mode,
2213 DWORD src_enc,
2214 CHAR* src,
2215 UINT* src_size,
2216 WCHAR* dest,
2217 UINT* dest_size)
2219 MLang_impl *This = impl_from_IMultiLanguage( iface );
2220 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2221 mode, src_enc, src, src_size, dest, dest_size);
2224 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2225 IMultiLanguage* iface,
2226 DWORD* mode,
2227 DWORD encoding,
2228 WCHAR* src,
2229 UINT* src_size,
2230 CHAR* dest,
2231 UINT* dest_size)
2233 MLang_impl *This = impl_from_IMultiLanguage(iface);
2234 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2235 mode, encoding, src, src_size, dest, dest_size);
2238 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2239 IMultiLanguage* iface)
2241 MLang_impl *This = impl_from_IMultiLanguage( iface );
2242 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2245 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2246 IMultiLanguage* iface,
2247 LCID lcid,
2248 BSTR* pbstrRfc1766)
2250 MLang_impl *This = impl_from_IMultiLanguage(iface);
2251 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2254 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2255 IMultiLanguage* iface,
2256 LCID* locale,
2257 BSTR rfc1766)
2259 MLang_impl *This = impl_from_IMultiLanguage(iface);
2260 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2263 /******************************************************************************/
2265 typedef struct tagEnumRfc1766_impl
2267 IEnumRfc1766 IEnumRfc1766_iface;
2268 LONG ref;
2269 RFC1766INFO *info;
2270 DWORD total, pos;
2271 } EnumRfc1766_impl;
2273 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2275 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2278 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2279 IEnumRfc1766 *iface,
2280 REFIID riid,
2281 void** ppvObject)
2283 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2285 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2287 if (IsEqualGUID(riid, &IID_IUnknown)
2288 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2290 IEnumRfc1766_AddRef(iface);
2291 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2292 *ppvObject = &This->IEnumRfc1766_iface;
2293 return S_OK;
2296 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2297 return E_NOINTERFACE;
2300 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2301 IEnumRfc1766 *iface)
2303 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2304 return InterlockedIncrement(&This->ref);
2307 static ULONG WINAPI fnIEnumRfc1766_Release(
2308 IEnumRfc1766 *iface)
2310 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2311 ULONG ref = InterlockedDecrement(&This->ref);
2313 TRACE("%p ref = %d\n", This, ref);
2314 if (ref == 0)
2316 TRACE("Destroying %p\n", This);
2317 HeapFree(GetProcessHeap(), 0, This->info);
2318 HeapFree(GetProcessHeap(), 0, This);
2320 return ref;
2323 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2324 IEnumRfc1766 *iface,
2325 IEnumRfc1766 **ppEnum)
2327 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2329 FIXME("%p %p\n", This, ppEnum);
2330 return E_NOTIMPL;
2333 static HRESULT WINAPI fnIEnumRfc1766_Next(
2334 IEnumRfc1766 *iface,
2335 ULONG celt,
2336 PRFC1766INFO rgelt,
2337 ULONG *pceltFetched)
2339 ULONG i;
2340 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2342 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2344 if (!pceltFetched) return S_FALSE;
2345 *pceltFetched = 0;
2347 if (!rgelt) return S_FALSE;
2349 if (This->pos + celt > This->total)
2350 celt = This->total - This->pos;
2352 if (!celt) return S_FALSE;
2354 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2355 *pceltFetched = celt;
2356 This->pos += celt;
2358 for (i = 0; i < celt; i++)
2360 TRACE("#%u: %08x %s %s\n",
2361 i, rgelt[i].lcid,
2362 wine_dbgstr_w(rgelt[i].wszRfc1766),
2363 wine_dbgstr_w(rgelt[i].wszLocaleName));
2365 return S_OK;
2368 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2369 IEnumRfc1766 *iface)
2371 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2373 TRACE("%p\n", This);
2375 This->pos = 0;
2376 return S_OK;
2379 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2380 IEnumRfc1766 *iface,
2381 ULONG celt)
2383 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2385 TRACE("%p %u\n", This, celt);
2387 if (celt >= This->total) return S_FALSE;
2389 This->pos += celt;
2390 return S_OK;
2393 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2395 fnIEnumRfc1766_QueryInterface,
2396 fnIEnumRfc1766_AddRef,
2397 fnIEnumRfc1766_Release,
2398 fnIEnumRfc1766_Clone,
2399 fnIEnumRfc1766_Next,
2400 fnIEnumRfc1766_Reset,
2401 fnIEnumRfc1766_Skip
2404 struct enum_locales_data
2406 RFC1766INFO *info;
2407 DWORD total, allocated;
2410 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2412 WCHAR *end;
2413 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2414 RFC1766INFO *info;
2416 TRACE("%s\n", debugstr_w(locale));
2418 if (data->total >= data->allocated)
2420 data->allocated += 32;
2421 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2422 if (!data->info) return FALSE;
2425 info = &data->info[data->total];
2427 info->lcid = wcstol(locale, &end, 16);
2428 if (*end) /* invalid number */
2429 return FALSE;
2431 info->wszRfc1766[0] = 0;
2432 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2434 info->wszLocaleName[0] = 0;
2435 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2436 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2438 data->total++;
2440 return TRUE;
2443 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2445 EnumRfc1766_impl *rfc;
2446 struct enum_locales_data data;
2448 TRACE("%04x, %p\n", LangId, ppEnum);
2450 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2451 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2452 rfc->ref = 1;
2453 rfc->pos = 0;
2454 rfc->total = 0;
2456 data.total = 0;
2457 data.allocated = 160;
2458 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2459 if (!data.info)
2461 HeapFree(GetProcessHeap(), 0, rfc);
2462 return E_OUTOFMEMORY;
2465 TlsSetValue(MLANG_tls_index, &data);
2466 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2467 TlsSetValue(MLANG_tls_index, NULL);
2469 TRACE("enumerated %d rfc1766 structures\n", data.total);
2471 if (!data.total)
2473 HeapFree(GetProcessHeap(), 0, data.info);
2474 HeapFree(GetProcessHeap(), 0, rfc);
2475 return E_FAIL;
2478 rfc->info = data.info;
2479 rfc->total = data.total;
2481 *ppEnum = &rfc->IEnumRfc1766_iface;
2482 return S_OK;
2485 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2486 IMultiLanguage *iface,
2487 IEnumRfc1766 **ppEnumRfc1766)
2489 MLang_impl *This = impl_from_IMultiLanguage( iface );
2491 TRACE("%p %p\n", This, ppEnumRfc1766);
2493 return EnumRfc1766_create(0, ppEnumRfc1766);
2496 /******************************************************************************/
2498 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2499 IMultiLanguage* iface,
2500 LCID Locale,
2501 PRFC1766INFO pRfc1766Info)
2503 LCTYPE type = LOCALE_SLANGUAGE;
2505 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2507 if (!pRfc1766Info)
2508 return E_INVALIDARG;
2510 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2511 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2512 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2514 if (!SUBLANGID(Locale))
2515 type = LOCALE_SENGLANGUAGE; /* suppress country */
2517 else
2519 if (!SUBLANGID(Locale)) {
2520 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2521 return E_FAIL;
2525 pRfc1766Info->lcid = Locale;
2526 pRfc1766Info->wszRfc1766[0] = 0;
2527 pRfc1766Info->wszLocaleName[0] = 0;
2529 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2530 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2531 return S_OK;
2533 /* Locale not supported */
2534 return E_INVALIDARG;
2537 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2538 IMultiLanguage* iface,
2539 UINT src_cp,
2540 UINT dst_cp,
2541 DWORD prop,
2542 IMLangConvertCharset** convert_charset)
2544 MLang_impl *This = impl_from_IMultiLanguage(iface);
2545 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2548 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2550 fnIMultiLanguage_QueryInterface,
2551 fnIMultiLanguage_AddRef,
2552 fnIMultiLanguage_Release,
2553 fnIMultiLanguage_GetNumberOfCodePageInfo,
2554 fnIMultiLanguage_GetCodePageInfo,
2555 fnIMultiLanguage_GetFamilyCodePage,
2556 fnIMultiLanguage_EnumCodePages,
2557 fnIMultiLanguage_GetCharsetInfo,
2558 fnIMultiLanguage_IsConvertible,
2559 fnIMultiLanguage_ConvertString,
2560 fnIMultiLanguage_ConvertStringToUnicode,
2561 fnIMultiLanguage_ConvertStringFromUnicode,
2562 fnIMultiLanguage_ConvertStringReset,
2563 fnIMultiLanguage_GetRfc1766FromLcid,
2564 fnIMultiLanguage_GetLcidFromRfc1766,
2565 fnIMultiLanguage_EnumRfc1766,
2566 fnIMultiLanguage_GetRfc1766Info,
2567 fnIMultiLanguage_CreateConvertCharset,
2571 /******************************************************************************/
2573 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2575 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2578 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2579 IMultiLanguage3* iface,
2580 REFIID riid,
2581 void** obj)
2583 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2585 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2587 if (IsEqualGUID(riid, &IID_IUnknown) ||
2588 IsEqualGUID(riid, &IID_IMultiLanguage))
2590 *obj = &This->IMultiLanguage_iface;
2592 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2593 IsEqualGUID(riid, &IID_IMLangFontLink))
2595 *obj = &This->IMLangFontLink_iface;
2597 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2599 *obj = &This->IMLangFontLink2_iface;
2601 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2602 IsEqualGUID(riid, &IID_IMultiLanguage3))
2604 *obj = &This->IMultiLanguage3_iface;
2606 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2608 *obj = &This->IMLangLineBreakConsole_iface;
2610 else
2612 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2613 *obj = NULL;
2614 return E_NOINTERFACE;
2617 IMultiLanguage3_AddRef(iface);
2618 return S_OK;
2621 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2623 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2624 return InterlockedIncrement(&This->ref);
2627 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2629 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2630 ULONG ref = InterlockedDecrement(&This->ref);
2632 TRACE("(%p)->(%d)\n", This, ref);
2633 if (ref == 0)
2635 HeapFree(GetProcessHeap(), 0, This);
2636 UnlockModule();
2639 return ref;
2642 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2643 IMultiLanguage3* iface,
2644 UINT* pcCodePage)
2646 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2648 TRACE("%p, %p\n", This, pcCodePage);
2650 if (!pcCodePage) return E_INVALIDARG;
2652 *pcCodePage = This->total_cp;
2653 return S_OK;
2656 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2658 CHARSETINFO csi;
2660 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2661 TCI_SRCCODEPAGE))
2662 mime_cp_info->bGDICharset = csi.ciCharset;
2663 else
2664 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2666 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2667 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2668 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2669 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2670 mime_cp_info->wszDescription, ARRAY_SIZE(mime_cp_info->wszDescription));
2671 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2672 mime_cp_info->wszWebCharset, ARRAY_SIZE(mime_cp_info->wszWebCharset));
2673 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2674 mime_cp_info->wszHeaderCharset, ARRAY_SIZE(mime_cp_info->wszHeaderCharset));
2675 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2676 mime_cp_info->wszBodyCharset, ARRAY_SIZE(mime_cp_info->wszBodyCharset));
2678 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2679 mime_cp_info->wszFixedWidthFont, ARRAY_SIZE(mime_cp_info->wszFixedWidthFont));
2680 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2681 mime_cp_info->wszProportionalFont, ARRAY_SIZE(mime_cp_info->wszProportionalFont));
2683 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2684 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2685 mime_cp_info->uiFamilyCodePage,
2686 wine_dbgstr_w(mime_cp_info->wszDescription),
2687 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2688 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2689 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2690 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2691 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2692 mime_cp_info->bGDICharset);
2695 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2696 IMultiLanguage3* iface,
2697 UINT uiCodePage,
2698 LANGID LangId,
2699 PMIMECPINFO pCodePageInfo)
2701 UINT i, n;
2702 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2704 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2706 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2708 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2710 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2712 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2713 return S_OK;
2718 return S_FALSE;
2721 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2722 IMultiLanguage3* iface,
2723 UINT uiCodePage,
2724 UINT* puiFamilyCodePage)
2726 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2729 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2730 IMultiLanguage3* iface,
2731 DWORD grfFlags,
2732 LANGID LangId,
2733 IEnumCodePage** ppEnumCodePage)
2735 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2737 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2739 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2742 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2743 IMultiLanguage3* iface,
2744 BSTR Charset,
2745 PMIMECSETINFO pCharsetInfo)
2747 UINT i, n;
2748 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2750 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2752 if (!pCharsetInfo) return E_FAIL;
2754 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2756 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2758 WCHAR csetW[MAX_MIMECSET_NAME];
2760 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2761 if (!lstrcmpiW(Charset, csetW))
2763 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2764 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2765 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2766 return S_OK;
2768 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2770 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2771 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2772 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2773 return S_OK;
2778 /* FIXME:
2779 * Since we do not support charsets like iso-2022-jp and do not have
2780 * them in our database as a primary (web_charset) encoding this loop
2781 * does an attempt to 'approximate' charset name by header_charset.
2783 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2785 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2787 WCHAR csetW[MAX_MIMECSET_NAME];
2789 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2790 if (!lstrcmpiW(Charset, csetW))
2792 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2793 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2794 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2795 return S_OK;
2800 return E_FAIL;
2803 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2804 IMultiLanguage3* iface,
2805 DWORD dwSrcEncoding,
2806 DWORD dwDstEncoding)
2808 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2811 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2812 IMultiLanguage3* iface,
2813 DWORD* pdwMode,
2814 DWORD dwSrcEncoding,
2815 DWORD dwDstEncoding,
2816 BYTE* pSrcStr,
2817 UINT* pcSrcSize,
2818 BYTE* pDstStr,
2819 UINT* pcDstSize)
2821 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2822 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2825 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2826 IMultiLanguage3* iface,
2827 DWORD* pdwMode,
2828 DWORD dwEncoding,
2829 CHAR* pSrcStr,
2830 UINT* pcSrcSize,
2831 WCHAR* pDstStr,
2832 UINT* pcDstSize)
2834 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2835 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2838 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2839 IMultiLanguage3* iface,
2840 DWORD* pdwMode,
2841 DWORD dwEncoding,
2842 WCHAR* pSrcStr,
2843 UINT* pcSrcSize,
2844 CHAR* pDstStr,
2845 UINT* pcDstSize)
2847 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2848 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2851 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2852 IMultiLanguage3* iface)
2854 FIXME("\n");
2855 return E_NOTIMPL;
2858 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2859 IMultiLanguage3* iface,
2860 LCID lcid,
2861 BSTR* pbstrRfc1766)
2863 WCHAR buf[MAX_RFC1766_NAME];
2865 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2866 if (!pbstrRfc1766)
2867 return E_INVALIDARG;
2869 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2871 *pbstrRfc1766 = SysAllocString( buf );
2872 return S_OK;
2874 return E_FAIL;
2877 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2878 IMultiLanguage3* iface,
2879 LCID* pLocale,
2880 BSTR bstrRfc1766)
2882 HRESULT hr;
2883 IEnumRfc1766 *rfc1766;
2885 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2887 if (!pLocale || !bstrRfc1766)
2888 return E_INVALIDARG;
2890 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2891 if (FAILED(hr))
2892 return hr;
2894 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2896 IEnumRfc1766_Release(rfc1766);
2897 return hr;
2900 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2901 IMultiLanguage3* iface,
2902 LANGID LangId,
2903 IEnumRfc1766** ppEnumRfc1766)
2905 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2907 TRACE("%p %p\n", This, ppEnumRfc1766);
2909 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2912 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2913 IMultiLanguage3* iface,
2914 LCID Locale,
2915 LANGID LangId,
2916 PRFC1766INFO pRfc1766Info)
2918 static LANGID last_lang = -1;
2919 LCTYPE type = LOCALE_SLANGUAGE;
2921 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2923 if (!pRfc1766Info)
2924 return E_INVALIDARG;
2926 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2927 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2928 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2930 if (!SUBLANGID(Locale))
2931 type = LOCALE_SENGLANGUAGE; /* suppress country */
2933 else
2935 if (!SUBLANGID(Locale)) {
2936 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2937 return E_FAIL;
2941 pRfc1766Info->lcid = Locale;
2942 pRfc1766Info->wszRfc1766[0] = 0;
2943 pRfc1766Info->wszLocaleName[0] = 0;
2945 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2946 (last_lang != LangId)) {
2947 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2948 last_lang = LangId;
2951 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2952 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2953 return S_OK;
2955 /* Locale not supported */
2956 return E_INVALIDARG;
2959 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2960 IMultiLanguage3* iface,
2961 UINT src_cp,
2962 UINT dst_cp,
2963 DWORD prop,
2964 IMLangConvertCharset** convert_charset)
2966 HRESULT hr;
2968 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2970 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2971 if (FAILED(hr)) return hr;
2973 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2976 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2977 IMultiLanguage3* iface,
2978 DWORD* pdwMode,
2979 DWORD dwFlag,
2980 WCHAR* lpFallBack,
2981 DWORD dwSrcEncoding,
2982 DWORD dwDstEncoding,
2983 IStream* pstmIn,
2984 IStream* pstmOut)
2986 char *src, *dst = NULL;
2987 INT srclen, dstlen;
2988 STATSTG stat;
2989 HRESULT hr;
2991 TRACE("%p %0x8 %s %u %u %p %p\n",
2992 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2994 FIXME("dwFlag and lpFallBack not handled\n");
2996 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2997 if (FAILED(hr)) return hr;
2999 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
3000 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
3002 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
3003 if (FAILED(hr)) goto exit;
3005 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
3006 if (FAILED(hr)) goto exit;
3008 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
3010 hr = E_OUTOFMEMORY;
3011 goto exit;
3013 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
3014 if (FAILED(hr)) goto exit;
3016 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
3018 exit:
3019 HeapFree(GetProcessHeap(), 0, src);
3020 HeapFree(GetProcessHeap(), 0, dst);
3021 return hr;
3024 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
3025 IMultiLanguage3* iface,
3026 DWORD* pdwMode,
3027 DWORD dwEncoding,
3028 CHAR* pSrcStr,
3029 UINT* pcSrcSize,
3030 WCHAR* pDstStr,
3031 UINT* pcDstSize,
3032 DWORD dwFlag,
3033 WCHAR* lpFallBack)
3035 if (dwFlag || lpFallBack)
3036 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
3037 dwFlag, dwFlag, lpFallBack);
3039 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
3040 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3043 /*****************************************************************************
3044 * MultiLanguage2::ConvertStringToUnicodeEx
3046 * Translates the multibyte string from the specified code page to Unicode.
3048 * PARAMS
3049 * see ConvertStringToUnicode
3050 * dwFlag
3051 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3052 * instead unconvertible characters.
3054 * RETURNS
3055 * S_OK Success.
3056 * S_FALSE The conversion is not supported.
3057 * E_FAIL Some error has occurred.
3059 * TODO: handle dwFlag and lpFallBack
3061 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3062 IMultiLanguage3* This,
3063 DWORD* pdwMode,
3064 DWORD dwEncoding,
3065 WCHAR* pSrcStr,
3066 UINT* pcSrcSize,
3067 CHAR* pDstStr,
3068 UINT* pcDstSize,
3069 DWORD dwFlag,
3070 WCHAR* lpFallBack)
3072 FIXME("\n");
3073 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3074 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3077 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3078 IMultiLanguage3* iface,
3079 DWORD dwFlag,
3080 DWORD dwPrefWinCodePage,
3081 IStream* pstmIn,
3082 DetectEncodingInfo* lpEncoding,
3083 INT* pnScores)
3085 FIXME("\n");
3086 return E_NOTIMPL;
3089 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3090 IMultiLanguage3* iface,
3091 DWORD dwFlag,
3092 DWORD dwPrefWinCodePage,
3093 CHAR* pSrcStr,
3094 INT* pcSrcSize,
3095 DetectEncodingInfo* lpEncoding,
3096 INT* pnScores)
3098 FIXME("\n");
3099 return E_NOTIMPL;
3102 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3103 IMultiLanguage3* iface,
3104 UINT uiCodePage,
3105 HWND hwnd)
3107 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3110 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3111 IMultiLanguage3* iface,
3112 UINT uiCodePage,
3113 LCID lcid,
3114 LPWSTR lpWideCharStr,
3115 int cchWideChar)
3117 /* Find first instance */
3118 unsigned int i,n;
3120 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3121 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3123 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3125 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3127 MultiByteToWideChar(CP_ACP, 0,
3128 mlang_data[i].mime_cp_info[n].description,
3129 -1, lpWideCharStr, cchWideChar);
3130 return S_OK;
3135 return S_FALSE;
3138 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3139 IMultiLanguage3* iface,
3140 UINT uiCodePage)
3142 TRACE("%u\n", uiCodePage);
3144 /* FIXME: the installable set is usually larger than the set of valid codepages */
3145 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3148 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3149 IMultiLanguage3* iface,
3150 MIMECONTF dwSource)
3152 FIXME("0x%08x\n", dwSource);
3153 return S_OK;
3156 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3157 IMultiLanguage3* iface,
3158 UINT* pnScripts)
3160 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3162 TRACE("%p %p\n", This, pnScripts);
3164 if (!pnScripts) return S_FALSE;
3166 *pnScripts = This->total_scripts;
3167 return S_OK;
3170 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3171 IMultiLanguage3* iface,
3172 DWORD dwFlags,
3173 LANGID LangId,
3174 IEnumScript** ppEnumScript)
3176 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3178 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3180 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3183 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3184 IMultiLanguage3* iface,
3185 UINT uiCodePage,
3186 HWND hwnd,
3187 DWORD dwfIODControl)
3189 unsigned int i;
3190 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3192 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3194 /* quick check for kernel32 supported code pages */
3195 if (IsValidCodePage(uiCodePage))
3196 return S_OK;
3198 /* check for mlang supported code pages */
3199 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3201 UINT n;
3202 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3204 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3205 return S_OK;
3209 if (dwfIODControl != CPIOD_PEEK)
3210 FIXME("Request to install codepage language pack not handled\n");
3212 return S_FALSE;
3215 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3216 IMultiLanguage3 *iface,
3217 DWORD dwFlags,
3218 LPCWSTR lpWideCharStr,
3219 UINT cchWideChar,
3220 UINT *puiPreferredCodePages,
3221 UINT nPreferredCodePages,
3222 UINT *puiDetectedCodePages,
3223 UINT *pnDetectedCodePages,
3224 WCHAR *lpSpecialChar)
3226 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3228 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3229 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3230 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3231 debugstr_w(lpSpecialChar));
3233 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3234 return E_INVALIDARG;
3236 puiDetectedCodePages[0] = CP_UTF8;
3237 *pnDetectedCodePages = 1;
3238 return S_OK;
3241 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3242 IMultiLanguage3 *iface,
3243 DWORD dwFlags,
3244 IStream *pStrIn,
3245 UINT *puiPreferredCodePages,
3246 UINT nPreferredCodePages,
3247 UINT *puiDetectedCodePages,
3248 UINT *pnDetectedCodePages,
3249 WCHAR *lpSpecialChar)
3251 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3253 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3254 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3255 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3256 debugstr_w(lpSpecialChar));
3258 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3259 return E_INVALIDARG;
3261 puiDetectedCodePages[0] = CP_UTF8;
3262 *pnDetectedCodePages = 1;
3263 return S_OK;
3266 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3268 fnIMultiLanguage3_QueryInterface,
3269 fnIMultiLanguage3_AddRef,
3270 fnIMultiLanguage3_Release,
3271 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3272 fnIMultiLanguage3_GetCodePageInfo,
3273 fnIMultiLanguage3_GetFamilyCodePage,
3274 fnIMultiLanguage3_EnumCodePages,
3275 fnIMultiLanguage3_GetCharsetInfo,
3276 fnIMultiLanguage3_IsConvertible,
3277 fnIMultiLanguage3_ConvertString,
3278 fnIMultiLanguage3_ConvertStringToUnicode,
3279 fnIMultiLanguage3_ConvertStringFromUnicode,
3280 fnIMultiLanguage3_ConvertStringReset,
3281 fnIMultiLanguage3_GetRfc1766FromLcid,
3282 fnIMultiLanguage3_GetLcidFromRfc1766,
3283 fnIMultiLanguage3_EnumRfc1766,
3284 fnIMultiLanguage3_GetRfc1766Info,
3285 fnIMultiLanguage3_CreateConvertCharset,
3286 fnIMultiLanguage3_ConvertStringInIStream,
3287 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3288 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3289 fnIMultiLanguage3_DetectCodepageInIStream,
3290 fnIMultiLanguage3_DetectInputCodepage,
3291 fnIMultiLanguage3_ValidateCodePage,
3292 fnIMultiLanguage3_GetCodePageDescription,
3293 fnIMultiLanguage3_IsCodePageInstallable,
3294 fnIMultiLanguage3_SetMimeDBSource,
3295 fnIMultiLanguage3_GetNumberOfScripts,
3296 fnIMultiLanguage3_EnumScripts,
3297 fnIMultiLanguage3_ValidateCodePageEx,
3298 fnIMultiLanguage3_DetectOutboundCodePage,
3299 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3302 /******************************************************************************/
3304 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3306 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3309 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3310 IMLangFontLink2 * iface,
3311 REFIID riid,
3312 void** ppvObject)
3314 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3315 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3318 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3320 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3321 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3324 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3326 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3327 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3330 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3331 WCHAR ch_src, DWORD *ret_codepages)
3333 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3334 unsigned int i;
3336 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3338 *ret_codepages = 0;
3340 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3342 BOOL used_dc;
3343 CHAR buf;
3345 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3346 &ch_src, 1, &buf, 1, NULL, &used_dc);
3348 /* If default char is not used, current codepage include the given symbol */
3349 if (!used_dc)
3351 DWORD codepages;
3353 IMLangFontLink2_CodePageToCodePages(iface,
3354 mlang_data[i].family_codepage, &codepages);
3355 *ret_codepages |= codepages;
3358 return S_OK;
3361 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3362 const WCHAR *src, LONG src_len, DWORD priority_cp,
3363 DWORD *codepages, LONG *ret_len)
3365 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3366 LONG i;
3367 DWORD cps = 0;
3369 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3370 codepages, ret_len);
3372 if (codepages) *codepages = 0;
3373 if (ret_len) *ret_len = 0;
3375 if (!src || !src_len || src_len < 0)
3376 return E_INVALIDARG;
3378 for (i = 0; i < src_len; i++)
3380 DWORD cp;
3381 HRESULT ret;
3383 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3384 if (ret != S_OK) return E_FAIL;
3386 if (!cps) cps = cp;
3387 else cps &= cp;
3389 /* FIXME: not tested */
3390 if (priority_cp & cps) break;
3393 if (codepages) *codepages = cps;
3394 if (ret_len) *ret_len = min( i + 1, src_len );
3395 return S_OK;
3398 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3399 UINT codepage,
3400 DWORD *codepages)
3402 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3403 CHARSETINFO cs;
3404 BOOL rc;
3406 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3408 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3409 if (rc)
3411 *codepages = cs.fs.fsCsb[0];
3412 TRACE("resulting codepages 0x%x\n", *codepages);
3413 return S_OK;
3416 TRACE("codepage not found\n");
3417 *codepages = 0;
3418 return E_FAIL;
3421 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3422 DWORD codepages, UINT def_codepage, UINT *codepage)
3424 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3425 DWORD mask = 0;
3426 CHARSETINFO cs;
3427 BOOL rc;
3428 UINT i;
3430 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3432 *codepage = 0;
3434 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3435 if (rc && (codepages & cs.fs.fsCsb[0]))
3437 TRACE("Found Default Codepage\n");
3438 *codepage = def_codepage;
3439 return S_OK;
3442 for (i = 0; i < 32; i++)
3444 mask = 1 << i;
3445 if (codepages & mask)
3447 DWORD Csb[2];
3448 Csb[0] = mask;
3449 Csb[1] = 0x0;
3450 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3451 if (!rc)
3452 continue;
3454 TRACE("Falling back to least significant found CodePage %u\n",
3455 cs.ciACP);
3456 *codepage = cs.ciACP;
3457 return S_OK;
3461 TRACE("no codepage found\n");
3462 return E_FAIL;
3465 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3466 HDC hdc, HFONT hfont, DWORD *codepages)
3468 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3469 FONTSIGNATURE fontsig;
3470 HFONT old_font;
3472 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3474 old_font = SelectObject(hdc, hfont);
3475 GetTextCharsetInfo(hdc, &fontsig, 0);
3476 SelectObject(hdc, old_font);
3478 *codepages = fontsig.fsCsb[0];
3479 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3481 return S_OK;
3484 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3485 HFONT hFont)
3487 TRACE("(%p)->%p\n",This, hFont);
3489 return release_font(hFont);
3492 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3494 TRACE("(%p)\n",This);
3496 return clear_font_cache();
3499 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3500 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3502 HFONT old_font;
3504 TRACE("(%p)->%p %08x %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
3506 if (!hDC) return E_FAIL;
3508 if (dwCodePages != 0)
3510 old_font = GetCurrentObject(hDC, OBJ_FONT);
3511 return map_font(hDC, dwCodePages, old_font, pFont);
3513 else
3515 if (pFont == NULL) return E_INVALIDARG;
3516 FIXME("the situation where dwCodepages is set to zero is not implemented\n");
3517 return E_FAIL;
3521 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3522 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3524 DWORD size;
3525 GLYPHSET *gs;
3527 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3529 if (!puiRanges) return E_INVALIDARG;
3530 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3531 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3533 GetFontUnicodeRanges(hDC, gs);
3534 *puiRanges = gs->cRanges;
3535 if (pUranges)
3537 UINT i;
3538 for (i = 0; i < gs->cRanges; i++)
3540 if (i >= *puiRanges) break;
3541 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3542 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3544 *puiRanges = i;
3546 HeapFree(GetProcessHeap(), 0, gs);
3547 return S_OK;
3550 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3551 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3552 SCRIPTFONTINFO *pScriptFont)
3554 UINT i, j;
3556 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3558 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3560 for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3562 if (sid == mlang_data[i].sid)
3564 if (pScriptFont)
3566 if (j >= *puiFonts) break;
3568 pScriptFont[j].scripts = 1 << mlang_data[i].sid;
3569 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3571 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3572 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3574 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3576 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3577 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3580 j++;
3583 *puiFonts = j;
3584 return S_OK;
3587 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3588 UINT uiCodePage, SCRIPT_ID *pSid)
3590 UINT i;
3592 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3594 if (uiCodePage == CP_UNICODE) return E_FAIL;
3596 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3598 if (uiCodePage == mlang_data[i].family_codepage)
3600 if (pSid) *pSid = mlang_data[i].sid;
3601 return S_OK;
3604 return E_FAIL;
3607 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3609 fnIMLangFontLink2_QueryInterface,
3610 fnIMLangFontLink2_AddRef,
3611 fnIMLangFontLink2_Release,
3612 fnIMLangFontLink2_GetCharCodePages,
3613 fnIMLangFontLink2_GetStrCodePages,
3614 fnIMLangFontLink2_CodePageToCodePages,
3615 fnIMLangFontLink2_CodePagesToCodePage,
3616 fnIMLangFontLink2_GetFontCodePages,
3617 fnIMLangFontLink2_ReleaseFont,
3618 fnIMLangFontLink2_ResetFontMapping,
3619 fnIMLangFontLink2_MapFont,
3620 fnIMLangFontLink2_GetFontUnicodeRanges,
3621 fnIMLangFontLink2_GetScriptFontInfo,
3622 fnIMLangFontLink2_CodePageToScriptID
3625 /******************************************************************************/
3627 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3629 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3632 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3633 IMLangLineBreakConsole* iface,
3634 REFIID riid,
3635 void** ppvObject)
3637 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3638 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3641 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3642 IMLangLineBreakConsole* iface )
3644 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3645 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3648 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3649 IMLangLineBreakConsole* iface )
3651 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3652 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3655 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3656 IMLangLineBreakConsole* iface,
3657 IMLangString* pSrcMLStr,
3658 LONG lSrcPos,
3659 LONG lSrcLen,
3660 LONG cMinColumns,
3661 LONG cMaxColumns,
3662 LONG* plLineLen,
3663 LONG* plSkipLen)
3665 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3666 return E_NOTIMPL;
3669 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3670 IMLangLineBreakConsole* iface,
3671 LCID locale,
3672 const WCHAR* pszSrc,
3673 LONG cchSrc,
3674 LONG cMaxColumns,
3675 LONG* pcchLine,
3676 LONG* pcchSkip )
3678 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3680 *pcchLine = cchSrc;
3681 *pcchSkip = 0;
3682 return S_OK;
3685 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3686 IMLangLineBreakConsole* iface,
3687 LCID locale,
3688 UINT uCodePage,
3689 const CHAR* pszSrc,
3690 LONG cchSrc,
3691 LONG cMaxColumns,
3692 LONG* pcchLine,
3693 LONG* pcchSkip)
3695 LONG i, line = cchSrc, skip = 0;
3697 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3699 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3701 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3703 if (pszSrc[i] == ' ')
3705 while (i >= 0 && pszSrc[i] == ' ')
3707 i--;
3708 line--;
3709 skip++;
3711 break;
3715 *pcchLine = line;
3716 *pcchSkip = skip;
3717 return S_OK;
3720 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3722 fnIMLangLineBreakConsole_QueryInterface,
3723 fnIMLangLineBreakConsole_AddRef,
3724 fnIMLangLineBreakConsole_Release,
3725 fnIMLangLineBreakConsole_BreakLineML,
3726 fnIMLangLineBreakConsole_BreakLineW,
3727 fnIMLangLineBreakConsole_BreakLineA
3730 struct convert_charset {
3731 IMLangConvertCharset IMLangConvertCharset_iface;
3732 LONG ref;
3734 UINT src_cp;
3735 UINT dst_cp;
3738 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3740 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3743 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3745 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3747 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3749 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3751 *obj = &This->IMLangConvertCharset_iface;
3752 IMLangConvertCharset_AddRef(iface);
3753 return S_OK;
3756 *obj = NULL;
3757 return E_NOINTERFACE;
3760 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3762 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3763 ULONG ref = InterlockedIncrement(&This->ref);
3764 TRACE("(%p)->(%u)\n", This, ref);
3765 return ref;
3768 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3770 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3771 ULONG ref = InterlockedDecrement(&This->ref);
3773 TRACE("(%p)->(%u)\n", This, ref);
3774 if (!ref)
3776 HeapFree(GetProcessHeap(), 0, This);
3777 UnlockModule();
3780 return ref;
3783 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3784 UINT src_cp, UINT dst_cp, DWORD prop)
3786 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3788 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3790 prop &= ~MLCONVCHARF_USEDEFCHAR;
3791 if (prop)
3792 FIXME("property 0x%08x not supported\n", prop);
3794 This->src_cp = src_cp;
3795 This->dst_cp = dst_cp;
3797 return S_OK;
3800 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3802 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3804 TRACE("(%p)->(%p)\n", This, src_cp);
3806 if (!src_cp) return E_INVALIDARG;
3807 *src_cp = This->src_cp;
3808 return S_OK;
3811 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3813 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3815 TRACE("(%p)->(%p)\n", This, dst_cp);
3817 if (!dst_cp) return E_INVALIDARG;
3818 *dst_cp = This->dst_cp;
3819 return S_OK;
3822 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3824 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3825 FIXME("(%p)->(%p): stub\n", This, prop);
3826 return E_NOTIMPL;
3829 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3830 UINT *src_size, BYTE *dest, UINT *dest_size)
3832 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3833 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3834 return E_NOTIMPL;
3837 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3838 UINT *src_size, WCHAR *dest, UINT *dest_size)
3840 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3841 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3842 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3845 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3846 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3848 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3849 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3850 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3853 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3855 MLangConvertCharset_QueryInterface,
3856 MLangConvertCharset_AddRef,
3857 MLangConvertCharset_Release,
3858 MLangConvertCharset_Initialize,
3859 MLangConvertCharset_GetSourceCodePage,
3860 MLangConvertCharset_GetDestinationCodePage,
3861 MLangConvertCharset_GetProperty,
3862 MLangConvertCharset_DoConversion,
3863 MLangConvertCharset_DoConversionToUnicode,
3864 MLangConvertCharset_DoConversionFromUnicode
3867 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3869 MLang_impl *mlang;
3870 UINT i;
3872 TRACE("Creating MultiLanguage object\n");
3874 if( pUnkOuter )
3875 return CLASS_E_NOAGGREGATION;
3877 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3878 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3879 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3880 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3881 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3882 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3884 mlang->total_cp = 0;
3885 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3886 mlang->total_cp += mlang_data[i].number_of_cp;
3888 /* do not enumerate unicode flavours */
3889 mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3891 mlang->ref = 1;
3892 *ppObj = &mlang->IMultiLanguage_iface;
3893 TRACE("returning %p\n", mlang);
3895 LockModule();
3897 return S_OK;
3900 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3902 struct convert_charset *convert;
3904 if (outer)
3905 return CLASS_E_NOAGGREGATION;
3907 *obj = NULL;
3909 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3910 if (!convert) return E_OUTOFMEMORY;
3912 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3913 convert->ref = 1;
3915 *obj = &convert->IMLangConvertCharset_iface;
3917 LockModule();
3919 return S_OK;
3922 /******************************************************************************/
3924 HRESULT WINAPI DllCanUnloadNow(void)
3926 return dll_count == 0 ? S_OK : S_FALSE;
3929 static BOOL register_codepages(void)
3931 const struct mlang_data *family;
3932 const MIME_CP_INFO *info;
3933 HKEY db_key, key;
3934 WCHAR buf[32];
3935 LSTATUS status;
3937 static const WCHAR db_key_nameW[] = {
3938 'M','I','M','E',
3939 '\\','D','a','t','a','b','a','s','e',
3940 '\\','C','o','d','e','p','a','g','e',0};
3941 static const WCHAR familyW[] = {'F','a','m','i','l','y',0};
3942 static const WCHAR formatW[] = {'%','u',0};
3944 status = RegCreateKeyW(HKEY_CLASSES_ROOT, db_key_nameW, &db_key);
3945 if (status != ERROR_SUCCESS)
3946 return FALSE;
3948 for (family = mlang_data; family < mlang_data + ARRAY_SIZE(mlang_data); family++)
3950 for (info = family->mime_cp_info; info < family->mime_cp_info + family->number_of_cp; info++)
3952 swprintf(buf, ARRAY_SIZE(buf), formatW, info->cp);
3953 status = RegCreateKeyW(db_key, buf, &key);
3954 if (status != ERROR_SUCCESS)
3955 continue;
3957 RegSetValueExA(key, "BodyCharset", 0, REG_SZ, (BYTE*)info->body_charset,
3958 strlen(info->body_charset) + 1);
3960 if (info->cp == family->family_codepage)
3962 RegSetValueExA(key, "FixedWidthFont", 0, REG_SZ, (BYTE*)family->fixed_font,
3963 strlen(family->fixed_font) + 1);
3964 RegSetValueExA(key, "ProportionalFont", 0, REG_SZ, (BYTE*)family->proportional_font,
3965 strlen(family->proportional_font) + 1);
3967 else
3969 RegSetValueExW(key, familyW, 0, REG_DWORD, (BYTE*)&family->family_codepage,
3970 sizeof(family->family_codepage));
3973 RegCloseKey(key);
3977 RegCloseKey(db_key);
3978 return TRUE;
3981 /***********************************************************************
3982 * DllRegisterServer (MLANG.@)
3984 HRESULT WINAPI DllRegisterServer(void)
3986 if(!register_codepages())
3987 return E_FAIL;
3988 return __wine_register_resources( instance );
3991 /***********************************************************************
3992 * DllUnregisterServer (MLANG.@)
3994 HRESULT WINAPI DllUnregisterServer(void)
3996 return __wine_unregister_resources( instance );
3999 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
4001 if (!unknown) return E_INVALIDARG;
4003 FIXME("%p: stub\n", unknown);
4005 return S_FALSE;