/*
 * xkeysym.c --
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  Software Research
 * Associates makes no representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied
 * warranty.
 */
 
#include "xlibInt.h" 

typedef struct {
	char *string;
	unsigned int keysym;
	unsigned int keycode;
} Keys;

Keys Expand[] = {
"",		0xFF69,		VK_CANCEL,
"\015",		0xFF08,		VK_BACK,
"\t",		0xFF09,		VK_TAB,
"",		0xFF0B,		VK_CLEAR,
"\r",		0xFF0D,		VK_RETURN,
"",		0xFFE1,		VK_SHIFT,
"",		0xFFE3,		VK_CONTROL,
"",		0xFFE9,		VK_MENU,
"",		0xFF13,		VK_PAUSE,
"",		0xFFE5,		VK_CAPITAL,
#ifdef KANJI
"",		NoSymbol,	VK_KANA,
"",		0xFF21,		VK_KANJI,
#endif /* KANJI */
"\033",		0xFF1B,		VK_ESCAPE,
#ifdef KANJI
"",		NoSymbol,	VK_CONVERT,
"",		NoSymbol,	VK_NONCONVERT,
#endif /* KANJI */
" ",		0x020,		VK_SPACE,
"",		0xFF55,		VK_PRIOR,
"",		0xFF56,		VK_NEXT,
"",		0xFF57,		VK_END,
"",		0xFF50,		VK_HOME,
"",		0xFF51,		VK_LEFT,
"",		0xFF52,		VK_UP,
"",		0xFF53,		VK_RIGHT,
"",		0xFF54,		VK_DOWN,
"",		0xFF60,		VK_SELECT,
"",		0xFF62,		VK_EXECUTE,
"",		0xFF61,		VK_PRINT,
"",		0xFF63,		VK_INSERT,
"\037",		0xFFFF,		VK_DELETE,
"",		0xFF6A,		VK_HELP,
NULL, 		0,		0
};

Keys  Function[] = {
"",		0xFFBE,		VK_F1,
"",		0xFFBF,		VK_F2,
"",		0xFFC0,		VK_F3,
"",		0xFFC1,		VK_F4,
"",		0xFFC2,		VK_F5,
"",		0xFFC3,		VK_F6,
"",		0xFFC4,		VK_F7,
"",		0xFFC5,		VK_F8,
"",		0xFFC6,		VK_F9,
"",		0xFFC7,		VK_F10,
"",		0xFFC8,		VK_F11,
"",		0xFFC9,		VK_F12,
"",		0xFFCA,		VK_F13,
"",		0xFFCB,		VK_F14,
"",		0xFFCC,		VK_F15,
"",		0xFFCD,		VK_F16,
"",		0xFFCE,		VK_F17,
"",		0xFFCF,		VK_F18,
"",		0xFFD0,		VK_F19,
"",		0xFFD1,		VK_F20,
"",		0xFFD2,		VK_F21,
"",		0xFFD3,		VK_F22,
"",		0xFFD4,		VK_F23,
"",		0xFFD5,		VK_F24,
NULL, 		0,		0
};

#if 0
Keys ShiftedNumPad[] = {
"",		0xFF63,		VK_NUMPAD0,
"",		0xFF57,		VK_NUMPAD1,
"",		0xFF54,		VK_NUMPAD2,
"",		0xFF55,		VK_NUMPAD3,
"",		0xFF51,		VK_NUMPAD4,
"",		NoSymbol,	VK_NUMPAD5,
"",		0xFF53,		VK_NUMPAD6,
"",		0xFF50,		VK_NUMPAD7,
"",		0xFF52,		VK_NUMPAD8,
"",		0xFF56,		VK_NUMPAD9,
"*",		0xFFAA,		VK_MULTIPLY,
"+",		0xFFAB,		VK_ADD,
"-",		0xFFAD,		VK_SUBTRACT,
"\037",		0xFFFF,		VK_DECIMAL,
"/",		0xFFAF,		VK_DIVIDE,
NULL, 		0,		0
};

