2009-10-31 18:13:26 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Build Tools [Keyboard Layout Compiler]
|
|
|
|
* LICENSE: BSD - See COPYING.BSD in the top level directory
|
|
|
|
* FILE: tools/kbdtool/parser.c
|
|
|
|
* PURPOSE: Parsing Logic
|
|
|
|
* PROGRAMMERS: ReactOS Foundation
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <host/typedefs.h>
|
|
|
|
|
2009-11-01 17:43:51 +00:00
|
|
|
typedef struct tagKEYNAME
|
|
|
|
{
|
2009-11-01 18:26:53 +00:00
|
|
|
ULONG Code;
|
2009-11-01 18:17:30 +00:00
|
|
|
PCHAR Name;
|
2009-11-01 17:43:51 +00:00
|
|
|
struct tagKEYNAME* Next;
|
|
|
|
} KEYNAME, *PKEYNAME;
|
|
|
|
|
2009-11-01 19:04:42 +00:00
|
|
|
typedef struct tagSCVK
|
|
|
|
{
|
|
|
|
USHORT ScanCode;
|
|
|
|
USHORT VirtualKey;
|
|
|
|
PCHAR Name;
|
2009-11-03 22:57:26 +00:00
|
|
|
BOOLEAN Processed;
|
2009-11-01 19:04:42 +00:00
|
|
|
} SCVK, *PSCVK;
|
|
|
|
|
2009-11-03 22:57:26 +00:00
|
|
|
typedef struct tagVKNAME
|
|
|
|
{
|
|
|
|
ULONG VirtualKey;
|
|
|
|
PCHAR Name;
|
|
|
|
} VKNAME, *PVKNAME;
|
|
|
|
|
|
|
|
typedef struct tagLAYOUTENTRY
|
|
|
|
{
|
|
|
|
USHORT ScanCode;
|
|
|
|
UCHAR VirtualKey;
|
|
|
|
UCHAR OriginalVirtualKey;
|
|
|
|
UCHAR Cap;
|
|
|
|
ULONG StateCount;
|
|
|
|
ULONG CharData[8];
|
|
|
|
ULONG DeadCharData[8];
|
|
|
|
ULONG OtherCharData[8];
|
|
|
|
struct LAYOUTENTRY* CapData;
|
|
|
|
PCHAR Name;
|
|
|
|
ULONG Processed;
|
|
|
|
ULONG LineCount;
|
|
|
|
} LAYOUTENTRY, *PLAYOUTENTRY;
|
|
|
|
|
|
|
|
typedef struct tagLAYOUT
|
|
|
|
{
|
|
|
|
LAYOUTENTRY Entry[110];
|
|
|
|
} LAYOUT, *PLAYOUT;
|
|
|
|
|
2009-10-31 18:13:26 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2009-10-31 20:03:43 +00:00
|
|
|
#define KEYWORD_COUNT 17
|
|
|
|
|
2009-10-31 21:54:26 +00:00
|
|
|
extern BOOLEAN Verbose, UnicodeFile;
|
2009-10-31 20:03:43 +00:00
|
|
|
extern PCHAR gpszFileName;
|
|
|
|
extern FILE* gfpInput;
|
|
|
|
CHAR gBuf[256];
|
2009-10-31 21:54:26 +00:00
|
|
|
CHAR gKBDName[10];
|
2009-10-31 22:18:28 +00:00
|
|
|
CHAR gCopyright[256];
|
2009-10-31 21:54:26 +00:00
|
|
|
CHAR gDescription[256];
|
2009-10-31 22:18:28 +00:00
|
|
|
CHAR gCompany[256];
|
|
|
|
CHAR gLocaleName[256];
|
2009-10-31 21:54:26 +00:00
|
|
|
ULONG gID = 0;
|
2009-10-31 22:18:28 +00:00
|
|
|
ULONG gKbdLayoutVersion;
|
2009-11-03 22:57:26 +00:00
|
|
|
LAYOUT g_Layout;
|
2009-10-31 20:03:43 +00:00
|
|
|
ULONG gLineCount;
|
|
|
|
PCHAR KeyWordList[KEYWORD_COUNT] =
|
|
|
|
{
|
|
|
|
"KBD",
|
|
|
|
"VERSION",
|
|
|
|
"COPYRIGHT",
|
|
|
|
"COMPANY",
|
|
|
|
"LOCALENAME",
|
|
|
|
"MODIIFERS",
|
|
|
|
"SHIFTSTATE",
|
|
|
|
"ATTRIBUTES",
|
|
|
|
"LAYOUT",
|
|
|
|
"DEADKEY",
|
|
|
|
"LIGATURE",
|
|
|
|
"KEYNAME",
|
|
|
|
"KEYNAME_EXT",
|
|
|
|
"KEYNAME_DEAD",
|
|
|
|
"DESCRIPTIONS",
|
|
|
|
"LANGUAGENAMES",
|
|
|
|
"ENDKBD",
|
|
|
|
};
|
|
|
|
|
2009-11-01 19:04:42 +00:00
|
|
|
/* ISO 110-key Keyboard Scancode to Virtual Key Conversion Table */
|
|
|
|
SCVK ScVk[] =
|
|
|
|
{
|
2009-11-03 22:57:26 +00:00
|
|
|
{0x02, '1', NULL, FALSE},
|
|
|
|
{0x03, '2', NULL, FALSE},
|
|
|
|
{0x04, '3', NULL, FALSE},
|
|
|
|
{0x05, '4', NULL, FALSE},
|
|
|
|
{0x06, '5', NULL, FALSE},
|
|
|
|
{0x07, '6', NULL, FALSE},
|
|
|
|
{0x08, '7', NULL, FALSE},
|
|
|
|
{0x09, '8', NULL, FALSE},
|
|
|
|
{0x0a, '9', NULL, FALSE},
|
|
|
|
{0x0b, '0', NULL, FALSE},
|
|
|
|
{0x0c, 0xbd, NULL, FALSE},
|
|
|
|
{0x0d, 0xbb, NULL, FALSE},
|
|
|
|
{0x10, 'Q', NULL, FALSE},
|
|
|
|
{0x11, 'W', NULL, FALSE},
|
|
|
|
{0x12, 'E', NULL, FALSE},
|
|
|
|
{0x13, 'R', NULL, FALSE},
|
|
|
|
{0x14, 'T', NULL, FALSE},
|
|
|
|
{0x15, 'Y', NULL, FALSE},
|
|
|
|
{0x16, 'U', NULL, FALSE},
|
|
|
|
{0x17, 'I', NULL, FALSE},
|
|
|
|
{0x18, 'O', NULL, FALSE},
|
|
|
|
{0x19, 'P', NULL, FALSE},
|
|
|
|
{0x1a, 0xdb, NULL, FALSE},
|
|
|
|
{0x1b, 0xdd, NULL, FALSE},
|
|
|
|
{0x1e, 'A', NULL, FALSE},
|
|
|
|
{0x1f, 'S', NULL, FALSE},
|
|
|
|
{0x20, 'D', NULL, FALSE},
|
|
|
|
{0x21, 'F', NULL, FALSE},
|
|
|
|
{0x22, 'G', NULL, FALSE},
|
|
|
|
{0x23, 'H', NULL, FALSE},
|
|
|
|
{0x24, 'J', NULL, FALSE},
|
|
|
|
{0x25, 'K', NULL, FALSE},
|
|
|
|
{0x26, 'L', NULL, FALSE},
|
|
|
|
{0x27, 0xba, NULL, FALSE},
|
|
|
|
{0x28, 0xde, NULL, FALSE},
|
|
|
|
{0x29, 0xc0, NULL, FALSE},
|
|
|
|
{0x2b, 0xdc, NULL, FALSE},
|
|
|
|
{0x2c, 'Z', NULL, FALSE},
|
|
|
|
{0x2d, 'X', NULL, FALSE},
|
|
|
|
{0x2e, 'C', NULL, FALSE},
|
|
|
|
{0x2f, 'V', NULL, FALSE},
|
|
|
|
{0x30, 'B', NULL, FALSE},
|
|
|
|
{0x31, 'N', NULL, FALSE},
|
|
|
|
{0x32, 'M', NULL, FALSE},
|
|
|
|
{0x33, 0xbc, NULL, FALSE},
|
|
|
|
{0x34, 0xbe, NULL, FALSE},
|
|
|
|
{0x35, 0xbf, NULL, FALSE},
|
|
|
|
{0x53, 0x6e, NULL, FALSE},
|
|
|
|
{0x56, 0xe2, NULL, FALSE},
|
|
|
|
{0x73, 0xc1, NULL, FALSE},
|
|
|
|
{0x7e, 0xc2, NULL, FALSE},
|
|
|
|
{0xe010, 0xb1, "Speedracer: Previous Track", FALSE},
|
|
|
|
{0xe019, 0xb0, "Speedracer: Next Track", FALSE},
|
|
|
|
{0xe01d, 0xa3, "RControl", FALSE},
|
|
|
|
{0xe020, 0xad, "Speedracer: Volume Mute", FALSE},
|
|
|
|
{0xe021, 0xb7, "Speedracer: Launch App 2", FALSE},
|
|
|
|
{0xe022, 0xb3, "Speedracer: Media Play/Pause", FALSE},
|
|
|
|
{0xe024, 0xb2, "Speedracer: Media Stop", FALSE},
|
|
|
|
{0xe02e, 0xae, "Speedracer: Volume Up", FALSE},
|
|
|
|
{0xe030, 0xaf, "Speedracer: Volume Down", FALSE},
|
|
|
|
{0xe032, 0xac, "Speedracer: Browser Home", FALSE},
|
|
|
|
{0xe035, 0x6f, "Numpad Divide", FALSE},
|
|
|
|
{0xe037, 0x2c, "Snapshot", FALSE},
|
|
|
|
{0xe038, 0xa5, "RMenu", FALSE},
|
|
|
|
{0xe047, 0x24, "Home", FALSE},
|
|
|
|
{0xe048, 0x26, "Up", FALSE},
|
|
|
|
{0xe049, 0x21, "Prior", FALSE},
|
|
|
|
{0xe04b, 0x25, "Left", FALSE},
|
|
|
|
{0xe04d, 0x27, "Right", FALSE},
|
|
|
|
{0xe04f, 0x23, "End", FALSE},
|
|
|
|
{0xe050, 0x28, "Down", FALSE},
|
|
|
|
{0xe051, 0x22, "Next", FALSE},
|
|
|
|
{0xe052, 0x2d, "Insert", FALSE},
|
|
|
|
{0xe053, 0x2e, "Delete", FALSE},
|
|
|
|
{0xe05b, 0x5b, "Left Win", FALSE},
|
|
|
|
{0xe05c, 0x5c, "Right Win", FALSE},
|
|
|
|
{0xe05d, 0x5d, "Application", FALSE},
|
|
|
|
{0xe05e, 0xff, "Power", FALSE},
|
|
|
|
{0xe05f, 0x5f, "Speedracer: Sleep", FALSE},
|
|
|
|
{0xe060, 0xff, "BAD SCANCODE", FALSE},
|
|
|
|
{0xe061, 0xff, "BAD SCANCODE", FALSE},
|
|
|
|
{0xe065, 0xaa, "Speedracer: Browser Search", FALSE},
|
|
|
|
{0xe066, 0xab, "Speedracer: Browser Favorites", FALSE},
|
|
|
|
{0xe067, 0xa8, "Speedracer: Browser Refresh", FALSE},
|
|
|
|
{0xe068, 0xa9, "Speedracer: Browser Stop", FALSE},
|
|
|
|
{0xe069, 0xa7, "Speedracer: Browser Foward", FALSE},
|
|
|
|
{0xe06a, 0xa6, "Speedracer: Browser Back", FALSE},
|
|
|
|
{0xe06b, 0xb6, "Speedracer: Launch App 1", FALSE},
|
|
|
|
{0xe06c, 0xb4, "Speedracer: Launch Mail", FALSE},
|
|
|
|
{0xe06d, 0xb5, "Speedracer: Launch Media Selector", FALSE},
|
|
|
|
{0x53, 0x6e, NULL, FALSE},
|
|
|
|
{0x0e, 0x08, NULL, FALSE},
|
|
|
|
{0x01, 0x1b, NULL, FALSE},
|
|
|
|
{0xe01c, 0x0d, "Numpad Enter", FALSE},
|
|
|
|
{0x1c, 0x0d, NULL, FALSE},
|
|
|
|
{0x39, 0x20, NULL, FALSE},
|
|
|
|
{0xe046, 0x03, "Break (Ctrl + Pause)", FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE},
|
|
|
|
{0xFFFF, 0x00, NULL, FALSE}
|
|
|
|
};
|
|
|
|
|
|
|
|
VKNAME VKName[] =
|
|
|
|
{
|
|
|
|
{0x08, "BACK"},
|
|
|
|
{0x03, "CANCEL"},
|
|
|
|
{0x1b, "ESCAPE"},
|
|
|
|
{0x0d, "RETURN"},
|
|
|
|
{0x20, "SPACE"},
|
|
|
|
{0x6e, "DECIMAL"},
|
|
|
|
{0xba, "OEM_1"},
|
|
|
|
{0xbb, "OEM_PLUS"},
|
|
|
|
{0xbc, "OEM_COMMA"},
|
|
|
|
{0xbd, "OEM_MINUS"},
|
|
|
|
{0xbe, "OEM_PERIOD"},
|
|
|
|
{0xbf, "OEM_2"},
|
|
|
|
{0xc0, "OEM_3"},
|
|
|
|
{0xdb, "OEM_4"},
|
|
|
|
{0xdc, "OEM_5"},
|
|
|
|
{0xdd, "OEM_6"},
|
|
|
|
{0xde, "OEM_7"},
|
|
|
|
{0xdf, "OEM_8"},
|
|
|
|
{0xe2, "OEM_102"},
|
|
|
|
{0xc1, "ABNT_C1"},
|
|
|
|
{0xc2, "ABNT_C2"},
|
|
|
|
{0x10, "SHIFT"},
|
|
|
|
{0xa0, "LSHIFT"},
|
|
|
|
{0xa1, "RSHIFT"},
|
|
|
|
{0x12, "MENU"},
|
|
|
|
{0xa4, "LMENU"},
|
|
|
|
{0xa5, "RMENU"},
|
|
|
|
{0x11, "CONTROL"},
|
|
|
|
{0xa2, "LCONTROL"},
|
|
|
|
{0xa3, "RCONTROL"},
|
|
|
|
{0x6c, "SEPARATOR"},
|
|
|
|
{0xe4, "ICO_00"},
|
|
|
|
{0x2e, "DELETE"},
|
|
|
|
{0x2d, "INSERT"},
|
|
|
|
{0xe5, "GROUPSHIFT"},
|
|
|
|
{0xe6, "RGROUPSHIFT"}
|
2009-11-01 19:04:42 +00:00
|
|
|
};
|
|
|
|
|
2009-11-03 22:57:26 +00:00
|
|
|
|
2009-10-31 18:13:26 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
2009-10-31 20:03:43 +00:00
|
|
|
ULONG
|
|
|
|
isKeyWord(PCHAR p)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
/* Check if we know this keyword */
|
|
|
|
for (i = 0; i < KEYWORD_COUNT; i++) if (strcmp(KeyWordList[i], p) == 0) break;
|
|
|
|
|
|
|
|
/* If we didn't find anything, i will be KEYWORD_COUNT, which is invalid */
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-11-03 22:57:26 +00:00
|
|
|
ULONG
|
|
|
|
getVKNum(IN PCHAR p)
|
|
|
|
{
|
|
|
|
ULONG Length;
|
|
|
|
ULONG i;
|
|
|
|
ULONG KeyNumber;
|
|
|
|
|
|
|
|
/* Compute the length of the string */
|
|
|
|
Length = strlen(p);
|
|
|
|
if (!Length) return -1;
|
|
|
|
|
|
|
|
/* Check if this is is a simple key */
|
|
|
|
if (Length == 1)
|
|
|
|
{
|
|
|
|
/* If it's a number, return it now */
|
|
|
|
if ((*p >= '0') && (*p <= '9')) return *p;
|
|
|
|
|
|
|
|
/* Otherwise, convert the letter to upper case */
|
|
|
|
*p = toupper(*p);
|
|
|
|
|
|
|
|
/* And make sure it's a valid letter */
|
|
|
|
if ((*p >= 'A') && (*p <='Z')) return *p;
|
|
|
|
|
|
|
|
/* Otherwise, fail */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, scan our virtual key names */
|
|
|
|
for (i = 0; i < 36; i++)
|
|
|
|
{
|
|
|
|
/* Check if we have a match */
|
|
|
|
if (!strcmp(VKName[i].Name, p)) return VKName[i].VirtualKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is a hex string */
|
|
|
|
if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X')))
|
|
|
|
{
|
|
|
|
/* Get the key number from the hex string */
|
|
|
|
*(p + 1) = 'x';
|
|
|
|
if (sscanf(p, "0x%x", &KeyNumber) == 1) return KeyNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No hope: fail */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-10-31 20:03:43 +00:00
|
|
|
BOOLEAN
|
|
|
|
NextLine(PCHAR LineBuffer,
|
|
|
|
ULONG BufferSize,
|
|
|
|
FILE *File)
|
|
|
|
{
|
|
|
|
PCHAR p, pp;
|
|
|
|
|
|
|
|
/* Scan each line */
|
|
|
|
while (fgets(LineBuffer, BufferSize, File))
|
|
|
|
{
|
|
|
|
/* Remember it */
|
|
|
|
gLineCount++;
|
|
|
|
|
|
|
|
/* Reset the pointer at the beginning of the line */
|
|
|
|
p = LineBuffer;
|
|
|
|
|
|
|
|
/* Now bypass all whitespace (and tabspace) */
|
|
|
|
while ((*p) && ((*p == ' ') || (*p == '\t'))) p++;
|
|
|
|
|
|
|
|
/* If this is an old-style comment, skip the line */
|
|
|
|
if (*p == ';') continue;
|
|
|
|
|
|
|
|
/* Otherwise, check for new-style comment */
|
|
|
|
pp = strstr(p, "//");
|
|
|
|
if (pp)
|
|
|
|
{
|
|
|
|
/* We have a comment, so terminate there (unless the whole line is one) */
|
|
|
|
if (pp == p) continue;
|
|
|
|
*pp = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No comment, so find the new line and terminate there */
|
|
|
|
p = strchr(p, '\n');
|
|
|
|
if (p) *p = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We have a line! */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No line found */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
SkipLines(VOID)
|
|
|
|
{
|
|
|
|
ULONG KeyWord;
|
|
|
|
CHAR KeyWordChars[32];
|
|
|
|
|
|
|
|
/* Scan each line, skipping it if it's not a keyword */
|
|
|
|
while (NextLine(gBuf, sizeof(gBuf), gfpInput))
|
|
|
|
{
|
|
|
|
/* Read a single word */
|
|
|
|
if (sscanf(gBuf, "%s", KeyWordChars) == 1)
|
|
|
|
{
|
|
|
|
/* If the word is a keyword, stop skipping lines */
|
|
|
|
KeyWord = isKeyWord(KeyWordChars);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) return KeyWord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We skipped all the possible lines, not finding anything */
|
|
|
|
return KEYWORD_COUNT;
|
|
|
|
}
|
|
|
|
|
2009-10-31 20:24:33 +00:00
|
|
|
ULONG
|
|
|
|
DoKBD(VOID)
|
|
|
|
{
|
2009-10-31 21:54:26 +00:00
|
|
|
/* On Unicode files, we need to find the Unicode marker (FEEF) */
|
|
|
|
ASSERT(UnicodeFile == FALSE);
|
|
|
|
|
|
|
|
/* Initial values */
|
|
|
|
*gKBDName = '\0';
|
|
|
|
*gDescription = '\0';
|
|
|
|
|
|
|
|
/* Scan for the values */
|
|
|
|
if (sscanf(gBuf, "KBD %8s \"%40[^\"]\" %d", gKBDName, gDescription, &gID) < 2)
|
|
|
|
{
|
|
|
|
/* Couldn't find them */
|
|
|
|
printf("Unable to read keyboard name or description.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("KBD Name: [%8s] Description: [%40s] ID: [%d]\n", gKBDName, gDescription, gID);
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoVERSION(VOID)
|
2009-10-31 22:18:28 +00:00
|
|
|
{
|
|
|
|
/* Scan for the value */
|
|
|
|
if (sscanf(gBuf, "VERSION %d", &gKbdLayoutVersion) < 1)
|
|
|
|
{
|
|
|
|
/* Couldn't find them */
|
|
|
|
printf("Unable to read keyboard version information.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("VERSION [%d]\n", gKbdLayoutVersion);
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoCOPYRIGHT(VOID)
|
|
|
|
{
|
2009-10-31 22:18:28 +00:00
|
|
|
/* Initial values */
|
|
|
|
*gCopyright = '\0';
|
|
|
|
|
|
|
|
/* Scan for the value */
|
|
|
|
if (sscanf(gBuf, "COPYRIGHT \"%40[^\"]\"", gCopyright) < 1)
|
|
|
|
{
|
|
|
|
/* Couldn't find them */
|
|
|
|
printf("Unable to read the specified COPYRIGHT string.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("COPYRIGHT [%40s]\n", gCopyright);
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoCOMPANY(VOID)
|
|
|
|
{
|
2009-10-31 22:18:28 +00:00
|
|
|
/* Initial values */
|
|
|
|
*gCompany = '\0';
|
|
|
|
|
|
|
|
/* Scan for the value */
|
|
|
|
if (sscanf(gBuf, "COMPANY \"%85[^\"]\"", gCompany) < 1)
|
|
|
|
{
|
|
|
|
/* Couldn't find them */
|
|
|
|
printf("Unable to read the specified COMPANY name.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("COMPANY [%85s]\n", gCompany);
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoLOCALENAME(VOID)
|
|
|
|
{
|
2009-10-31 22:18:28 +00:00
|
|
|
/* Initial values */
|
|
|
|
*gLocaleName = '\0';
|
|
|
|
|
|
|
|
/* Scan for the value */
|
|
|
|
if (sscanf(gBuf, "LOCALENAME \"%40[^\"]\"", gLocaleName) < 1)
|
|
|
|
{
|
|
|
|
/* Couldn't find them */
|
|
|
|
printf("Unable to read the specified COPYRIGHT string.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("LOCALENAME [%40s]\n", gLocaleName);
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
2009-11-01 17:43:51 +00:00
|
|
|
DoDESCRIPTIONS(IN PKEYNAME* DescriptionData)
|
2009-10-31 20:24:33 +00:00
|
|
|
{
|
2009-11-01 17:43:51 +00:00
|
|
|
ULONG KeyWord = 0;
|
|
|
|
CHAR Token[32];
|
|
|
|
ULONG LanguageCode;
|
|
|
|
PCHAR p, pp;
|
|
|
|
PKEYNAME Description;
|
|
|
|
|
|
|
|
/* Assume nothing */
|
|
|
|
*DescriptionData = 0;
|
|
|
|
|
|
|
|
/* Start scanning */
|
|
|
|
while (NextLine(gBuf, 256, gfpInput))
|
|
|
|
{
|
|
|
|
/* Search for token */
|
|
|
|
if (sscanf(gBuf, "%s", Token) != 1) continue;
|
|
|
|
|
|
|
|
/* Make sure it's not just a comment */
|
|
|
|
if (*Token == ';') continue;
|
|
|
|
|
|
|
|
/* Make sure it's not a keyword */
|
|
|
|
KeyWord = isKeyWord(Token);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) break;
|
|
|
|
|
|
|
|
/* Now scan for the language code */
|
|
|
|
if (sscanf(Token, " %4x", &LanguageCode) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("An invalid LANGID was specified.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now get the actual description */
|
|
|
|
if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("A language description is missing.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the description string and find the ending */
|
|
|
|
p = strstr(gBuf, Token);
|
|
|
|
pp = strchr(p, '\n');
|
|
|
|
if (!pp) pp = strchr(p, '\r');
|
|
|
|
|
|
|
|
/* Terminate the description string here */
|
|
|
|
if (pp) *pp = 0;
|
|
|
|
|
|
|
|
/* Now allocate the description */
|
|
|
|
Description = malloc(sizeof(KEYNAME));
|
|
|
|
if (!Description)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out the structure */
|
2009-11-01 18:26:53 +00:00
|
|
|
Description->Code = LanguageCode;
|
2009-11-01 18:17:30 +00:00
|
|
|
Description->Name = strdup(p);
|
2009-11-01 17:43:51 +00:00
|
|
|
Description->Next = NULL;
|
|
|
|
|
|
|
|
/* Debug only */
|
2009-11-01 18:26:53 +00:00
|
|
|
DPRINT1("LANGID: [%4x] Description: [%s]\n", Description->Code, Description->Name);
|
2009-11-01 17:43:51 +00:00
|
|
|
|
|
|
|
/* Point to it and advance the pointer */
|
|
|
|
*DescriptionData = Description;
|
|
|
|
DescriptionData = &Description->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are done */
|
|
|
|
return KeyWord;
|
2009-10-31 20:24:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
2009-11-01 18:17:30 +00:00
|
|
|
DoLANGUAGENAMES(IN PKEYNAME* LanguageData)
|
2009-10-31 20:24:33 +00:00
|
|
|
{
|
2009-11-01 18:17:30 +00:00
|
|
|
ULONG KeyWord = 0;
|
|
|
|
CHAR Token[32];
|
|
|
|
ULONG LanguageCode;
|
|
|
|
PCHAR p, pp;
|
|
|
|
PKEYNAME Language;
|
|
|
|
|
|
|
|
/* Assume nothing */
|
|
|
|
*LanguageData = 0;
|
|
|
|
|
|
|
|
/* Start scanning */
|
|
|
|
while (NextLine(gBuf, 256, gfpInput))
|
|
|
|
{
|
|
|
|
/* Search for token */
|
|
|
|
if (sscanf(gBuf, "%s", Token) != 1) continue;
|
|
|
|
|
|
|
|
/* Make sure it's not just a comment */
|
|
|
|
if (*Token == ';') continue;
|
|
|
|
|
|
|
|
/* Make sure it's not a keyword */
|
|
|
|
KeyWord = isKeyWord(Token);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) break;
|
|
|
|
|
|
|
|
/* Now scan for the language code */
|
|
|
|
if (sscanf(Token, " %4x", &LanguageCode) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("An invalid LANGID was specified.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now get the actual language */
|
|
|
|
if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("A language name is missing\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the language string and find the ending */
|
|
|
|
p = strstr(gBuf, Token);
|
|
|
|
pp = strchr(p, '\n');
|
|
|
|
if (!pp) pp = strchr(p, '\r');
|
|
|
|
|
|
|
|
/* Terminate the language string here */
|
|
|
|
if (pp) *pp = 0;
|
|
|
|
|
|
|
|
/* Now allocate the language */
|
|
|
|
Language = malloc(sizeof(KEYNAME));
|
|
|
|
if (!Language)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out the structure */
|
2009-11-01 18:26:53 +00:00
|
|
|
Language->Code = LanguageCode;
|
2009-11-01 18:17:30 +00:00
|
|
|
Language->Name = strdup(p);
|
|
|
|
Language->Next = NULL;
|
|
|
|
|
|
|
|
/* Debug only */
|
2009-11-01 18:26:53 +00:00
|
|
|
DPRINT1("LANGID: [%4x] Name: [%s]\n", Language->Code, Language->Name);
|
2009-11-01 18:17:30 +00:00
|
|
|
|
|
|
|
/* Point to it and advance the pointer */
|
|
|
|
*LanguageData = Language;
|
|
|
|
LanguageData = &Language->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are done */
|
|
|
|
return KeyWord;
|
2009-10-31 20:24:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
2009-11-01 18:26:53 +00:00
|
|
|
DoKEYNAME(IN PKEYNAME* KeyNameData)
|
2009-10-31 20:24:33 +00:00
|
|
|
{
|
2009-11-01 18:26:53 +00:00
|
|
|
ULONG KeyWord = 0;
|
|
|
|
CHAR Token[32];
|
|
|
|
ULONG CharacterCode;
|
|
|
|
PCHAR p, pp;
|
|
|
|
PKEYNAME KeyName;
|
|
|
|
|
|
|
|
/* Assume nothing */
|
|
|
|
*KeyNameData = 0;
|
|
|
|
|
|
|
|
/* Start scanning */
|
|
|
|
while (NextLine(gBuf, 256, gfpInput))
|
|
|
|
{
|
|
|
|
/* Search for token */
|
|
|
|
if (sscanf(gBuf, "%s", Token) != 1) continue;
|
|
|
|
|
|
|
|
/* Make sure it's not just a comment */
|
|
|
|
if (*Token == ';') continue;
|
|
|
|
|
|
|
|
/* Make sure it's not a keyword */
|
|
|
|
KeyWord = isKeyWord(Token);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) break;
|
|
|
|
|
|
|
|
/* Now scan for the character code */
|
|
|
|
if (sscanf(Token, " %4x", &CharacterCode) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("An invalid character code was specified.\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now get the actual key name */
|
|
|
|
if (sscanf(gBuf, " %*4x %s[^\n]", Token) != 1)
|
|
|
|
{
|
|
|
|
/* Skip */
|
|
|
|
printf("A key name is missing\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the key name string and find the ending */
|
|
|
|
p = strstr(gBuf, Token);
|
|
|
|
pp = strchr(p, '\n');
|
|
|
|
if (!pp) pp = strchr(p, '\r');
|
|
|
|
|
|
|
|
/* Terminate the key name string here */
|
|
|
|
if (pp) *pp = 0;
|
|
|
|
|
|
|
|
/* Now allocate the language */
|
|
|
|
KeyName = malloc(sizeof(KEYNAME));
|
|
|
|
if (!KeyName)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
printf("Unable to allocate the KEYNAME struct (out of memory?).\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out the structure */
|
|
|
|
KeyName->Code = CharacterCode;
|
|
|
|
KeyName->Name = strdup(p);
|
|
|
|
KeyName->Next = NULL;
|
|
|
|
|
|
|
|
/* Debug only */
|
|
|
|
DPRINT1("CHARCODE: [%4x] Name: [%s]\n", KeyName->Code, KeyName->Name);
|
|
|
|
|
|
|
|
/* Point to it and advance the pointer */
|
|
|
|
*KeyNameData = KeyName;
|
|
|
|
KeyNameData = &KeyName->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are done */
|
|
|
|
return KeyWord;
|
2009-10-31 20:24:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoSHIFTSTATE(IN PULONG StateCount,
|
|
|
|
IN OUT PULONG ShiftStates)
|
|
|
|
{
|
2009-11-01 15:46:36 +00:00
|
|
|
ULONG KeyWord;
|
|
|
|
ULONG i;
|
|
|
|
ULONG ShiftState;
|
|
|
|
CHAR Token[32];
|
|
|
|
|
|
|
|
/* Reset the shift states */
|
|
|
|
for (i = 0; i < 8; i++) ShiftStates[i] = -1;
|
|
|
|
|
|
|
|
/* Start with no states */
|
|
|
|
*StateCount = 0;
|
|
|
|
|
|
|
|
/* Scan for shift states */
|
|
|
|
while (NextLine(gBuf, 256, gfpInput))
|
|
|
|
{
|
|
|
|
/* Search for token */
|
|
|
|
if (sscanf(gBuf, "%s", Token) != 1) continue;
|
|
|
|
|
|
|
|
/* Make sure it's not a keyword */
|
|
|
|
KeyWord = isKeyWord(Token);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) break;
|
|
|
|
|
|
|
|
/* Now scan for the shift state */
|
2009-11-01 17:43:51 +00:00
|
|
|
if (sscanf(gBuf, " %1s[012367]", Token) != 1)
|
2009-11-01 15:46:36 +00:00
|
|
|
{
|
|
|
|
/* We failed -- should we warn? */
|
2009-11-01 17:43:51 +00:00
|
|
|
if (Verbose) printf("An invalid shift state '%s' was found (use 0, 1, 2, 3, 6, or 7.)\n", Token);
|
2009-11-01 15:46:36 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now read the state */
|
|
|
|
ShiftState = atoi(Token);
|
2009-11-01 18:26:53 +00:00
|
|
|
|
2009-11-01 15:46:36 +00:00
|
|
|
/* Scan existing states */
|
|
|
|
for (i = 0; i < *StateCount; i++)
|
|
|
|
{
|
|
|
|
/* Check for duplicate */
|
|
|
|
if ((ShiftStates[i] == ShiftState) && (Verbose))
|
|
|
|
{
|
|
|
|
/* Warn user */
|
2009-11-01 17:43:51 +00:00
|
|
|
printf("The state '%d' was duplicated for this Virtual Key.\n", ShiftStates[i]);
|
2009-11-01 15:46:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure we won't overflow */
|
|
|
|
if (*StateCount < 8)
|
|
|
|
{
|
|
|
|
/* Save this state */
|
|
|
|
ShiftStates[(*StateCount)++] = ShiftState;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Too many states -- should we warn? */
|
2009-11-01 17:43:51 +00:00
|
|
|
if (Verbose) printf("There were too many states (you defined %d).\n", *StateCount);
|
2009-11-01 15:46:36 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-01 18:26:53 +00:00
|
|
|
|
2009-11-01 15:46:36 +00:00
|
|
|
/* Debug only */
|
2009-11-01 17:43:51 +00:00
|
|
|
DPRINT1("Found %d Shift States: [", *StateCount);
|
|
|
|
for (i = 0; i < *StateCount; i++) DPRINT1("%d ", ShiftStates[i]);
|
|
|
|
DPRINT1("]\n");
|
2009-11-01 15:46:36 +00:00
|
|
|
|
|
|
|
/* We are done */
|
|
|
|
return KeyWord;
|
2009-10-31 20:24:33 +00:00
|
|
|
}
|
|
|
|
|
2009-11-01 18:26:53 +00:00
|
|
|
ULONG
|
|
|
|
DoLIGATURE(PVOID LigatureData)
|
|
|
|
{
|
2009-11-01 18:30:57 +00:00
|
|
|
printf("LIGATURE support is not yet implemented. Please bug Arch to fix it\n");
|
2009-11-01 18:26:53 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoATTRIBUTES(PVOID AttributeData)
|
|
|
|
{
|
2009-11-01 18:30:57 +00:00
|
|
|
printf("ATTRIBUTES support is not yet implemented. Please bug Arch to fix it\n");
|
2009-11-01 18:26:53 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoMODIFIERS(VOID)
|
2009-11-01 18:30:57 +00:00
|
|
|
{
|
|
|
|
printf("MODIFIERS support is not yet implemented. Please bug Arch to fix it\n");
|
2009-11-01 18:26:53 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
DoDEADKEY(PVOID DeadKeyData)
|
|
|
|
{
|
2009-11-01 18:30:57 +00:00
|
|
|
printf("DEADKEY support is not yet implemented. Please bug Arch to fix it\n");
|
2009-11-01 18:26:53 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
2009-10-31 20:24:33 +00:00
|
|
|
ULONG
|
2009-11-03 22:57:26 +00:00
|
|
|
DoLAYOUT(IN PLAYOUT LayoutData,
|
2009-10-31 20:24:33 +00:00
|
|
|
IN PVOID LigatureData,
|
|
|
|
IN PULONG ShiftStates,
|
|
|
|
IN ULONG StateCount)
|
|
|
|
{
|
2009-11-03 22:57:26 +00:00
|
|
|
CHAR Token[32];
|
|
|
|
CHAR Cap[8];
|
|
|
|
ULONG KeyWord;
|
|
|
|
ULONG ScanCode, CurrentCode;
|
|
|
|
ULONG TokenCount;
|
|
|
|
ULONG VirtualKey;
|
|
|
|
ULONG i;
|
|
|
|
BOOLEAN FullEntry;
|
|
|
|
ULONG ScanCodeCount = -1;
|
|
|
|
PLAYOUTENTRY Entry;
|
|
|
|
|
|
|
|
/* Only attempt this is Verbose is enabled (FOR DEBUGGING ONLY) */
|
|
|
|
if (!Verbose) return SkipLines();
|
|
|
|
|
|
|
|
/* Zero out the layout */
|
|
|
|
memset(LayoutData, 0, sizeof(LAYOUT));
|
|
|
|
|
|
|
|
/* Read each line */
|
|
|
|
Entry = &LayoutData->Entry[0];
|
|
|
|
while (NextLine(gBuf, 256, gfpInput))
|
|
|
|
{
|
|
|
|
/* Search for token */
|
|
|
|
if (sscanf(gBuf, "%s", Token) != 1) continue;
|
|
|
|
|
|
|
|
/* Make sure it's not just a comment */
|
|
|
|
if (*Token == ';') continue;
|
|
|
|
|
|
|
|
/* Make sure it's not a keyword */
|
|
|
|
KeyWord = isKeyWord(Token);
|
|
|
|
if (KeyWord < KEYWORD_COUNT) break;
|
|
|
|
|
|
|
|
/* Now read the entry */
|
|
|
|
TokenCount = sscanf(gBuf, " %x %s %s", &ScanCode, Token, Cap);
|
|
|
|
if (TokenCount == 3)
|
|
|
|
{
|
|
|
|
/* Full entry with cap */
|
|
|
|
FullEntry = TRUE;
|
|
|
|
}
|
|
|
|
else if (TokenCount != 2)
|
|
|
|
{
|
|
|
|
/* Fail, invalid LAYOUT entry */
|
|
|
|
printf("There are not enough columns in the layout list.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Simplified layout with no cap */
|
|
|
|
FullEntry = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One more */
|
|
|
|
Entry++;
|
|
|
|
if (++ScanCodeCount >= 110)
|
|
|
|
{
|
|
|
|
/* Too many! */
|
|
|
|
printf("ScanCode %02x - too many scancodes here to parse.\n", ScanCode);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out this entry */
|
|
|
|
Entry->ScanCode = ScanCode;
|
|
|
|
Entry->LineCount = gLineCount;
|
|
|
|
|
|
|
|
/* Loop scancode table */
|
|
|
|
for (i = 0; i < 110; i++)
|
|
|
|
{
|
|
|
|
/* Get the current code */
|
|
|
|
CurrentCode = ScVk[i].ScanCode;
|
|
|
|
if (CurrentCode == 0xFFFF)
|
|
|
|
{
|
|
|
|
/* New code */
|
|
|
|
if (Verbose) printf("A new scancode is being defined: 0x%2X, %s\n", Entry->ScanCode, Token);
|
|
|
|
|
|
|
|
/* Fill out the entry */
|
|
|
|
Entry->VirtualKey = getVKNum(Token);
|
|
|
|
goto FillEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we found it, process it */
|
|
|
|
if (ScanCode == CurrentCode) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure we didn't already process it */
|
|
|
|
if (ScVk[i].Processed)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
printf("Scancode %X was previously defined.\n", ScanCode);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if there is a valid virtual key */
|
|
|
|
if (ScVk[i].VirtualKey == 0xFFFF)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
printf("The Scancode you tried to use (%X) is reserved.\n", ScanCode);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out the entry */
|
|
|
|
Entry->OriginalVirtualKey = ScVk[i].VirtualKey;
|
|
|
|
Entry->Name = ScVk[i].Name;
|
|
|
|
|
|
|
|
FillEntry:
|
|
|
|
Entry->Processed = TRUE;
|
|
|
|
ScVk[i].Processed = TRUE;
|
|
|
|
|
|
|
|
/* Get the virtual key from the entry */
|
|
|
|
VirtualKey = getVKNum(Token);
|
|
|
|
Entry->VirtualKey = VirtualKey;
|
|
|
|
|
|
|
|
/* Make sure it's valid */
|
|
|
|
if (VirtualKey == 0xFFFF)
|
|
|
|
{
|
|
|
|
/* Warn the user */
|
|
|
|
if (Verbose) printf("An invalid Virtual Key '%s' was defined.\n", Token);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip what's left */
|
2009-10-31 20:24:33 +00:00
|
|
|
return SkipLines();
|
|
|
|
}
|
|
|
|
|
2009-10-31 20:03:43 +00:00
|
|
|
VOID
|
|
|
|
DoParsing(VOID)
|
|
|
|
{
|
|
|
|
ULONG KeyWords[KEYWORD_COUNT];
|
|
|
|
ULONG KeyWord;
|
2009-10-31 20:24:33 +00:00
|
|
|
ULONG StateCount;
|
|
|
|
ULONG ShiftStates[8];
|
2009-11-01 18:17:30 +00:00
|
|
|
PKEYNAME DescriptionData, LanguageData;
|
2009-11-01 18:26:53 +00:00
|
|
|
PKEYNAME KeyNameData, KeyNameExtData, KeyNameDeadData;
|
2009-11-01 17:43:51 +00:00
|
|
|
PVOID AttributeData, LigatureData, DeadKeyData;
|
2009-10-31 20:03:43 +00:00
|
|
|
|
|
|
|
/* Parse keywords */
|
|
|
|
gLineCount = 0;
|
|
|
|
KeyWord = SkipLines();
|
|
|
|
if (KeyWord >= KEYWORD_COUNT)
|
|
|
|
{
|
|
|
|
/* Invalid keyword count, fail */
|
|
|
|
fclose(gfpInput);
|
|
|
|
printf("No keywords were found in '%s'.\n", gpszFileName);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now parse the keywords */
|
|
|
|
while (KeyWord < (KEYWORD_COUNT - 1))
|
|
|
|
{
|
|
|
|
/* Save this keyword */
|
|
|
|
KeyWords[KeyWord]++;
|
|
|
|
|
|
|
|
/* Check for duplicate entires, other than DEADKEY, which is okay */
|
|
|
|
if ((KeyWord != 9) && (KeyWords[KeyWord] > 1) && (Verbose))
|
|
|
|
{
|
|
|
|
/* On a verbose run, warn the user */
|
|
|
|
printf("The '%s' keyword appeared multiple times.\n",
|
|
|
|
KeyWordList[KeyWord]);
|
|
|
|
}
|
2009-10-31 20:24:33 +00:00
|
|
|
|
2009-10-31 20:03:43 +00:00
|
|
|
|
|
|
|
/* Now parse this keyword */
|
|
|
|
switch (KeyWord)
|
|
|
|
{
|
|
|
|
/* KBD */
|
|
|
|
case 0:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found KBD section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoKBD();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* VERSION */
|
|
|
|
case 1:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found VERSION section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoVERSION();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* COPYRIGHT */
|
|
|
|
case 2:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found COPYRIGHT section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoCOPYRIGHT();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* COMPANY */
|
|
|
|
case 3:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found COMPANY section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoCOMPANY();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* LOCALENAME */
|
|
|
|
case 4:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found LOCALENAME section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoLOCALENAME();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* MODIFIERS */
|
|
|
|
case 5:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found MODIFIERS section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoMODIFIERS();
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* SHIFTSTATE */
|
|
|
|
case 6:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found SHIFTSTATE section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoSHIFTSTATE(&StateCount, ShiftStates);
|
|
|
|
if (StateCount < 2)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
fclose(gfpInput);
|
|
|
|
printf("ERROR");
|
|
|
|
exit(1);
|
|
|
|
}
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* ATTRIBUTES */
|
|
|
|
case 7:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found ATTRIBUTES section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoATTRIBUTES(&AttributeData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* LAYOUT */
|
|
|
|
case 8:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found LAYOUT section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoLAYOUT(&g_Layout,
|
|
|
|
&LigatureData,
|
|
|
|
ShiftStates,
|
|
|
|
StateCount);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* DEADKEY */
|
|
|
|
case 9:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found DEADKEY section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoDEADKEY(&DeadKeyData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* LIGATURE */
|
|
|
|
case 10:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found LIGATURE section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoLIGATURE(&LigatureData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* KEYNAME */
|
|
|
|
case 11:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found KEYNAME section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoKEYNAME(&KeyNameData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* KEYNAME_EXT */
|
|
|
|
case 12:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found KEYNAME_EXT section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoKEYNAME(&KeyNameExtData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* KEYNAME_DEAD */
|
|
|
|
case 13:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found KEYNAME_DEAD section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoKEYNAME(&KeyNameDeadData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* DESCRIPTIONS */
|
|
|
|
case 14:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found DESCRIPTIONS section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoDESCRIPTIONS(&DescriptionData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* LANGUAGENAMES */
|
|
|
|
case 15:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found LANGUAGENAMES section\n");
|
2009-10-31 20:24:33 +00:00
|
|
|
KeyWord = DoLANGUAGENAMES(&LanguageData);
|
2009-10-31 20:03:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* ENDKBD */
|
|
|
|
case 16:
|
|
|
|
|
2009-11-01 18:30:57 +00:00
|
|
|
DPRINT1("Found ENDKBD section\n");
|
2009-10-31 20:03:43 +00:00
|
|
|
KeyWord = SkipLines();
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-31 18:13:26 +00:00
|
|
|
/* EOF */
|