ddraw: Move the wined3d_texture_update_desc() call into ddraw_surface_create_wined3d_...
[wine.git] / dlls / mlang / mlang.c
blob8a062971dc4b41d8268a94c85deb356f874ac11d
1 /*
2 * MLANG Class Factory
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2003,2004 Mike McCormack
6 * Copyright 2004,2005 Dmitry Timoshkov
7 * Copyright 2009 Detlef Riekenberg
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define COBJMACROS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "objbase.h"
36 #include "rpcproxy.h"
37 #include "mlang.h"
38 #include "mimeole.h"
40 #include "wine/debug.h"
41 #include "wine/list.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
45 #include "initguid.h"
47 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
48 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
49 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
51 /* FIXME:
52 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
53 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
56 typedef struct
58 const WCHAR *description;
59 UINT cp;
60 DWORD flags;
61 const WCHAR *web_charset;
62 const WCHAR *header_charset;
63 const WCHAR *body_charset;
64 const WCHAR *alias;
65 } MIME_CP_INFO;
67 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
68 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
70 static const MIME_CP_INFO arabic_cp[] =
72 { L"Arabic (864)",
73 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
74 MIMECONTF_MIME_LATEST,
75 L"ibm864", L"ibm864", L"ibm864" },
76 { L"Arabic (1006)",
77 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
78 MIMECONTF_MIME_LATEST,
79 L"ibm1006", L"ibm1006", L"ibm1006" },
80 { L"Arabic (Windows)",
81 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
82 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
83 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
84 L"windows-1256", L"windows-1256", L"windows-1256" },
85 { L"Arabic (ISO)",
86 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
87 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
88 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
89 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
90 L"iso-8859-6", L"iso-8859-6", L"iso-8859-6" }
92 static const MIME_CP_INFO baltic_cp[] =
94 { L"Baltic (DOS)",
95 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
96 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
97 L"ibm775", L"ibm775", L"ibm775" },
98 { L"Baltic (Windows)",
99 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
100 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
101 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
102 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
103 L"windows-1257", L"windows-1257", L"windows-1257" },
104 { L"Baltic (ISO)",
105 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
106 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
107 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
108 MIMECONTF_MIME_LATEST,
109 L"iso-8859-4", L"iso-8859-4", L"iso-8859-4" },
110 { L"Estonian (ISO)",
111 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
112 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
113 L"iso-8859-13", L"iso-8859-13", L"iso-8859-13" }
115 static const MIME_CP_INFO chinese_simplified_cp[] =
117 { L"Chinese Simplified (Auto-Select)",
118 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
119 MIMECONTF_MIME_LATEST,
120 L"_autodetect_chs", L"_autodetect_chs", L"_autodetect_chs" },
121 { L"Chinese Simplified (GB2312)",
122 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
123 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
124 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
125 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
126 L"gb2312", L"gb2312", L"gb2312" },
127 { L"Chinese Simplified (GB2312-80)",
128 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
129 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
130 L"x-cp20936", L"x-cp20936", L"x-cp20936" },
131 { L"Chinese Simplified (HZ)",
132 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
133 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
134 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
135 MIMECONTF_MIME_LATEST,
136 L"hz-gb-2312", L"hz-gb-2312", L"hz-gb-2312" },
137 { L"Chinese Simplified (GB18030)",
138 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
139 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
140 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
141 MIMECONTF_MIME_LATEST,
142 L"GB18030", L"GB18030", L"GB18030" },
143 { L"Chinese Simplified (GBK)",
144 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
145 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
146 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
147 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
148 L"gbk", L"gbk", L"gbk" }
150 static const MIME_CP_INFO chinese_traditional_cp[] =
152 { L"Chinese Traditional (Auto-Select)",
153 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
154 MIMECONTF_MIME_LATEST,
155 L"_autodetect_cht", L"_autodetect_cht", L"_autodetect_cht" },
156 { L"Chinese Traditional (Big5)",
157 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
158 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
159 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
160 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
161 L"big5", L"big5", L"big5" },
162 { L"Chinese Traditional (CNS)",
163 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
164 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
165 L"x-Chinese-CNS", L"x-Chinese-CNS", L"x-Chinese-CNS" }
167 static const MIME_CP_INFO central_european_cp[] =
169 { L"Central European (DOS)",
170 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
171 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
172 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
173 L"ibm852", L"ibm852", L"ibm852" },
174 { L"Central European (Windows)",
175 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
176 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
177 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
178 MIMECONTF_MIME_LATEST,
179 L"windows-1250", L"windows-1250", L"windows-1250" },
180 { L"Central European (Mac)",
181 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
182 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
183 L"x-mac-ce", L"x-mac-ce", L"x-mac-ce" },
184 { L"Central European (ISO)",
185 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
186 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
187 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
188 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
189 L"iso-8859-2", L"iso-8859-2", L"iso-8859-2" }
191 static const MIME_CP_INFO cyrillic_cp[] =
193 { L"OEM Cyrillic",
194 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
195 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
196 L"ibm855", L"ibm855", L"ibm855" },
197 { L"Cyrillic (DOS)",
198 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
199 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
200 MIMECONTF_MIME_LATEST,
201 L"cp866", L"cp866", L"cp866" },
202 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
203 { L"Cyrillic (KOI8-R)",
204 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
205 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
206 L"koi8-r", L"koi8-r", L"koi8-r" },
207 #endif
208 { L"Cyrillic (Windows)",
209 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
210 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
211 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
212 L"windows-1251", L"windows-1251", L"windows-1251" },
213 { L"Cyrillic (Mac)",
214 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
215 MIMECONTF_MIME_LATEST,
216 L"x-mac-cyrillic", L"x-mac-cyrillic", L"x-mac-cyrillic" },
217 { L"Cyrillic (KOI8-R)",
218 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
219 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
220 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
221 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
222 L"koi8-r", L"koi8-r", L"koi8-r" },
223 { L"Cyrillic (KOI8-U)",
224 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
225 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
226 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
227 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
228 L"koi8-u", L"koi8-u", L"koi8-u" },
229 { L"Cyrillic (ISO)",
230 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
231 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
232 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
233 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
234 L"iso-8859-5", L"iso-8859-5", L"iso-8859-5" }
236 static const MIME_CP_INFO greek_cp[] =
238 { L"Greek (DOS)",
239 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
240 MIMECONTF_MIME_LATEST,
241 L"ibm737", L"ibm737", L"ibm737" },
242 { L"Greek, Modern (DOS)",
243 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
244 MIMECONTF_MIME_LATEST,
245 L"ibm869", L"ibm869", L"ibm869" },
246 { L"IBM EBCDIC (Greek Modern)",
247 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
248 MIMECONTF_MIME_LATEST,
249 L"cp875", L"cp875", L"cp875" },
250 { L"Greek (Windows)",
251 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
252 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
253 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
254 L"windows-1253", L"windows-1253", L"windows-1253" },
255 { L"Greek (Mac)",
256 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
257 MIMECONTF_MIME_LATEST,
258 L"x-mac-greek", L"x-mac-greek", L"x-mac-greek" },
259 { L"Greek (ISO)",
260 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
261 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
262 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
263 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
264 L"iso-8859-7", L"iso-8859-7", L"iso-8859-7" }
266 static const MIME_CP_INFO hebrew_cp[] =
268 { L"Hebrew (424)",
269 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
270 MIMECONTF_MIME_LATEST,
271 L"ibm424", L"ibm424", L"ibm424" },
272 { L"Hebrew (856)",
273 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
274 MIMECONTF_MIME_LATEST,
275 L"cp856", L"cp856", L"cp856" },
276 { L"Hebrew (DOS)",
277 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
278 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
279 MIMECONTF_MIME_LATEST,
280 L"dos-862", L"dos-862", L"dos-862" },
281 { L"Hebrew (Windows)",
282 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
283 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
284 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
285 L"windows-1255", L"windows-1255", L"windows-1255" },
286 { L"Hebrew (ISO-Visual)",
287 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
288 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
289 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
290 L"iso-8859-8", L"iso-8859-8", L"iso-8859-8" }
292 static const MIME_CP_INFO japanese_cp[] =
294 { L"Japanese (Auto-Select)",
295 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
296 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
297 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
298 L"_autodetect", L"_autodetect", L"_autodetect" },
299 { L"Japanese (EUC)",
300 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
301 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
302 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
303 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
304 L"euc-jp", L"euc-jp", L"euc-jp" },
305 { L"Japanese (JIS)",
306 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
307 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
308 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
309 MIMECONTF_MIME_IE4,
310 L"iso-2022-jp", L"iso-2022-jp", L"iso-2022-jp"},
311 { L"Japanese (JIS 0208-1990 and 0212-1990)",
312 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
313 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
314 L"EUC-JP", L"EUC-JP", L"EUC-JP"},
315 { L"Japanese (JIS-Allow 1 byte Kana)",
316 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
317 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
318 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
319 L"csISO2022JP", L"iso-2022-jp", L"iso-2022-jp"},
320 { L"Japanese (JIS-Allow 1 byte Kana - SO/SI)",
321 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
322 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
323 L"iso-2022-jp", L"iso-2022-jp", L"iso-2022-jp"},
324 { L"Japanese (Mac)",
325 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
326 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
327 L"x-mac-japanese", L"x-mac-japanese", L"x-mac-japanese"},
328 { L"Japanese (Shift-JIS)",
329 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
330 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
331 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
332 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
333 L"shift_jis", L"iso-2022-jp", L"iso-2022-jp" }
335 static const MIME_CP_INFO korean_cp[] =
337 { L"Korean",
338 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
339 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
340 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
341 MIMECONTF_MIME_LATEST,
342 L"ks_c_5601-1987", L"ks_c_5601-1987", L"ks_c_5601-1987" }
344 static const MIME_CP_INFO thai_cp[] =
346 { L"Thai (Windows)",
347 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
348 L"ibm-thai", L"ibm-thai", L"ibm-thai" }
350 static const MIME_CP_INFO turkish_cp[] =
352 { L"Turkish (DOS)",
353 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
354 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
355 L"ibm857", L"ibm857", L"ibm857" },
356 { L"IBM EBCDIC (Turkish Latin-5)",
357 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
358 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
359 L"ibm1026", L"ibm1026", L"ibm1026" },
360 { L"Turkish (Windows)",
361 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
362 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
363 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
364 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
365 L"windows-1254", L"windows-1254", L"windows-1254" },
366 { L"Turkish (Mac)",
367 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
368 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
369 L"x-mac-turkish", L"x-mac-turkish", L"x-mac-turkish" },
370 { L"Latin 3 (ISO)",
371 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
372 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
373 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
374 L"iso-8859-3", L"iso-8859-3", L"iso-8859-3" },
375 { L"Turkish (ISO)",
376 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
377 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
378 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
379 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
380 L"iso-8859-9", L"iso-8859-9", L"iso-8859-9" }
382 static const MIME_CP_INFO vietnamese_cp[] =
384 { L"Vietnamese (Windows)",
385 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
386 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
387 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
388 MIMECONTF_MIME_LATEST,
389 L"windows-1258", L"windows-1258", L"windows-1258" }
392 static const MIME_CP_INFO western_cp[] =
394 { L"IBM EBCDIC (US-Canada)",
395 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
396 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
397 L"ibm037", L"ibm037", L"ibm037" },
398 { L"OEM United States",
399 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
400 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
401 L"ibm437", L"ibm437", L"ibm437" },
402 { L"IBM EBCDIC (International)",
403 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
404 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
405 L"ibm500", L"ibm500", L"ibm500" },
406 { L"Western European (DOS)",
407 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
408 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
409 L"ibm850", L"ibm850", L"ibm850" },
410 { L"Portuguese (DOS)",
411 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
412 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
413 L"ibm860", L"ibm860", L"ibm860" },
414 { L"Icelandic (DOS)",
415 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
416 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
417 L"ibm861", L"ibm861", L"ibm861" },
418 { L"French Canadian (DOS)",
419 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
420 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
421 L"ibm863", L"ibm863", L"ibm863" },
422 { L"Nordic (DOS)",
423 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
424 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
425 L"ibm865", L"ibm865", L"ibm865" },
426 { L"Western European (Windows)",
427 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
428 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
429 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
430 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
431 L"windows-1252", L"windows-1252", L"iso-8859-1" },
432 { L"Western European (Mac)",
433 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
434 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
435 L"macintosh", L"macintosh", L"macintosh" },
436 { L"Icelandic (Mac)",
437 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
438 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
439 L"x-mac-icelandic", L"x-mac-icelandic", L"x-mac-icelandic" },
440 { L"US-ASCII",
441 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
442 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
443 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
444 L"us-ascii", L"us-ascii", L"us-ascii", L"ascii" },
445 { L"Western European (ISO)",
446 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
447 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
448 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
449 MIMECONTF_MIME_LATEST,
450 L"iso-8859-1", L"iso-8859-1", L"iso-8859-1" },
451 { L"Latin 9 (ISO)",
452 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
453 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
454 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
455 MIMECONTF_MIME_LATEST,
456 L"iso-8859-15", L"iso-8859-15", L"iso-8859-15" }
458 static const MIME_CP_INFO unicode_cp[] =
460 { L"Unicode",
461 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
462 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
463 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
464 MIMECONTF_MIME_LATEST,
465 L"unicode", L"unicode", L"unicode" },
466 { L"Unicode (UTF-7)",
467 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
468 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
469 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
470 L"utf-7", L"utf-7", L"utf-7" },
471 { L"Unicode (UTF-8)",
472 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
473 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
474 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
475 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
476 L"utf-8", L"utf-8", L"utf-8" }
479 static const struct mlang_data
481 const WCHAR *description;
482 UINT family_codepage;
483 UINT number_of_cp;
484 const MIME_CP_INFO *mime_cp_info;
485 const WCHAR *fixed_font;
486 const WCHAR *proportional_font;
487 SCRIPT_ID sid;
488 } mlang_data[] =
490 { L"Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
491 L"Simplified Arabic Fixed", L"Simplified Arabic", sidArabic },
492 { L"Baltic", 1257, ARRAY_SIZE(baltic_cp), baltic_cp,
493 L"Courier New", L"Arial", sidAsciiLatin },
494 { L"Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
495 L"Simsun", L"Simsun", sidHan },
496 { L"Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
497 L"MingLiu", L"New MingLiu", sidBopomofo },
498 { L"Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
499 L"Courier New", L"Arial", sidAsciiLatin },
500 { L"Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
501 L"Courier New", L"Arial", sidCyrillic },
502 { L"Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
503 L"Courier New", L"Arial", sidGreek },
504 { L"Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
505 L"Miriam Fixed", L"David", sidHebrew },
506 { L"Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
507 L"MS Gothic", L"MS PGothic", sidKana },
508 { L"Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
509 L"GulimChe", L"Gulim", sidHangul },
510 { L"Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
511 L"Tahoma", L"Tahoma", sidThai },
512 { L"Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
513 L"Courier New", L"Arial", sidAsciiLatin },
514 { L"Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
515 L"Courier New", L"Arial", sidAsciiLatin },
516 { L"Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
517 L"Courier New", L"Arial", sidAsciiLatin },
518 { L"Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
519 L"Courier New", L"Arial" }
522 struct font_list
524 struct list list_entry;
525 HFONT base_font;
526 HFONT font;
527 UINT charset;
530 static struct list font_cache = LIST_INIT(font_cache);
531 static CRITICAL_SECTION font_cache_critical;
532 static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
534 0, 0, &font_cache_critical,
535 { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
536 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
538 static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
540 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
542 static LONG dll_count;
545 * Japanese Detection and Conversion Functions
548 #define HANKATA(A) ((A >= 161) && (A <= 223))
549 #define ISEUC(A) ((A >= 161) && (A <= 254))
550 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
551 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
552 #define SJIS2(A) ((A >= 64) && (A <= 252))
553 #define ISMARU(A) ((A >= 202) && (A <= 206))
554 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
556 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
558 UINT code = 0;
559 DWORD i = 0;
560 unsigned char c1,c2;
562 while ((code == 0 || code == 51932) && i < count)
564 c1 = input[i];
565 if (c1 == 0x1b /* ESC */)
567 i++;
568 if (i >= count)
569 return code;
570 c1 = input[i];
571 if (c1 == '$')
573 i++;
574 if (i >= count)
575 return code;
576 c1 = input[i];
577 if (c1 =='B' || c1 == '@')
578 code = 50220;
580 if (c1 == 'K')
581 code = 50220;
583 else if (c1 >= 129)
585 i++;
586 if (i >= count)
587 return code;
588 c2 = input[i];
589 if NOTEUC(c1,c2)
590 code = 932;
591 else if (ISEUC(c1) && ISEUC(c2))
592 code = 51932;
593 else if (((c1 == 142)) && HANKATA(c2))
594 code = 51932;
596 i++;
598 return code;
601 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
603 unsigned char c1 = *p1;
604 unsigned char c2 = *p2;
605 int row = c1 < 95 ? 112 : 176;
606 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
608 *p1 = ((c1 + 1) >> 1) + row;
609 *p2 = c2 + cell;
612 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
614 unsigned char c1 = *p1;
615 unsigned char c2 = *p2;
616 int shift = c2 < 159;
617 int row = c1 < 160 ? 112 : 176;
618 int cell = shift ? (31 + (c2 > 127)): 126;
620 *p1 = ((c1 - row) << 1) - shift;
621 *p2 -= cell;
624 static int han2zen(unsigned char *p1, unsigned char *p2)
626 BOOL maru = FALSE;
627 BOOL nigori = FALSE;
628 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
629 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
630 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
631 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
632 131,129,129 };
633 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
634 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
635 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
636 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
638 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
639 nigori = TRUE;
640 else if ((*p2 == 223) && (ISMARU(*p1)))
641 maru = TRUE;
643 if (*p1 >= 161 && *p1 <= 223)
645 unsigned char index = *p1 - 161;
646 *p1 = char1[index];
647 *p2 = char2[index];
650 if (maru || nigori)
652 if (nigori)
654 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
655 (*p2)++;
656 else if ((*p1 == 131) && (*p2 == 69))
657 *p2 = 148;
659 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
660 *p2+= 2;
662 return 1;
665 return 0;
669 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
671 DWORD i = 0;
672 int j = 0;
673 unsigned char p2,p;
674 BOOL shifted = FALSE;
676 while (i < count)
678 p = input[i];
679 if (p == 0x1b /* ESC */)
681 i++;
682 if (i >= count)
683 return 0;
684 p2 = input[i];
685 if (p2 == '$' || p2 =='(')
686 i++;
687 if (p2 == 'K' || p2 =='$')
688 shifted = TRUE;
689 else
690 shifted = FALSE;
692 else
694 if (shifted)
696 i++;
697 if (i >= count)
698 return 0;
699 p2 = input[i];
700 jis2sjis(&p,&p2);
701 output[j++]=p;
702 output[j++]=p2;
704 else
706 output[j++] = p;
709 i++;
711 return j;
714 static inline int exit_shift(LPSTR out, int c)
716 if (out)
718 out[c] = 0x1b;
719 out[c+1] = '(';
720 out[c+2] = 'B';
722 return 3;
725 static inline int enter_shift(LPSTR out, int c)
727 if (out)
729 out[c] = 0x1b;
730 out[c+1] = '$';
731 out[c+2] = 'B';
733 return 3;
737 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
739 DWORD i = 0;
740 int j = 0;
741 unsigned char p2,p;
742 BOOL shifted = FALSE;
744 while (i < count)
746 p = input[i] & 0xff;
747 if (p == 10 || p == 13) /* NL and CR */
749 if (shifted)
751 shifted = FALSE;
752 j += exit_shift(output,j);
754 if (output)
755 output[j++] = p;
756 else
757 j++;
759 else
761 if (SJIS1(p))
763 i++;
764 if (i >= count)
765 return 0;
766 p2 = input[i] & 0xff;
767 if (SJIS2(p2))
769 sjis2jis(&p,&p2);
770 if (!shifted)
772 shifted = TRUE;
773 j+=enter_shift(output,j);
777 if (output)
779 output[j++]=p;
780 output[j++]=p2;
782 else
783 j+=2;
785 else
787 if (HANKATA(p))
789 if ((i+1) >= count)
790 return 0;
791 p2 = input[i+1] & 0xff;
792 i+=han2zen(&p,&p2);
793 sjis2jis(&p,&p2);
794 if (!shifted)
796 shifted = TRUE;
797 j+=enter_shift(output,j);
799 if (output)
801 output[j++]=p;
802 output[j++]=p2;
804 else
805 j+=2;
807 else
809 if (shifted)
811 shifted = FALSE;
812 j += exit_shift(output,j);
814 if (output)
815 output[j++]=p;
816 else
817 j++;
821 i++;
823 if (shifted)
824 j += exit_shift(output,j);
825 return j;
828 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
829 LPWSTR output, DWORD out_count)
831 CHAR *sjis_string;
832 UINT rc = 0;
833 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
834 rc = ConvertJIS2SJIS(input,count,sjis_string);
835 if (rc)
837 TRACE("%s\n",debugstr_an(sjis_string,rc));
838 if (output)
839 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
840 else
841 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
843 HeapFree(GetProcessHeap(),0,sjis_string);
844 return rc;
848 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
849 LPWSTR output, DWORD out_count)
851 CHAR *sjis_string;
852 UINT rc = 0;
853 int code = DetectJapaneseCode(input,count);
854 TRACE("Japanese code %i\n",code);
856 switch (code)
858 case 0:
859 if (output)
860 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
861 else
862 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
863 break;
865 case 932:
866 if (output)
867 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
868 else
869 rc = MultiByteToWideChar(932,0,input,count,0,0);
870 break;
872 case 51932:
873 if (output)
874 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
875 else
876 rc = MultiByteToWideChar(20932,0,input,count,0,0);
877 break;
879 case 50220:
880 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
881 rc = ConvertJIS2SJIS(input,count,sjis_string);
882 if (rc)
884 TRACE("%s\n",debugstr_an(sjis_string,rc));
885 if (output)
886 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
887 else
888 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
890 HeapFree(GetProcessHeap(),0,sjis_string);
891 break;
893 return rc;
896 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
897 LPSTR output, DWORD out_count)
899 CHAR *sjis_string;
900 INT len;
901 UINT rc = 0;
903 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
904 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
905 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
906 TRACE("%s\n",debugstr_an(sjis_string,len));
908 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
909 if (out_count >= rc)
911 ConvertSJIS2JIS(sjis_string, len, output);
913 HeapFree(GetProcessHeap(),0,sjis_string);
914 return rc;
919 * Dll lifetime tracking declaration
921 static void LockModule(void)
923 InterlockedIncrement(&dll_count);
926 static void UnlockModule(void)
928 InterlockedDecrement(&dll_count);
931 HRESULT WINAPI ConvertINetMultiByteToUnicode(
932 LPDWORD pdwMode,
933 DWORD dwEncoding,
934 LPCSTR pSrcStr,
935 LPINT pcSrcSize,
936 LPWSTR pDstStr,
937 LPINT pcDstSize)
939 INT src_len = -1;
941 TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
942 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
944 if (!pcDstSize)
945 return E_FAIL;
947 if (!pcSrcSize)
948 pcSrcSize = &src_len;
950 if (!*pcSrcSize)
952 *pcDstSize = 0;
953 return S_OK;
956 /* forwarding euc-jp to EUC-JP */
957 if (dwEncoding == 51932)
958 dwEncoding = 20932;
960 switch (dwEncoding)
962 case CP_UNICODE:
963 if (*pcSrcSize == -1)
964 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
965 *pcDstSize = min(*pcSrcSize, *pcDstSize);
966 *pcSrcSize *= sizeof(WCHAR);
967 if (pDstStr)
968 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
969 break;
971 case 50220:
972 case 50221:
973 case 50222:
974 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
975 break;
976 case 50932:
977 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
978 break;
980 default:
981 if (*pcSrcSize == -1)
982 *pcSrcSize = lstrlenA(pSrcStr);
984 if (pDstStr)
985 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
986 else
987 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
988 break;
991 if (!*pcDstSize)
992 return E_FAIL;
994 return S_OK;
997 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
998 LPDWORD pdwMode,
999 DWORD dwEncoding,
1000 LPCWSTR pSrcStr,
1001 LPINT pcSrcSize,
1002 LPSTR pDstStr,
1003 LPINT pcDstSize)
1005 INT destsz, size;
1006 INT src_len = -1;
1008 TRACE("%p %ld %s %p %p %p\n", pdwMode, dwEncoding,
1009 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1011 if (!pcDstSize)
1012 return S_OK;
1014 if (!pcSrcSize)
1015 pcSrcSize = &src_len;
1017 destsz = (pDstStr) ? *pcDstSize : 0;
1018 *pcDstSize = 0;
1020 if (!pSrcStr || !*pcSrcSize)
1021 return S_OK;
1023 if (*pcSrcSize == -1)
1024 *pcSrcSize = lstrlenW(pSrcStr);
1026 /* forwarding euc-jp to EUC-JP */
1027 if (dwEncoding == 51932)
1028 dwEncoding = 20932;
1030 if (dwEncoding == CP_UNICODE)
1032 if (*pcSrcSize == -1)
1033 *pcSrcSize = lstrlenW(pSrcStr);
1035 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1036 if (pDstStr)
1037 memmove(pDstStr, pSrcStr, size);
1039 if (size >= destsz)
1040 goto fail;
1042 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1044 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1045 if (!size)
1046 goto fail;
1048 if (pDstStr)
1050 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1051 destsz);
1052 if (!size)
1053 goto fail;
1057 else
1059 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1060 NULL, 0, NULL, NULL);
1061 if (!size)
1062 goto fail;
1064 if (pDstStr)
1066 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1067 pDstStr, destsz, NULL, NULL);
1068 if (!size)
1069 goto fail;
1073 *pcDstSize = size;
1074 return S_OK;
1076 fail:
1077 *pcSrcSize = 0;
1078 *pcDstSize = 0;
1079 return E_FAIL;
1082 HRESULT WINAPI ConvertINetString(
1083 LPDWORD pdwMode,
1084 DWORD dwSrcEncoding,
1085 DWORD dwDstEncoding,
1086 LPCSTR pSrcStr,
1087 LPINT pcSrcSize,
1088 LPSTR pDstStr,
1089 LPINT pcDstSize
1092 TRACE("%p %ld %ld %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1093 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1095 if (dwSrcEncoding == CP_UNICODE)
1097 INT cSrcSizeW;
1098 if (pcSrcSize && *pcSrcSize != -1)
1100 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1101 pcSrcSize = &cSrcSizeW;
1103 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1105 else if (dwDstEncoding == CP_UNICODE)
1107 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1108 *pcDstSize *= sizeof(WCHAR);
1109 return hr;
1111 else
1113 INT cDstSizeW;
1114 LPWSTR pDstStrW;
1115 HRESULT hr;
1117 TRACE("convert %s from %ld to %ld\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1119 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1120 if (hr != S_OK)
1121 return hr;
1123 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1124 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1125 if (hr == S_OK)
1126 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1128 HeapFree(GetProcessHeap(), 0, pDstStrW);
1129 return hr;
1133 static HRESULT GetFamilyCodePage(
1134 UINT uiCodePage,
1135 UINT* puiFamilyCodePage)
1137 UINT i, n;
1139 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1141 if (!puiFamilyCodePage) return S_FALSE;
1143 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1145 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1147 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1149 *puiFamilyCodePage = mlang_data[i].family_codepage;
1150 return S_OK;
1155 return S_FALSE;
1158 HRESULT WINAPI IsConvertINetStringAvailable(
1159 DWORD dwSrcEncoding,
1160 DWORD dwDstEncoding)
1162 UINT src_family, dst_family;
1164 TRACE("%ld %ld\n", dwSrcEncoding, dwDstEncoding);
1166 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1167 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1168 return S_FALSE;
1170 if (src_family == dst_family) return S_OK;
1172 /* we can convert any codepage to/from unicode */
1173 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1175 return S_FALSE;
1178 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1180 CHAR buffer[MAX_RFC1766_NAME];
1181 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1182 INT i;
1184 if (n)
1186 i = PRIMARYLANGID(lcid);
1187 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1188 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1189 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1191 buffer[n - 1] = '-';
1192 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1193 if (!i)
1194 buffer[n - 1] = '\0';
1196 else
1197 i = 0;
1199 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1200 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1202 return E_FAIL;
1205 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1207 WCHAR buffer[MAX_RFC1766_NAME];
1208 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1209 INT i;
1211 if (n)
1213 i = PRIMARYLANGID(lcid);
1214 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1215 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1216 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1218 buffer[n - 1] = '-';
1219 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1220 if (!i)
1221 buffer[n - 1] = '\0';
1223 else
1224 i = 0;
1226 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1227 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1229 return E_FAIL;
1232 HRESULT WINAPI LcidToRfc1766A(
1233 LCID lcid,
1234 LPSTR pszRfc1766,
1235 INT nChar)
1237 TRACE("%04lx %p %u\n", lcid, pszRfc1766, nChar);
1238 if (!pszRfc1766)
1239 return E_INVALIDARG;
1241 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1244 HRESULT WINAPI LcidToRfc1766W(
1245 LCID lcid,
1246 LPWSTR pszRfc1766,
1247 INT nChar)
1249 TRACE("%04lx %p %u\n", lcid, pszRfc1766, nChar);
1250 if (!pszRfc1766)
1251 return E_INVALIDARG;
1253 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1256 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1258 RFC1766INFO info;
1259 ULONG num;
1261 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1263 if (!wcsicmp(info.wszRfc1766, rfc1766))
1265 *lcid = info.lcid;
1266 return S_OK;
1268 if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1270 *lcid = PRIMARYLANGID(info.lcid);
1271 return S_OK;
1275 return E_FAIL;
1278 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1280 IEnumRfc1766 *enumrfc1766;
1281 HRESULT hr;
1283 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1285 if (!pLocale || !pszRfc1766)
1286 return E_INVALIDARG;
1288 hr = EnumRfc1766_create(0, &enumrfc1766);
1289 if (FAILED(hr))
1290 return hr;
1292 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1293 IEnumRfc1766_Release(enumrfc1766);
1295 return hr;
1298 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1300 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1302 if (!rfc1766A)
1303 return E_INVALIDARG;
1305 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1306 rfc1766W[MAX_RFC1766_NAME] = 0;
1308 return Rfc1766ToLcidW(lcid, rfc1766W);
1311 static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
1313 struct font_list *font_list_entry;
1314 CHARSETINFO charset_info;
1315 HFONT new_font, old_font;
1316 LOGFONTW font_attr;
1317 DWORD mask, Csb[2];
1318 BOOL found_cached;
1319 UINT charset;
1320 BOOL ret;
1321 UINT i;
1323 if (hdc == NULL || src_font == NULL) return E_FAIL;
1325 for (i = 0; i < 32; i++)
1327 mask = (DWORD)(1 << i);
1328 if (codepages & mask)
1330 Csb[0] = mask;
1331 Csb[1] = 0x0;
1332 ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
1333 if (!ret) continue;
1335 /* use cached font if possible */
1336 found_cached = FALSE;
1337 EnterCriticalSection(&font_cache_critical);
1338 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1340 if (font_list_entry->charset == charset_info.ciCharset &&
1341 font_list_entry->base_font == src_font)
1343 if (dst_font != NULL)
1344 *dst_font = font_list_entry->font;
1345 found_cached = TRUE;
1348 LeaveCriticalSection(&font_cache_critical);
1349 if (found_cached) return S_OK;
1351 GetObjectW(src_font, sizeof(font_attr), &font_attr);
1352 font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
1353 font_attr.lfWidth = 0;
1354 font_attr.lfFaceName[0] = 0;
1355 new_font = CreateFontIndirectW(&font_attr);
1356 if (new_font == NULL) continue;
1358 old_font = SelectObject(hdc, new_font);
1359 charset = GetTextCharset(hdc);
1360 SelectObject(hdc, old_font);
1361 if (charset == charset_info.ciCharset)
1363 font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
1364 if (font_list_entry == NULL) return E_OUTOFMEMORY;
1366 font_list_entry->base_font = src_font;
1367 font_list_entry->font = new_font;
1368 font_list_entry->charset = charset;
1370 EnterCriticalSection(&font_cache_critical);
1371 list_add_tail(&font_cache, &font_list_entry->list_entry);
1372 LeaveCriticalSection(&font_cache_critical);
1374 if (dst_font != NULL)
1375 *dst_font = new_font;
1376 return S_OK;
1381 return E_FAIL;
1384 static HRESULT release_font(HFONT font)
1386 struct font_list *font_list_entry;
1387 HRESULT hr;
1389 hr = E_FAIL;
1390 EnterCriticalSection(&font_cache_critical);
1391 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1393 if (font_list_entry->font == font)
1395 list_remove(&font_list_entry->list_entry);
1396 DeleteObject(font);
1397 HeapFree(GetProcessHeap(), 0, font_list_entry);
1398 hr = S_OK;
1399 break;
1402 LeaveCriticalSection(&font_cache_critical);
1404 return hr;
1407 static HRESULT clear_font_cache(void)
1409 struct font_list *font_list_entry;
1410 struct font_list *font_list_entry2;
1412 EnterCriticalSection(&font_cache_critical);
1413 LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
1415 list_remove(&font_list_entry->list_entry);
1416 DeleteObject(font_list_entry->font);
1417 HeapFree(GetProcessHeap(), 0, font_list_entry);
1419 LeaveCriticalSection(&font_cache_critical);
1421 return S_OK;
1424 /******************************************************************************
1425 * MLANG ClassFactory
1427 typedef struct {
1428 IClassFactory IClassFactory_iface;
1429 LONG ref;
1430 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1431 } IClassFactoryImpl;
1433 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1435 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1438 struct object_creation_info
1440 const CLSID *clsid;
1441 LPCSTR szClassName;
1442 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1445 static const struct object_creation_info object_creation[] =
1447 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1448 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1451 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1453 TRACE("%s\n", debugstr_guid(riid) );
1455 if (IsEqualGUID(riid, &IID_IUnknown)
1456 || IsEqualGUID(riid, &IID_IClassFactory))
1458 IClassFactory_AddRef(iface);
1459 *ppobj = iface;
1460 return S_OK;
1463 *ppobj = NULL;
1464 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1465 return E_NOINTERFACE;
1468 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1470 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1471 return InterlockedIncrement(&This->ref);
1474 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1476 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1477 ULONG ref = InterlockedDecrement(&This->ref);
1479 if (ref == 0)
1481 TRACE("Destroying %p\n", This);
1482 HeapFree(GetProcessHeap(), 0, This);
1485 return ref;
1488 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1489 REFIID riid, void **ppobj)
1491 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1492 HRESULT hres;
1493 LPUNKNOWN punk;
1495 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1497 *ppobj = NULL;
1498 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1499 if (SUCCEEDED(hres)) {
1500 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1501 IUnknown_Release(punk);
1503 TRACE("returning (%p) -> %lx\n", *ppobj, hres);
1504 return hres;
1507 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1509 if (dolock)
1510 LockModule();
1511 else
1512 UnlockModule();
1514 return S_OK;
1517 static const IClassFactoryVtbl MLANGCF_Vtbl =
1519 MLANGCF_QueryInterface,
1520 MLANGCF_AddRef,
1521 MLANGCF_Release,
1522 MLANGCF_CreateInstance,
1523 MLANGCF_LockServer
1526 /******************************************************************
1527 * DllGetClassObject (MLANG.@)
1529 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1531 unsigned int i;
1532 IClassFactoryImpl *factory;
1534 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1536 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1537 && ! IsEqualGUID( &IID_IUnknown, iid) )
1538 return E_NOINTERFACE;
1540 for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1542 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1543 break;
1546 if (i == ARRAY_SIZE(object_creation))
1548 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1549 return CLASS_E_CLASSNOTAVAILABLE;
1552 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1554 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1555 if (factory == NULL) return E_OUTOFMEMORY;
1557 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1558 factory->ref = 1;
1560 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1562 *ppv = &factory->IClassFactory_iface;
1564 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1566 return S_OK;
1570 /******************************************************************************/
1572 typedef struct tagMLang_impl
1574 IMLangFontLink IMLangFontLink_iface;
1575 IMultiLanguage IMultiLanguage_iface;
1576 IMultiLanguage3 IMultiLanguage3_iface;
1577 IMLangFontLink2 IMLangFontLink2_iface;
1578 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1579 LONG ref;
1580 DWORD total_cp, total_scripts;
1581 } MLang_impl;
1583 /******************************************************************************/
1585 typedef struct tagEnumCodePage_impl
1587 IEnumCodePage IEnumCodePage_iface;
1588 LONG ref;
1589 MIMECPINFO *cpinfo;
1590 DWORD total, pos;
1591 } EnumCodePage_impl;
1593 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1595 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1598 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1599 IEnumCodePage* iface,
1600 REFIID riid,
1601 void** ppvObject)
1603 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1605 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1607 if (IsEqualGUID(riid, &IID_IUnknown)
1608 || IsEqualGUID(riid, &IID_IEnumCodePage))
1610 IEnumCodePage_AddRef(iface);
1611 TRACE("Returning IID_IEnumCodePage %p ref = %ld\n", This, This->ref);
1612 *ppvObject = &This->IEnumCodePage_iface;
1613 return S_OK;
1616 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1617 return E_NOINTERFACE;
1620 static ULONG WINAPI fnIEnumCodePage_AddRef(
1621 IEnumCodePage* iface)
1623 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1624 return InterlockedIncrement(&This->ref);
1627 static ULONG WINAPI fnIEnumCodePage_Release(
1628 IEnumCodePage* iface)
1630 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1631 ULONG ref = InterlockedDecrement(&This->ref);
1633 TRACE("%p ref = %ld\n", This, ref);
1634 if (ref == 0)
1636 TRACE("Destroying %p\n", This);
1637 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1638 HeapFree(GetProcessHeap(), 0, This);
1641 return ref;
1644 static HRESULT WINAPI fnIEnumCodePage_Clone(
1645 IEnumCodePage* iface,
1646 IEnumCodePage** ppEnum)
1648 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1649 FIXME("%p %p\n", This, ppEnum);
1650 return E_NOTIMPL;
1653 static HRESULT WINAPI fnIEnumCodePage_Next(
1654 IEnumCodePage* iface,
1655 ULONG celt,
1656 PMIMECPINFO rgelt,
1657 ULONG* pceltFetched)
1659 ULONG i;
1660 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1662 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
1664 if (!pceltFetched) return S_FALSE;
1665 *pceltFetched = 0;
1667 if (!rgelt) return S_FALSE;
1669 if (This->pos + celt > This->total)
1670 celt = This->total - This->pos;
1672 if (!celt) return S_FALSE;
1674 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1675 *pceltFetched = celt;
1676 This->pos += celt;
1678 for (i = 0; i < celt; i++)
1680 TRACE("#%lu: %08lx %u %u %s %s %s %s %s %s %d\n",
1681 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1682 rgelt[i].uiFamilyCodePage,
1683 wine_dbgstr_w(rgelt[i].wszDescription),
1684 wine_dbgstr_w(rgelt[i].wszWebCharset),
1685 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1686 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1687 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1688 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1689 rgelt[i].bGDICharset);
1691 return S_OK;
1694 static HRESULT WINAPI fnIEnumCodePage_Reset(
1695 IEnumCodePage* iface)
1697 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1699 TRACE("%p\n", This);
1701 This->pos = 0;
1702 return S_OK;
1705 static HRESULT WINAPI fnIEnumCodePage_Skip(
1706 IEnumCodePage* iface,
1707 ULONG celt)
1709 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1711 TRACE("%p %lu\n", This, celt);
1713 if (celt >= This->total) return S_FALSE;
1715 This->pos += celt;
1716 return S_OK;
1719 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1721 fnIEnumCodePage_QueryInterface,
1722 fnIEnumCodePage_AddRef,
1723 fnIEnumCodePage_Release,
1724 fnIEnumCodePage_Clone,
1725 fnIEnumCodePage_Next,
1726 fnIEnumCodePage_Reset,
1727 fnIEnumCodePage_Skip
1730 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1731 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1733 EnumCodePage_impl *ecp;
1734 MIMECPINFO *cpinfo;
1735 UINT i, n;
1737 TRACE("%p, %08lx, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1739 if (!grfFlags) /* enumerate internal data base of encodings */
1740 grfFlags = MIMECONTF_MIME_LATEST;
1742 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1743 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1744 ecp->ref = 1;
1745 ecp->pos = 0;
1746 ecp->total = 0;
1747 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1749 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1751 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1752 ecp->total++;
1756 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1757 sizeof(MIMECPINFO) * ecp->total);
1758 cpinfo = ecp->cpinfo;
1760 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1762 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1764 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1765 fill_cp_info(&mlang_data[i], n, cpinfo++);
1769 TRACE("enumerated %ld codepages with flags %08lx\n", ecp->total, grfFlags);
1771 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1773 return S_OK;
1776 /******************************************************************************/
1778 typedef struct tagEnumScript_impl
1780 IEnumScript IEnumScript_iface;
1781 LONG ref;
1782 SCRIPTINFO *script_info;
1783 DWORD total, pos;
1784 } EnumScript_impl;
1786 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1788 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1791 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1792 IEnumScript* iface,
1793 REFIID riid,
1794 void** ppvObject)
1796 EnumScript_impl *This = impl_from_IEnumScript( iface );
1798 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1800 if (IsEqualGUID(riid, &IID_IUnknown)
1801 || IsEqualGUID(riid, &IID_IEnumScript))
1803 IEnumScript_AddRef(iface);
1804 TRACE("Returning IID_IEnumScript %p ref = %ld\n", This, This->ref);
1805 *ppvObject = &This->IEnumScript_iface;
1806 return S_OK;
1809 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1810 return E_NOINTERFACE;
1813 static ULONG WINAPI fnIEnumScript_AddRef(
1814 IEnumScript* iface)
1816 EnumScript_impl *This = impl_from_IEnumScript( iface );
1817 return InterlockedIncrement(&This->ref);
1820 static ULONG WINAPI fnIEnumScript_Release(
1821 IEnumScript* iface)
1823 EnumScript_impl *This = impl_from_IEnumScript( iface );
1824 ULONG ref = InterlockedDecrement(&This->ref);
1826 TRACE("%p ref = %ld\n", This, ref);
1827 if (ref == 0)
1829 TRACE("Destroying %p\n", This);
1830 HeapFree(GetProcessHeap(), 0, This->script_info);
1831 HeapFree(GetProcessHeap(), 0, This);
1834 return ref;
1837 static HRESULT WINAPI fnIEnumScript_Clone(
1838 IEnumScript* iface,
1839 IEnumScript** ppEnum)
1841 EnumScript_impl *This = impl_from_IEnumScript( iface );
1842 FIXME("%p %p: stub!\n", This, ppEnum);
1843 return E_NOTIMPL;
1846 static HRESULT WINAPI fnIEnumScript_Next(
1847 IEnumScript* iface,
1848 ULONG celt,
1849 PSCRIPTINFO rgelt,
1850 ULONG* pceltFetched)
1852 EnumScript_impl *This = impl_from_IEnumScript( iface );
1854 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
1856 if (!pceltFetched || !rgelt) return E_FAIL;
1858 *pceltFetched = 0;
1860 if (This->pos + celt > This->total)
1861 celt = This->total - This->pos;
1863 if (!celt) return S_FALSE;
1865 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1866 *pceltFetched = celt;
1867 This->pos += celt;
1869 return S_OK;
1872 static HRESULT WINAPI fnIEnumScript_Reset(
1873 IEnumScript* iface)
1875 EnumScript_impl *This = impl_from_IEnumScript( iface );
1877 TRACE("%p\n", This);
1879 This->pos = 0;
1880 return S_OK;
1883 static HRESULT WINAPI fnIEnumScript_Skip(
1884 IEnumScript* iface,
1885 ULONG celt)
1887 EnumScript_impl *This = impl_from_IEnumScript( iface );
1889 TRACE("%p %lu\n", This, celt);
1891 if (celt >= This->total) return S_FALSE;
1893 This->pos += celt;
1894 return S_OK;
1897 static const IEnumScriptVtbl IEnumScript_vtbl =
1899 fnIEnumScript_QueryInterface,
1900 fnIEnumScript_AddRef,
1901 fnIEnumScript_Release,
1902 fnIEnumScript_Clone,
1903 fnIEnumScript_Next,
1904 fnIEnumScript_Reset,
1905 fnIEnumScript_Skip
1908 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1909 LANGID LangId, IEnumScript** ppEnumScript )
1911 EnumScript_impl *es;
1912 UINT i;
1914 TRACE("%p, %08lx, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1916 if (!dwFlags) /* enumerate all available scripts */
1917 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1919 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1920 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1921 es->ref = 1;
1922 es->pos = 0;
1923 /* do not enumerate unicode flavours */
1924 es->total = ARRAY_SIZE(mlang_data) - 1;
1925 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1927 for (i = 0; i < es->total; i++)
1929 es->script_info[i].ScriptId = i;
1930 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1931 wcscpy( es->script_info[i].wszDescription, mlang_data[i].description );
1932 wcscpy( es->script_info[i].wszFixedWidthFont, mlang_data[i].fixed_font );
1933 wcscpy( es->script_info[i].wszProportionalFont, mlang_data[i].proportional_font );
1936 TRACE("enumerated %ld scripts with flags %08lx\n", es->total, dwFlags);
1938 *ppEnumScript = &es->IEnumScript_iface;
1940 return S_OK;
1943 /******************************************************************************/
1945 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1947 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1950 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1951 IMLangFontLink* iface,
1952 REFIID riid,
1953 void** ppvObject)
1955 MLang_impl *This = impl_from_IMLangFontLink( iface );
1956 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1959 static ULONG WINAPI fnIMLangFontLink_AddRef(
1960 IMLangFontLink* iface)
1962 MLang_impl *This = impl_from_IMLangFontLink( iface );
1963 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1966 static ULONG WINAPI fnIMLangFontLink_Release(
1967 IMLangFontLink* iface)
1969 MLang_impl *This = impl_from_IMLangFontLink( iface );
1970 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1973 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1974 IMLangFontLink* iface,
1975 WCHAR ch_src,
1976 DWORD* codepages)
1978 MLang_impl *This = impl_from_IMLangFontLink( iface );
1979 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
1982 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1983 IMLangFontLink* iface,
1984 const WCHAR* src,
1985 LONG src_len,
1986 DWORD priority_cp,
1987 DWORD* codepages,
1988 LONG* ret_len)
1990 MLang_impl *This = impl_from_IMLangFontLink( iface );
1991 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
1992 codepages, ret_len);
1995 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1996 IMLangFontLink* iface,
1997 UINT codepage,
1998 DWORD* codepages)
2000 MLang_impl *This = impl_from_IMLangFontLink( iface );
2001 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2004 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2005 IMLangFontLink* iface,
2006 DWORD codepages,
2007 UINT def_codepage,
2008 UINT* codepage)
2010 MLang_impl *This = impl_from_IMLangFontLink(iface);
2011 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2012 def_codepage, codepage);
2015 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2016 IMLangFontLink* iface,
2017 HDC hdc,
2018 HFONT hfont,
2019 DWORD* codepages)
2021 MLang_impl *This = impl_from_IMLangFontLink(iface);
2022 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2025 static HRESULT WINAPI fnIMLangFontLink_MapFont(
2026 IMLangFontLink* iface,
2027 HDC hDC,
2028 DWORD dwCodePages,
2029 HFONT hSrcFont,
2030 HFONT* phDestFont)
2032 TRACE("(%p)->%p %08lx %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
2034 return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2037 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2038 IMLangFontLink* iface,
2039 HFONT hFont)
2041 TRACE("(%p)->%p\n",iface, hFont);
2043 return release_font(hFont);
2046 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2047 IMLangFontLink* iface)
2049 TRACE("(%p)\n",iface);
2051 return clear_font_cache();
2055 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2057 fnIMLangFontLink_QueryInterface,
2058 fnIMLangFontLink_AddRef,
2059 fnIMLangFontLink_Release,
2060 fnIMLangFontLink_GetCharCodePages,
2061 fnIMLangFontLink_GetStrCodePages,
2062 fnIMLangFontLink_CodePageToCodePages,
2063 fnIMLangFontLink_CodePagesToCodePage,
2064 fnIMLangFontLink_GetFontCodePages,
2065 fnIMLangFontLink_MapFont,
2066 fnIMLangFontLink_ReleaseFont,
2067 fnIMLangFontLink_ResetFontMapping,
2070 /******************************************************************************/
2072 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2074 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2077 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2078 IMultiLanguage* iface,
2079 REFIID riid,
2080 void** obj)
2082 MLang_impl *This = impl_from_IMultiLanguage( iface );
2083 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2086 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2088 MLang_impl *This = impl_from_IMultiLanguage( iface );
2089 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2092 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2094 MLang_impl *This = impl_from_IMultiLanguage( iface );
2095 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2098 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2099 IMultiLanguage* iface,
2100 UINT* cp)
2102 MLang_impl *This = impl_from_IMultiLanguage( iface );
2103 TRACE("(%p, %p)\n", This, cp);
2104 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2107 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2108 IMultiLanguage* iface,
2109 UINT uiCodePage,
2110 PMIMECPINFO pCodePageInfo)
2112 UINT i, n;
2113 MLang_impl *This = impl_from_IMultiLanguage( iface );
2115 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2117 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2119 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2121 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2123 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2124 return S_OK;
2129 return S_FALSE;
2132 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2133 IMultiLanguage* iface,
2134 UINT cp,
2135 UINT* family_cp)
2137 MLang_impl *This = impl_from_IMultiLanguage( iface );
2138 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2141 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2142 IMultiLanguage* iface,
2143 DWORD grfFlags,
2144 IEnumCodePage** ppEnumCodePage)
2146 MLang_impl *This = impl_from_IMultiLanguage( iface );
2148 TRACE("%p %08lx %p\n", This, grfFlags, ppEnumCodePage);
2150 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2153 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2154 IMultiLanguage* iface,
2155 BSTR Charset,
2156 PMIMECSETINFO pCharsetInfo)
2158 MLang_impl *This = impl_from_IMultiLanguage( iface );
2159 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2162 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2163 IMultiLanguage* iface,
2164 DWORD src_enc,
2165 DWORD dst_enc)
2167 MLang_impl *This = impl_from_IMultiLanguage( iface );
2168 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2171 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2172 IMultiLanguage* iface,
2173 DWORD* mode,
2174 DWORD src_enc,
2175 DWORD dst_enc,
2176 BYTE* src,
2177 UINT* src_size,
2178 BYTE* dest,
2179 UINT* dest_size)
2181 MLang_impl *This = impl_from_IMultiLanguage( iface );
2182 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2183 dst_enc, src, src_size, dest, dest_size);
2186 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2187 IMultiLanguage* iface,
2188 DWORD* mode,
2189 DWORD src_enc,
2190 CHAR* src,
2191 UINT* src_size,
2192 WCHAR* dest,
2193 UINT* dest_size)
2195 MLang_impl *This = impl_from_IMultiLanguage( iface );
2196 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2197 mode, src_enc, src, src_size, dest, dest_size);
2200 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2201 IMultiLanguage* iface,
2202 DWORD* mode,
2203 DWORD encoding,
2204 WCHAR* src,
2205 UINT* src_size,
2206 CHAR* dest,
2207 UINT* dest_size)
2209 MLang_impl *This = impl_from_IMultiLanguage(iface);
2210 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2211 mode, encoding, src, src_size, dest, dest_size);
2214 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2215 IMultiLanguage* iface)
2217 MLang_impl *This = impl_from_IMultiLanguage( iface );
2218 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2221 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2222 IMultiLanguage* iface,
2223 LCID lcid,
2224 BSTR* pbstrRfc1766)
2226 MLang_impl *This = impl_from_IMultiLanguage(iface);
2227 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2230 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2231 IMultiLanguage* iface,
2232 LCID* locale,
2233 BSTR rfc1766)
2235 MLang_impl *This = impl_from_IMultiLanguage(iface);
2236 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2239 /******************************************************************************/
2241 typedef struct tagEnumRfc1766_impl
2243 IEnumRfc1766 IEnumRfc1766_iface;
2244 LONG ref;
2245 RFC1766INFO *info;
2246 DWORD total, pos;
2247 } EnumRfc1766_impl;
2249 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2251 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2254 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2255 IEnumRfc1766 *iface,
2256 REFIID riid,
2257 void** ppvObject)
2259 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2261 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2263 if (IsEqualGUID(riid, &IID_IUnknown)
2264 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2266 IEnumRfc1766_AddRef(iface);
2267 TRACE("Returning IID_IEnumRfc1766 %p ref = %ld\n", This, This->ref);
2268 *ppvObject = &This->IEnumRfc1766_iface;
2269 return S_OK;
2272 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2273 return E_NOINTERFACE;
2276 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2277 IEnumRfc1766 *iface)
2279 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2280 return InterlockedIncrement(&This->ref);
2283 static ULONG WINAPI fnIEnumRfc1766_Release(
2284 IEnumRfc1766 *iface)
2286 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2287 ULONG ref = InterlockedDecrement(&This->ref);
2289 TRACE("%p ref = %ld\n", This, ref);
2290 if (ref == 0)
2292 TRACE("Destroying %p\n", This);
2293 HeapFree(GetProcessHeap(), 0, This->info);
2294 HeapFree(GetProcessHeap(), 0, This);
2296 return ref;
2299 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2300 IEnumRfc1766 *iface,
2301 IEnumRfc1766 **ppEnum)
2303 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2305 FIXME("%p %p\n", This, ppEnum);
2306 return E_NOTIMPL;
2309 static HRESULT WINAPI fnIEnumRfc1766_Next(
2310 IEnumRfc1766 *iface,
2311 ULONG celt,
2312 PRFC1766INFO rgelt,
2313 ULONG *pceltFetched)
2315 ULONG i;
2316 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2318 TRACE("%p %lu %p %p\n", This, celt, rgelt, pceltFetched);
2320 if (!pceltFetched) return S_FALSE;
2321 *pceltFetched = 0;
2323 if (!rgelt) return S_FALSE;
2325 if (This->pos + celt > This->total)
2326 celt = This->total - This->pos;
2328 if (!celt) return S_FALSE;
2330 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2331 *pceltFetched = celt;
2332 This->pos += celt;
2334 for (i = 0; i < celt; i++)
2336 TRACE("#%lu: %08lx %s %s\n",
2337 i, rgelt[i].lcid,
2338 wine_dbgstr_w(rgelt[i].wszRfc1766),
2339 wine_dbgstr_w(rgelt[i].wszLocaleName));
2341 return S_OK;
2344 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2345 IEnumRfc1766 *iface)
2347 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2349 TRACE("%p\n", This);
2351 This->pos = 0;
2352 return S_OK;
2355 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2356 IEnumRfc1766 *iface,
2357 ULONG celt)
2359 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2361 TRACE("%p %lu\n", This, celt);
2363 if (celt >= This->total) return S_FALSE;
2365 This->pos += celt;
2366 return S_OK;
2369 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2371 fnIEnumRfc1766_QueryInterface,
2372 fnIEnumRfc1766_AddRef,
2373 fnIEnumRfc1766_Release,
2374 fnIEnumRfc1766_Clone,
2375 fnIEnumRfc1766_Next,
2376 fnIEnumRfc1766_Reset,
2377 fnIEnumRfc1766_Skip
2380 struct enum_locales_data
2382 RFC1766INFO *info;
2383 DWORD total, allocated;
2386 static BOOL CALLBACK enum_locales_proc(LPWSTR locale, DWORD flags, LPARAM lparam)
2388 struct enum_locales_data *data = (struct enum_locales_data *)lparam;
2389 RFC1766INFO *info;
2391 TRACE("%s\n", debugstr_w(locale));
2393 if (data->total >= data->allocated)
2395 data->allocated *= 2;
2396 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2397 if (!data->info) return FALSE;
2400 info = &data->info[data->total];
2402 info->lcid = LocaleNameToLCID( locale, 0 );
2403 if (info->lcid == LOCALE_CUSTOM_UNSPECIFIED) return TRUE;
2405 info->wszRfc1766[0] = 0;
2406 if (FAILED( lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME ))) return TRUE;
2408 info->wszLocaleName[0] = 0;
2409 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2410 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2412 data->total++;
2414 return TRUE;
2417 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2419 EnumRfc1766_impl *rfc;
2420 struct enum_locales_data data;
2422 TRACE("%04x, %p\n", LangId, ppEnum);
2424 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2425 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2426 rfc->ref = 1;
2427 rfc->pos = 0;
2428 rfc->total = 0;
2430 data.total = 0;
2431 data.allocated = 160;
2432 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2433 if (!data.info)
2435 HeapFree(GetProcessHeap(), 0, rfc);
2436 return E_OUTOFMEMORY;
2439 EnumSystemLocalesEx(enum_locales_proc, LOCALE_WINDOWS, (LPARAM)&data, NULL);
2441 TRACE("enumerated %ld rfc1766 structures\n", data.total);
2443 if (!data.total)
2445 HeapFree(GetProcessHeap(), 0, data.info);
2446 HeapFree(GetProcessHeap(), 0, rfc);
2447 return E_FAIL;
2450 rfc->info = data.info;
2451 rfc->total = data.total;
2453 *ppEnum = &rfc->IEnumRfc1766_iface;
2454 return S_OK;
2457 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2458 IMultiLanguage *iface,
2459 IEnumRfc1766 **ppEnumRfc1766)
2461 MLang_impl *This = impl_from_IMultiLanguage( iface );
2463 TRACE("%p %p\n", This, ppEnumRfc1766);
2465 return EnumRfc1766_create(0, ppEnumRfc1766);
2468 /******************************************************************************/
2470 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2471 IMultiLanguage* iface,
2472 LCID Locale,
2473 PRFC1766INFO pRfc1766Info)
2475 LCTYPE type = LOCALE_SLANGUAGE;
2477 TRACE("(%p, 0x%04lx, %p)\n", iface, Locale, pRfc1766Info);
2479 if (!pRfc1766Info)
2480 return E_INVALIDARG;
2482 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2483 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2484 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2486 if (!SUBLANGID(Locale))
2487 type = LOCALE_SENGLANGUAGE; /* suppress country */
2489 else
2491 if (!SUBLANGID(Locale)) {
2492 TRACE("SUBLANGID missing in 0x%04lx\n", Locale);
2493 return E_FAIL;
2497 pRfc1766Info->lcid = Locale;
2498 pRfc1766Info->wszRfc1766[0] = 0;
2499 pRfc1766Info->wszLocaleName[0] = 0;
2501 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2502 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2503 return S_OK;
2505 /* Locale not supported */
2506 return E_INVALIDARG;
2509 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2510 IMultiLanguage* iface,
2511 UINT src_cp,
2512 UINT dst_cp,
2513 DWORD prop,
2514 IMLangConvertCharset** convert_charset)
2516 MLang_impl *This = impl_from_IMultiLanguage(iface);
2517 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2520 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2522 fnIMultiLanguage_QueryInterface,
2523 fnIMultiLanguage_AddRef,
2524 fnIMultiLanguage_Release,
2525 fnIMultiLanguage_GetNumberOfCodePageInfo,
2526 fnIMultiLanguage_GetCodePageInfo,
2527 fnIMultiLanguage_GetFamilyCodePage,
2528 fnIMultiLanguage_EnumCodePages,
2529 fnIMultiLanguage_GetCharsetInfo,
2530 fnIMultiLanguage_IsConvertible,
2531 fnIMultiLanguage_ConvertString,
2532 fnIMultiLanguage_ConvertStringToUnicode,
2533 fnIMultiLanguage_ConvertStringFromUnicode,
2534 fnIMultiLanguage_ConvertStringReset,
2535 fnIMultiLanguage_GetRfc1766FromLcid,
2536 fnIMultiLanguage_GetLcidFromRfc1766,
2537 fnIMultiLanguage_EnumRfc1766,
2538 fnIMultiLanguage_GetRfc1766Info,
2539 fnIMultiLanguage_CreateConvertCharset,
2543 /******************************************************************************/
2545 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2547 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2550 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2551 IMultiLanguage3* iface,
2552 REFIID riid,
2553 void** obj)
2555 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2557 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2559 if (IsEqualGUID(riid, &IID_IUnknown) ||
2560 IsEqualGUID(riid, &IID_IMultiLanguage))
2562 *obj = &This->IMultiLanguage_iface;
2564 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2565 IsEqualGUID(riid, &IID_IMLangFontLink))
2567 *obj = &This->IMLangFontLink_iface;
2569 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2571 *obj = &This->IMLangFontLink2_iface;
2573 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2574 IsEqualGUID(riid, &IID_IMultiLanguage3))
2576 *obj = &This->IMultiLanguage3_iface;
2578 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2580 *obj = &This->IMLangLineBreakConsole_iface;
2582 else
2584 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2585 *obj = NULL;
2586 return E_NOINTERFACE;
2589 IMultiLanguage3_AddRef(iface);
2590 return S_OK;
2593 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2595 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2596 return InterlockedIncrement(&This->ref);
2599 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2601 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2602 ULONG ref = InterlockedDecrement(&This->ref);
2604 TRACE("(%p)->(%ld)\n", This, ref);
2605 if (ref == 0)
2607 HeapFree(GetProcessHeap(), 0, This);
2608 UnlockModule();
2611 return ref;
2614 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2615 IMultiLanguage3* iface,
2616 UINT* pcCodePage)
2618 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2620 TRACE("%p, %p\n", This, pcCodePage);
2622 if (!pcCodePage) return E_INVALIDARG;
2624 *pcCodePage = This->total_cp;
2625 return S_OK;
2628 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2630 CHARSETINFO csi;
2632 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2633 TCI_SRCCODEPAGE))
2634 mime_cp_info->bGDICharset = csi.ciCharset;
2635 else
2636 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2638 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2639 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2640 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2641 wcscpy( mime_cp_info->wszDescription, ml_data->mime_cp_info[index].description );
2642 wcscpy( mime_cp_info->wszWebCharset, ml_data->mime_cp_info[index].web_charset );
2643 wcscpy( mime_cp_info->wszHeaderCharset, ml_data->mime_cp_info[index].header_charset );
2644 wcscpy( mime_cp_info->wszBodyCharset, ml_data->mime_cp_info[index].body_charset );
2645 wcscpy( mime_cp_info->wszFixedWidthFont, ml_data->fixed_font );
2646 wcscpy( mime_cp_info->wszProportionalFont, ml_data->proportional_font );
2648 TRACE("%08lx %u %u %s %s %s %s %s %s %d\n",
2649 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2650 mime_cp_info->uiFamilyCodePage,
2651 wine_dbgstr_w(mime_cp_info->wszDescription),
2652 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2653 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2654 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2655 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2656 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2657 mime_cp_info->bGDICharset);
2660 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2661 IMultiLanguage3* iface,
2662 UINT uiCodePage,
2663 LANGID LangId,
2664 PMIMECPINFO pCodePageInfo)
2666 UINT i, n;
2667 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2669 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2671 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2673 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2675 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2677 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2678 return S_OK;
2683 return S_FALSE;
2686 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2687 IMultiLanguage3* iface,
2688 UINT uiCodePage,
2689 UINT* puiFamilyCodePage)
2691 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2694 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2695 IMultiLanguage3* iface,
2696 DWORD grfFlags,
2697 LANGID LangId,
2698 IEnumCodePage** ppEnumCodePage)
2700 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2702 TRACE("%p %08lx %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2704 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2707 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2708 IMultiLanguage3* iface,
2709 BSTR Charset,
2710 PMIMECSETINFO pCharsetInfo)
2712 UINT i, n;
2713 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2715 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2717 if (!pCharsetInfo) return E_FAIL;
2719 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2721 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2723 if (!lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].web_charset))
2725 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2726 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2727 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].web_charset);
2728 return S_OK;
2730 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2732 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2733 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2734 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2735 return S_OK;
2740 /* FIXME:
2741 * Since we do not support charsets like iso-2022-jp and do not have
2742 * them in our database as a primary (web_charset) encoding this loop
2743 * does an attempt to 'approximate' charset name by header_charset.
2745 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2747 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2749 if (!lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].header_charset))
2751 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2752 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2753 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].header_charset);
2754 return S_OK;
2759 return E_FAIL;
2762 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2763 IMultiLanguage3* iface,
2764 DWORD dwSrcEncoding,
2765 DWORD dwDstEncoding)
2767 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2770 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2771 IMultiLanguage3* iface,
2772 DWORD* pdwMode,
2773 DWORD dwSrcEncoding,
2774 DWORD dwDstEncoding,
2775 BYTE* pSrcStr,
2776 UINT* pcSrcSize,
2777 BYTE* pDstStr,
2778 UINT* pcDstSize)
2780 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2781 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2784 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2785 IMultiLanguage3* iface,
2786 DWORD* pdwMode,
2787 DWORD dwEncoding,
2788 CHAR* pSrcStr,
2789 UINT* pcSrcSize,
2790 WCHAR* pDstStr,
2791 UINT* pcDstSize)
2793 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2794 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2797 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2798 IMultiLanguage3* iface,
2799 DWORD* pdwMode,
2800 DWORD dwEncoding,
2801 WCHAR* pSrcStr,
2802 UINT* pcSrcSize,
2803 CHAR* pDstStr,
2804 UINT* pcDstSize)
2806 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2807 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2810 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2811 IMultiLanguage3* iface)
2813 FIXME("\n");
2814 return E_NOTIMPL;
2817 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2818 IMultiLanguage3* iface,
2819 LCID lcid,
2820 BSTR* pbstrRfc1766)
2822 WCHAR buf[MAX_RFC1766_NAME];
2824 TRACE("%p %04lx %p\n", iface, lcid, pbstrRfc1766);
2825 if (!pbstrRfc1766)
2826 return E_INVALIDARG;
2828 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2830 *pbstrRfc1766 = SysAllocString( buf );
2831 return S_OK;
2833 return E_FAIL;
2836 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2837 IMultiLanguage3* iface,
2838 LCID* pLocale,
2839 BSTR bstrRfc1766)
2841 HRESULT hr;
2842 IEnumRfc1766 *rfc1766;
2844 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2846 if (!pLocale || !bstrRfc1766)
2847 return E_INVALIDARG;
2849 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2850 if (FAILED(hr))
2851 return hr;
2853 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2855 IEnumRfc1766_Release(rfc1766);
2856 return hr;
2859 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2860 IMultiLanguage3* iface,
2861 LANGID LangId,
2862 IEnumRfc1766** ppEnumRfc1766)
2864 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2866 TRACE("%p %p\n", This, ppEnumRfc1766);
2868 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2871 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2872 IMultiLanguage3* iface,
2873 LCID Locale,
2874 LANGID LangId,
2875 PRFC1766INFO pRfc1766Info)
2877 static LANGID last_lang = -1;
2878 LCTYPE type = LOCALE_SLANGUAGE;
2880 TRACE("(%p, 0x%04lx, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2882 if (!pRfc1766Info)
2883 return E_INVALIDARG;
2885 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2886 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2887 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2889 if (!SUBLANGID(Locale))
2890 type = LOCALE_SENGLANGUAGE; /* suppress country */
2892 else
2894 if (!SUBLANGID(Locale)) {
2895 TRACE("SUBLANGID missing in 0x%04lx\n", Locale);
2896 return E_FAIL;
2900 pRfc1766Info->lcid = Locale;
2901 pRfc1766Info->wszRfc1766[0] = 0;
2902 pRfc1766Info->wszLocaleName[0] = 0;
2904 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2905 (last_lang != LangId)) {
2906 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2907 last_lang = LangId;
2910 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2911 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2912 return S_OK;
2914 /* Locale not supported */
2915 return E_INVALIDARG;
2918 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2919 IMultiLanguage3* iface,
2920 UINT src_cp,
2921 UINT dst_cp,
2922 DWORD prop,
2923 IMLangConvertCharset** convert_charset)
2925 HRESULT hr;
2927 TRACE("(%u %u 0x%08lx %p)\n", src_cp, dst_cp, prop, convert_charset);
2929 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2930 if (FAILED(hr)) return hr;
2932 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2935 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2936 IMultiLanguage3* iface,
2937 DWORD* pdwMode,
2938 DWORD dwFlag,
2939 WCHAR* lpFallBack,
2940 DWORD dwSrcEncoding,
2941 DWORD dwDstEncoding,
2942 IStream* pstmIn,
2943 IStream* pstmOut)
2945 char *src, *dst = NULL;
2946 INT srclen, dstlen;
2947 STATSTG stat;
2948 HRESULT hr;
2950 TRACE("%p %0lx8 %s %lu %lu %p %p\n",
2951 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2953 FIXME("dwFlag and lpFallBack not handled\n");
2955 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2956 if (FAILED(hr)) return hr;
2958 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2959 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2961 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2962 if (FAILED(hr)) goto exit;
2964 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
2965 if (FAILED(hr)) goto exit;
2967 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
2969 hr = E_OUTOFMEMORY;
2970 goto exit;
2972 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
2973 if (FAILED(hr)) goto exit;
2975 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
2977 exit:
2978 HeapFree(GetProcessHeap(), 0, src);
2979 HeapFree(GetProcessHeap(), 0, dst);
2980 return hr;
2983 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
2984 IMultiLanguage3* iface,
2985 DWORD* pdwMode,
2986 DWORD dwEncoding,
2987 CHAR* pSrcStr,
2988 UINT* pcSrcSize,
2989 WCHAR* pDstStr,
2990 UINT* pcDstSize,
2991 DWORD dwFlag,
2992 WCHAR* lpFallBack)
2994 if (dwFlag || lpFallBack)
2995 FIXME("Ignoring dwFlag (0x%lx/%ld) and lpFallBack (%p)\n",
2996 dwFlag, dwFlag, lpFallBack);
2998 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2999 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3002 /*****************************************************************************
3003 * MultiLanguage2::ConvertStringToUnicodeEx
3005 * Translates the multibyte string from the specified code page to Unicode.
3007 * PARAMS
3008 * see ConvertStringToUnicode
3009 * dwFlag
3010 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3011 * instead unconvertible characters.
3013 * RETURNS
3014 * S_OK Success.
3015 * S_FALSE The conversion is not supported.
3016 * E_FAIL Some error has occurred.
3018 * TODO: handle dwFlag and lpFallBack
3020 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3021 IMultiLanguage3* This,
3022 DWORD* pdwMode,
3023 DWORD dwEncoding,
3024 WCHAR* pSrcStr,
3025 UINT* pcSrcSize,
3026 CHAR* pDstStr,
3027 UINT* pcDstSize,
3028 DWORD dwFlag,
3029 WCHAR* lpFallBack)
3031 FIXME("\n");
3032 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3033 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3036 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3037 IMultiLanguage3* iface,
3038 DWORD dwFlag,
3039 DWORD dwPrefWinCodePage,
3040 IStream* pstmIn,
3041 DetectEncodingInfo* lpEncoding,
3042 INT* pnScores)
3044 FIXME("\n");
3045 return E_NOTIMPL;
3048 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3049 IMultiLanguage3* iface,
3050 DWORD dwFlag,
3051 DWORD dwPrefWinCodePage,
3052 CHAR* pSrcStr,
3053 INT* pcSrcSize,
3054 DetectEncodingInfo* lpEncoding,
3055 INT* pnScores)
3057 FIXME("\n");
3058 return E_NOTIMPL;
3061 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3062 IMultiLanguage3* iface,
3063 UINT uiCodePage,
3064 HWND hwnd)
3066 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3069 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3070 IMultiLanguage3* iface,
3071 UINT uiCodePage,
3072 LCID lcid,
3073 LPWSTR lpWideCharStr,
3074 int cchWideChar)
3076 /* Find first instance */
3077 unsigned int i,n;
3079 TRACE ("%u, %04lx, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3080 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3082 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3084 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3086 lstrcpynW( lpWideCharStr, mlang_data[i].mime_cp_info[n].description, cchWideChar);
3087 return S_OK;
3092 return S_FALSE;
3095 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3096 IMultiLanguage3* iface,
3097 UINT uiCodePage)
3099 TRACE("%u\n", uiCodePage);
3101 /* FIXME: the installable set is usually larger than the set of valid codepages */
3102 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3105 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3106 IMultiLanguage3* iface,
3107 MIMECONTF dwSource)
3109 FIXME("0x%08x\n", dwSource);
3110 return S_OK;
3113 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3114 IMultiLanguage3* iface,
3115 UINT* pnScripts)
3117 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3119 TRACE("%p %p\n", This, pnScripts);
3121 if (!pnScripts) return S_FALSE;
3123 *pnScripts = This->total_scripts;
3124 return S_OK;
3127 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3128 IMultiLanguage3* iface,
3129 DWORD dwFlags,
3130 LANGID LangId,
3131 IEnumScript** ppEnumScript)
3133 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3135 TRACE("%p %08lx %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3137 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3140 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3141 IMultiLanguage3* iface,
3142 UINT uiCodePage,
3143 HWND hwnd,
3144 DWORD dwfIODControl)
3146 unsigned int i;
3147 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3149 TRACE("%p %u %p %08lx\n", This, uiCodePage, hwnd, dwfIODControl);
3151 /* quick check for kernel32 supported code pages */
3152 if (IsValidCodePage(uiCodePage))
3153 return S_OK;
3155 /* check for mlang supported code pages */
3156 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3158 UINT n;
3159 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3161 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3162 return S_OK;
3166 if (dwfIODControl != CPIOD_PEEK)
3167 FIXME("Request to install codepage language pack not handled\n");
3169 return S_FALSE;
3172 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3173 IMultiLanguage3 *iface,
3174 DWORD dwFlags,
3175 LPCWSTR lpWideCharStr,
3176 UINT cchWideChar,
3177 UINT *puiPreferredCodePages,
3178 UINT nPreferredCodePages,
3179 UINT *puiDetectedCodePages,
3180 UINT *pnDetectedCodePages,
3181 WCHAR *lpSpecialChar)
3183 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3185 FIXME("(%p)->(%08lx %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3186 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3187 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3188 debugstr_w(lpSpecialChar));
3190 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3191 return E_INVALIDARG;
3193 puiDetectedCodePages[0] = CP_UTF8;
3194 *pnDetectedCodePages = 1;
3195 return S_OK;
3198 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3199 IMultiLanguage3 *iface,
3200 DWORD dwFlags,
3201 IStream *pStrIn,
3202 UINT *puiPreferredCodePages,
3203 UINT nPreferredCodePages,
3204 UINT *puiDetectedCodePages,
3205 UINT *pnDetectedCodePages,
3206 WCHAR *lpSpecialChar)
3208 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3210 FIXME("(%p)->(%08lx %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3211 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3212 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3213 debugstr_w(lpSpecialChar));
3215 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3216 return E_INVALIDARG;
3218 puiDetectedCodePages[0] = CP_UTF8;
3219 *pnDetectedCodePages = 1;
3220 return S_OK;
3223 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3225 fnIMultiLanguage3_QueryInterface,
3226 fnIMultiLanguage3_AddRef,
3227 fnIMultiLanguage3_Release,
3228 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3229 fnIMultiLanguage3_GetCodePageInfo,
3230 fnIMultiLanguage3_GetFamilyCodePage,
3231 fnIMultiLanguage3_EnumCodePages,
3232 fnIMultiLanguage3_GetCharsetInfo,
3233 fnIMultiLanguage3_IsConvertible,
3234 fnIMultiLanguage3_ConvertString,
3235 fnIMultiLanguage3_ConvertStringToUnicode,
3236 fnIMultiLanguage3_ConvertStringFromUnicode,
3237 fnIMultiLanguage3_ConvertStringReset,
3238 fnIMultiLanguage3_GetRfc1766FromLcid,
3239 fnIMultiLanguage3_GetLcidFromRfc1766,
3240 fnIMultiLanguage3_EnumRfc1766,
3241 fnIMultiLanguage3_GetRfc1766Info,
3242 fnIMultiLanguage3_CreateConvertCharset,
3243 fnIMultiLanguage3_ConvertStringInIStream,
3244 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3245 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3246 fnIMultiLanguage3_DetectCodepageInIStream,
3247 fnIMultiLanguage3_DetectInputCodepage,
3248 fnIMultiLanguage3_ValidateCodePage,
3249 fnIMultiLanguage3_GetCodePageDescription,
3250 fnIMultiLanguage3_IsCodePageInstallable,
3251 fnIMultiLanguage3_SetMimeDBSource,
3252 fnIMultiLanguage3_GetNumberOfScripts,
3253 fnIMultiLanguage3_EnumScripts,
3254 fnIMultiLanguage3_ValidateCodePageEx,
3255 fnIMultiLanguage3_DetectOutboundCodePage,
3256 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3259 /******************************************************************************/
3261 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3263 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3266 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3267 IMLangFontLink2 * iface,
3268 REFIID riid,
3269 void** ppvObject)
3271 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3272 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3275 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3277 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3278 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3281 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3283 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3284 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3287 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3288 WCHAR ch_src, DWORD *ret_codepages)
3290 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3291 unsigned int i;
3293 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3295 *ret_codepages = 0;
3297 for (i = 0; i < ARRAY_SIZE(mlang_data) - 1 /* skip unicode codepages */; i++)
3299 BOOL used_dc;
3300 CHAR buf;
3302 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3303 &ch_src, 1, &buf, 1, NULL, &used_dc);
3305 /* If default char is not used, current codepage include the given symbol */
3306 if (!used_dc)
3308 DWORD codepages;
3310 IMLangFontLink2_CodePageToCodePages(iface,
3311 mlang_data[i].family_codepage, &codepages);
3312 *ret_codepages |= codepages;
3315 return S_OK;
3318 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3319 const WCHAR *src, LONG src_len, DWORD priority_cp,
3320 DWORD *codepages, LONG *ret_len)
3322 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3323 LONG i;
3324 DWORD cps = 0;
3326 TRACE("(%p)->(%s:%ld %lx %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3327 codepages, ret_len);
3329 if (codepages) *codepages = 0;
3330 if (ret_len) *ret_len = 0;
3332 if (!src || !src_len || src_len < 0)
3333 return E_INVALIDARG;
3335 for (i = 0; i < src_len; i++)
3337 DWORD cp;
3338 HRESULT ret;
3340 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3341 if (ret != S_OK) return E_FAIL;
3343 if (!cps) cps = cp;
3344 else cps &= cp;
3346 /* FIXME: not tested */
3347 if (priority_cp & cps) break;
3350 if (codepages) *codepages = cps;
3351 if (ret_len) *ret_len = min( i + 1, src_len );
3352 return S_OK;
3355 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3356 UINT codepage,
3357 DWORD *codepages)
3359 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3360 CHARSETINFO cs;
3361 BOOL rc;
3363 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3365 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3366 if (rc)
3368 *codepages = cs.fs.fsCsb[0];
3369 TRACE("resulting codepages 0x%lx\n", *codepages);
3370 return S_OK;
3373 TRACE("codepage not found\n");
3374 *codepages = 0;
3375 return E_FAIL;
3378 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3379 DWORD codepages, UINT def_codepage, UINT *codepage)
3381 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3382 DWORD mask = 0;
3383 CHARSETINFO cs;
3384 BOOL rc;
3385 UINT i;
3387 TRACE("(%p)->(0x%lx %u %p)\n", This, codepages, def_codepage, codepage);
3389 *codepage = 0;
3391 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3392 if (rc && (codepages & cs.fs.fsCsb[0]))
3394 TRACE("Found Default Codepage\n");
3395 *codepage = def_codepage;
3396 return S_OK;
3399 for (i = 0; i < 32; i++)
3401 mask = 1 << i;
3402 if (codepages & mask)
3404 DWORD Csb[2];
3405 Csb[0] = mask;
3406 Csb[1] = 0x0;
3407 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3408 if (!rc)
3409 continue;
3411 TRACE("Falling back to least significant found CodePage %u\n",
3412 cs.ciACP);
3413 *codepage = cs.ciACP;
3414 return S_OK;
3418 TRACE("no codepage found\n");
3419 return E_FAIL;
3422 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3423 HDC hdc, HFONT hfont, DWORD *codepages)
3425 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3426 FONTSIGNATURE fontsig;
3427 HFONT old_font;
3429 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3431 old_font = SelectObject(hdc, hfont);
3432 GetTextCharsetInfo(hdc, &fontsig, 0);
3433 SelectObject(hdc, old_font);
3435 *codepages = fontsig.fsCsb[0];
3436 TRACE("ret 0x%lx\n", fontsig.fsCsb[0]);
3438 return S_OK;
3441 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3442 HFONT hFont)
3444 TRACE("(%p)->%p\n",This, hFont);
3446 return release_font(hFont);
3449 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3451 TRACE("(%p)\n",This);
3453 return clear_font_cache();
3456 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3457 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3459 HFONT old_font;
3461 TRACE("(%p)->%p %08lx %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
3463 if (!hDC) return E_FAIL;
3465 if (dwCodePages != 0)
3467 old_font = GetCurrentObject(hDC, OBJ_FONT);
3468 return map_font(hDC, dwCodePages, old_font, pFont);
3470 else
3472 if (pFont == NULL) return E_INVALIDARG;
3473 FIXME("the situation where dwCodepages is set to zero is not implemented\n");
3474 return E_FAIL;
3478 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3479 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3481 DWORD size;
3482 GLYPHSET *gs;
3484 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3486 if (!puiRanges) return E_INVALIDARG;
3487 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3488 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3490 GetFontUnicodeRanges(hDC, gs);
3491 *puiRanges = gs->cRanges;
3492 if (pUranges)
3494 UINT i;
3495 for (i = 0; i < gs->cRanges; i++)
3497 if (i >= *puiRanges) break;
3498 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3499 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3501 *puiRanges = i;
3503 HeapFree(GetProcessHeap(), 0, gs);
3504 return S_OK;
3507 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3508 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3509 SCRIPTFONTINFO *pScriptFont)
3511 UINT i, j;
3513 TRACE("(%p)->%u %lx %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3515 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3517 for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3519 if (sid == mlang_data[i].sid)
3521 if (pScriptFont)
3523 if (j >= *puiFonts) break;
3525 pScriptFont[j].scripts = (SCRIPT_IDS)1 << mlang_data[i].sid;
3526 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3527 wcscpy( pScriptFont[j].wszFont, mlang_data[i].fixed_font );
3528 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3529 wcscpy( pScriptFont[j].wszFont, mlang_data[i].proportional_font );
3531 j++;
3534 *puiFonts = j;
3535 return S_OK;
3538 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3539 UINT uiCodePage, SCRIPT_ID *pSid)
3541 UINT i;
3543 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3545 if (uiCodePage == CP_UNICODE) return E_FAIL;
3547 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3549 if (uiCodePage == mlang_data[i].family_codepage)
3551 if (pSid) *pSid = mlang_data[i].sid;
3552 return S_OK;
3555 return E_FAIL;
3558 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3560 fnIMLangFontLink2_QueryInterface,
3561 fnIMLangFontLink2_AddRef,
3562 fnIMLangFontLink2_Release,
3563 fnIMLangFontLink2_GetCharCodePages,
3564 fnIMLangFontLink2_GetStrCodePages,
3565 fnIMLangFontLink2_CodePageToCodePages,
3566 fnIMLangFontLink2_CodePagesToCodePage,
3567 fnIMLangFontLink2_GetFontCodePages,
3568 fnIMLangFontLink2_ReleaseFont,
3569 fnIMLangFontLink2_ResetFontMapping,
3570 fnIMLangFontLink2_MapFont,
3571 fnIMLangFontLink2_GetFontUnicodeRanges,
3572 fnIMLangFontLink2_GetScriptFontInfo,
3573 fnIMLangFontLink2_CodePageToScriptID
3576 /******************************************************************************/
3578 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3580 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3583 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3584 IMLangLineBreakConsole* iface,
3585 REFIID riid,
3586 void** ppvObject)
3588 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3589 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3592 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3593 IMLangLineBreakConsole* iface )
3595 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3596 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3599 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3600 IMLangLineBreakConsole* iface )
3602 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3603 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3606 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3607 IMLangLineBreakConsole* iface,
3608 IMLangString* pSrcMLStr,
3609 LONG lSrcPos,
3610 LONG lSrcLen,
3611 LONG cMinColumns,
3612 LONG cMaxColumns,
3613 LONG* plLineLen,
3614 LONG* plSkipLen)
3616 FIXME("(%p)->%p %li %li %li %li %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3617 return E_NOTIMPL;
3620 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3621 IMLangLineBreakConsole* iface,
3622 LCID locale,
3623 const WCHAR* pszSrc,
3624 LONG cchSrc,
3625 LONG cMaxColumns,
3626 LONG* pcchLine,
3627 LONG* pcchSkip )
3629 FIXME("(%p)->%li %s %li %li %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3631 *pcchLine = cchSrc;
3632 *pcchSkip = 0;
3633 return S_OK;
3636 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3637 IMLangLineBreakConsole* iface,
3638 LCID locale,
3639 UINT uCodePage,
3640 const CHAR* pszSrc,
3641 LONG cchSrc,
3642 LONG cMaxColumns,
3643 LONG* pcchLine,
3644 LONG* pcchSkip)
3646 LONG i, line = cchSrc, skip = 0;
3648 FIXME("(%p)->%li %i %s %li %li %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3650 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3652 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3654 if (pszSrc[i] == ' ')
3656 while (i >= 0 && pszSrc[i] == ' ')
3658 i--;
3659 line--;
3660 skip++;
3662 break;
3666 *pcchLine = line;
3667 *pcchSkip = skip;
3668 return S_OK;
3671 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3673 fnIMLangLineBreakConsole_QueryInterface,
3674 fnIMLangLineBreakConsole_AddRef,
3675 fnIMLangLineBreakConsole_Release,
3676 fnIMLangLineBreakConsole_BreakLineML,
3677 fnIMLangLineBreakConsole_BreakLineW,
3678 fnIMLangLineBreakConsole_BreakLineA
3681 struct convert_charset {
3682 IMLangConvertCharset IMLangConvertCharset_iface;
3683 LONG ref;
3685 UINT src_cp;
3686 UINT dst_cp;
3689 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3691 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3694 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3696 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3698 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3700 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3702 *obj = &This->IMLangConvertCharset_iface;
3703 IMLangConvertCharset_AddRef(iface);
3704 return S_OK;
3707 *obj = NULL;
3708 return E_NOINTERFACE;
3711 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3713 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3714 ULONG ref = InterlockedIncrement(&This->ref);
3715 TRACE("(%p)->(%lu)\n", This, ref);
3716 return ref;
3719 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3721 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3722 ULONG ref = InterlockedDecrement(&This->ref);
3724 TRACE("(%p)->(%lu)\n", This, ref);
3725 if (!ref)
3727 HeapFree(GetProcessHeap(), 0, This);
3728 UnlockModule();
3731 return ref;
3734 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3735 UINT src_cp, UINT dst_cp, DWORD prop)
3737 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3739 TRACE("(%p)->(%u %u 0x%08lx)\n", This, src_cp, dst_cp, prop);
3741 prop &= ~MLCONVCHARF_USEDEFCHAR;
3742 if (prop)
3743 FIXME("property 0x%08lx not supported\n", prop);
3745 This->src_cp = src_cp;
3746 This->dst_cp = dst_cp;
3748 return S_OK;
3751 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3753 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3755 TRACE("(%p)->(%p)\n", This, src_cp);
3757 if (!src_cp) return E_INVALIDARG;
3758 *src_cp = This->src_cp;
3759 return S_OK;
3762 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3764 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3766 TRACE("(%p)->(%p)\n", This, dst_cp);
3768 if (!dst_cp) return E_INVALIDARG;
3769 *dst_cp = This->dst_cp;
3770 return S_OK;
3773 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3775 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3776 FIXME("(%p)->(%p): stub\n", This, prop);
3777 return E_NOTIMPL;
3780 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3781 UINT *src_size, BYTE *dest, UINT *dest_size)
3783 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3784 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3785 return E_NOTIMPL;
3788 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3789 UINT *src_size, WCHAR *dest, UINT *dest_size)
3791 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3792 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3793 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3796 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3797 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3799 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3800 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3801 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3804 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3806 MLangConvertCharset_QueryInterface,
3807 MLangConvertCharset_AddRef,
3808 MLangConvertCharset_Release,
3809 MLangConvertCharset_Initialize,
3810 MLangConvertCharset_GetSourceCodePage,
3811 MLangConvertCharset_GetDestinationCodePage,
3812 MLangConvertCharset_GetProperty,
3813 MLangConvertCharset_DoConversion,
3814 MLangConvertCharset_DoConversionToUnicode,
3815 MLangConvertCharset_DoConversionFromUnicode
3818 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3820 MLang_impl *mlang;
3821 UINT i;
3823 TRACE("Creating MultiLanguage object\n");
3825 if( pUnkOuter )
3826 return CLASS_E_NOAGGREGATION;
3828 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3829 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3830 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3831 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3832 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3833 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3835 mlang->total_cp = 0;
3836 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3837 mlang->total_cp += mlang_data[i].number_of_cp;
3839 /* do not enumerate unicode flavours */
3840 mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3842 mlang->ref = 1;
3843 *ppObj = &mlang->IMultiLanguage_iface;
3844 TRACE("returning %p\n", mlang);
3846 LockModule();
3848 return S_OK;
3851 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3853 struct convert_charset *convert;
3855 if (outer)
3856 return CLASS_E_NOAGGREGATION;
3858 *obj = NULL;
3860 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3861 if (!convert) return E_OUTOFMEMORY;
3863 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3864 convert->ref = 1;
3866 *obj = &convert->IMLangConvertCharset_iface;
3868 LockModule();
3870 return S_OK;
3873 /******************************************************************************/
3875 HRESULT WINAPI DllCanUnloadNow(void)
3877 return dll_count == 0 ? S_OK : S_FALSE;
3880 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3882 if (!unknown) return E_INVALIDARG;
3884 FIXME("%p: stub\n", unknown);
3886 return S_FALSE;