Keys NumPad[] = {
"0",		0xFFB0,		VK_NUMPAD0,
"1",		0xFFB1,		VK_NUMPAD1,
"2",		0xFFB2,		VK_NUMPAD2,
"3",		0xFFB3,		VK_NUMPAD3,
"4",		0xFFB4,		VK_NUMPAD4,
"5",		0xFFB5,		VK_NUMPAD5,
"6",		0xFFB6,		VK_NUMPAD6,
"7",		0xFFB7,		VK_NUMPAD7,
"8",		0xFFB8,		VK_NUMPAD8,
"9",		0xFFB9,		VK_NUMPAD9,
"*",		0xFFAA,		VK_MULTIPLY,
"+",		0xFFAB,		VK_ADD,
"-",		0xFFAD,		VK_SUBTRACT,
".",		0xFFAE,		VK_DECIMAL,
"/",		0xFFAF,		VK_DIVIDE,
NULL,		0,		0
};

Keys ShiftedNumJ[] = {
"",		NoSymbol,	'0',
"!",		0x021,		'1',
"\"",		0x022,		'2',
"#",		0x023,		'3',
"$",		0x024,		'4',
"%",		0x025,		'5',
"&",		0x026,		'6',
"'",		0x027,		'7',
"(",		0x028,		'8',
")",		0x029,		'9',
NULL,	 	0,		0
};
		
Keys ShiftedNumE[] = {
")",		NoSymbol,	'0',
"!",		0x021,		'1',
"@",		0x022,		'2',
"#",		0x023,		'3',
"$",		0x024,		'4',
"%",		0x025,		'5',
"^",		0x026,		'6',
"&",		0x027,		'7',
"*",		0x028,		'8',
"(",		0x029,		'9',
NULL,	 	0,		0
};

Keys ShiftedPuncJ[] = {
"*",		0x02A,		0x0BA,
"+",		0x02B,		0x0BB,
"<",		0x03C,		0x0BC,
"=",		0x03D,		0x0BD,
">",		0x03E,		0x0BE,
"?",		0x03F,		0x0BF,
"`",		0x060,		0x0C0,
"{",		0x07B,		0x0DB,
"|",		0x07C,		0x0DC,
"}",		0x07D,		0x0DD,
"~",		0x07E,		0x0DE,
"_",		0x05F,		0x0E2,
NULL,	 	0,		0
};

Keys PuncJ[] = {
":",		0x03A,		0x0BA,
";",		0x03B,		0x0BB,
",",		0x02C,		0x0BC,
"-",		0x02D,		0x0BD,
".",		0x02E,		0x0BE,
"/",		0x02F,		0x0BF,
"@",		0x040,		0x0C0,
"[",		0x05B,		0x0DB,
"\\",		0x05C,		0x0DC,
"]",		0x05D,		0x0DD,
"^",		0x05E,		0x0DE,
"\\",		0x05C,		0x0E2,
NULL,	 	0,		0
};

Keys ShiftedPuncE[] = {
";",		0x03B,		0x0BA,
"+",		0x02B,		0x0BB,
"<",		0x03C,		0x0BC,
"_",		0x05F,		0x0BD,
">",		0x03E,		0x0BE,
"?",		0x03F,		0x0BF,
"~",		0x07E,		0x0C0,
"{",		0x07B,		0x0DB,
"|",		0x07C,		0x0DC,
"}",		0x07D,		0x0DD,
"\"",		0x022,		0x0DE,
NULL,	 	0,		0
};

Keys PuncE[] = {
":",		0x03A,		0x0BA,
"=",		0x03D,		0x0BB,
",",		0x02C,		0x0BC,
"-",		0x02D,		0x0BD,
".",		0x02E,		0x0BE,
"/",		0x02F,		0x0BF,
"`",		0x060,		0x0C0,
"[",		0x05B,		0x0DB,
"\\",		0x05C,		0x0DC,
"]",		0x05D,		0x0DD,
"'",		0x027,		0x0DE,
NULL,	 	0,		0
};
#endif

