1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS Build Tools [Keyboard Layout Compiler]
3*c2c66affSColin Finck * LICENSE: BSD - See COPYING.BSD in the top level directory
4*c2c66affSColin Finck * FILE: tools/kbdtool/parser.c
5*c2c66affSColin Finck * PURPOSE: Parsing Logic
6*c2c66affSColin Finck * PROGRAMMERS: ReactOS Foundation
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include "kbdtool.h"
12*c2c66affSColin Finck
13*c2c66affSColin Finck /* GLOBALS ********************************************************************/
14*c2c66affSColin Finck
15*c2c66affSColin Finck /* Internal parser data about everything that was parsed */
16*c2c66affSColin Finck CHAR gBuf[256];
17*c2c66affSColin Finck CHAR gKBDName[10];
18*c2c66affSColin Finck CHAR gCopyright[256];
19*c2c66affSColin Finck CHAR gDescription[256];
20*c2c66affSColin Finck CHAR gCompany[256];
21*c2c66affSColin Finck CHAR gLocaleName[256];
22*c2c66affSColin Finck CHAR gVKeyName[32];
23*c2c66affSColin Finck ULONG gID = 0;
24*c2c66affSColin Finck ULONG gKbdLayoutVersion;
25*c2c66affSColin Finck LAYOUT g_Layout;
26*c2c66affSColin Finck ULONG gLineCount;
27*c2c66affSColin Finck
28*c2c66affSColin Finck /* Table of keywords the parser recognizes */
29*c2c66affSColin Finck PCHAR KeyWordList[KEYWORD_COUNT] =
30*c2c66affSColin Finck {
31*c2c66affSColin Finck "KBD",
32*c2c66affSColin Finck "VERSION",
33*c2c66affSColin Finck "COPYRIGHT",
34*c2c66affSColin Finck "COMPANY",
35*c2c66affSColin Finck "LOCALENAME",
36*c2c66affSColin Finck "MODIIFERS",
37*c2c66affSColin Finck "SHIFTSTATE",
38*c2c66affSColin Finck "ATTRIBUTES",
39*c2c66affSColin Finck "LAYOUT",
40*c2c66affSColin Finck "DEADKEY",
41*c2c66affSColin Finck "LIGATURE",
42*c2c66affSColin Finck "KEYNAME",
43*c2c66affSColin Finck "KEYNAME_EXT",
44*c2c66affSColin Finck "KEYNAME_DEAD",
45*c2c66affSColin Finck "DESCRIPTIONS",
46*c2c66affSColin Finck "LANGUAGENAMES",
47*c2c66affSColin Finck "ENDKBD",
48*c2c66affSColin Finck };
49*c2c66affSColin Finck
50*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
51*c2c66affSColin Finck
52*c2c66affSColin Finck ULONG
isKeyWord(PCHAR p)53*c2c66affSColin Finck isKeyWord(PCHAR p)
54*c2c66affSColin Finck {
55*c2c66affSColin Finck ULONG i;
56*c2c66affSColin Finck
57*c2c66affSColin Finck /* Check if we know this keyword */
58*c2c66affSColin Finck for (i = 0; i < KEYWORD_COUNT; i++) if (strcmp(KeyWordList[i], p) == 0) break;
59*c2c66affSColin Finck
60*c2c66affSColin Finck /* If we didn't find anything, i will be KEYWORD_COUNT, which is invalid */
61*c2c66affSColin Finck return i;
62*c2c66affSColin Finck }
63*c2c66affSColin Finck
64*c2c66affSColin Finck PCHAR
getVKName(IN ULONG VirtualKey,IN BOOLEAN Prefix)65*c2c66affSColin Finck getVKName(IN ULONG VirtualKey,
66*c2c66affSColin Finck IN BOOLEAN Prefix)
67*c2c66affSColin Finck {
68*c2c66affSColin Finck ULONG i;
69*c2c66affSColin Finck
70*c2c66affSColin Finck /* Loop for standard virtual key */
71*c2c66affSColin Finck if (((VirtualKey >= 'A') && (VirtualKey <= 'Z')) ||
72*c2c66affSColin Finck ((VirtualKey >= '0') && (VirtualKey <= '9')))
73*c2c66affSColin Finck {
74*c2c66affSColin Finck /* Fill out the name */
75*c2c66affSColin Finck gVKeyName[0] = '\'';
76*c2c66affSColin Finck gVKeyName[1] = VirtualKey;
77*c2c66affSColin Finck gVKeyName[2] = '\'';
78*c2c66affSColin Finck gVKeyName[3] = '\0';
79*c2c66affSColin Finck return gVKeyName;
80*c2c66affSColin Finck }
81*c2c66affSColin Finck
82*c2c66affSColin Finck /* Check if a prefix is required */
83*c2c66affSColin Finck if (Prefix)
84*c2c66affSColin Finck {
85*c2c66affSColin Finck /* Add it */
86*c2c66affSColin Finck strcpy(gVKeyName, "VK_");
87*c2c66affSColin Finck }
88*c2c66affSColin Finck else
89*c2c66affSColin Finck {
90*c2c66affSColin Finck /* Otherwise, don't add anything */
91*c2c66affSColin Finck strcpy(gVKeyName, "");
92*c2c66affSColin Finck }
93*c2c66affSColin Finck
94*c2c66affSColin Finck /* Loop all virtual keys */
95*c2c66affSColin Finck for (i = 0; i < 36; i++)
96*c2c66affSColin Finck {
97*c2c66affSColin Finck /* Check if this key matches */
98*c2c66affSColin Finck if (VKName[i].VirtualKey == VirtualKey)
99*c2c66affSColin Finck {
100*c2c66affSColin Finck /* Copy the key's name into the buffer */
101*c2c66affSColin Finck strcat(gVKeyName, VKName[i].Name);
102*c2c66affSColin Finck return gVKeyName;
103*c2c66affSColin Finck }
104*c2c66affSColin Finck }
105*c2c66affSColin Finck
106*c2c66affSColin Finck /* If we got here, then we failed, so print out an error name */
107*c2c66affSColin Finck strcpy(gVKeyName, "#ERROR#");
108*c2c66affSColin Finck return gVKeyName;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck
111*c2c66affSColin Finck ULONG
getVKNum(IN PCHAR p)112*c2c66affSColin Finck getVKNum(IN PCHAR p)
113*c2c66affSColin Finck {
114*c2c66affSColin Finck ULONG Length;
115*c2c66affSColin Finck ULONG i;
116*c2c66affSColin Finck ULONG KeyNumber;
117*c2c66affSColin Finck
118*c2c66affSColin Finck /* Compute the length of the string */
119*c2c66affSColin Finck Length = strlen(p);
120*c2c66affSColin Finck if (!Length) return -1;
121*c2c66affSColin Finck
122*c2c66affSColin Finck /* Check if this is is a simple key */
123*c2c66affSColin Finck if (Length == 1)
124*c2c66affSColin Finck {
125*c2c66affSColin Finck /* If it's a number, return it now */
126*c2c66affSColin Finck if ((*p >= '0') && (*p <= '9')) return *p;
127*c2c66affSColin Finck
128*c2c66affSColin Finck /* Otherwise, convert the letter to upper case */
129*c2c66affSColin Finck *p = toupper(*p);
130*c2c66affSColin Finck
131*c2c66affSColin Finck /* And make sure it's a valid letter */
132*c2c66affSColin Finck if ((*p >= 'A') && (*p <='Z')) return *p;
133*c2c66affSColin Finck
134*c2c66affSColin Finck /* Otherwise, fail */
135*c2c66affSColin Finck return -1;
136*c2c66affSColin Finck }
137*c2c66affSColin Finck
138*c2c66affSColin Finck /* Otherwise, scan our virtual key names */
139*c2c66affSColin Finck for (i = 0; i < 36; i++)
140*c2c66affSColin Finck {
141*c2c66affSColin Finck /* Check if we have a match */
142*c2c66affSColin Finck if (!strcmp(VKName[i].Name, p)) return VKName[i].VirtualKey;
143*c2c66affSColin Finck }
144*c2c66affSColin Finck
145*c2c66affSColin Finck /* Check if this is a hex string */
146*c2c66affSColin Finck if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X')))
147*c2c66affSColin Finck {
148*c2c66affSColin Finck /* Get the key number from the hex string */
149*c2c66affSColin Finck *(p + 1) = 'x';
150*c2c66affSColin Finck if (sscanf(p, "0x%x", &KeyNumber) == 1) return KeyNumber;
151*c2c66affSColin Finck }
152*c2c66affSColin Finck
153*c2c66affSColin Finck /* No hope: fail */
154*c2c66affSColin Finck return -1;
155*c2c66affSColin Finck }
156*c2c66affSColin Finck
157*c2c66affSColin Finck UCHAR
getCharacterInfo(IN PCHAR State,OUT PULONG EntryChar,OUT PCHAR LigatureChar)158*c2c66affSColin Finck getCharacterInfo(IN PCHAR State,
159*c2c66affSColin Finck OUT PULONG EntryChar,
160*c2c66affSColin Finck OUT PCHAR LigatureChar)
161*c2c66affSColin Finck {
162*c2c66affSColin Finck ULONG Length;
163*c2c66affSColin Finck ULONG CharInfo = CHAR_NORMAL_KEY;
164*c2c66affSColin Finck UCHAR StateChar;
165*c2c66affSColin Finck ULONG CharCode;
166*c2c66affSColin Finck
167*c2c66affSColin Finck /* Calculate the length of the state */
168*c2c66affSColin Finck Length = strlen(State);
169*c2c66affSColin Finck
170*c2c66affSColin Finck /* Check if this is at least a simple key state */
171*c2c66affSColin Finck if (Length > 1)
172*c2c66affSColin Finck {
173*c2c66affSColin Finck /* Read the first character and check if it's a dead key */
174*c2c66affSColin Finck StateChar = State[Length - 1];
175*c2c66affSColin Finck if (StateChar == '@')
176*c2c66affSColin Finck {
177*c2c66affSColin Finck /* This is a dead key */
178*c2c66affSColin Finck CharInfo = CHAR_DEAD_KEY;
179*c2c66affSColin Finck }
180*c2c66affSColin Finck else if (StateChar == '%')
181*c2c66affSColin Finck {
182*c2c66affSColin Finck /* This is another key */
183*c2c66affSColin Finck CharInfo = CHAR_OTHER_KEY;
184*c2c66affSColin Finck }
185*c2c66affSColin Finck }
186*c2c66affSColin Finck
187*c2c66affSColin Finck /* Check if this is a numerical key state */
188*c2c66affSColin Finck if ((Length - 1) >= 2)
189*c2c66affSColin Finck {
190*c2c66affSColin Finck /* Scan for extended character code entry */
191*c2c66affSColin Finck if ((sscanf(State, "%6x", &CharCode) == 1) &&
192*c2c66affSColin Finck (((Length == 5) && (State[0] == '0')) ||
193*c2c66affSColin Finck ((Length == 6) && ((State[0] == '0') && (State[1] == '0')))))
194*c2c66affSColin Finck {
195*c2c66affSColin Finck /* Handle a ligature key */
196*c2c66affSColin Finck CharInfo = CHAR_LIGATURE_KEY;
197*c2c66affSColin Finck
198*c2c66affSColin Finck /* Not yet handled */
199*c2c66affSColin Finck printf("Ligatured character entries not yet supported!\n");
200*c2c66affSColin Finck exit(1);
201*c2c66affSColin Finck }
202*c2c66affSColin Finck else
203*c2c66affSColin Finck {
204*c2c66affSColin Finck /* Get the normal character entry */
205*c2c66affSColin Finck if (sscanf(State, "%4x", &CharCode) == 1)
206*c2c66affSColin Finck {
207*c2c66affSColin Finck /* Does the caller want the key? */
208*c2c66affSColin Finck if (EntryChar) *EntryChar = CharCode;
209*c2c66affSColin Finck }
210*c2c66affSColin Finck else
211*c2c66affSColin Finck {
212*c2c66affSColin Finck /* The entry is totally invalid */
213*c2c66affSColin Finck if (Verbose) printf("An unparseable character entry '%s' was found.\n", State);
214*c2c66affSColin Finck if (EntryChar) *EntryChar = 0;
215*c2c66affSColin Finck CharInfo = CHAR_INVALID_KEY;
216*c2c66affSColin Finck }
217*c2c66affSColin Finck }
218*c2c66affSColin Finck }
219*c2c66affSColin Finck else
220*c2c66affSColin Finck {
221*c2c66affSColin Finck /* Save the key if the caller requested it */
222*c2c66affSColin Finck if (EntryChar) *EntryChar = *State;
223*c2c66affSColin Finck }
224*c2c66affSColin Finck
225*c2c66affSColin Finck /* Return the type of character this is */
226*c2c66affSColin Finck return CharInfo;
227*c2c66affSColin Finck }
228*c2c66affSColin Finck
229*c2c66affSColin Finck BOOLEAN
NextLine(PCHAR LineBuffer,ULONG BufferSize,FILE * File)230*c2c66affSColin Finck NextLine(PCHAR LineBuffer,
231*c2c66affSColin Finck ULONG BufferSize,
232*c2c66affSColin Finck FILE *File)
233*c2c66affSColin Finck {
234*c2c66affSColin Finck PCHAR p, pp;
235*c2c66affSColin Finck
236*c2c66affSColin Finck /* Scan each line */
237*c2c66affSColin Finck while (fgets(LineBuffer, BufferSize, File))
238*c2c66affSColin Finck {
239*c2c66affSColin Finck /* Remember it */
240*c2c66affSColin Finck gLineCount++;
241*c2c66affSColin Finck
242*c2c66affSColin Finck /* Reset the pointer at the beginning of the line */
243*c2c66affSColin Finck p = LineBuffer;
244*c2c66affSColin Finck
245*c2c66affSColin Finck /* Now bypass all whitespace (and tabspace) */
246*c2c66affSColin Finck while ((*p) && ((*p == ' ') || (*p == '\t'))) p++;
247*c2c66affSColin Finck
248*c2c66affSColin Finck /* If this is an old-style comment, skip the line */
249*c2c66affSColin Finck if (*p == ';') continue;
250*c2c66affSColin Finck
251*c2c66affSColin Finck /* Otherwise, check for new-style comment */
252*c2c66affSColin Finck pp = strstr(p, "//");
253*c2c66affSColin Finck if (pp)
254*c2c66affSColin Finck {
255*c2c66affSColin Finck /* We have a comment, so terminate there (unless the whole line is one) */
256*c2c66affSColin Finck if (pp == p) continue;
257*c2c66affSColin Finck *pp = '\0';
258*c2c66affSColin Finck }
259*c2c66affSColin Finck else
260*c2c66affSColin Finck {
261*c2c66affSColin Finck /* No comment, so find the new line and terminate there */
262*c2c66affSColin Finck p = strchr(p, '\n');
263*c2c66affSColin Finck if (p) *p = '\0';
264*c2c66affSColin Finck }
265*c2c66affSColin Finck
266*c2c66affSColin Finck /* We have a line! */
267*c2c66affSColin Finck return TRUE;
268*c2c66affSColin Finck }
269*c2c66affSColin Finck
270*c2c66affSColin Finck /* No line found */
271*c2c66affSColin Finck return FALSE;
272*c2c66affSColin Finck }
273*c2c66affSColin Finck
274*c2c66affSColin Finck ULONG
SkipLines(VOID)275*c2c66affSColin Finck SkipLines(VOID)
276*c2c66affSColin Finck {
277*c2c66affSColin Finck ULONG KeyWord;
278*c2c66affSColin Finck CHAR KeyWordChars[32];
279*c2c66affSColin Finck
280*c2c66affSColin Finck /* Scan each line, skipping it if it's not a keyword */
281*c2c66affSColin Finck while (NextLine(gBuf, sizeof(gBuf), gfpInput))
282*c2c66affSColin Finck {
283*c2c66affSColin Finck /* Read a single word */
284*c2c66affSColin Finck if (sscanf(gBuf, "%s", KeyWordChars) == 1)
285*c2c66affSColin Finck {
286*c2c66affSColin Finck /* If the word is a keyword, stop skipping lines */
287*c2c66affSColin Finck KeyWord = isKeyWord(KeyWordChars);
288*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) return KeyWord;
289*c2c66affSColin Finck }
290*c2c66affSColin Finck }
291*c2c66affSColin Finck
292*c2c66affSColin Finck /* We skipped all the possible lines, not finding anything */
293*c2c66affSColin Finck return KEYWORD_COUNT;
294*c2c66affSColin Finck }
295*c2c66affSColin Finck
296*c2c66affSColin Finck ULONG
DoKBD(VOID)297*c2c66affSColin Finck DoKBD(VOID)
298*c2c66affSColin Finck {
299*c2c66affSColin Finck /* On Unicode files, we need to find the Unicode marker (FEEF) */
300*c2c66affSColin Finck ASSERT(UnicodeFile == FALSE);
301*c2c66affSColin Finck
302*c2c66affSColin Finck /* Initial values */
303*c2c66affSColin Finck *gKBDName = '\0';
304*c2c66affSColin Finck *gDescription = '\0';
305*c2c66affSColin Finck
306*c2c66affSColin Finck /* Scan for the values */
307*c2c66affSColin Finck if (sscanf(gBuf, "KBD %8s \"%40[^\"]\" %d", gKBDName, gDescription, &gID) < 2)
308*c2c66affSColin Finck {
309*c2c66affSColin Finck /* Couldn't find them */
310*c2c66affSColin Finck printf("Unable to read keyboard name or description.\n");
311*c2c66affSColin Finck exit(1);
312*c2c66affSColin Finck }
313*c2c66affSColin Finck
314*c2c66affSColin Finck /* Debug only */
315*c2c66affSColin Finck DPRINT1("KBD Name: [%8s] Description: [%40s] ID: [%d]\n", gKBDName, gDescription, gID);
316*c2c66affSColin Finck return SkipLines();
317*c2c66affSColin Finck }
318*c2c66affSColin Finck
319*c2c66affSColin Finck ULONG
DoVERSION(VOID)320*c2c66affSColin Finck DoVERSION(VOID)
321*c2c66affSColin Finck {
322*c2c66affSColin Finck /* Scan for the value */
323*c2c66affSColin Finck if (sscanf(gBuf, "VERSION %d", &gKbdLayoutVersion) < 1)
324*c2c66affSColin Finck {
325*c2c66affSColin Finck /* Couldn't find them */
326*c2c66affSColin Finck printf("Unable to read keyboard version information.\n");
327*c2c66affSColin Finck }
328*c2c66affSColin Finck
329*c2c66affSColin Finck /* Debug only */
330*c2c66affSColin Finck DPRINT1("VERSION [%d]\n", gKbdLayoutVersion);
331*c2c66affSColin Finck return SkipLines();
332*c2c66affSColin Finck }
333*c2c66affSColin Finck
334*c2c66affSColin Finck ULONG
DoCOPYRIGHT(VOID)335*c2c66affSColin Finck DoCOPYRIGHT(VOID)
336*c2c66affSColin Finck {
337*c2c66affSColin Finck /* Initial values */
338*c2c66affSColin Finck *gCopyright = '\0';
339*c2c66affSColin Finck
340*c2c66affSColin Finck /* Scan for the value */
341*c2c66affSColin Finck if (sscanf(gBuf, "COPYRIGHT \"%40[^\"]\"", gCopyright) < 1)
342*c2c66affSColin Finck {
343*c2c66affSColin Finck /* Couldn't find them */
344*c2c66affSColin Finck printf("Unable to read the specified COPYRIGHT string.\n");
345*c2c66affSColin Finck }
346*c2c66affSColin Finck
347*c2c66affSColin Finck /* Debug only */
348*c2c66affSColin Finck DPRINT1("COPYRIGHT [%40s]\n", gCopyright);
349*c2c66affSColin Finck return SkipLines();
350*c2c66affSColin Finck }
351*c2c66affSColin Finck
352*c2c66affSColin Finck ULONG
DoCOMPANY(VOID)353*c2c66affSColin Finck DoCOMPANY(VOID)
354*c2c66affSColin Finck {
355*c2c66affSColin Finck /* Initial values */
356*c2c66affSColin Finck *gCompany = '\0';
357*c2c66affSColin Finck
358*c2c66affSColin Finck /* Scan for the value */
359*c2c66affSColin Finck if (sscanf(gBuf, "COMPANY \"%85[^\"]\"", gCompany) < 1)
360*c2c66affSColin Finck {
361*c2c66affSColin Finck /* Couldn't find them */
362*c2c66affSColin Finck printf("Unable to read the specified COMPANY name.\n");
363*c2c66affSColin Finck }
364*c2c66affSColin Finck
365*c2c66affSColin Finck /* Debug only */
366*c2c66affSColin Finck DPRINT1("COMPANY [%85s]\n", gCompany);
367*c2c66affSColin Finck return SkipLines();
368*c2c66affSColin Finck }
369*c2c66affSColin Finck
370*c2c66affSColin Finck ULONG
DoLOCALENAME(VOID)371*c2c66affSColin Finck DoLOCALENAME(VOID)
372*c2c66affSColin Finck {
373*c2c66affSColin Finck /* Initial values */
374*c2c66affSColin Finck *gLocaleName = '\0';
375*c2c66affSColin Finck
376*c2c66affSColin Finck /* Scan for the value */
377*c2c66affSColin Finck if (sscanf(gBuf, "LOCALENAME \"%40[^\"]\"", gLocaleName) < 1)
378*c2c66affSColin Finck {
379*c2c66affSColin Finck /* Couldn't find them */
380*c2c66affSColin Finck printf("Unable to read the specified COPYRIGHT string.\n");
381*c2c66affSColin Finck }
382*c2c66affSColin Finck
383*c2c66affSColin Finck /* Debug only */
384*c2c66affSColin Finck DPRINT1("LOCALENAME [%40s]\n", gLocaleName);
385*c2c66affSColin Finck return SkipLines();
386*c2c66affSColin Finck }
387*c2c66affSColin Finck
388*c2c66affSColin Finck ULONG
DoDESCRIPTIONS(IN PKEYNAME * DescriptionData)389*c2c66affSColin Finck DoDESCRIPTIONS(IN PKEYNAME* DescriptionData)
390*c2c66affSColin Finck {
391*c2c66affSColin Finck ULONG KeyWord = 0;
392*c2c66affSColin Finck CHAR Token[32];
393*c2c66affSColin Finck ULONG LanguageCode;
394*c2c66affSColin Finck PCHAR p, pp;
395*c2c66affSColin Finck PKEYNAME Description;
396*c2c66affSColin Finck
397*c2c66affSColin Finck /* Assume nothing */
398*c2c66affSColin Finck *DescriptionData = 0;
399*c2c66affSColin Finck
400*c2c66affSColin Finck /* Start scanning */
401*c2c66affSColin Finck while (NextLine(gBuf, 256, gfpInput))
402*c2c66affSColin Finck {
403*c2c66affSColin Finck /* Search for token */
404*c2c66affSColin Finck if (sscanf(gBuf, "%s", Token) != 1) continue;
405*c2c66affSColin Finck
406*c2c66affSColin Finck /* Make sure it's not just a comment */
407*c2c66affSColin Finck if (*Token == ';') continue;
408*c2c66affSColin Finck
409*c2c66affSColin Finck /* Make sure it's not a keyword */
410*c2c66affSColin Finck KeyWord = isKeyWord(Token);
411*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) break;
412*c2c66affSColin Finck
413*c2c66affSColin Finck /* Now scan for the language code */
414*c2c66affSColin Finck if (sscanf(Token, " %4x", &LanguageCode) != 1)
415*c2c66affSColin Finck {
416*c2c66affSColin Finck /* Skip */
417*c2c66affSColin Finck printf("An invalid LANGID was specified.\n");
418*c2c66affSColin Finck continue;
419*c2c66affSColin Finck }
420*c2c66affSColin Finck
421*c2c66affSColin Finck /* Now get the actual description */
422*c2c66affSColin Finck if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
423*c2c66affSColin Finck {
424*c2c66affSColin Finck /* Skip */
425*c2c66affSColin Finck printf("A language description is missing.\n");
426*c2c66affSColin Finck continue;
427*c2c66affSColin Finck }
428*c2c66affSColin Finck
429*c2c66affSColin Finck /* Get the description string and find the ending */
430*c2c66affSColin Finck p = strstr(gBuf, Token);
431*c2c66affSColin Finck pp = strchr(p, '\n');
432*c2c66affSColin Finck if (!pp) pp = strchr(p, '\r');
433*c2c66affSColin Finck
434*c2c66affSColin Finck /* Terminate the description string here */
435*c2c66affSColin Finck if (pp) *pp = 0;
436*c2c66affSColin Finck
437*c2c66affSColin Finck /* Now allocate the description */
438*c2c66affSColin Finck Description = malloc(sizeof(KEYNAME));
439*c2c66affSColin Finck if (!Description)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck /* Fail */
442*c2c66affSColin Finck printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
443*c2c66affSColin Finck exit(1);
444*c2c66affSColin Finck }
445*c2c66affSColin Finck
446*c2c66affSColin Finck /* Fill out the structure */
447*c2c66affSColin Finck Description->Code = LanguageCode;
448*c2c66affSColin Finck Description->Name = strdup(p);
449*c2c66affSColin Finck Description->Next = NULL;
450*c2c66affSColin Finck
451*c2c66affSColin Finck /* Debug only */
452*c2c66affSColin Finck DPRINT1("LANGID: [%4x] Description: [%s]\n", Description->Code, Description->Name);
453*c2c66affSColin Finck
454*c2c66affSColin Finck /* Point to it and advance the pointer */
455*c2c66affSColin Finck *DescriptionData = Description;
456*c2c66affSColin Finck DescriptionData = &Description->Next;
457*c2c66affSColin Finck }
458*c2c66affSColin Finck
459*c2c66affSColin Finck /* We are done */
460*c2c66affSColin Finck return KeyWord;
461*c2c66affSColin Finck }
462*c2c66affSColin Finck
463*c2c66affSColin Finck ULONG
DoLANGUAGENAMES(IN PKEYNAME * LanguageData)464*c2c66affSColin Finck DoLANGUAGENAMES(IN PKEYNAME* LanguageData)
465*c2c66affSColin Finck {
466*c2c66affSColin Finck ULONG KeyWord = 0;
467*c2c66affSColin Finck CHAR Token[32];
468*c2c66affSColin Finck ULONG LanguageCode;
469*c2c66affSColin Finck PCHAR p, pp;
470*c2c66affSColin Finck PKEYNAME Language;
471*c2c66affSColin Finck
472*c2c66affSColin Finck /* Assume nothing */
473*c2c66affSColin Finck *LanguageData = 0;
474*c2c66affSColin Finck
475*c2c66affSColin Finck /* Start scanning */
476*c2c66affSColin Finck while (NextLine(gBuf, 256, gfpInput))
477*c2c66affSColin Finck {
478*c2c66affSColin Finck /* Search for token */
479*c2c66affSColin Finck if (sscanf(gBuf, "%s", Token) != 1) continue;
480*c2c66affSColin Finck
481*c2c66affSColin Finck /* Make sure it's not just a comment */
482*c2c66affSColin Finck if (*Token == ';') continue;
483*c2c66affSColin Finck
484*c2c66affSColin Finck /* Make sure it's not a keyword */
485*c2c66affSColin Finck KeyWord = isKeyWord(Token);
486*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) break;
487*c2c66affSColin Finck
488*c2c66affSColin Finck /* Now scan for the language code */
489*c2c66affSColin Finck if (sscanf(Token, " %4x", &LanguageCode) != 1)
490*c2c66affSColin Finck {
491*c2c66affSColin Finck /* Skip */
492*c2c66affSColin Finck printf("An invalid LANGID was specified.\n");
493*c2c66affSColin Finck continue;
494*c2c66affSColin Finck }
495*c2c66affSColin Finck
496*c2c66affSColin Finck /* Now get the actual language */
497*c2c66affSColin Finck if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
498*c2c66affSColin Finck {
499*c2c66affSColin Finck /* Skip */
500*c2c66affSColin Finck printf("A language name is missing\n");
501*c2c66affSColin Finck continue;
502*c2c66affSColin Finck }
503*c2c66affSColin Finck
504*c2c66affSColin Finck /* Get the language string and find the ending */
505*c2c66affSColin Finck p = strstr(gBuf, Token);
506*c2c66affSColin Finck pp = strchr(p, '\n');
507*c2c66affSColin Finck if (!pp) pp = strchr(p, '\r');
508*c2c66affSColin Finck
509*c2c66affSColin Finck /* Terminate the language string here */
510*c2c66affSColin Finck if (pp) *pp = 0;
511*c2c66affSColin Finck
512*c2c66affSColin Finck /* Now allocate the language */
513*c2c66affSColin Finck Language = malloc(sizeof(KEYNAME));
514*c2c66affSColin Finck if (!Language)
515*c2c66affSColin Finck {
516*c2c66affSColin Finck /* Fail */
517*c2c66affSColin Finck printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
518*c2c66affSColin Finck exit(1);
519*c2c66affSColin Finck }
520*c2c66affSColin Finck
521*c2c66affSColin Finck /* Fill out the structure */
522*c2c66affSColin Finck Language->Code = LanguageCode;
523*c2c66affSColin Finck Language->Name = strdup(p);
524*c2c66affSColin Finck Language->Next = NULL;
525*c2c66affSColin Finck
526*c2c66affSColin Finck /* Debug only */
527*c2c66affSColin Finck DPRINT1("LANGID: [%4x] Name: [%s]\n", Language->Code, Language->Name);
528*c2c66affSColin Finck
529*c2c66affSColin Finck /* Point to it and advance the pointer */
530*c2c66affSColin Finck *LanguageData = Language;
531*c2c66affSColin Finck LanguageData = &Language->Next;
532*c2c66affSColin Finck }
533*c2c66affSColin Finck
534*c2c66affSColin Finck /* We are done */
535*c2c66affSColin Finck return KeyWord;
536*c2c66affSColin Finck }
537*c2c66affSColin Finck
538*c2c66affSColin Finck ULONG
DoKEYNAME(IN PKEYNAME * KeyNameData)539*c2c66affSColin Finck DoKEYNAME(IN PKEYNAME* KeyNameData)
540*c2c66affSColin Finck {
541*c2c66affSColin Finck ULONG KeyWord = 0;
542*c2c66affSColin Finck CHAR Token[32];
543*c2c66affSColin Finck ULONG CharacterCode;
544*c2c66affSColin Finck PCHAR p, pp;
545*c2c66affSColin Finck PKEYNAME KeyName;
546*c2c66affSColin Finck
547*c2c66affSColin Finck /* Assume nothing */
548*c2c66affSColin Finck *KeyNameData = 0;
549*c2c66affSColin Finck
550*c2c66affSColin Finck /* Start scanning */
551*c2c66affSColin Finck while (NextLine(gBuf, 256, gfpInput))
552*c2c66affSColin Finck {
553*c2c66affSColin Finck /* Search for token */
554*c2c66affSColin Finck if (sscanf(gBuf, "%s", Token) != 1) continue;
555*c2c66affSColin Finck
556*c2c66affSColin Finck /* Make sure it's not just a comment */
557*c2c66affSColin Finck if (*Token == ';') continue;
558*c2c66affSColin Finck
559*c2c66affSColin Finck /* Make sure it's not a keyword */
560*c2c66affSColin Finck KeyWord = isKeyWord(Token);
561*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) break;
562*c2c66affSColin Finck
563*c2c66affSColin Finck /* Now scan for the character code */
564*c2c66affSColin Finck if (sscanf(Token, " %4x", &CharacterCode) != 1)
565*c2c66affSColin Finck {
566*c2c66affSColin Finck /* Skip */
567*c2c66affSColin Finck printf("An invalid character code was specified.\n");
568*c2c66affSColin Finck continue;
569*c2c66affSColin Finck }
570*c2c66affSColin Finck
571*c2c66affSColin Finck /* Now get the actual key name */
572*c2c66affSColin Finck if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
573*c2c66affSColin Finck {
574*c2c66affSColin Finck /* Skip */
575*c2c66affSColin Finck printf("A key name is missing\n");
576*c2c66affSColin Finck continue;
577*c2c66affSColin Finck }
578*c2c66affSColin Finck
579*c2c66affSColin Finck /* Get the key name string and find the ending */
580*c2c66affSColin Finck p = strstr(gBuf, Token);
581*c2c66affSColin Finck pp = strchr(p, '\n');
582*c2c66affSColin Finck if (!pp) pp = strchr(p, '\r');
583*c2c66affSColin Finck
584*c2c66affSColin Finck /* Terminate the key name string here */
585*c2c66affSColin Finck if (pp) *pp = 0;
586*c2c66affSColin Finck
587*c2c66affSColin Finck /* Now allocate the language */
588*c2c66affSColin Finck KeyName = malloc(sizeof(KEYNAME));
589*c2c66affSColin Finck if (!KeyName)
590*c2c66affSColin Finck {
591*c2c66affSColin Finck /* Fail */
592*c2c66affSColin Finck printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
593*c2c66affSColin Finck exit(1);
594*c2c66affSColin Finck }
595*c2c66affSColin Finck
596*c2c66affSColin Finck /* Fill out the structure */
597*c2c66affSColin Finck KeyName->Code = CharacterCode;
598*c2c66affSColin Finck KeyName->Name = strdup(p);
599*c2c66affSColin Finck KeyName->Next = NULL;
600*c2c66affSColin Finck
601*c2c66affSColin Finck /* Debug only */
602*c2c66affSColin Finck DPRINT1("CHARCODE: [%4x] Name: [%s]\n", KeyName->Code, KeyName->Name);
603*c2c66affSColin Finck
604*c2c66affSColin Finck /* Point to it and advance the pointer */
605*c2c66affSColin Finck *KeyNameData = KeyName;
606*c2c66affSColin Finck KeyNameData = &KeyName->Next;
607*c2c66affSColin Finck }
608*c2c66affSColin Finck
609*c2c66affSColin Finck /* We are done */
610*c2c66affSColin Finck return KeyWord;
611*c2c66affSColin Finck }
612*c2c66affSColin Finck
613*c2c66affSColin Finck ULONG
DoSHIFTSTATE(IN PULONG StateCount,IN OUT PULONG ShiftStates)614*c2c66affSColin Finck DoSHIFTSTATE(IN PULONG StateCount,
615*c2c66affSColin Finck IN OUT PULONG ShiftStates)
616*c2c66affSColin Finck {
617*c2c66affSColin Finck ULONG KeyWord;
618*c2c66affSColin Finck ULONG i;
619*c2c66affSColin Finck ULONG ShiftState;
620*c2c66affSColin Finck CHAR Token[32];
621*c2c66affSColin Finck
622*c2c66affSColin Finck /* Reset the shift states */
623*c2c66affSColin Finck for (i = 0; i < 8; i++) ShiftStates[i] = -1;
624*c2c66affSColin Finck
625*c2c66affSColin Finck /* Start with no states */
626*c2c66affSColin Finck *StateCount = 0;
627*c2c66affSColin Finck
628*c2c66affSColin Finck /* Scan for shift states */
629*c2c66affSColin Finck while (NextLine(gBuf, 256, gfpInput))
630*c2c66affSColin Finck {
631*c2c66affSColin Finck /* Search for token */
632*c2c66affSColin Finck if (sscanf(gBuf, "%s", Token) != 1) continue;
633*c2c66affSColin Finck
634*c2c66affSColin Finck /* Make sure it's not a keyword */
635*c2c66affSColin Finck KeyWord = isKeyWord(Token);
636*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) break;
637*c2c66affSColin Finck
638*c2c66affSColin Finck /* Now scan for the shift state */
639*c2c66affSColin Finck if (sscanf(gBuf, " %1s[012367]", Token) != 1)
640*c2c66affSColin Finck {
641*c2c66affSColin Finck /* We failed -- should we warn? */
642*c2c66affSColin Finck if (Verbose) printf("An invalid shift state '%s' was found (use 0, 1, 2, 3, 6, or 7.)\n", Token);
643*c2c66affSColin Finck continue;
644*c2c66affSColin Finck }
645*c2c66affSColin Finck
646*c2c66affSColin Finck /* Now read the state */
647*c2c66affSColin Finck ShiftState = atoi(Token);
648*c2c66affSColin Finck
649*c2c66affSColin Finck /* Scan existing states */
650*c2c66affSColin Finck for (i = 0; i < *StateCount; i++)
651*c2c66affSColin Finck {
652*c2c66affSColin Finck /* Check for duplicate */
653*c2c66affSColin Finck if ((ShiftStates[i] == ShiftState) && (Verbose))
654*c2c66affSColin Finck {
655*c2c66affSColin Finck /* Warn user */
656*c2c66affSColin Finck printf("The state '%d' was duplicated for this Virtual Key.\n", ShiftStates[i]);
657*c2c66affSColin Finck break;
658*c2c66affSColin Finck }
659*c2c66affSColin Finck }
660*c2c66affSColin Finck
661*c2c66affSColin Finck /* Make sure we won't overflow */
662*c2c66affSColin Finck if (*StateCount < 8)
663*c2c66affSColin Finck {
664*c2c66affSColin Finck /* Save this state */
665*c2c66affSColin Finck ShiftStates[(*StateCount)++] = ShiftState;
666*c2c66affSColin Finck }
667*c2c66affSColin Finck else
668*c2c66affSColin Finck {
669*c2c66affSColin Finck /* Too many states -- should we warn? */
670*c2c66affSColin Finck if (Verbose) printf("There were too many states (you defined %d).\n", *StateCount);
671*c2c66affSColin Finck }
672*c2c66affSColin Finck }
673*c2c66affSColin Finck
674*c2c66affSColin Finck /* Debug only */
675*c2c66affSColin Finck DPRINT1("Found %d Shift States: [", *StateCount);
676*c2c66affSColin Finck for (i = 0; i < *StateCount; i++) DPRINT1("%d ", ShiftStates[i]);
677*c2c66affSColin Finck DPRINT1("]\n");
678*c2c66affSColin Finck
679*c2c66affSColin Finck /* We are done */
680*c2c66affSColin Finck return KeyWord;
681*c2c66affSColin Finck }
682*c2c66affSColin Finck
683*c2c66affSColin Finck ULONG
DoLIGATURE(PVOID LigatureData)684*c2c66affSColin Finck DoLIGATURE(PVOID LigatureData)
685*c2c66affSColin Finck {
686*c2c66affSColin Finck printf("LIGATURE support is not yet implemented. Please bug Arch to fix it\n");
687*c2c66affSColin Finck return SkipLines();
688*c2c66affSColin Finck }
689*c2c66affSColin Finck
690*c2c66affSColin Finck ULONG
DoATTRIBUTES(PVOID AttributeData)691*c2c66affSColin Finck DoATTRIBUTES(PVOID AttributeData)
692*c2c66affSColin Finck {
693*c2c66affSColin Finck printf("ATTRIBUTES support is not yet implemented. Please bug Arch to fix it\n");
694*c2c66affSColin Finck return SkipLines();
695*c2c66affSColin Finck }
696*c2c66affSColin Finck
697*c2c66affSColin Finck ULONG
DoMODIFIERS(VOID)698*c2c66affSColin Finck DoMODIFIERS(VOID)
699*c2c66affSColin Finck {
700*c2c66affSColin Finck printf("MODIFIERS support is not yet implemented. Please bug Arch to fix it\n");
701*c2c66affSColin Finck return SkipLines();
702*c2c66affSColin Finck }
703*c2c66affSColin Finck
704*c2c66affSColin Finck ULONG
DoDEADKEY(PVOID DeadKeyData)705*c2c66affSColin Finck DoDEADKEY(PVOID DeadKeyData)
706*c2c66affSColin Finck {
707*c2c66affSColin Finck printf("DEADKEY support is not yet implemented. Please bug Arch to fix it\n");
708*c2c66affSColin Finck return SkipLines();
709*c2c66affSColin Finck }
710*c2c66affSColin Finck
711*c2c66affSColin Finck ULONG
DoLAYOUT(IN PLAYOUT LayoutData,IN PVOID LigatureData,IN PULONG ShiftStates,IN ULONG StateCount)712*c2c66affSColin Finck DoLAYOUT(IN PLAYOUT LayoutData,
713*c2c66affSColin Finck IN PVOID LigatureData,
714*c2c66affSColin Finck IN PULONG ShiftStates,
715*c2c66affSColin Finck IN ULONG StateCount)
716*c2c66affSColin Finck {
717*c2c66affSColin Finck CHAR Token[32];
718*c2c66affSColin Finck CHAR Cap[8];
719*c2c66affSColin Finck ULONG KeyWord;
720*c2c66affSColin Finck ULONG ScanCode, CurrentCode;
721*c2c66affSColin Finck ULONG TokenCount;
722*c2c66affSColin Finck ULONG VirtualKey;
723*c2c66affSColin Finck ULONG i;
724*c2c66affSColin Finck ULONG Count;
725*c2c66affSColin Finck BOOLEAN FullEntry;
726*c2c66affSColin Finck CHAR State[8][8];
727*c2c66affSColin Finck ULONG ScanCodeCount = -1;
728*c2c66affSColin Finck PLAYOUTENTRY Entry;
729*c2c66affSColin Finck UCHAR CharacterType;
730*c2c66affSColin Finck CHAR LigatureChar;
731*c2c66affSColin Finck
732*c2c66affSColin Finck /* Zero out the layout */
733*c2c66affSColin Finck memset(LayoutData, 0, sizeof(LAYOUT));
734*c2c66affSColin Finck
735*c2c66affSColin Finck /* Read each line */
736*c2c66affSColin Finck Entry = &LayoutData->Entry[0];
737*c2c66affSColin Finck while (NextLine(gBuf, 256, gfpInput))
738*c2c66affSColin Finck {
739*c2c66affSColin Finck /* Search for token */
740*c2c66affSColin Finck if (sscanf(gBuf, "%s", Token) != 1) continue;
741*c2c66affSColin Finck
742*c2c66affSColin Finck /* Make sure it's not just a comment */
743*c2c66affSColin Finck if (*Token == ';') continue;
744*c2c66affSColin Finck
745*c2c66affSColin Finck /* Make sure it's not a keyword */
746*c2c66affSColin Finck KeyWord = isKeyWord(Token);
747*c2c66affSColin Finck if (KeyWord < KEYWORD_COUNT) break;
748*c2c66affSColin Finck
749*c2c66affSColin Finck /* Now read the entry */
750*c2c66affSColin Finck TokenCount = sscanf(gBuf, " %x %s %s", &ScanCode, Token, Cap);
751*c2c66affSColin Finck if (TokenCount == 3)
752*c2c66affSColin Finck {
753*c2c66affSColin Finck /* Full entry with cap */
754*c2c66affSColin Finck FullEntry = TRUE;
755*c2c66affSColin Finck }
756*c2c66affSColin Finck else if (TokenCount != 2)
757*c2c66affSColin Finck {
758*c2c66affSColin Finck /* Fail, invalid LAYOUT entry */
759*c2c66affSColin Finck printf("There are not enough columns in the layout list.\n");
760*c2c66affSColin Finck exit(1);
761*c2c66affSColin Finck }
762*c2c66affSColin Finck else
763*c2c66affSColin Finck {
764*c2c66affSColin Finck /* Simplified layout with no cap */
765*c2c66affSColin Finck FullEntry = FALSE;
766*c2c66affSColin Finck }
767*c2c66affSColin Finck
768*c2c66affSColin Finck /* One more */
769*c2c66affSColin Finck DPRINT1("RAW ENTRY: [%x %s %s]\n", ScanCode, Token, Cap);
770*c2c66affSColin Finck Entry++;
771*c2c66affSColin Finck if (++ScanCodeCount >= 110)
772*c2c66affSColin Finck {
773*c2c66affSColin Finck /* Too many! */
774*c2c66affSColin Finck printf("ScanCode %02x - too many scancodes here to parse.\n", ScanCode);
775*c2c66affSColin Finck exit(1);
776*c2c66affSColin Finck }
777*c2c66affSColin Finck
778*c2c66affSColin Finck /* Fill out this entry */
779*c2c66affSColin Finck Entry->ScanCode = ScanCode;
780*c2c66affSColin Finck Entry->LineCount = gLineCount;
781*c2c66affSColin Finck
782*c2c66affSColin Finck /* Loop scancode table */
783*c2c66affSColin Finck for (i = 0; i < 110; i++)
784*c2c66affSColin Finck {
785*c2c66affSColin Finck /* Get the current code */
786*c2c66affSColin Finck CurrentCode = ScVk[i].ScanCode;
787*c2c66affSColin Finck if (CurrentCode == 0xFFFF)
788*c2c66affSColin Finck {
789*c2c66affSColin Finck /* New code */
790*c2c66affSColin Finck if (Verbose) printf("A new scancode is being defined: 0x%2X, %s\n", Entry->ScanCode, Token);
791*c2c66affSColin Finck
792*c2c66affSColin Finck /* Fill out the entry */
793*c2c66affSColin Finck Entry->VirtualKey = getVKNum(Token);
794*c2c66affSColin Finck break;
795*c2c66affSColin Finck }
796*c2c66affSColin Finck else if (ScanCode == CurrentCode)
797*c2c66affSColin Finck {
798*c2c66affSColin Finck /* Make sure we didn't already process it */
799*c2c66affSColin Finck if (ScVk[i].Processed)
800*c2c66affSColin Finck {
801*c2c66affSColin Finck /* Fail */
802*c2c66affSColin Finck printf("Scancode %X was previously defined.\n", ScanCode);
803*c2c66affSColin Finck exit(1);
804*c2c66affSColin Finck }
805*c2c66affSColin Finck
806*c2c66affSColin Finck /* Check if there is a valid virtual key */
807*c2c66affSColin Finck if (ScVk[i].VirtualKey == 0xFFFF)
808*c2c66affSColin Finck {
809*c2c66affSColin Finck /* Fail */
810*c2c66affSColin Finck printf("The Scancode you tried to use (%X) is reserved.\n", ScanCode);
811*c2c66affSColin Finck exit(1);
812*c2c66affSColin Finck }
813*c2c66affSColin Finck
814*c2c66affSColin Finck /* Fill out the entry */
815*c2c66affSColin Finck Entry->OriginalVirtualKey = ScVk[i].VirtualKey;
816*c2c66affSColin Finck Entry->Name = ScVk[i].Name;
817*c2c66affSColin Finck break;
818*c2c66affSColin Finck }
819*c2c66affSColin Finck }
820*c2c66affSColin Finck
821*c2c66affSColin Finck /* The entry is now processed */
822*c2c66affSColin Finck Entry->Processed = TRUE;
823*c2c66affSColin Finck ScVk[i].Processed = TRUE;
824*c2c66affSColin Finck
825*c2c66affSColin Finck /* Get the virtual key from the entry */
826*c2c66affSColin Finck VirtualKey = getVKNum(Token);
827*c2c66affSColin Finck Entry->VirtualKey = VirtualKey;
828*c2c66affSColin Finck DPRINT1("ENTRY: [%x %x %x %s] with ",
829*c2c66affSColin Finck Entry->VirtualKey, Entry->OriginalVirtualKey, Entry->ScanCode, Entry->Name);
830*c2c66affSColin Finck
831*c2c66affSColin Finck /* Make sure it's valid */
832*c2c66affSColin Finck if (VirtualKey == 0xFFFF)
833*c2c66affSColin Finck {
834*c2c66affSColin Finck /* Warn the user */
835*c2c66affSColin Finck if (Verbose) printf("An invalid Virtual Key '%s' was defined.\n", Token);
836*c2c66affSColin Finck continue;
837*c2c66affSColin Finck }
838*c2c66affSColin Finck
839*c2c66affSColin Finck /* Is this a full entry */
840*c2c66affSColin Finck if (FullEntry)
841*c2c66affSColin Finck {
842*c2c66affSColin Finck /* Do we have SGCAP data? Set cap mode to 2 */
843*c2c66affSColin Finck if (!strcmp(Cap, "SGCAP")) *Cap = '2';
844*c2c66affSColin Finck
845*c2c66affSColin Finck /* Read the cap mode */
846*c2c66affSColin Finck if (sscanf(Cap, "%1d[012]", &Entry->Cap) != 1)
847*c2c66affSColin Finck {
848*c2c66affSColin Finck /* Invalid cap mode */
849*c2c66affSColin Finck printf("invalid Cap specified (%s). Must be 0, 1, or 2.\n", Cap);
850*c2c66affSColin Finck exit(1);
851*c2c66affSColin Finck }
852*c2c66affSColin Finck }
853*c2c66affSColin Finck
854*c2c66affSColin Finck /* Read the states */
855*c2c66affSColin Finck Count = sscanf(gBuf,
856*c2c66affSColin Finck " %*s %*s %*s %s %s %s %s %s %s %s %s",
857*c2c66affSColin Finck State[0],
858*c2c66affSColin Finck State[1],
859*c2c66affSColin Finck State[2],
860*c2c66affSColin Finck State[3],
861*c2c66affSColin Finck State[4],
862*c2c66affSColin Finck State[5],
863*c2c66affSColin Finck State[6],
864*c2c66affSColin Finck State[7]);
865*c2c66affSColin Finck Entry->StateCount = Count;
866*c2c66affSColin Finck DPRINT1("%d STATES: [", Count);
867*c2c66affSColin Finck
868*c2c66affSColin Finck /* Check if there are less than 2 states */
869*c2c66affSColin Finck if ((Count < 2) && (FullEntry))
870*c2c66affSColin Finck {
871*c2c66affSColin Finck /* Fail */
872*c2c66affSColin Finck printf("You must have at least 2 characters.\n");
873*c2c66affSColin Finck exit(1);
874*c2c66affSColin Finck }
875*c2c66affSColin Finck
876*c2c66affSColin Finck /* Loop all states */
877*c2c66affSColin Finck for (i = 0; i < Count; i++)
878*c2c66affSColin Finck {
879*c2c66affSColin Finck /* Check if this is an undefined state */
880*c2c66affSColin Finck DPRINT1("%s ", State[i]);
881*c2c66affSColin Finck if (!strcmp(State[i], "-1"))
882*c2c66affSColin Finck {
883*c2c66affSColin Finck /* No data for this state */
884*c2c66affSColin Finck Entry->CharData[i] = -1;
885*c2c66affSColin Finck continue;
886*c2c66affSColin Finck }
887*c2c66affSColin Finck
888*c2c66affSColin Finck /* Otherwise, check what kind of character this is */
889*c2c66affSColin Finck CharacterType = getCharacterInfo(State[i],
890*c2c66affSColin Finck &Entry->CharData[i],
891*c2c66affSColin Finck &LigatureChar);
892*c2c66affSColin Finck if (CharacterType == CHAR_DEAD_KEY)
893*c2c66affSColin Finck {
894*c2c66affSColin Finck /* Save it as such */
895*c2c66affSColin Finck Entry->DeadCharData[i] = 1;
896*c2c66affSColin Finck }
897*c2c66affSColin Finck else if (CharacterType == CHAR_OTHER_KEY)
898*c2c66affSColin Finck {
899*c2c66affSColin Finck /* Save it as such */
900*c2c66affSColin Finck Entry->OtherCharData[i] = 1;
901*c2c66affSColin Finck }
902*c2c66affSColin Finck }
903*c2c66affSColin Finck
904*c2c66affSColin Finck /* Check for sanity checks */
905*c2c66affSColin Finck DPRINT1("]\n");
906*c2c66affSColin Finck if (SanityCheck)
907*c2c66affSColin Finck {
908*c2c66affSColin Finck /* Not yet handled... */
909*c2c66affSColin Finck printf("Sanity checks not yet handled!\n");
910*c2c66affSColin Finck exit(1);
911*c2c66affSColin Finck }
912*c2c66affSColin Finck
913*c2c66affSColin Finck /* Check if we had SGCAP data */
914*c2c66affSColin Finck if (Entry->Cap & 2)
915*c2c66affSColin Finck {
916*c2c66affSColin Finck /* Not yet handled... */
917*c2c66affSColin Finck printf("SGCAP state not yet handled!\n");
918*c2c66affSColin Finck exit(1);
919*c2c66affSColin Finck }
920*c2c66affSColin Finck }
921*c2c66affSColin Finck
922*c2c66affSColin Finck /* Check if we have found any ScanCode in the file */
923*c2c66affSColin Finck
924*c2c66affSColin Finck if (ScanCodeCount == -1)
925*c2c66affSColin Finck {
926*c2c66affSColin Finck printf("No ScanCode found!\n");
927*c2c66affSColin Finck exit(1);
928*c2c66affSColin Finck }
929*c2c66affSColin Finck
930*c2c66affSColin Finck /* Process the scan code table */
931*c2c66affSColin Finck Entry = &LayoutData->Entry[ScanCodeCount];
932*c2c66affSColin Finck for (i = 0; i < 110; i++)
933*c2c66affSColin Finck {
934*c2c66affSColin Finck /* Get the scan code */
935*c2c66affSColin Finck CurrentCode = ScVk[i].ScanCode;
936*c2c66affSColin Finck if (CurrentCode == 0xFFFF) break;
937*c2c66affSColin Finck
938*c2c66affSColin Finck /* Check if this entry had been processed */
939*c2c66affSColin Finck if (ScVk[i].Processed)
940*c2c66affSColin Finck {
941*c2c66affSColin Finck /* Skip it */
942*c2c66affSColin Finck ScVk[i].Processed = FALSE;
943*c2c66affSColin Finck }
944*c2c66affSColin Finck else
945*c2c66affSColin Finck {
946*c2c66affSColin Finck /* Do we have too many? */
947*c2c66affSColin Finck if (++ScanCodeCount >= 110)
948*c2c66affSColin Finck {
949*c2c66affSColin Finck /* Fail */
950*c2c66affSColin Finck printf("ScanCode %02x - too many scancodes here to parse.\n", CurrentCode);
951*c2c66affSColin Finck exit(1);
952*c2c66affSColin Finck }
953*c2c66affSColin Finck
954*c2c66affSColin Finck /* Build an entry for it */
955*c2c66affSColin Finck Entry++;
956*c2c66affSColin Finck Entry->ScanCode = CurrentCode;
957*c2c66affSColin Finck Entry->VirtualKey = ScVk[i].VirtualKey;
958*c2c66affSColin Finck Entry->OriginalVirtualKey = ScVk[i].VirtualKey;
959*c2c66affSColin Finck Entry->Name = ScVk[i].Name;
960*c2c66affSColin Finck Entry->Processed = TRUE;
961*c2c66affSColin Finck Entry->LineCount = 0;
962*c2c66affSColin Finck DPRINT1("AUTOMATIC ENTRY: [%x %x %s]\n",
963*c2c66affSColin Finck Entry->VirtualKey, Entry->ScanCode, Entry->Name);
964*c2c66affSColin Finck }
965*c2c66affSColin Finck }
966*c2c66affSColin Finck
967*c2c66affSColin Finck /* Skip what's left */
968*c2c66affSColin Finck return KeyWord;
969*c2c66affSColin Finck }
970*c2c66affSColin Finck
971*c2c66affSColin Finck ULONG
DoParsing(VOID)972*c2c66affSColin Finck DoParsing(VOID)
973*c2c66affSColin Finck {
974*c2c66affSColin Finck ULONG KeyWords[KEYWORD_COUNT];
975*c2c66affSColin Finck ULONG KeyWord;
976*c2c66affSColin Finck ULONG StateCount;
977*c2c66affSColin Finck ULONG ShiftStates[8];
978*c2c66affSColin Finck PKEYNAME DescriptionData = NULL, LanguageData = NULL;
979*c2c66affSColin Finck PKEYNAME KeyNameData = NULL, KeyNameExtData = NULL, KeyNameDeadData = NULL;
980*c2c66affSColin Finck PVOID AttributeData = NULL, LigatureData = NULL, DeadKeyData = NULL;
981*c2c66affSColin Finck
982*c2c66affSColin Finck /* Parse keywords */
983*c2c66affSColin Finck gLineCount = 0;
984*c2c66affSColin Finck KeyWord = SkipLines();
985*c2c66affSColin Finck if (KeyWord >= KEYWORD_COUNT)
986*c2c66affSColin Finck {
987*c2c66affSColin Finck /* Invalid keyword count, fail */
988*c2c66affSColin Finck fclose(gfpInput);
989*c2c66affSColin Finck printf("No keywords were found in '%s'.\n", gpszFileName);
990*c2c66affSColin Finck exit(1);
991*c2c66affSColin Finck }
992*c2c66affSColin Finck
993*c2c66affSColin Finck /* Now parse the keywords */
994*c2c66affSColin Finck memset(KeyWords, 0, sizeof(KeyWords));
995*c2c66affSColin Finck while (KeyWord < (KEYWORD_COUNT - 1))
996*c2c66affSColin Finck {
997*c2c66affSColin Finck /* Save this keyword */
998*c2c66affSColin Finck KeyWords[KeyWord]++;
999*c2c66affSColin Finck
1000*c2c66affSColin Finck /* Check for duplicate entires, other than DEADKEY, which is okay */
1001*c2c66affSColin Finck if ((KeyWord != 9) && (KeyWords[KeyWord] > 1) && (Verbose))
1002*c2c66affSColin Finck {
1003*c2c66affSColin Finck /* On a verbose run, warn the user */
1004*c2c66affSColin Finck printf("The '%s' keyword appeared multiple times.\n",
1005*c2c66affSColin Finck KeyWordList[KeyWord]);
1006*c2c66affSColin Finck }
1007*c2c66affSColin Finck
1008*c2c66affSColin Finck /* Now parse this keyword */
1009*c2c66affSColin Finck switch (KeyWord)
1010*c2c66affSColin Finck {
1011*c2c66affSColin Finck /* KBD */
1012*c2c66affSColin Finck case 0:
1013*c2c66affSColin Finck
1014*c2c66affSColin Finck DPRINT1("Found KBD section\n");
1015*c2c66affSColin Finck KeyWord = DoKBD();
1016*c2c66affSColin Finck break;
1017*c2c66affSColin Finck
1018*c2c66affSColin Finck /* VERSION */
1019*c2c66affSColin Finck case 1:
1020*c2c66affSColin Finck
1021*c2c66affSColin Finck DPRINT1("Found VERSION section\n");
1022*c2c66affSColin Finck KeyWord = DoVERSION();
1023*c2c66affSColin Finck break;
1024*c2c66affSColin Finck
1025*c2c66affSColin Finck /* COPYRIGHT */
1026*c2c66affSColin Finck case 2:
1027*c2c66affSColin Finck
1028*c2c66affSColin Finck DPRINT1("Found COPYRIGHT section\n");
1029*c2c66affSColin Finck KeyWord = DoCOPYRIGHT();
1030*c2c66affSColin Finck break;
1031*c2c66affSColin Finck
1032*c2c66affSColin Finck /* COMPANY */
1033*c2c66affSColin Finck case 3:
1034*c2c66affSColin Finck
1035*c2c66affSColin Finck DPRINT1("Found COMPANY section\n");
1036*c2c66affSColin Finck KeyWord = DoCOMPANY();
1037*c2c66affSColin Finck break;
1038*c2c66affSColin Finck
1039*c2c66affSColin Finck /* LOCALENAME */
1040*c2c66affSColin Finck case 4:
1041*c2c66affSColin Finck
1042*c2c66affSColin Finck DPRINT1("Found LOCALENAME section\n");
1043*c2c66affSColin Finck KeyWord = DoLOCALENAME();
1044*c2c66affSColin Finck break;
1045*c2c66affSColin Finck
1046*c2c66affSColin Finck /* MODIFIERS */
1047*c2c66affSColin Finck case 5:
1048*c2c66affSColin Finck
1049*c2c66affSColin Finck DPRINT1("Found MODIFIERS section\n");
1050*c2c66affSColin Finck KeyWord = DoMODIFIERS();
1051*c2c66affSColin Finck break;
1052*c2c66affSColin Finck
1053*c2c66affSColin Finck /* SHIFTSTATE */
1054*c2c66affSColin Finck case 6:
1055*c2c66affSColin Finck
1056*c2c66affSColin Finck DPRINT1("Found SHIFTSTATE section\n");
1057*c2c66affSColin Finck KeyWord = DoSHIFTSTATE(&StateCount, ShiftStates);
1058*c2c66affSColin Finck if (StateCount < 2)
1059*c2c66affSColin Finck {
1060*c2c66affSColin Finck /* Fail */
1061*c2c66affSColin Finck fclose(gfpInput);
1062*c2c66affSColin Finck printf("ERROR");
1063*c2c66affSColin Finck exit(1);
1064*c2c66affSColin Finck }
1065*c2c66affSColin Finck break;
1066*c2c66affSColin Finck
1067*c2c66affSColin Finck /* ATTRIBUTES */
1068*c2c66affSColin Finck case 7:
1069*c2c66affSColin Finck
1070*c2c66affSColin Finck DPRINT1("Found ATTRIBUTES section\n");
1071*c2c66affSColin Finck KeyWord = DoATTRIBUTES(&AttributeData);
1072*c2c66affSColin Finck break;
1073*c2c66affSColin Finck
1074*c2c66affSColin Finck /* LAYOUT */
1075*c2c66affSColin Finck case 8:
1076*c2c66affSColin Finck
1077*c2c66affSColin Finck DPRINT1("Found LAYOUT section\n");
1078*c2c66affSColin Finck KeyWord = DoLAYOUT(&g_Layout,
1079*c2c66affSColin Finck &LigatureData,
1080*c2c66affSColin Finck ShiftStates,
1081*c2c66affSColin Finck StateCount);
1082*c2c66affSColin Finck break;
1083*c2c66affSColin Finck
1084*c2c66affSColin Finck /* DEADKEY */
1085*c2c66affSColin Finck case 9:
1086*c2c66affSColin Finck
1087*c2c66affSColin Finck DPRINT1("Found DEADKEY section\n");
1088*c2c66affSColin Finck KeyWord = DoDEADKEY(&DeadKeyData);
1089*c2c66affSColin Finck break;
1090*c2c66affSColin Finck
1091*c2c66affSColin Finck /* LIGATURE */
1092*c2c66affSColin Finck case 10:
1093*c2c66affSColin Finck
1094*c2c66affSColin Finck DPRINT1("Found LIGATURE section\n");
1095*c2c66affSColin Finck KeyWord = DoLIGATURE(&LigatureData);
1096*c2c66affSColin Finck break;
1097*c2c66affSColin Finck
1098*c2c66affSColin Finck /* KEYNAME */
1099*c2c66affSColin Finck case 11:
1100*c2c66affSColin Finck
1101*c2c66affSColin Finck DPRINT1("Found KEYNAME section\n");
1102*c2c66affSColin Finck KeyWord = DoKEYNAME(&KeyNameData);
1103*c2c66affSColin Finck break;
1104*c2c66affSColin Finck
1105*c2c66affSColin Finck /* KEYNAME_EXT */
1106*c2c66affSColin Finck case 12:
1107*c2c66affSColin Finck
1108*c2c66affSColin Finck DPRINT1("Found KEYNAME_EXT section\n");
1109*c2c66affSColin Finck KeyWord = DoKEYNAME(&KeyNameExtData);
1110*c2c66affSColin Finck break;
1111*c2c66affSColin Finck
1112*c2c66affSColin Finck /* KEYNAME_DEAD */
1113*c2c66affSColin Finck case 13:
1114*c2c66affSColin Finck
1115*c2c66affSColin Finck DPRINT1("Found KEYNAME_DEAD section\n");
1116*c2c66affSColin Finck KeyWord = DoKEYNAME(&KeyNameDeadData);
1117*c2c66affSColin Finck break;
1118*c2c66affSColin Finck
1119*c2c66affSColin Finck /* DESCRIPTIONS */
1120*c2c66affSColin Finck case 14:
1121*c2c66affSColin Finck
1122*c2c66affSColin Finck DPRINT1("Found DESCRIPTIONS section\n");
1123*c2c66affSColin Finck KeyWord = DoDESCRIPTIONS(&DescriptionData);
1124*c2c66affSColin Finck break;
1125*c2c66affSColin Finck
1126*c2c66affSColin Finck /* LANGUAGENAMES */
1127*c2c66affSColin Finck case 15:
1128*c2c66affSColin Finck
1129*c2c66affSColin Finck DPRINT1("Found LANGUAGENAMES section\n");
1130*c2c66affSColin Finck KeyWord = DoLANGUAGENAMES(&LanguageData);
1131*c2c66affSColin Finck break;
1132*c2c66affSColin Finck
1133*c2c66affSColin Finck /* ENDKBD */
1134*c2c66affSColin Finck case 16:
1135*c2c66affSColin Finck
1136*c2c66affSColin Finck DPRINT1("Found ENDKBD section\n");
1137*c2c66affSColin Finck KeyWord = SkipLines();
1138*c2c66affSColin Finck break;
1139*c2c66affSColin Finck
1140*c2c66affSColin Finck
1141*c2c66affSColin Finck default:
1142*c2c66affSColin Finck break;
1143*c2c66affSColin Finck }
1144*c2c66affSColin Finck }
1145*c2c66affSColin Finck
1146*c2c66affSColin Finck /* We are done */
1147*c2c66affSColin Finck fclose(gfpInput);
1148*c2c66affSColin Finck
1149*c2c66affSColin Finck /* Now enter the output phase */
1150*c2c66affSColin Finck return DoOutput(StateCount,
1151*c2c66affSColin Finck ShiftStates,
1152*c2c66affSColin Finck DescriptionData,
1153*c2c66affSColin Finck LanguageData,
1154*c2c66affSColin Finck AttributeData,
1155*c2c66affSColin Finck DeadKeyData,
1156*c2c66affSColin Finck LigatureData,
1157*c2c66affSColin Finck KeyNameData,
1158*c2c66affSColin Finck KeyNameExtData,
1159*c2c66affSColin Finck KeyNameDeadData);
1160*c2c66affSColin Finck }
1161*c2c66affSColin Finck /* EOF */
1162