mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1997 lines
51 KiB
1997 lines
51 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: KBDTXT2C.C *
|
|
* *
|
|
* Copyright (c) 1985-95, Microsoft Corporation *
|
|
* *
|
|
* History: *
|
|
* 26-Mar-1995 a-KChang *
|
|
\***************************************************************************/
|
|
|
|
#include "kbdx.h"
|
|
|
|
DWORD gVersion = 1;
|
|
DWORD gSubVersion = 3;
|
|
|
|
char *KeyWord[] = { /* used by isKeyWord() */
|
|
"KBD", /* 0 */
|
|
"VERSION", /* 1 */
|
|
"SHIFTSTATE", /* 2 */
|
|
"LAYOUT", /* 3 */
|
|
"DEADKEY", /* 4 */
|
|
"KEYNAME", /* 5 */
|
|
"KEYNAME_EXT", /* 6 */
|
|
"KEYNAME_DEAD", /* 7 */
|
|
"ENDKBD", /* 8 */
|
|
};
|
|
|
|
#define NUMKEYWORD ( sizeof(KeyWord) / sizeof(char*) )
|
|
|
|
#define DEADKEYCODE 4 /* only DEADKEY can have multiple entries */
|
|
|
|
VKEYNAME VKName[] = { /* used only by virtual keys other than 0-9 and A-Z */
|
|
{110, "DECIMAL" },
|
|
{186, "OEM_1" },
|
|
{187, "OEM_PLUS" },
|
|
{188, "OEM_COMMA" },
|
|
{189, "OEM_MINUS" },
|
|
{190, "OEM_PERIOD" },
|
|
{191, "OEM_2" },
|
|
{192, "OEM_3" },
|
|
{219, "OEM_4" },
|
|
{220, "OEM_5" },
|
|
{221, "OEM_6" },
|
|
{222, "OEM_7" },
|
|
{223, "OEM_8" },
|
|
{226, "OEM_102" },
|
|
{0xc1, "ABNT_C1" },
|
|
{0xc2, "ABNT_C2" },
|
|
};
|
|
|
|
#define NUMVKNAME ( sizeof(VKName) / sizeof(VKEYNAME) )
|
|
|
|
SC_VK ScVk[] = { /* default ScanCode-VirtualKey relation */
|
|
/* Scan VKey */
|
|
{0x02, 0x31}, /* 1 */
|
|
{0x03, 0x32}, /* 2 */
|
|
{0x04, 0x33}, /* 3 */
|
|
{0x05, 0x34}, /* 4 */
|
|
{0x06, 0x35}, /* 5 */
|
|
{0x07, 0x36}, /* 6 */
|
|
{0x08, 0x37}, /* 7 */
|
|
{0x09, 0x38}, /* 8 */
|
|
{0x0a, 0x39}, /* 9 */
|
|
{0x0b, 0x30}, /* 0 */
|
|
{0x0c, 0xbd}, /* OEM_MINUS */
|
|
{0x0d, 0xbb}, /* OEM_PLUS */
|
|
{0x10, 0x51}, /* Q */
|
|
{0x11, 0x57}, /* W */
|
|
{0x12, 0x45}, /* E */
|
|
{0x13, 0x52}, /* R */
|
|
{0x14, 0x54}, /* T */
|
|
{0x15, 0x59}, /* Y */
|
|
{0x16, 0x55}, /* U */
|
|
{0x17, 0x49}, /* I */
|
|
{0x18, 0x4f}, /* O */
|
|
{0x19, 0x50}, /* P */
|
|
{0x1a, 0xdb}, /* OEM_4 */
|
|
{0x1b, 0xdd}, /* OEM_6 */
|
|
{0x1e, 0x41}, /* A */
|
|
{0x1f, 0x53}, /* S */
|
|
{0x20, 0x44}, /* D */
|
|
{0x21, 0x46}, /* F */
|
|
{0x22, 0x47}, /* G */
|
|
{0x23, 0x48}, /* H */
|
|
{0x24, 0x4a}, /* J */
|
|
{0x25, 0x4b}, /* K */
|
|
{0x26, 0x4c}, /* L */
|
|
{0x27, 0xba}, /* OEM_1 */
|
|
{0x28, 0xde}, /* OEM_7 */
|
|
{0x29, 0xc0}, /* OEM_3 */
|
|
{0x2b, 0xdc}, /* OEM_5 */
|
|
{0x2c, 0x5a}, /* Z */
|
|
{0x2d, 0x58}, /* X */
|
|
{0x2e, 0x43}, /* C */
|
|
{0x2f, 0x56}, /* V */
|
|
{0x30, 0x42}, /* B */
|
|
{0x31, 0x4e}, /* N */
|
|
{0x32, 0x4d}, /* M */
|
|
{0x33, 0xbc}, /* OEM_COMMA */
|
|
{0x34, 0xbe}, /* OEM_PERIOD */
|
|
{0x35, 0xbf}, /* OEM_2 */
|
|
{0x53, 0x6e}, /* DECIMAL */
|
|
{0x56, 0xe2}, /* OEM_102 */
|
|
{0x73, 0xc1}, /* ABNT_C1 */
|
|
{0x7e, 0xc2}, /* ABNT_C2 */
|
|
};
|
|
|
|
#define NUMSCVK ( sizeof(ScVk) / sizeof(SC_VK) )
|
|
|
|
char* StateLabel[] = {
|
|
"", /* 0 */
|
|
"Shift", /* 1 */
|
|
" Ctrl", /* 2 */
|
|
"S+Ctrl", /* 3 */
|
|
" Alt", /* 4:not used */
|
|
"Shift+Alt", /* 5:not used */
|
|
" Ctl+Alt", /* 6 */
|
|
"S+Ctl+Alt" /* 7 */
|
|
};
|
|
|
|
/*************************************************************\
|
|
* forward declarations *
|
|
\*************************************************************/
|
|
BOOL NextLine(char *Buf, DWORD cchBuf, FILE *fIn);
|
|
int SkipLines(void);
|
|
int isKeyWord(char *s);
|
|
int getVKNum(char *pVK);
|
|
char *getVKName(int VK, BOOL prefixVK_);
|
|
int doKBD();
|
|
int doSHIFTSTATE(int *nState, int iState[]);
|
|
int doLAYOUT(KEYLAYOUT Layout[]);
|
|
int doDEADKEY(PDEADKEY *ppDeadKey);
|
|
int doKEYNAME(PKEYNAME *ppKeyName);
|
|
int kbd_h(KEYLAYOUT Layout[]);
|
|
int kbd_rc(void);
|
|
int kbd_def(void);
|
|
char *WChName(int WC, int Zero);
|
|
ULONG Error(const char *Text, ... );
|
|
ULONG Warning(const char *Text, ... );
|
|
|
|
int kbd_c(int nState,
|
|
int iState[],
|
|
KEYLAYOUT Layout[],
|
|
PDEADKEY pDeadKey,
|
|
PKEYNAME pKeyName,
|
|
PKEYNAME pKeyNameExt,
|
|
PKEYNAME pKeyNameDead);
|
|
void PrintNameTable(FILE *pOut, PKEYNAME pKN, BOOL bDead);
|
|
|
|
/*************************************************************\
|
|
* Global variables
|
|
\*************************************************************/
|
|
BOOL verbose;
|
|
FILE *gfpInput;
|
|
char gBuf[LINEBUFSIZE];
|
|
int gLineCount;
|
|
LPSTR gpszFileName;
|
|
char gVKeyName[WORDBUFSIZE];
|
|
char gKBDName[MAXKBDNAME];
|
|
char gDescription[LINEBUFSIZE];
|
|
int gID = 0;
|
|
char gCharName[WORDBUFSIZE];
|
|
|
|
struct tm *Now;
|
|
time_t Clock;
|
|
|
|
/*************************************************************\
|
|
* Main
|
|
\*************************************************************/
|
|
int _cdecl main(int argc, char** argv)
|
|
{
|
|
int i;
|
|
int nKW[NUMKEYWORD]; /* keep track of KeyWord read to prvent duplicates */
|
|
int iKW;
|
|
int nState; /* number of states */
|
|
int iState[MAXSTATES];
|
|
int nTotal = 0;
|
|
int nFailH = 0;
|
|
int nFailC = 0;
|
|
int nFailRC = 0;
|
|
int nFailDEF = 0;
|
|
|
|
KEYLAYOUT Layout[NUMSCVK];
|
|
PDEADKEY pDeadKey = NULL;
|
|
PKEYNAME pKeyName = NULL;
|
|
PKEYNAME pKeyNameExt = NULL;
|
|
PKEYNAME pKeyNameDead = NULL;
|
|
|
|
printf("\nKbdTool v%d.%02d - convert keyboard text file to C file\n\n",
|
|
gVersion, gSubVersion);
|
|
|
|
verbose =FALSE;
|
|
|
|
argc--;
|
|
argv++;
|
|
|
|
if(argc > 0 && _strcmpi(*argv, "-v") == 0)
|
|
{
|
|
verbose =TRUE;
|
|
argc--; argv ++;
|
|
}
|
|
|
|
if ((argc == 0) || (_strcmpi(*argv, "-?") == 0) || (_strcmpi(*argv, "/?") == 0))
|
|
{
|
|
printf("Usage: KbdTool [-v] FileSpec\n");
|
|
return FAILURE;
|
|
}
|
|
|
|
while(*argv)
|
|
{
|
|
nTotal++;
|
|
gpszFileName = *argv;
|
|
if((gfpInput = fopen(*argv, "rt")) == NULL)
|
|
{
|
|
Error("can't open for read\n");
|
|
nFailH++;
|
|
nFailC++;
|
|
nFailRC++;
|
|
nFailDEF++;
|
|
argv++;
|
|
continue;
|
|
}
|
|
printf("%-23s:\n", *argv);
|
|
|
|
/* initialize for each input file */
|
|
for(i = 0; i < NUMKEYWORD; i++)
|
|
{
|
|
nKW[i]=0;
|
|
}
|
|
gLineCount = 0;
|
|
/**********************************/
|
|
|
|
if((iKW = SkipLines()) >= NUMKEYWORD)
|
|
{
|
|
fclose(gfpInput);
|
|
Error("no keyword found\n");
|
|
nFailH++;
|
|
nFailC++;
|
|
nFailRC++;
|
|
nFailDEF++;
|
|
continue;
|
|
}
|
|
|
|
while(iKW < NUMKEYWORD - 1)
|
|
{
|
|
nKW[iKW]++;
|
|
if(iKW != DEADKEYCODE && nKW[iKW] > 1 && verbose)
|
|
{
|
|
Warning("duplicate %s", KeyWord[iKW]);
|
|
}
|
|
|
|
switch(iKW)
|
|
{
|
|
case 0 : /* KBD */
|
|
|
|
iKW = doKBD();
|
|
break;
|
|
|
|
case 1 : /* VERSION ignored for now */
|
|
|
|
iKW = SkipLines();
|
|
break;
|
|
|
|
case 2 : /* SHIFTSTATE */
|
|
|
|
iKW = doSHIFTSTATE(&nState, iState);
|
|
if(nState < 2)
|
|
{
|
|
fclose(gfpInput);
|
|
Error("must have at least 2 states\n");
|
|
nFailH++;
|
|
nFailC++;
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case 3 : /* LAYOUT */
|
|
|
|
if((iKW = doLAYOUT(Layout)) == -1)
|
|
{
|
|
fclose(gfpInput);
|
|
return FAILURE;
|
|
}
|
|
|
|
/* add layout checking later */
|
|
|
|
break;
|
|
|
|
case 4 : /* DEADKEY */
|
|
|
|
if((iKW = doDEADKEY(&pDeadKey)) == -1)
|
|
{
|
|
fclose(gfpInput);
|
|
return FAILURE;
|
|
}
|
|
|
|
break;
|
|
|
|
case 5 : /* KEYNAME */
|
|
|
|
if((iKW = doKEYNAME(&pKeyName)) == -1)
|
|
{
|
|
fclose(gfpInput);
|
|
return FAILURE;
|
|
}
|
|
|
|
break;
|
|
|
|
case 6 : /* KEYNAME_EXT */
|
|
|
|
if((iKW = doKEYNAME(&pKeyNameExt)) == -1)
|
|
{
|
|
fclose(gfpInput);
|
|
return FAILURE;
|
|
}
|
|
|
|
break;
|
|
|
|
case 7 : /* KEYNAME_DEAD */
|
|
|
|
if((iKW = doKEYNAME(&pKeyNameDead)) == -1)
|
|
{
|
|
fclose(gfpInput);
|
|
return FAILURE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(gfpInput);
|
|
|
|
/* add later : checking for LAYOUT & DEADKEY */
|
|
|
|
if(kbd_h(Layout) == FAILURE)
|
|
{
|
|
nFailH++;
|
|
}
|
|
|
|
if(kbd_rc() != SUCCESS)
|
|
{
|
|
nFailRC++;
|
|
}
|
|
|
|
if(kbd_c(nState, iState, Layout,
|
|
pDeadKey, pKeyName, pKeyNameExt, pKeyNameDead) == FAILURE)
|
|
{
|
|
nFailC++;
|
|
}
|
|
|
|
if(kbd_def() != SUCCESS)
|
|
{
|
|
nFailDEF++;
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
argv++;
|
|
}
|
|
|
|
printf("\n %13d ->% 12d %12d %12d %12d\n",
|
|
nTotal, nTotal - nFailH, nTotal - nFailRC,
|
|
nTotal - nFailC, nTotal - nFailDEF);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* Check keyword
|
|
* Return: 0 - 8 for valid keyword
|
|
* 9 for invalid keyword
|
|
\*************************************************************/
|
|
int isKeyWord(char *s)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < NUMKEYWORD; i++)
|
|
{
|
|
if(_strcmpi(KeyWord[i], s) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* Skip lines till a valid keyword is available
|
|
* Return: 0 - 8 for valid keyword
|
|
* 9 for invalid keyword
|
|
\*************************************************************/
|
|
int SkipLines()
|
|
{
|
|
int iKW;
|
|
char KW[WORDBUFSIZE];
|
|
|
|
while (NextLine(gBuf, LINEBUFSIZE, gfpInput))
|
|
{
|
|
if(sscanf(gBuf, "%s", KW) == 1)
|
|
{
|
|
if((iKW = isKeyWord(KW)) < NUMKEYWORD)
|
|
{
|
|
return iKW;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NUMKEYWORD;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* Convert Virtual Key name to integer
|
|
* Return : -1 if fail
|
|
\*************************************************************/
|
|
int getVKNum(char *pVK)
|
|
{
|
|
int i;
|
|
|
|
if(strlen(pVK) == 1)
|
|
{
|
|
if(*pVK >= '0' && *pVK <= '9')
|
|
{
|
|
return *pVK;
|
|
}
|
|
|
|
*pVK = toupper(*pVK);
|
|
if(*pVK >= 'A' && *pVK <='Z')
|
|
{
|
|
return *pVK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i < NUMVKNAME; i++)
|
|
{
|
|
if(_strcmpi(VKName[i].pName, pVK) == 0)
|
|
{
|
|
return VKName[i].VKey;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*************************************************************\
|
|
* Convert VK integer to name and store it in gVKeyName
|
|
\*************************************************************/
|
|
char *getVKName(int VK, BOOL prefixVK_)
|
|
{
|
|
int i;
|
|
char *s;
|
|
|
|
s = gVKeyName;
|
|
|
|
if((VK >= 'A' && VK <= 'Z') || (VK >= '0' && VK <= '9'))
|
|
{
|
|
*s++ = '\'';
|
|
*s++ = VK;
|
|
*s++ = '\'';
|
|
*s = '\0';
|
|
return gVKeyName;
|
|
}
|
|
|
|
if(prefixVK_)
|
|
{
|
|
strcpy(gVKeyName, "VK_");
|
|
}
|
|
else
|
|
{
|
|
strcpy(gVKeyName, "");
|
|
}
|
|
|
|
for(i = 0; i < NUMVKNAME; i++)
|
|
{
|
|
if(VKName[i].VKey == VK)
|
|
{
|
|
strcat(s, VKName[i].pName);
|
|
return gVKeyName;
|
|
}
|
|
}
|
|
|
|
strcpy(gVKeyName, "#ERROR#");
|
|
return gVKeyName;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* KBD section
|
|
* read in gKBDName and gDescription if any
|
|
* Return : next keyword
|
|
\*************************************************************/
|
|
int doKBD()
|
|
{
|
|
char *p;
|
|
|
|
*gKBDName = '\0';
|
|
*gDescription = '\0';
|
|
|
|
if (sscanf(gBuf, "KBD %5s \"%40[^\"]\" %d", gKBDName, gDescription, &gID) < 2)
|
|
{
|
|
// if (sscanf(gBuf, "KBD %5s ;%40[^\n]", gKBDName, gDescription) < 2)
|
|
// {
|
|
Error("unrecognized keyword");
|
|
// }
|
|
}
|
|
|
|
return (SkipLines());
|
|
}
|
|
|
|
/*************************************************************\
|
|
* SHIFTSTATE section
|
|
* read number of states and each state
|
|
* return : next keyword
|
|
\*************************************************************/
|
|
int doSHIFTSTATE(int *nState, int* iState)
|
|
{
|
|
int i;
|
|
int iKW;
|
|
int iSt;
|
|
char Tmp[WORDBUFSIZE];
|
|
|
|
for(i = 0; i < MAXSTATES; i++)
|
|
{
|
|
iState[i] = -1;
|
|
}
|
|
|
|
*nState = 0;
|
|
while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
|
|
{
|
|
if(sscanf(gBuf, "%s", Tmp) != 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(sscanf(gBuf, " %1s[012367]", Tmp) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid state");
|
|
}
|
|
continue; /* add printf error later */
|
|
}
|
|
|
|
iSt = atoi(Tmp);
|
|
for(i = 0; i < *nState; i++)
|
|
{
|
|
if(iState[i] == iSt && verbose)
|
|
{
|
|
Warning("duplicate state %d", iSt);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(*nState < MAXSTATES)
|
|
{
|
|
iState[(*nState)++] = iSt;
|
|
}
|
|
else
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("too many states %d", *nState);
|
|
}
|
|
}
|
|
}
|
|
|
|
return iKW;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* LAYOUT section
|
|
* return : next keyword
|
|
* -1 if memory problem
|
|
\*************************************************************/
|
|
int doLAYOUT(KEYLAYOUT Layout[])
|
|
{
|
|
int i, idx;
|
|
int iKW;
|
|
int Len;
|
|
DWORD Scan;
|
|
DWORD WChr;
|
|
char Cap[MAXWCLENGTH];
|
|
unsigned char WC[MAXSTATES][MAXWCLENGTH];
|
|
char Tmp[WORDBUFSIZE];
|
|
|
|
memset(Layout, 0, NUMSCVK * sizeof(KEYLAYOUT));
|
|
|
|
for(i = 0; i < NUMSCVK; i++)
|
|
{
|
|
Layout[i].Scan = ScVk[i].Scan;
|
|
}
|
|
|
|
while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
|
|
{
|
|
if(sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(sscanf(gBuf, " %x %s %s", &Scan, Tmp, Cap) != 3)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid LAYOUT");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
for(idx = 0; idx < NUMSCVK; idx++)
|
|
{
|
|
if(Layout[idx].Scan == Scan)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(idx == NUMSCVK)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid ScanCode %02x", Scan);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if((Layout[idx].VKey = getVKNum(Tmp)) == -1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid VK %s", Tmp);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(_strcmpi(Cap, "SGCAP") == 0)
|
|
{
|
|
*Cap = '2';
|
|
}
|
|
if(sscanf(Cap, "%1d[012]", &(Layout[idx].Cap)) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid Cap %s", Cap);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if((Layout[idx].nState = \
|
|
sscanf(gBuf, " %*s %*s %*s %s %s %s %s %s %s", \
|
|
WC[0], WC[1], WC[2], WC[3], WC[4], WC[5])) < 2)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("must have at least 2 states");
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
for(i = 0; i < Layout[idx].nState; i++)
|
|
{
|
|
if(_strcmpi(WC[i], "-1") == 0)
|
|
{
|
|
Layout[idx].WCh[i] = -1;
|
|
continue;
|
|
}
|
|
|
|
if((Len = strlen(WC[i]) - 1) > 0 && *(WC[i] + Len) == '@')
|
|
{
|
|
Layout[idx].DKy[i] = 1; /* it is a dead key */
|
|
}
|
|
|
|
if(Len < 2)
|
|
{
|
|
Layout[idx].WCh[i] = *WC[i];
|
|
}
|
|
else
|
|
{
|
|
if(sscanf(WC[i], "%4x", &WChr) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("LAYOUT error %s", WC[i]);
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
Layout[idx].WCh[i] = WChr;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check that characters a-z and A-Z are on VK_A - VK_Z
|
|
*/
|
|
if (((Layout[idx].WCh[0] >= 'a') && (Layout[idx].WCh[0] <= 'z')) ||
|
|
((Layout[idx].WCh[1] >= 'A') && (Layout[idx].WCh[1] <= 'Z'))) {
|
|
if ((Layout[idx].VKey != _toupper(Layout[idx].WCh[0])) && (Layout[idx].VKey != Layout[idx].WCh[1])) {
|
|
Warning("VK_%s (0x%2x) does not match %c %c",
|
|
Tmp, Layout[idx].VKey, Layout[idx].WCh[0], Layout[idx].WCh[1]);
|
|
}
|
|
}
|
|
|
|
/* SGCAP: read the next line */
|
|
if(Layout[idx].Cap & 0x02)
|
|
{
|
|
if((Layout[idx].pSGCAP = malloc( sizeof(KEYLAYOUT) )) == NULL)
|
|
{
|
|
Error("can't allocate SGCAP struct");
|
|
return -1;
|
|
}
|
|
memset(Layout[idx].pSGCAP, 0, sizeof(KEYLAYOUT));
|
|
|
|
if(NextLine(gBuf, LINEBUFSIZE, gfpInput) &&
|
|
(Layout[idx].pSGCAP->nState =
|
|
sscanf(gBuf, " -1 -1 0 %s %s %s %s %s %s",
|
|
WC[0], WC[1], WC[2], WC[3], WC[4], WC[5])) != 0)
|
|
{
|
|
for(i = 0; i < Layout[idx].pSGCAP->nState; i++)
|
|
{
|
|
if(_strcmpi(WC[i], "-1") == 0)
|
|
{
|
|
Layout[idx].pSGCAP->WCh[i] = -1;
|
|
continue;
|
|
}
|
|
|
|
if((Len = strlen(WC[i]) - 1) > 0 && *WC[i + Len] == '@')
|
|
{
|
|
Layout[idx].pSGCAP->DKy[i] = 1; /* it is a dead key */
|
|
}
|
|
|
|
if(Len == 0)
|
|
{
|
|
Layout[idx].pSGCAP->WCh[i] = *WC[i];
|
|
}
|
|
else
|
|
{
|
|
if(sscanf(WC[i], "%4x", &WChr) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("SGCAP LAYOUT error %s", WC[i]);
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
Layout[idx].pSGCAP->WCh[i] = WChr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Error("invalid SGCAP");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return iKW;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* DEADKEY section
|
|
* return : next keyword
|
|
* -1 if memory problem
|
|
\*************************************************************/
|
|
int doDEADKEY(PDEADKEY *ppDeadKey)
|
|
{
|
|
char Tmp[WORDBUFSIZE];
|
|
int iKW;
|
|
DEADKEY *pDeadKey;
|
|
PDEADTRANS pDeadTrans;
|
|
PDEADTRANS *ppDeadTrans;
|
|
DWORD dw;
|
|
static PDEADKEY pLastDeadKey;
|
|
|
|
|
|
if(sscanf(gBuf, " DEADKEY %s", Tmp) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("missing dead key");
|
|
}
|
|
return (SkipLines());
|
|
}
|
|
|
|
if(strlen(Tmp) == 1)
|
|
{
|
|
dw = *Tmp;
|
|
}
|
|
else if(sscanf(Tmp, "%4x", &dw) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("dead key error");
|
|
}
|
|
return (SkipLines());
|
|
}
|
|
|
|
/* add later : check if dw is in Layout*/
|
|
|
|
if((pDeadKey = (DEADKEY*) malloc( sizeof(DEADKEY) )) == NULL)
|
|
{
|
|
Error("can't allocate DEADKEY struct");
|
|
return -1;
|
|
}
|
|
|
|
pDeadKey->pNext = NULL;
|
|
pDeadKey->Dead = dw;
|
|
pDeadKey->pDeadTrans = NULL;
|
|
|
|
/*
|
|
* Link into end of list (maintaining original order)
|
|
*/
|
|
if (*ppDeadKey) {
|
|
ppDeadKey = &(pLastDeadKey->pNext);
|
|
}
|
|
*ppDeadKey = pDeadKey;
|
|
pLastDeadKey = pDeadKey;
|
|
// ppDeadKey = &(pDeadKey->pNext);
|
|
|
|
|
|
ppDeadTrans = &(pDeadKey->pDeadTrans);
|
|
while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
|
|
{
|
|
if(sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(strlen(Tmp) == 1)
|
|
{
|
|
dw = *Tmp;
|
|
}
|
|
else if(sscanf(Tmp, "%4x", &dw) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid base key %s", Tmp);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* add later : check dw */
|
|
|
|
if((pDeadTrans = (DEADTRANS *) malloc( sizeof(DEADTRANS) )) == NULL)
|
|
{
|
|
Error("can't allocate DEADTRANS struct");
|
|
return -1;
|
|
}
|
|
memset(pDeadTrans, 0, sizeof(DEADTRANS));
|
|
|
|
pDeadTrans->pNext = NULL;
|
|
pDeadTrans->Base = dw;
|
|
|
|
/*
|
|
* Link to end of list (maintaining original order)
|
|
*/
|
|
*ppDeadTrans = pDeadTrans;
|
|
ppDeadTrans = &(pDeadTrans->pNext);
|
|
|
|
if(sscanf(gBuf, " %*s %s", Tmp) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("missing deadtrans key");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(strlen(Tmp) == 1)
|
|
{
|
|
dw = *Tmp;
|
|
}
|
|
else if(sscanf(Tmp, "%4x", &dw) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid deadtrans key %s", Tmp);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
pDeadTrans->WChar = dw;
|
|
}
|
|
|
|
return iKW;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* KEYNAME, KEYNAME_EXT, KEYNAME_DEAD sections
|
|
* return : next keyword
|
|
* -1 if memory problem
|
|
\*************************************************************/
|
|
int doKEYNAME(PKEYNAME *ppKeyName)
|
|
{
|
|
KEYNAME *pKN;
|
|
int iKW;
|
|
char Tmp[WORDBUFSIZE];
|
|
int Char;
|
|
char *p;
|
|
char *q;
|
|
|
|
*ppKeyName = NULL;
|
|
|
|
while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
|
|
{
|
|
if(sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(sscanf(Tmp, " %4x", &Char) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("invalid char code");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/* add later : check Scan code */
|
|
|
|
if(sscanf(gBuf, " %*4x %s[^\n]", Tmp) != 1)
|
|
{
|
|
if(verbose)
|
|
{
|
|
Warning("missing name");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
p = strstr(gBuf, Tmp);
|
|
if((q = strchr(p, '\n')) != NULL)
|
|
{
|
|
*q = '\0';
|
|
}
|
|
|
|
if((pKN = (void*) malloc( sizeof(KEYNAME) )) == NULL)
|
|
{
|
|
Error("can't allocate KEYNAME struct");
|
|
return -1;
|
|
}
|
|
|
|
pKN->Code = Char;
|
|
pKN->pName = _strdup(p);
|
|
pKN->pNext = NULL;
|
|
|
|
/*
|
|
* Link to end of list (maintaining original order)
|
|
*/
|
|
*ppKeyName = pKN;
|
|
ppKeyName = &(pKN->pNext);
|
|
}
|
|
|
|
return iKW;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* write kbd*.rc *
|
|
\*************************************************************/
|
|
int kbd_rc(void)
|
|
{
|
|
char OutName[FILENAMESIZE];
|
|
char kbdname[MAXKBDNAME];
|
|
FILE *pOut;
|
|
|
|
strcpy(OutName, "KBD");
|
|
strcat(OutName, gKBDName);
|
|
strcat(OutName, ".RC");
|
|
|
|
strcpy(kbdname, gKBDName);
|
|
_strlwr(kbdname);
|
|
|
|
printf(" %12s", OutName);
|
|
if((pOut = fopen(OutName, "wt")) == NULL)
|
|
{
|
|
printf(": can't open for write; ");
|
|
return FAILURE;
|
|
}
|
|
|
|
fprintf(pOut,
|
|
"#include <windows.h>\n"
|
|
"#include <ntverp.h>\n"
|
|
"\n"
|
|
"#define VER_FILETYPE VFT_DLL\n"
|
|
"#define VER_FILESUBTYPE VFT2_UNKNOWN\n" );
|
|
|
|
fprintf(pOut,
|
|
"#define VER_FILEDESCRIPTION_STR \"%s Keyboard Layout\"\n", gDescription);
|
|
|
|
fprintf(pOut,
|
|
"#define VER_INTERNALNAME_STR \"kbd%s\"\n", kbdname);
|
|
|
|
fprintf(pOut,
|
|
"#define VER_ORIGINALFILENAME_STR \"kbd%s.dll\"\n", kbdname);
|
|
|
|
fprintf(pOut,
|
|
"\n"
|
|
"#include \"common.ver\"\n");
|
|
|
|
fclose(pOut);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* write kbd*.def *
|
|
\*************************************************************/
|
|
int kbd_def(void)
|
|
{
|
|
char OutName[FILENAMESIZE];
|
|
FILE *pOut;
|
|
|
|
strcpy(OutName, "KBD");
|
|
strcat(OutName, gKBDName);
|
|
strcat(OutName, ".DEF");
|
|
|
|
printf(" %12s", OutName);
|
|
if((pOut = fopen(OutName, "wt")) == NULL)
|
|
{
|
|
printf(": can't open for write; ");
|
|
return FAILURE;
|
|
}
|
|
|
|
fprintf(pOut,
|
|
"LIBRARY KBD%s\n"
|
|
"\n"
|
|
"EXPORTS\n"
|
|
" KbdLayerDescriptor @1\n", gKBDName);
|
|
|
|
fclose(pOut);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* write kbd*.h *
|
|
\*************************************************************/
|
|
int kbd_h(KEYLAYOUT Layout[])
|
|
{
|
|
char OutName[FILENAMESIZE];
|
|
FILE *pOut;
|
|
|
|
int Diff[NUMSCVK];
|
|
int nDiff = 0;
|
|
int i;
|
|
|
|
time( &Clock );
|
|
Now = localtime( &Clock );
|
|
|
|
strcpy(OutName, "KBD");
|
|
strcat(OutName, gKBDName);
|
|
strcat(OutName, ".H");
|
|
|
|
printf(" %12s ", OutName);
|
|
if((pOut = fopen(OutName, "wt")) == NULL)
|
|
{
|
|
printf(": can't open for write; ");
|
|
return FAILURE;
|
|
}
|
|
|
|
fprintf(pOut,"/****************************** Module Header ******************************\\\n"
|
|
"* Module Name: %s\n*\n* keyboard layout header for %s\n"
|
|
"*\n"
|
|
"* Copyright (c) 1985-95, Microsoft Corporation\n"
|
|
"*\n"
|
|
"* Various defines for use by keyboard input code.\n*\n* History:\n"
|
|
"*\n"
|
|
"* created by KBDTOOL %s*\n"
|
|
"\\***************************************************************************/\n\n"
|
|
, OutName, gDescription, asctime(Now));
|
|
|
|
for(i = 0; i < NUMSCVK; i++)
|
|
{
|
|
if(Layout[i].VKey == ScVk[i].VKey)
|
|
{
|
|
Diff[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
Diff[i] = 1;
|
|
nDiff++;
|
|
}
|
|
}
|
|
|
|
if(nDiff == 0)
|
|
{
|
|
fprintf(pOut,"/*\n"
|
|
" * kbd.h is for the USA. There are no values to be overridden.\n"
|
|
"*/\n"
|
|
"#include \"kbd.h\"\n\n");
|
|
fclose(pOut);
|
|
return SUCCESS;
|
|
}
|
|
|
|
fprintf(pOut,"/*\n"
|
|
" * kbd type should be controlled by cl command-line argument\n"
|
|
"#define KBD_TYPE 4\n\n"
|
|
"/*\n"
|
|
"* Include the basis of all keyboard table values\n"
|
|
"*/\n"
|
|
"#include \"kbd.h\"\n\n");
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* The table below defines the virtual keys for various keyboard types where\n"
|
|
"* the keyboard differ from the US keyboard.\n"
|
|
"*\n"
|
|
"* _EQ() : all keyboard types have the same virtual key for this scancode\n"
|
|
"* _NE() : different virtual keys for this scancode, depending on kbd type\n"
|
|
"*\n"
|
|
"* +------+ +----------+----------+----------+----------+----------+----------+\n"
|
|
"* | Scan | | kbd | kbd | kbd | kbd | kbd | kbd |\n"
|
|
"* | code | | type 1 | type 2 | type 3 | type 4 | type 5 | type 6 |\n"
|
|
"\\****+-------+_+----------+----------+----------+----------+----------+----------+*/\n\n");
|
|
|
|
for(i = 0; i < NUMSCVK; i++)
|
|
{
|
|
if((Diff[i] == 1) && (Layout[i].VKey != 0))
|
|
{
|
|
fprintf(pOut,"#undef T%02X\n#define T%02X _EQ(%43s%23s\n"
|
|
,Layout[i].Scan,Layout[i].Scan, getVKName(Layout[i].VKey, 0), ")");
|
|
}
|
|
}
|
|
|
|
fprintf(pOut,"\n");
|
|
fclose(pOut);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*************************************************************\
|
|
* Convert a Unicode value to a text string
|
|
* Zero = 0 : return 'A'; 0x????
|
|
* 1 : return A ; \x????
|
|
* return : ptr to gCharName where result is stored
|
|
\*************************************************************/
|
|
char *WChName(int WC, int Zero)
|
|
{
|
|
char *s;
|
|
|
|
if(WC == -1)
|
|
{
|
|
strcpy(gCharName, "WCH_NONE");
|
|
}
|
|
else if(WC > 31 && WC < 128)
|
|
{
|
|
s = gCharName;
|
|
|
|
if(Zero == 0)
|
|
{
|
|
*s++ = '\'';
|
|
}
|
|
|
|
if(WC == '\"' || WC == '\'' || WC == '\\')
|
|
{
|
|
*s++ = '\\';
|
|
}
|
|
|
|
*s++ = WC;
|
|
|
|
if(Zero == 0)
|
|
{
|
|
*s++ = '\'';
|
|
}
|
|
|
|
*s = '\0';
|
|
}
|
|
else
|
|
{
|
|
if(Zero == 0)
|
|
{
|
|
sprintf(gCharName, "0x%04x", WC);
|
|
}
|
|
else
|
|
{
|
|
sprintf(gCharName, "\\x%04x", WC);
|
|
}
|
|
}
|
|
|
|
return gCharName;
|
|
}
|
|
|
|
void PrintNameTable(
|
|
FILE *pOut,
|
|
PKEYNAME pKN,
|
|
BOOL bDead)
|
|
{
|
|
char *p;
|
|
char *q;
|
|
int k;
|
|
char ExtraLine[LINEBUFSIZE];
|
|
|
|
while (pKN)
|
|
{
|
|
KEYNAME *pKNOld;
|
|
p = ExtraLine;
|
|
q = pKN->pName;
|
|
|
|
if( *q != '\"' )
|
|
{
|
|
*p++ = '\"';
|
|
}
|
|
|
|
while(*q)
|
|
{
|
|
if( *q == '\\' && ( *(q+1) == 'x' || *(q+1) == 'X' ) )
|
|
{
|
|
while( *q == '\\' && ( *(q+1) == 'x' || *(q+1) == 'X' ) )
|
|
{
|
|
for(k = 0; *q && k < 6; k++)
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
}
|
|
if( *q )
|
|
{
|
|
*p++ = '\"';
|
|
*p++ = ' ';
|
|
*p++ = 'L';
|
|
*p++ = '\"';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
}
|
|
|
|
if( *(p - 1) != '\"' )
|
|
{
|
|
*p++ = '\"';
|
|
}
|
|
*p++ = '\0';
|
|
|
|
if (bDead) {
|
|
fprintf(pOut," L\"%s\"\tL%s,\n", WChName(pKN->Code, 1), ExtraLine);
|
|
} else {
|
|
fprintf(pOut," 0x%02x, L%s,\n", pKN->Code, ExtraLine);
|
|
}
|
|
|
|
pKNOld = pKN;
|
|
pKN = pKN->pNext;
|
|
|
|
/*
|
|
* Free the memory (why bother???)
|
|
*/
|
|
free(pKNOld->pName);
|
|
free(pKNOld);
|
|
}
|
|
|
|
if (bDead) {
|
|
fprintf(pOut," NULL\n");
|
|
} else {
|
|
fprintf(pOut," 0 , NULL\n");
|
|
}
|
|
}
|
|
|
|
/*************************************************************\
|
|
* write kbd*.c *
|
|
\*************************************************************/
|
|
int kbd_c(
|
|
int nState,
|
|
int iState[],
|
|
KEYLAYOUT Layout[],
|
|
PDEADKEY pDeadKey,
|
|
PKEYNAME pKeyName,
|
|
PKEYNAME pKeyNameExt,
|
|
PKEYNAME pKeyNameDead)
|
|
{
|
|
char OutName[13];
|
|
char ExtraLine[LINEBUFSIZE];
|
|
char Tmp[WORDBUFSIZE];
|
|
char *p;
|
|
char *q;
|
|
FILE *pOut;
|
|
int MaxSt;
|
|
int iSt[MAXSTATES];
|
|
int i, j, k, m;
|
|
|
|
KEYNAME *pKN;
|
|
DEADTRANS *pDeadTrans;
|
|
|
|
char *Cap[] = {
|
|
"0",
|
|
"CAPLOK",
|
|
"SGCAPS",
|
|
"CAPLOK | SGCAPS",
|
|
"CAPLOKALTGR",
|
|
"CAPLOK | CAPLOKALTGR"
|
|
};
|
|
|
|
strcpy(OutName, "KBD");
|
|
strcat(OutName, gKBDName);
|
|
strcat(OutName, ".C");
|
|
|
|
printf(" %12s", OutName);
|
|
if((pOut = fopen(OutName, "wt")) == NULL)
|
|
{
|
|
printf(": can't open for write\n");
|
|
return FAILURE;
|
|
}
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* Module Name: %s\n*\n* keyboard layout for %s\n"
|
|
"*\n"
|
|
"* Copyright (c) 1985-95, Microsoft Corporation\n"
|
|
"*\n"
|
|
"* History:\n"
|
|
"* KBDTOOL v%d.%02d - Created %s"
|
|
"\\***************************************************************************/\n\n"
|
|
"#include <windows.h>\n"
|
|
"#include \"vkoem.h\"\n"
|
|
"#include \"kbd.h\"\n"
|
|
"#include \"kbd%s.h\"\n\n"
|
|
,OutName, gDescription, gVersion, gSubVersion, asctime(Now), gKBDName);
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* ausVK[] - Virtual Scan Code to Virtual Key conversion table for %s\n"
|
|
"\\***************************************************************************/\n\n"
|
|
,gDescription);
|
|
|
|
fprintf(pOut,"static USHORT ausVK[] = {\n"
|
|
" T00, T01, T02, T03, T04, T05, T06, T07,\n"
|
|
" T08, T09, T0A, T0B, T0C, T0D, T0E, T0F,\n"
|
|
" T10, T11, T12, T13, T14, T15, T16, T17,\n"
|
|
" T18, T19, T1A, T1B, T1C, T1D, T1E, T1F,\n"
|
|
" T20, T21, T22, T23, T24, T25, T26, T27,\n"
|
|
" T28, T29, T2A, T2B, T2C, T2D, T2E, T2F,\n"
|
|
" T30, T31, T32, T33, T34, T35,\n\n");
|
|
|
|
fprintf(pOut," /*\n"
|
|
" * Right-hand Shift key must have KBDEXT bit set.\n"
|
|
" */\n"
|
|
" T36 | KBDEXT,\n\n"
|
|
" T37 | KBDMULTIVK, // numpad_* + Shift/Alt -> SnapShot\n\n"
|
|
" T38, T39, T3A, T3B, T3C, T3D, T3E,\n"
|
|
" T3F, T40, T41, T42, T43, T44,\n\n");
|
|
|
|
fprintf(pOut," /*\n"
|
|
" * NumLock Key:\n"
|
|
" * KBDEXT - VK_NUMLOCK is an Extended key\n"
|
|
" * KBDMULTIVK - VK_NUMLOCK or VK_PAUSE (without or with CTRL)\n"
|
|
" */\n"
|
|
" T45 | KBDEXT | KBDMULTIVK,\n\n"
|
|
" T46 | KBDMULTIVK,\n\n");
|
|
|
|
fprintf(pOut," /*\n"
|
|
" * Number Pad keys:\n"
|
|
" * KBDNUMPAD - digits 0-9 and decimal point.\n"
|
|
" * KBDSPECIAL - require special processing by Windows\n"
|
|
" */\n"
|
|
" T47 | KBDNUMPAD | KBDSPECIAL, // Numpad 7 (Home)\n"
|
|
" T48 | KBDNUMPAD | KBDSPECIAL, // Numpad 8 (Up),\n"
|
|
" T49 | KBDNUMPAD | KBDSPECIAL, // Numpad 9 (PgUp),\n"
|
|
" T4A,\n"
|
|
" T4B | KBDNUMPAD | KBDSPECIAL, // Numpad 4 (Left),\n"
|
|
" T4C | KBDNUMPAD | KBDSPECIAL, // Numpad 5 (Clear),\n"
|
|
" T4D | KBDNUMPAD | KBDSPECIAL, // Numpad 6 (Right),\n"
|
|
" T4E,\n"
|
|
" T4F | KBDNUMPAD | KBDSPECIAL, // Numpad 1 (End),\n"
|
|
" T50 | KBDNUMPAD | KBDSPECIAL, // Numpad 2 (Down),\n"
|
|
" T51 | KBDNUMPAD | KBDSPECIAL, // Numpad 3 (PgDn),\n"
|
|
" T52 | KBDNUMPAD | KBDSPECIAL, // Numpad 0 (Ins),\n"
|
|
" T53 | KBDNUMPAD | KBDSPECIAL, // Numpad . (Del),\n\n");
|
|
|
|
fprintf(pOut," T54, T55, T56, T57, T58, T59, T5A, T5B,\n"
|
|
" T5C, T5D, T5E, T5F, T60, T61, T62, T63,\n"
|
|
" T64, T65, T66, T67, T68, T69, T6A, T6B,\n"
|
|
" T6C, T6D, T6E, T6F, T70, T71, T72, T73,\n"
|
|
" T74, T75, T76, T77, T78, T79, T7A, T7B,\n"
|
|
" T7C, T7D, T7E\n\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"static VSC_VK aE0VscToVk[] = {\n"
|
|
" { 0x1C, X1C | KBDEXT }, // Numpad Entern\n"
|
|
" { 0x1D, X1D | KBDEXT }, // RControln\n"
|
|
" { 0x35, X35 | KBDEXT }, // Numpad Dividen\n"
|
|
" { 0x37, X37 | KBDEXT }, // Snapshotn\n"
|
|
" { 0x38, X38 | KBDEXT }, // RMenun\n"
|
|
" { 0x46, X46 | KBDEXT }, // Break (Ctrl + Pause)\n"
|
|
" { 0x47, X47 | KBDEXT }, // Home\n"
|
|
" { 0x48, X48 | KBDEXT }, // Up\n"
|
|
" { 0x49, X49 | KBDEXT }, // Prior\n"
|
|
" { 0x4B, X4B | KBDEXT }, // Left\n"
|
|
" { 0x4D, X4D | KBDEXT }, // Right\n"
|
|
" { 0x4F, X4F | KBDEXT }, // End\n"
|
|
" { 0x50, X50 | KBDEXT }, // Down\n"
|
|
" { 0x51, X51 | KBDEXT }, // Next\n"
|
|
" { 0x52, X52 | KBDEXT }, // Insert\n"
|
|
" { 0x53, X53 | KBDEXT }, // Delete\n"
|
|
" { 0x5B, X5B | KBDEXT }, // Left Win\n"
|
|
" { 0x5C, X5C | KBDEXT }, // Right Win\n"
|
|
" { 0x5D, X5D | KBDEXT }, // Application\n"
|
|
" { 0, 0 }\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"static VSC_VK aE1VscToVk[] = {\n"
|
|
" { 0x1D, Y1D }, // Pause\n"
|
|
" { 0 , 0 }\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* aVkToBits[] - map Virtual Keys to Modifier Bits\n"
|
|
"*\n"
|
|
"* See kbd.h for a full description.\n"
|
|
"*\n"
|
|
"* %s Keyboard has only three shifter keys:\n"
|
|
"* SHIFT (L & R) affects alphabnumeric keys,\n"
|
|
"* CTRL (L & R) is used to generate control characters\n"
|
|
"* ALT (L & R) used for generating characters by number with numpad\n"
|
|
"\\***************************************************************************/\n"
|
|
,gDescription);
|
|
|
|
fprintf(pOut,"static VK_TO_BIT aVkToBits[] = {\n"
|
|
" { VK_SHIFT, KBDSHIFT },\n"
|
|
" { VK_CONTROL, KBDCTRL },\n"
|
|
" { VK_MENU, KBDALT },\n"
|
|
" { 0, 0 }\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* aModification[] - map character modifier bits to modification number\n"
|
|
"*\n"
|
|
"* See kbd.h for a full description.\n"
|
|
"*\n"
|
|
"\\***************************************************************************/\n\n");
|
|
|
|
for(i = 0; i < MAXSTATES; i++)
|
|
{
|
|
iSt[i] = -1;
|
|
}
|
|
|
|
MaxSt = 1;
|
|
for(i = 0; i < MAXSTATES && iState[i] > -1; i++)
|
|
{
|
|
iSt[iState[i]] = i;
|
|
if(iState[i] > MaxSt)
|
|
{
|
|
MaxSt = iState[i];
|
|
}
|
|
}
|
|
|
|
fprintf(pOut,"static MODIFIERS CharModifiers = {\n"
|
|
" &aVkToBits[0],\n"
|
|
" %d,\n"
|
|
" {\n"
|
|
" // Modification# // Keys Pressed\n"
|
|
" // ============= // =============\n"
|
|
,MaxSt);
|
|
|
|
for(i = 0; i < (sizeof(StateLabel)/sizeof(char*)); i++)
|
|
{
|
|
if(i > MaxSt)
|
|
{
|
|
fprintf(pOut," // %s\n", StateLabel[i]);
|
|
}
|
|
else if(iSt[i] == -1)
|
|
{
|
|
fprintf(pOut," SHFT_INVALID, // %s\n", StateLabel[i]);
|
|
}
|
|
else if(i == MaxSt)
|
|
{
|
|
fprintf(pOut," %d // %s\n", iSt[i], StateLabel[i]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," %d, // %s\n", iSt[i], StateLabel[i]);
|
|
}
|
|
}
|
|
|
|
fprintf(pOut," }\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"*\n"
|
|
"* aVkToWch2[] - Virtual Key to WCHAR translation for 2 shift states\n"
|
|
"* aVkToWch3[] - Virtual Key to WCHAR translation for 3 shift states\n"
|
|
"* aVkToWch4[] - Virtual Key to WCHAR translation for 4 shift states\n");
|
|
|
|
for(i = 5; i < MaxSt; i++)
|
|
{
|
|
fprintf(pOut,"* aVkToWch%d[] - Virtual Key to WCHAR translation for %d shift states\n", i, i);
|
|
}
|
|
|
|
fprintf(pOut,"*\n"
|
|
"* Table attributes: Unordered Scan, null-terminated\n"
|
|
"*\n"
|
|
"* Search this table for an entry with a matching Virtual Key to find the\n"
|
|
"* corresponding unshifted and shifted WCHAR characters.\n"
|
|
"*\n"
|
|
"* Special values for VirtualKey (column 1)\n"
|
|
"* 0xff - dead chars for the previous entry\n"
|
|
"* 0 - terminate the list\n"
|
|
"*\n"
|
|
"* Special values for Attributes (column 2)\n"
|
|
"* CAPLOK bit - CAPS-LOCK affect this key like SHIFT\n"
|
|
"*\n"
|
|
"* Special values for wch[*] (column 3 & 4)\n"
|
|
"* WCH_NONE - No character\n"
|
|
"* WCH_DEAD - Dead Key (diaresis) or invalid (US keyboard has none)\n"
|
|
"*\n"
|
|
"\\***************************************************************************/\n\n");
|
|
|
|
for(i = 2; i <= nState; i++)
|
|
{
|
|
fprintf(pOut,"static VK_TO_WCHARS%d aVkToWch%d[] = {\n"
|
|
"// | | Shift |"
|
|
,i, i);
|
|
|
|
for(j = 2; j < i; j++)
|
|
{
|
|
fprintf(pOut,"%-9s|", StateLabel[iState[j]]);
|
|
}
|
|
|
|
fprintf(pOut,"\n// |=========|=========|");
|
|
for(j = 2; j < i; j++)
|
|
{
|
|
fprintf(pOut,"=========|");
|
|
}
|
|
fprintf(pOut,"\n");
|
|
|
|
for(j = 0; j < NUMSCVK; j++)
|
|
{
|
|
if(i != Layout[j].nState)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
fprintf(pOut," {%-13s,%-7s", \
|
|
getVKName(Layout[j].VKey, 1), Cap[Layout[j].Cap]);
|
|
|
|
*ExtraLine = '\0';
|
|
|
|
for(k = 0; k < i; k++)
|
|
{
|
|
/*
|
|
*Tmp = '\0';
|
|
|
|
if(pDeadKey != NULL)
|
|
{
|
|
PDEADKEY pDeadKeyTmp;
|
|
for(pDeadKeyTmp = pDeadKey; pDeadKeyTmp != NULL;
|
|
pDeadKeyTmp = pDeadKeyTmp->pNext)
|
|
{
|
|
if(pDeadKeyTmp->Dead == Layout[j].WCh[k])
|
|
{
|
|
if(*ExtraLine == '\0')
|
|
{
|
|
strcpy(ExtraLine, " {0xff ,0 ");
|
|
for(m = 0; m < k; m++)
|
|
{
|
|
strcat(ExtraLine, ",WCH_NONE ");
|
|
}
|
|
}
|
|
sprintf(Tmp,",%-9s", WChName(Layout[j].WCh[k], 0));
|
|
strcat(ExtraLine, Tmp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(*ExtraLine != '\0' && *Tmp == '\0')
|
|
{
|
|
strcat(ExtraLine, ",WCH_NONE ");
|
|
}
|
|
}
|
|
*/
|
|
if(pDeadKey != NULL && Layout[j].DKy[k] == 1) /* it is a dead key */
|
|
{
|
|
if(*ExtraLine == '\0')
|
|
{
|
|
strcpy(ExtraLine, " {0xff ,0 ");
|
|
if(Layout[j].Cap != 2) /* Not SGCap */
|
|
{
|
|
for(m = 0; m < k; m++)
|
|
{
|
|
strcat(ExtraLine, ",WCH_NONE ");
|
|
}
|
|
}
|
|
else // added for a new kbdCZ that has both SGCap and WCH_DEAD
|
|
{
|
|
for( m = 0; m < k; m++ )
|
|
{
|
|
if(Layout[j].pSGCAP->WCh[m] == 0)
|
|
{
|
|
strcat( ExtraLine, ",WCH_NONE " );
|
|
}
|
|
else
|
|
{
|
|
sprintf( Tmp, ",%-9s", WChName( Layout[j].pSGCAP->WCh[m], 0 ) );
|
|
strcat( ExtraLine, Tmp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sprintf(Tmp,",%-9s", WChName(Layout[j].WCh[k], 0));
|
|
strcat(ExtraLine, Tmp);
|
|
fprintf(pOut,",WCH_DEAD ");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut,",%-9s", WChName(Layout[j].WCh[k], 0));
|
|
if(*ExtraLine != '\0')
|
|
{
|
|
strcat(ExtraLine, ",WCH_NONE ");
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(pOut,"},\n");
|
|
|
|
if(*ExtraLine != '\0')
|
|
{
|
|
fprintf(pOut,"%s},\n", ExtraLine);
|
|
continue; /* skip if WCH_DEAD */
|
|
}
|
|
|
|
if(Layout[j].Cap != 2) /* skip if not SGCAP */
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(Layout[j].pSGCAP == NULL)
|
|
{
|
|
fclose(pOut);
|
|
Error("failed SGCAP error");
|
|
return FAILURE;
|
|
}
|
|
|
|
fprintf(pOut," {%-13s,0 ", getVKName(Layout[j].VKey, 1));
|
|
|
|
for(k = 0; k < Layout[j].pSGCAP->nState; k++)
|
|
{
|
|
fprintf(pOut,",%-9s", WChName(Layout[j].pSGCAP->WCh[k], 0));
|
|
}
|
|
|
|
fprintf(pOut,"},\n");
|
|
|
|
free( Layout[j].pSGCAP );
|
|
}
|
|
|
|
if(i == 2)
|
|
{
|
|
fprintf(pOut," {VK_TAB ,0 ,'\\t' ,'\\t' },\n"
|
|
" {VK_ADD ,0 ,'+' ,'+' },\n"
|
|
" {VK_DIVIDE ,0 ,'/' ,'/' },\n"
|
|
" {VK_MULTIPLY ,0 ,'*' ,'*' },\n"
|
|
" {VK_SUBTRACT ,0 ,'-' ,'-' },\n");
|
|
}
|
|
else if(i == 3 && iState[2] == 2)
|
|
{
|
|
fprintf(pOut," {VK_BACK ,0 ,'\\b' ,'\\b' ,0x007f },\n"
|
|
" {VK_CANCEL ,0 ,0x0003 ,0x0003 ,0x0003 },\n"
|
|
" {VK_ESCAPE ,0 ,0x001b ,0x001b ,0x001b },\n"
|
|
" {VK_RETURN ,0 ,'\\r' ,'\\r' ,'\\n' },\n"
|
|
" {VK_SPACE ,0 ,' ' ,' ' ,' ' },\n");
|
|
}
|
|
else if(i == 4 && iState[3] == 2)
|
|
{
|
|
fprintf(pOut," {VK_BACK ,0 ,'\\b' ,'\\b' ,WCH_NONE ,0x007f },\n"
|
|
" {VK_CANCEL ,0 ,0x0003 ,0x0003 ,WCH_NONE ,0x0003 },\n"
|
|
" {VK_ESCAPE ,0 ,0x001b ,0x001b ,WCH_NONE ,0x001b },\n"
|
|
" {VK_RETURN ,0 ,'\\r' ,'\\r' ,WCH_NONE ,'\\n' },\n"
|
|
" {VK_SPACE ,0 ,' ' ,' ' ,WCH_NONE ,' ' },\n");
|
|
}
|
|
else if(i == 5 && iState[4] == 2)
|
|
{
|
|
fprintf(pOut," {VK_BACK ,0 ,'\\b' ,'\\b' ,WCH_NONE ,WCH_NONE ,0x007f },\n"
|
|
" {VK_CANCEL ,0 ,0x0003 ,0x0003 ,WCH_NONE ,WCH_NONE ,0x0003 },\n"
|
|
" {VK_ESCAPE ,0 ,0x001b ,0x001b ,WCH_NONE ,WCH_NONE ,0x001b },\n"
|
|
" {VK_RETURN ,0 ,'\\r' ,'\\r' ,WCH_NONE ,WCH_NONE ,'\\n' },\n"
|
|
" {VK_SPACE ,0 ,' ' ,' ' ,WCH_NONE ,WCH_NONE ,' ' },\n");
|
|
}
|
|
|
|
fprintf(pOut," {0 ,0 ");
|
|
for(k = 0; k < i; k++)
|
|
{
|
|
fprintf(pOut,",0 ");
|
|
}
|
|
fprintf(pOut,"}\n"
|
|
"};\n\n");
|
|
}
|
|
|
|
fprintf(pOut,"// Put this last so that VkKeyScan interprets number characters\n"
|
|
"// as coming from the main section of the kbd (aVkToWch2 and\n"
|
|
"// aVkToWch5) before considering the numpad (aVkToWch1).\n\n"
|
|
"static VK_TO_WCHARS1 aVkToWch1[] = {\n"
|
|
" { VK_NUMPAD0 , 0 , '0' },\n"
|
|
" { VK_NUMPAD1 , 0 , '1' },\n"
|
|
" { VK_NUMPAD2 , 0 , '2' },\n"
|
|
" { VK_NUMPAD3 , 0 , '3' },\n"
|
|
" { VK_NUMPAD4 , 0 , '4' },\n"
|
|
" { VK_NUMPAD5 , 0 , '5' },\n"
|
|
" { VK_NUMPAD6 , 0 , '6' },\n"
|
|
" { VK_NUMPAD7 , 0 , '7' },\n"
|
|
" { VK_NUMPAD8 , 0 , '8' },\n"
|
|
" { VK_NUMPAD9 , 0 , '9' },\n"
|
|
" { 0 , 0 , '\\0' }\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"static VK_TO_WCHAR_TABLE aVkToWcharTable[] = {\n");
|
|
|
|
for(i = 3; i <= nState; i++)
|
|
{
|
|
fprintf(pOut," { (PVK_TO_WCHARS1)aVkToWch%d, %d, sizeof(aVkToWch%d[0]) },\n", i, i, i);
|
|
}
|
|
fprintf(pOut," { (PVK_TO_WCHARS1)aVkToWch2, 2, sizeof(aVkToWch2[0]) },\n"
|
|
" { (PVK_TO_WCHARS1)aVkToWch1, 1, sizeof(aVkToWch1[0]) },\n"
|
|
" { NULL, 0, 0 },\n"
|
|
"};\n\n");
|
|
|
|
fprintf(pOut,"/***************************************************************************\\\n"
|
|
"* aKeyNames[], aKeyNamesExt[] - Virtual Scancode to Key Name tables\n"
|
|
"*\n"
|
|
"* Table attributes: Ordered Scan (by scancode), null-terminated\n"
|
|
"*\n"
|
|
"* Only the names of Extended, NumPad, Dead and Non-Printable keys are here.\n"
|
|
"* (Keys producing printable characters are named by that character)\n"
|
|
"\\***************************************************************************/\n\n");
|
|
|
|
if(pKeyName != NULL)
|
|
{
|
|
fprintf(pOut,"static VSC_LPWSTR aKeyNames[] = {\n");
|
|
PrintNameTable(pOut, pKeyName, FALSE);
|
|
fprintf(pOut,"};\n\n");
|
|
}
|
|
|
|
if(pKeyNameExt != NULL)
|
|
{
|
|
fprintf(pOut,"static VSC_LPWSTR aKeyNamesExt[] = {\n");
|
|
PrintNameTable(pOut, pKeyNameExt, FALSE);
|
|
fprintf(pOut,"};\n\n");
|
|
}
|
|
|
|
if(pKeyNameDead != NULL)
|
|
{
|
|
if(pDeadKey == NULL)
|
|
{
|
|
fprintf(pOut,"/*** No dead key defined, dead key names ignored ! ***\\\n\n");
|
|
}
|
|
|
|
fprintf(pOut,"static LPWSTR aKeyNamesDead[] = {\n");
|
|
PrintNameTable(pOut, pKeyNameDead, TRUE);
|
|
fprintf(pOut,"};\n\n");
|
|
|
|
if(pDeadKey == NULL)
|
|
{
|
|
fprintf(pOut,"\\*****************************************************/\n\n");
|
|
}
|
|
|
|
}
|
|
|
|
if(pDeadKey != NULL)
|
|
{
|
|
PDEADKEY pDeadKeyTmp = pDeadKey;
|
|
fprintf(pOut,"static DEADKEY aDeadKey[] = {\n");
|
|
while (pDeadKeyTmp != NULL)
|
|
{
|
|
PDEADKEY pDeadKeyOld;
|
|
pDeadTrans = pDeadKeyTmp->pDeadTrans;
|
|
while (pDeadTrans != NULL)
|
|
{
|
|
PDEADTRANS pDeadTransOld;
|
|
fprintf(pOut," DEADTRANS( ");
|
|
if(strlen(WChName(pDeadTrans->Base, 0)) == 3)
|
|
{
|
|
fprintf(pOut,"L%-6s, ", WChName(pDeadTrans->Base, 0));
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut,"%-7s, ", WChName(pDeadTrans->Base, 0));
|
|
}
|
|
|
|
if(strlen(WChName(pDeadKeyTmp->Dead, 0)) == 3)
|
|
{
|
|
fprintf(pOut,"L%-6s, ", WChName(pDeadKeyTmp->Dead, 0));
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut,"%-7s, ", WChName(pDeadKeyTmp->Dead, 0));
|
|
}
|
|
|
|
if(strlen(WChName(pDeadTrans->WChar, 0)) == 3)
|
|
{
|
|
fprintf(pOut,"L%-6s),\n", WChName(pDeadTrans->WChar, 0));
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut,"%-7s),\n", WChName(pDeadTrans->WChar, 0));
|
|
}
|
|
|
|
pDeadTransOld = pDeadTrans;
|
|
pDeadTrans = pDeadTrans->pNext;
|
|
free(pDeadTransOld);
|
|
}
|
|
fprintf(pOut,"\n");
|
|
|
|
pDeadKeyOld = pDeadKeyTmp;
|
|
pDeadKeyTmp = pDeadKeyTmp->pNext;
|
|
free(pDeadKeyOld);
|
|
}
|
|
|
|
fprintf(pOut," 0, 0\n");
|
|
fprintf(pOut,"};\n\n");
|
|
}
|
|
|
|
fprintf(pOut,"static KBDTABLES KbdTables = {\n"
|
|
" /*\n"
|
|
" * Modifier keys\n"
|
|
" */\n"
|
|
" &CharModifiers,\n\n"
|
|
" /*\n"
|
|
" * Characters tables\n"
|
|
" */\n"
|
|
" aVkToWcharTable,\n\n"
|
|
" /*\n"
|
|
" * Diacritics\n"
|
|
" */\n");
|
|
|
|
if(pDeadKey != NULL)
|
|
{
|
|
fprintf(pOut," aDeadKey,\n\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," NULL,\n\n");
|
|
}
|
|
|
|
fprintf(pOut," /*\n"
|
|
" * Names of Keys\n"
|
|
" */\n");
|
|
|
|
if(pKeyName != NULL)
|
|
{
|
|
fprintf(pOut," aKeyNames,\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," NULL,\n");
|
|
}
|
|
|
|
if(pKeyNameExt != NULL)
|
|
{
|
|
fprintf(pOut," aKeyNamesExt,\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," NULL,\n");
|
|
}
|
|
|
|
if(pDeadKey != NULL && pKeyNameDead != NULL)
|
|
{
|
|
fprintf(pOut," aKeyNamesDead,\n\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," NULL,\n\n");
|
|
}
|
|
|
|
fprintf(pOut," /*\n"
|
|
" * Scan codes to Virtual Keys\n"
|
|
" */\n"
|
|
" ausVK,\n"
|
|
" sizeof(ausVK) / sizeof(ausVK[0]),\n"
|
|
" aE0VscToVk,\n"
|
|
" aE1VscToVk,\n\n"
|
|
" /*\n"
|
|
" * Locale-specific special processing\n"
|
|
" */\n");
|
|
|
|
if(MaxSt > 5)
|
|
{
|
|
fprintf(pOut," KLLF_ALTGR\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(pOut," 0\n");
|
|
}
|
|
|
|
fprintf(pOut,"};\n\n"
|
|
"PKBDTABLES KbdLayerDescriptor(VOID)\n"
|
|
"{\n"
|
|
" return &KbdTables;\n"
|
|
"}\n");
|
|
|
|
fclose(pOut);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* read next (content-containing) line from input file
|
|
* Consumes lines the are empty, or contain just comments.
|
|
*
|
|
* Buf - contains the new line.
|
|
* (A nul character is inserted before any comment portion)
|
|
* cchBuf - provides number of characters in Buf
|
|
* gLineCount - Incremented for each line read (including skipped lines)
|
|
*
|
|
* Returns TRUE - if new line is returned in Buf
|
|
* FALSE - if end of file was reached
|
|
\*****************************************************************************/
|
|
|
|
BOOL NextLine(char *Buf, DWORD cchBuf, FILE *fIn)
|
|
{
|
|
char *p;
|
|
char *pComment;
|
|
|
|
while (fgets(Buf, cchBuf, fIn) != NULL) {
|
|
gLineCount++;
|
|
p = Buf;
|
|
|
|
// skip leading white spaces
|
|
while( *p && (*p == ' ' || *p == '\t')) {
|
|
p++;
|
|
}
|
|
|
|
if (*p == ';') {
|
|
// This line is purely comment, so skip it
|
|
continue;
|
|
}
|
|
|
|
if ((pComment = strstr(p, "//")) != NULL) {
|
|
if (pComment == p) {
|
|
// This line is purely comment, so skip it
|
|
continue;
|
|
}
|
|
|
|
// separate comment portion from content-containing portion
|
|
*pComment = '\0';
|
|
|
|
} else {
|
|
|
|
// remove newline at the end
|
|
if ((p = strchr(p, '\n')) != NULL) {
|
|
*p = '\0';
|
|
}
|
|
}
|
|
|
|
// We are returning a content-containing line
|
|
return TRUE;
|
|
}
|
|
|
|
// we reached the end of the file
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG Error(const char *Text, ... )
|
|
{
|
|
char Temp[1024];
|
|
va_list valist;
|
|
|
|
va_start(valist, Text);
|
|
vsprintf(Temp,Text,valist);
|
|
printf("%s(%d): error : %s\n", gpszFileName, gLineCount, Temp);
|
|
va_end(valist);
|
|
|
|
return 0;
|
|
}
|
|
|
|
ULONG Warning(const char *Text, ... )
|
|
{
|
|
char Temp[1024];
|
|
va_list valist;
|
|
|
|
va_start(valist, Text);
|
|
vsprintf(Temp,Text,valist);
|
|
printf("%s(%d): warning : %s\n", gpszFileName, gLineCount, Temp);
|
|
va_end(valist);
|
|
|
|
return 0;
|
|
}
|