KeySym	  
XKeycodeToKeysym(Display *display, UINT keycode, int index)
{
    Keys *table;

    display->request++;

    if (keycode <= 0x2F || (keycode == 0x90 || keycode == 0x91)) {  
	table = Expand;
    } else if (0x70 <= keycode && keycode <= 0x87) {  
	table = Function;
    } else {	
	int result;
	LONG uScanCode;
	unsigned char kbuf[256];
	unsigned char chb[4];

	memset(kbuf, 0, 256);
	uScanCode = GetWindowLong(GetPostWindow(), GWL_ID);
	if (index & 0x01) {
	    kbuf[VK_NUMLOCK] = 1;
	}
	if (index & 0x02) {
	    kbuf[VK_SHIFT] = 0x80;
	}
	if (index & 0x04) {
	    kbuf[VK_CAPITAL] = 1;
	}
	result=ToAscii(keycode, uScanCode, kbuf, chb, 0); 
	if (result == 1) {
	    return (KeySym) chb[0];
	}
    	return NoSymbol;
    }

    for (; table->string != NULL; table++) {
 	if (table->keycode == keycode) {
 	    return table->keysym;
	}
    }
    return NoSymbol;
}

int	   
XLookupString(XKeyEvent *eventPtr, char *buffer_return, int bytes_buffer, 
	KeySym *dummy1, XComposeStatus *dummy2)
{					    
    Keys *kPtr;
    int index = 0;
    static char mbBuffer[3] = {0, 0, 0};
    static mbflag = 0;
    unsigned char code = 0; 

#ifdef KANJI
    if(eventPtr->flag == 0x1234 && _ismbblead((unsigned short)eventPtr->keycode)) {
    	mbBuffer[0] = (unsigned char) eventPtr->keycode;
	mbflag = 1;
    	return NoSymbol;
    } else if(eventPtr->flag == 0x5678 && _ismbbtrail((unsigned short)eventPtr->keycode)) {
    	mbBuffer[1] = (unsigned char) eventPtr->keycode;
	mbflag = 0;
        if (buffer_return) strncpy(buffer_return, mbBuffer, bytes_buffer-1); 
	return 2; 
    } else if (eventPtr->flag == 0xABCD) {
	*buffer_return  = (unsigned char) eventPtr->keycode;
	*(buffer_return+1) = '\0';
	return 1;
#else
    if (eventPtr->flag == 0xABCD) {
	*buffer_return  = (unsigned char) eventPtr->keycode;
	*(buffer_return+1) = '\0';
	return 1;
#endif /* KANJI */
    } else {
    	LONG uScanCode;
	int result;
	BYTE kbuf[256];

	memset(kbuf, 0, 256);
	uScanCode = GetWindowLong(GetPostWindow(), GWL_ID);
	if (eventPtr->state & ShiftMask) {
	    kbuf[VK_SHIFT] = 0x80;
	}
	if (eventPtr->state & LockMask) {
	    kbuf[VK_CAPITAL] = 1;
	}
	if (eventPtr->state & Mod1Mask) {
	    kbuf[VK_NUMLOCK] = 1;
	}
	result=ToAscii(eventPtr->keycode, uScanCode, kbuf, buffer_return, 0); 
	if (result == 1) { 
	    return 1;
	}
       	mbflag = 0;
    }

    if (eventPtr->keycode <= 0x2F 
	|| eventPtr->keycode == 0x90 || eventPtr->keycode == 0x91) {  
	kPtr = Expand;
    } else if (0x70 <= eventPtr->keycode && eventPtr->keycode <= 0x87) {  
	kPtr = Function;
    } else {
    	return NoSymbol;
    }

    for (; kPtr->string != NULL; kPtr++) {
	if (kPtr->keycode == eventPtr->keycode) {
	    if (buffer_return) strncpy(buffer_return, kPtr->string, bytes_buffer-1); 
            return min(strlen(kPtr->string), (unsigned)bytes_buffer -1);
	}
    }
    return NoSymbol;
}
