:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / ntuser / keyboard.c
1 /* $Id$
2  *
3  * COPYRIGHT:        See COPYING in the top level directory
4  * PROJECT:          ReactOS kernel
5  * PURPOSE:          Messages
6  * FILE:             subsys/win32k/ntuser/message.c
7  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
8  * REVISION HISTORY:
9  *       06-06-2001  CSH  Created
10  */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <win32k/win32k.h>
16 #include <include/guicheck.h>
17 #include <include/msgqueue.h>
18 #include <include/window.h>
19 #include <include/class.h>
20 #include <include/error.h>
21 #include <include/object.h>
22 #include <include/winsta.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 /* FUNCTIONS *****************************************************************/
28
29 BYTE QueueKeyStateTable[256];
30
31 struct accent_char
32 {
33     BYTE ac_accent;
34     BYTE ac_char;
35     BYTE ac_result;
36 };
37
38 static const struct accent_char accent_chars[] =
39 {
40 /* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */
41     {'`', 'A', '\300'},  {'`', 'a', '\340'},
42     {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
43     {'^', 'A', '\302'},  {'^', 'a', '\342'},
44     {'~', 'A', '\303'},  {'~', 'a', '\343'},
45     {'"', 'A', '\304'},  {'"', 'a', '\344'},
46     {'O', 'A', '\305'},  {'o', 'a', '\345'},
47     {'0', 'A', '\305'},  {'0', 'a', '\345'},
48     {'A', 'A', '\305'},  {'a', 'a', '\345'},
49     {'A', 'E', '\306'},  {'a', 'e', '\346'},
50     {',', 'C', '\307'},  {',', 'c', '\347'},
51     {'`', 'E', '\310'},  {'`', 'e', '\350'},
52     {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
53     {'^', 'E', '\312'},  {'^', 'e', '\352'},
54     {'"', 'E', '\313'},  {'"', 'e', '\353'},
55     {'`', 'I', '\314'},  {'`', 'i', '\354'},
56     {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
57     {'^', 'I', '\316'},  {'^', 'i', '\356'},
58     {'"', 'I', '\317'},  {'"', 'i', '\357'},
59     {'-', 'D', '\320'},  {'-', 'd', '\360'},
60     {'~', 'N', '\321'},  {'~', 'n', '\361'},
61     {'`', 'O', '\322'},  {'`', 'o', '\362'},
62     {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
63     {'^', 'O', '\324'},  {'^', 'o', '\364'},
64     {'~', 'O', '\325'},  {'~', 'o', '\365'},
65     {'"', 'O', '\326'},  {'"', 'o', '\366'},
66     {'/', 'O', '\330'},  {'/', 'o', '\370'},
67     {'`', 'U', '\331'},  {'`', 'u', '\371'},
68     {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
69     {'^', 'U', '\333'},  {'^', 'u', '\373'},
70     {'"', 'U', '\334'},  {'"', 'u', '\374'},
71     {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
72     {'T', 'H', '\336'},  {'t', 'h', '\376'},
73     {'s', 's', '\337'},  {'"', 'y', '\377'},
74     {'s', 'z', '\337'},  {'i', 'j', '\377'},
75         /* iso-8859-2 uses this */
76     {'<', 'L', '\245'},  {'<', 'l', '\265'},    /* caron */
77     {'<', 'S', '\251'},  {'<', 's', '\271'},
78     {'<', 'T', '\253'},  {'<', 't', '\273'},
79     {'<', 'Z', '\256'},  {'<', 'z', '\276'},
80     {'<', 'C', '\310'},  {'<', 'c', '\350'},
81     {'<', 'E', '\314'},  {'<', 'e', '\354'},
82     {'<', 'D', '\317'},  {'<', 'd', '\357'},
83     {'<', 'N', '\322'},  {'<', 'n', '\362'},
84     {'<', 'R', '\330'},  {'<', 'r', '\370'},
85     {';', 'A', '\241'},  {';', 'a', '\261'},    /* ogonek */
86     {';', 'E', '\312'},  {';', 'e', '\332'},
87     {'\'', 'Z', '\254'}, {'\'', 'z', '\274'},   /* acute */
88     {'\'', 'R', '\300'}, {'\'', 'r', '\340'},
89     {'\'', 'L', '\305'}, {'\'', 'l', '\345'},
90     {'\'', 'C', '\306'}, {'\'', 'c', '\346'},
91     {'\'', 'N', '\321'}, {'\'', 'n', '\361'},
92 /*  collision whith S, from iso-8859-9 !!! */
93     {',', 'S', '\252'},  {',', 's', '\272'},    /* cedilla */
94     {',', 'T', '\336'},  {',', 't', '\376'},
95     {'.', 'Z', '\257'},  {'.', 'z', '\277'},    /* dot above */
96     {'/', 'L', '\243'},  {'/', 'l', '\263'},    /* slash */
97     {'/', 'D', '\320'},  {'/', 'd', '\360'},
98     {'(', 'A', '\303'},  {'(', 'a', '\343'},    /* breve */
99     {'\275', 'O', '\325'}, {'\275', 'o', '\365'},       /* double acute */
100     {'\275', 'U', '\334'}, {'\275', 'u', '\374'},
101     {'0', 'U', '\332'},  {'0', 'u', '\372'},    /* ring above */
102         /* iso-8859-3 uses this */
103     {'/', 'H', '\241'},  {'/', 'h', '\261'},    /* slash */
104     {'>', 'H', '\246'},  {'>', 'h', '\266'},    /* circumflex */
105     {'>', 'J', '\254'},  {'>', 'j', '\274'},
106     {'>', 'C', '\306'},  {'>', 'c', '\346'},
107     {'>', 'G', '\330'},  {'>', 'g', '\370'},
108     {'>', 'S', '\336'},  {'>', 's', '\376'},
109 /*  collision whith G( from iso-8859-9 !!!   */
110     {'(', 'G', '\253'},  {'(', 'g', '\273'},    /* breve */
111     {'(', 'U', '\335'},  {'(', 'u', '\375'},
112 /*  collision whith I. from iso-8859-3 !!!   */
113     {'.', 'I', '\251'},  {'.', 'i', '\271'},    /* dot above */
114     {'.', 'C', '\305'},  {'.', 'c', '\345'},
115     {'.', 'G', '\325'},  {'.', 'g', '\365'},
116         /* iso-8859-4 uses this */
117     {',', 'R', '\243'},  {',', 'r', '\263'},    /* cedilla */
118     {',', 'L', '\246'},  {',', 'l', '\266'},
119     {',', 'G', '\253'},  {',', 'g', '\273'},
120     {',', 'N', '\321'},  {',', 'n', '\361'},
121     {',', 'K', '\323'},  {',', 'k', '\363'},
122     {'~', 'I', '\245'},  {'~', 'i', '\265'},    /* tilde */
123     {'-', 'E', '\252'},  {'-', 'e', '\272'},    /* macron */
124     {'-', 'A', '\300'},  {'-', 'a', '\340'},
125     {'-', 'I', '\317'},  {'-', 'i', '\357'},
126     {'-', 'O', '\322'},  {'-', 'o', '\362'},
127     {'-', 'U', '\336'},  {'-', 'u', '\376'},
128     {'/', 'T', '\254'},  {'/', 't', '\274'},    /* slash */
129     {'.', 'E', '\314'},  {'.', 'e', '\344'},    /* dot above */
130     {';', 'I', '\307'},  {';', 'i', '\347'},    /* ogonek */
131     {';', 'U', '\331'},  {';', 'u', '\371'},
132         /* iso-8859-9 uses this */
133         /* iso-8859-9 has really bad choosen G( S, and I. as they collide
134          * whith the same letters on other iso-8859-x (that is they are on
135          * different places :-( ), if you use turkish uncomment these and
136          * comment out the lines in iso-8859-2 and iso-8859-3 sections
137          * FIXME: should be dynamic according to chosen language
138          *        if/when Wine has turkish support.  
139          */ 
140 /*  collision whith G( from iso-8859-3 !!!   */
141 /*  {'(', 'G', '\320'},  {'(', 'g', '\360'}, */ /* breve */
142 /*  collision whith S, from iso-8859-2 !!! */
143 /*  {',', 'S', '\336'},  {',', 's', '\376'}, */ /* cedilla */
144 /*  collision whith I. from iso-8859-3 !!!   */
145 /*  {'.', 'I', '\335'},  {'.', 'i', '\375'}, */ /* dot above */
146 };
147
148 int STDCALL
149 ToUnicode(UINT wVirtKey,
150           UINT wScanCode,
151           PBYTE lpKeyState,
152           LPWSTR pwszBuff,
153           int cchBuff,
154           UINT wFlags)
155 {
156 }
157
158 BOOL STDCALL
159 NtUserTranslateMessage(LPMSG lpMsg,
160                        DWORD Unknown1)
161 {
162   LONG UState;
163   WCHAR wp[2];
164   MSG NewMsg;
165   static INT dead_char;
166   PUSER_MESSAGE UMsg;
167
168   if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
169     {
170       return(FALSE);
171     }
172
173   /* FIXME: Should pass current keyboard layout for this thread. */
174   UState = ToUnicode(lpMsg->wParam, HIWORD(lpMsg->lParam),
175                      QueueKeyStateTable, wp, 2, 0);
176   if (UState == 1)
177     {
178       NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
179       if (dead_char)
180         {
181           int i;
182           
183           if (wp[0] == ' ') wp[0] =  dead_char;
184           if (dead_char == 0xa2) dead_char = '(';
185           else if (dead_char == 0xa8) dead_char = '"';
186           else if (dead_char == 0xb2) dead_char = ';';
187           else if (dead_char == 0xb4) dead_char = '\'';
188           else if (dead_char == 0xb7) dead_char = '<';
189           else if (dead_char == 0xb8) dead_char = ',';
190           else if (dead_char == 0xff) dead_char = '.';
191           for (i = 0; i < sizeof(accent_chars)/sizeof(accent_chars[0]); i++)
192             {
193               if ((accent_chars[i].ac_accent == dead_char) &&
194                   (accent_chars[i].ac_char == wp[0]))
195                 {
196                   wp[0] = accent_chars[i].ac_result;
197                   break;
198                 }
199               dead_char = 0;
200             }
201           NewMsg.hwnd = lpMsg->hwnd;
202           NewMsg.wParam = wp[0];
203           NewMsg.lParam = lpMsg->lParam;
204           UMsg = MsqCreateMessage(&NewMsg);
205           MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
206           return(TRUE);
207         }
208     }
209   else if (UState == -1)
210     {
211       NewMsg.message = 
212         (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
213       NewMsg.hwnd = lpMsg->hwnd;
214       NewMsg.wParam = wp[0];
215       NewMsg.lParam = lpMsg->lParam;
216       dead_char = wp[0];
217       UMsg = MsqCreateMessage(&NewMsg);
218       MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
219       return(TRUE);
220     }
221   return(FALSE);
222 }