3 * FILE: dll/cpl/input/input_list.c
5 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
6 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
9 #include "input_list.h"
17 #include "../../../base/setup/usetup/muifonts.h"
19 BOOL
UpdateRegistryForFontSubstitutes(MUI_SUBFONT
*pSubstitutes
)
23 static const WCHAR pszKey
[] =
24 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
27 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, pszKey
, 0, KEY_ALL_ACCESS
, &hKey
);
32 for (; pSubstitutes
->FontName
; ++pSubstitutes
)
34 cbData
= (lstrlenW(pSubstitutes
->SubFontName
) + 1) * sizeof(WCHAR
);
35 RegSetValueExW(hKey
, pSubstitutes
->FontName
, 0,
36 REG_SZ
, (LPBYTE
)pSubstitutes
->SubFontName
, cbData
);
45 InputList_SetFontSubstitutes(LCID dwLocaleId
)
47 MUI_SUBFONT
*pSubstitutes
;
48 WORD wLangID
, wPrimaryLangID
, wSubLangID
;
50 wLangID
= LANGIDFROMLCID(dwLocaleId
);
51 wPrimaryLangID
= PRIMARYLANGID(wLangID
);
52 wSubLangID
= SUBLANGID(wLangID
);
54 /* FIXME: Add more if necessary */
55 switch (wPrimaryLangID
)
58 pSubstitutes
= LatinFonts
;
69 pSubstitutes
= CyrillicFonts
;
72 pSubstitutes
= GreekFonts
;
75 pSubstitutes
= HebrewFonts
;
80 case SUBLANG_CHINESE_SIMPLIFIED
:
81 case SUBLANG_CHINESE_SINGAPORE
:
82 case SUBLANG_CHINESE_MACAU
:
83 pSubstitutes
= ChineseSimplifiedFonts
;
85 case SUBLANG_CHINESE_TRADITIONAL
:
86 case SUBLANG_CHINESE_HONGKONG
:
87 pSubstitutes
= ChineseTraditionalFonts
;
96 pSubstitutes
= JapaneseFonts
;
99 pSubstitutes
= KoreanFonts
;
116 case LANG_VIETNAMESE
:
117 pSubstitutes
= UnicodeFonts
;
123 UpdateRegistryForFontSubstitutes(pSubstitutes
);
129 static INPUT_LIST_NODE
*_InputList
= NULL
;
132 static INPUT_LIST_NODE
*
133 InputList_AppendNode(VOID
)
135 INPUT_LIST_NODE
*pCurrent
;
136 INPUT_LIST_NODE
*pNew
;
138 pCurrent
= _InputList
;
140 pNew
= (INPUT_LIST_NODE
*)malloc(sizeof(INPUT_LIST_NODE
));
144 ZeroMemory(pNew
, sizeof(INPUT_LIST_NODE
));
146 if (pCurrent
== NULL
)
152 while (pCurrent
->pNext
!= NULL
)
154 pCurrent
= pCurrent
->pNext
;
157 pNew
->pPrev
= pCurrent
;
158 pCurrent
->pNext
= pNew
;
166 InputList_RemoveNode(INPUT_LIST_NODE
*pNode
)
168 INPUT_LIST_NODE
*pCurrent
= pNode
;
170 if (_InputList
== NULL
)
173 if (pCurrent
!= NULL
)
175 INPUT_LIST_NODE
*pNext
= pCurrent
->pNext
;
176 INPUT_LIST_NODE
*pPrev
= pCurrent
->pPrev
;
178 free(pCurrent
->pszIndicator
);
182 pNext
->pPrev
= pPrev
;
185 pPrev
->pNext
= pNext
;
193 InputList_Destroy(VOID
)
195 INPUT_LIST_NODE
*pCurrent
;
197 if (_InputList
== NULL
)
200 pCurrent
= _InputList
;
202 while (pCurrent
!= NULL
)
204 INPUT_LIST_NODE
*pNext
= pCurrent
->pNext
;
206 free(pCurrent
->pszIndicator
);
217 InputList_PrepareUserRegistry(VOID
)
219 BOOL bResult
= FALSE
;
220 HKEY hTempKey
= NULL
;
223 if (RegOpenKeyExW(HKEY_CURRENT_USER
,
227 &hKey
) == ERROR_SUCCESS
)
229 RegDeleteKeyW(hKey
, L
"Preload");
230 RegDeleteKeyW(hKey
, L
"Substitutes");
235 if (RegCreateKeyW(HKEY_CURRENT_USER
, L
"Keyboard Layout", &hKey
) != ERROR_SUCCESS
)
240 if (RegCreateKeyW(hKey
, L
"Preload", &hTempKey
) != ERROR_SUCCESS
)
245 RegCloseKey(hTempKey
);
247 if (RegCreateKeyW(hKey
, L
"Substitutes", &hTempKey
) != ERROR_SUCCESS
)
252 RegCloseKey(hTempKey
);
257 if (hTempKey
!= NULL
)
258 RegCloseKey(hTempKey
);
267 InputList_AddInputMethodToUserRegistry(DWORD dwIndex
, INPUT_LIST_NODE
*pNode
)
269 WCHAR szMethodIndex
[MAX_PATH
];
270 WCHAR szPreload
[MAX_PATH
];
271 BOOL bIsImeMethod
= FALSE
;
274 StringCchPrintfW(szMethodIndex
, ARRAYSIZE(szMethodIndex
), L
"%lu", dwIndex
);
276 /* Check is IME method */
277 if ((HIWORD(pNode
->pLayout
->dwId
) & 0xF000) == 0xE000)
279 StringCchPrintfW(szPreload
, ARRAYSIZE(szPreload
), L
"%08X", pNode
->pLayout
->dwId
);
284 StringCchPrintfW(szPreload
, ARRAYSIZE(szPreload
), L
"%08X", pNode
->pLocale
->dwId
);
287 if (RegOpenKeyExW(HKEY_CURRENT_USER
,
288 L
"Keyboard Layout\\Preload",
291 &hKey
) == ERROR_SUCCESS
)
298 (wcslen(szPreload
) + 1) * sizeof(WCHAR
));
303 if (pNode
->pLocale
->dwId
!= pNode
->pLayout
->dwId
&& bIsImeMethod
== FALSE
)
305 if (RegOpenKeyExW(HKEY_CURRENT_USER
,
306 L
"Keyboard Layout\\Substitutes",
309 &hKey
) == ERROR_SUCCESS
)
311 WCHAR szSubstitutes
[MAX_PATH
];
313 StringCchPrintfW(szSubstitutes
, ARRAYSIZE(szSubstitutes
), L
"%08X", pNode
->pLayout
->dwId
);
319 (LPBYTE
)szSubstitutes
,
320 (wcslen(szSubstitutes
) + 1) * sizeof(WCHAR
));
326 if ((pNode
->wFlags
& INPUT_LIST_NODE_FLAG_ADDED
) ||
327 (pNode
->wFlags
& INPUT_LIST_NODE_FLAG_EDITED
))
329 pNode
->hkl
= LoadKeyboardLayoutW(szPreload
, KLF_SUBSTITUTE_OK
| KLF_NOTELLSHELL
);
335 * Writes any changes in input methods to the registry
338 InputList_Process(VOID
)
340 INPUT_LIST_NODE
*pCurrent
;
344 /* Process deleted and edited input methods */
345 for (pCurrent
= _InputList
; pCurrent
!= NULL
; pCurrent
= pCurrent
->pNext
)
347 if ((pCurrent
->wFlags
& INPUT_LIST_NODE_FLAG_DELETED
) ||
348 (pCurrent
->wFlags
& INPUT_LIST_NODE_FLAG_EDITED
))
350 if (UnloadKeyboardLayout(pCurrent
->hkl
))
352 /* Only unload the edited input method, but does not delete it from the list */
353 if (!(pCurrent
->wFlags
& INPUT_LIST_NODE_FLAG_EDITED
))
355 InputList_RemoveNode(pCurrent
);
361 InputList_PrepareUserRegistry();
363 /* Find default input method */
364 for (pCurrent
= _InputList
; pCurrent
!= NULL
; pCurrent
= pCurrent
->pNext
)
366 if (pCurrent
->wFlags
& INPUT_LIST_NODE_FLAG_DEFAULT
)
368 bRet
= InputList_SetFontSubstitutes(pCurrent
->pLocale
->dwId
);
369 InputList_AddInputMethodToUserRegistry(1, pCurrent
);
374 if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG
,
376 (LPVOID
)((LPDWORD
)&pCurrent
->hkl
),
381 dwRecipients
= BSM_ALLCOMPONENTS
;
383 BroadcastSystemMessageW(BSF_POSTMESSAGE
,
385 WM_INPUTLANGCHANGEREQUEST
,
387 (LPARAM
)pCurrent
->hkl
);
390 /* Add methods to registry */
393 for (pCurrent
= _InputList
; pCurrent
!= NULL
; pCurrent
= pCurrent
->pNext
)
395 if (pCurrent
->wFlags
& INPUT_LIST_NODE_FLAG_DEFAULT
)
398 InputList_AddInputMethodToUserRegistry(dwIndex
, pCurrent
);
408 InputList_Add(LOCALE_LIST_NODE
*pLocale
, LAYOUT_LIST_NODE
*pLayout
)
410 WCHAR szIndicator
[MAX_STR_LEN
];
411 INPUT_LIST_NODE
*pInput
;
413 if (pLocale
== NULL
|| pLayout
== NULL
)
418 for (pInput
= _InputList
; pInput
!= NULL
; pInput
= pInput
->pNext
)
420 if (pInput
->pLocale
== pLocale
&& pInput
->pLayout
== pLayout
)
426 pInput
= InputList_AppendNode();
428 pInput
->wFlags
= INPUT_LIST_NODE_FLAG_ADDED
;
430 pInput
->pLocale
= pLocale
;
431 pInput
->pLayout
= pLayout
;
433 if (GetLocaleInfoW(LOWORD(pInput
->pLocale
->dwId
),
434 LOCALE_SABBREVLANGNAME
| LOCALE_NOUSEROVERRIDE
,
436 ARRAYSIZE(szIndicator
)))
438 size_t len
= wcslen(szIndicator
);
442 szIndicator
[len
- 1] = 0;
443 pInput
->pszIndicator
= _wcsdup(szIndicator
);
452 InputList_SetDefault(INPUT_LIST_NODE
*pNode
)
454 INPUT_LIST_NODE
*pCurrent
;
459 for (pCurrent
= _InputList
; pCurrent
!= NULL
; pCurrent
= pCurrent
->pNext
)
461 if (pCurrent
== pNode
)
463 pCurrent
->wFlags
|= INPUT_LIST_NODE_FLAG_DEFAULT
;
467 pCurrent
->wFlags
&= ~INPUT_LIST_NODE_FLAG_DEFAULT
;
474 * It marks the input method for deletion, but does not delete it directly.
475 * To apply the changes using InputList_Process()
478 InputList_Remove(INPUT_LIST_NODE
*pNode
)
480 BOOL bRemoveNode
= FALSE
;
485 if (pNode
->wFlags
& INPUT_LIST_NODE_FLAG_ADDED
)
488 * If the input method has been added to the list, but not yet written
489 * in the registry, then simply remove it from the list
495 pNode
->wFlags
= INPUT_LIST_NODE_FLAG_DELETED
;
498 if (pNode
->wFlags
& INPUT_LIST_NODE_FLAG_DEFAULT
)
500 if (pNode
->pNext
!= NULL
)
502 pNode
->pNext
->wFlags
|= INPUT_LIST_NODE_FLAG_DEFAULT
;
504 else if (pNode
->pPrev
!= NULL
)
506 pNode
->pPrev
->wFlags
|= INPUT_LIST_NODE_FLAG_DEFAULT
;
510 if (bRemoveNode
!= FALSE
)
512 InputList_RemoveNode(pNode
);
518 InputList_Create(VOID
)
523 iLayoutCount
= GetKeyboardLayoutList(0, NULL
);
524 pLayoutList
= (HKL
*) malloc(iLayoutCount
* sizeof(HKL
));
526 if (pLayoutList
!= NULL
)
528 if (GetKeyboardLayoutList(iLayoutCount
, pLayoutList
) > 0)
532 for (iIndex
= 0; iIndex
< iLayoutCount
; iIndex
++)
534 LOCALE_LIST_NODE
*pLocale
= LocaleList_GetByHkl(pLayoutList
[iIndex
]);
535 LAYOUT_LIST_NODE
*pLayout
= LayoutList_GetByHkl(pLayoutList
[iIndex
]);
537 if (pLocale
!= NULL
&& pLayout
!= NULL
)
539 WCHAR szIndicator
[MAX_STR_LEN
] = { 0 };
540 INPUT_LIST_NODE
*pInput
;
543 pInput
= InputList_AppendNode();
545 pInput
->pLocale
= pLocale
;
546 pInput
->pLayout
= pLayout
;
547 pInput
->hkl
= pLayoutList
[iIndex
];
549 if (SystemParametersInfoW(SPI_GETDEFAULTINPUTLANG
,
551 (LPVOID
)((LPDWORD
)&hklDefault
),
554 hklDefault
= GetKeyboardLayout(0);
557 if (pInput
->hkl
== hklDefault
)
559 pInput
->wFlags
|= INPUT_LIST_NODE_FLAG_DEFAULT
;
562 if (GetLocaleInfoW(LOWORD(pInput
->pLocale
->dwId
),
563 LOCALE_SABBREVLANGNAME
| LOCALE_NOUSEROVERRIDE
,
565 ARRAYSIZE(szIndicator
)))
567 size_t len
= wcslen(szIndicator
);
571 szIndicator
[len
- 1] = 0;
572 pInput
->pszIndicator
= _wcsdup(szIndicator
);
585 InputList_GetFirst(VOID
)