#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "root.h"
#include "err.h"
#include "inter.h"
#include "resource.h"
#include "help_id.h"


#define INCLUDE_KEY_TABLE_H
#include "key_table.h"

void AdjustPropPage( HWND hwnd ); // tabctrl.c
void SetMargin(HWND); // wmain.c
/*
!0	ID_STOPOFF
!1	ID_STOPON
!2	ID_DINOFF
!3	ID_DINON
!A  ID_PAINTOFF
!B  ID_PAINTON
!C  ID_COVERRETURN
!D  ID_SCRDW
!E  ID_PAGEFOOT
!F  ID_DEFIT
!G  ID_BACKGROUND
!H  ID_PAGEHEAD
!I  ID_INITIALIZE
!J  ID_RELATEDVI
!K  ID_SETSTARTMENU
!L  ID_SCRLF
!M  ID_WINMAX
!N  ID_PRESENTOFF
!P  ID_PRESENTON
!Q  ID_ONEPAGE
!R  ID_SCRRT
!S  ID_COVERSUSPEND
!T	ID_RESCUTEDGE
!U  ID_SCRUP
!V  ID_TOREVERSE
!W  ID_TONORMAL
!X  ID_LEFTHOME
!Y  ID_RIGHTHOME
!Z  ID_CUTEDGE1
D1	ID_SCALE1
D2	ID_SCALE2
D3	ID_SCALE3 
D4	ID_SCALE4
D6  ID_16PAGE
DA	ID_LLITTLE
DB	ID_BLACKER
DC  ID_COLOR
DD	ID_LREDUCE
DE	ID_LBIG
DF	ID_FIT
DG	ID_LMAGNIFY
DH	ID_MHAND
DI  ID_GRAPHIC
DL	ID_FULL
DM	ID_MAGNIFY
DN	ID_RECTON
DO  ID_RDOUBLE
DP  ID_REPCOLOR
DR	ID_REDUCE
DS  ID_CROSS
DT  ID_DOUBLE
DU	ID_LMEASURE
DV	ID_REVERSE
DW	ID_WHITER
DX	ID_RECTREC 
DY	ID_VDOUBLE
F1  ID_FMENU1
FD  ID_DVIPRT
FH	ID_F_HISTORY
FN	ID_REOPEN
FO	ID_FILEOPEN
FP	ID_PRINT
FQ	ID_QUIT
FS	ID_SAVEIMG
FX	ID_APPEXIT
HA  ID_ABOUT
HB	ID_INFO_BUFFER
HF	ID_INFO_FONT
HH  ID_HELP_CONTENTS
HI	ID_INFO
HK	ID_INFO_KEY
HP	ID_INFO_PARA
HS  ID_INFO_SYS
J0	ID_50PAGE
J1	ID_m50PAGE
J2	ID_m20PAGE
J3	ID_m10PAGE
J4	ID_m5PAGE
J5	ID_m2PAGE
J6	ID_2PAGE
J7	ID_5PAGE
J8	ID_10PAGE
J9	ID_20PAGE
JB	ID_LASTPAGE
JD  ID_FOOTHEAD
JE	ID_DOWNPAG
JF	ID_FORMERHIST
JG	ID_GOMARK
JH	ID_P_HISTORY
JI	ID_EDITPAGE
JJ	ID_HYPERTEX
JL	ID_NEXTHIST
JM	ID_MARKPAGE
JN	ID_NEXTPAGE
JP	ID_PREVPAGE
JQ	ID_QUITHIST
JR	ID_MARKRANGE
JS  ID_LASTFILE
JT	ID_TOPPAGE
JU  ID_HEADFOOT
JV	ID_UPPAGE
JX	ID_EXMARK
N0	ID_DEFDEF
N1	ID_WHITEDEF 
N2	ID_BLACKDEF
N3	ID_WHITEBACK
N4	ID_BLACKBACK 
N5	ID_COVERB
N6	ID_COVERR
N7	ID_COVERL
N8	ID_COVERBR
N9	ID_COVERBL
NB	ID_DRBLUE
NC	ID_DRERACE
ND	ID_DRRED
NE  ID_CUTEDGE
NF	ID_COVEROFF
NG	ID_DRGREEN
NI	ID_DRLINE
NK	ID_DRBLACK
NL	ID_USELBUTTON
NN  ID_PRESENTATION
NO	ID_COVERON
NP	ID_COVERSHEET
NR	ID_USERBUTTON
NS  ID_SAVEPRESENT
NT	ID_DTHICK
NX	ID_DRBOX
O1	ID_MACRO1
O2	ID_MACRO2
O3	ID_MACRO3
O4	ID_MACRO4
O5	ID_MACRO5
OC  ID_SRCSPECIAL
OD  ID_DIFOPTION
OP  ID_PREPARA
OS	ID_OPTION	
OV  ID_DVIOUTSPECIAL
PL  ID_LANDSCAPE
SD  ID_NEXTCAND
SF  ID_SEARCH
SU  ID_PRECAND
V0  ID_FRAME0
VA	ID_INF_SMALL
VC  ID_TOOLBAR_CHANGE 
VE  ID_EDITOR_VIEW
VL	ID_INF_LARGE
VP  ID_SLIDER_VIEW
VR  ID_SCROLLBAR_VIEW 
VS  ID_STATUS_VIEW
VT  ID_TOOLBAR_VIEW
VU	ID_INF_MEDIUM
VV  ID_REVERSE_MOVEBUTTON
VW  ID_WARNING_VIEW
*/

enum {
	K_NULL,								// 0

	K_FO, K_FN, K_FH, K_FP, K_FX, K_FQ,

	K_JN, K_JE, K_JP, K_JV, K_JT, K_JB, K_JI,

	K_JH, K_JF, K_JL, K_JQ,
	K_JJ, K_JM, K_JG, K_JX, K_JR, 

	K_J1, K_J2, K_J3, K_J4, K_J5, 
	K_J6, K_J7, K_J8, K_J9, K_J0,		// 32

	K_SF, K_SU, K_SD,

	K_DM, K_DR, K_DF, K_DL, K_DB, K_DW, K_DV, 
	K_D1, K_D2, K_D3, K_D4, 
	K_DG, K_DD, K_DE, K_DA, K_DH,		// 51

	K_VT, K_VS, K_VP, K_VR, K_VC,

	K_HI, K_HF, K_HB, K_HK, K_HP, K_HA,

	K__H, K__E,							// 64
	
	K_VW, K_DC, K_DP, K_HH, K_FS, K_DI, K_F1, K_VE, 
	K_DT, K_DO, K_DS, K_D6,	 // 76

	K__U, K__D, K__L, K__R, // 80

	K_DU, K_JS, K_PL, K_O1, K_O2, K_O3, K_O4, K_O5,	// 88
	K_VL, K_VU, K_VA,	// 91

	K_NN, K__P, K__N, K_OV, K_NP, K_NO, // 97
	K_N0, K_N1, K_N2, K_N3, K_N4, K_N5, K_N6, K_N7, K_N8, K_N9,	// 107

	K_NF, K__S, K__C, K__I, 		// 111

	K__V, K__W, K_NS, K_NL, K_NR, K_VV, K_JU, K_JD,
	K__X, K__Y,	K__A, K__B, 	// 123

	K__G, K_OC, K_NE, K__Z, K__F, K_HS, K_DN, K_DY,
	K_NI, K_NX, K_NC, K_ND, K_NK, K_NB, K_NG, K__Q,		// 141

	K_OD, K_OS, K__T, K_D_, K_NT, K_OP, K__M, K_FD,		//149
	K__J, K__K, K_V0, K__0, K__1, K__2, K__3
};


// ! ABCDEFGHILMNOPRSUVWXY
struct KEY_TRANS key_trans[] =
{
	{"^^", 0, 0},

	{"FO", 0, ID_FILEOPEN},  {"FN", 0, ID_REOPEN},     {"FH", 0, ID_F_HISTORY},
	{"FP", 0, ID_PRINT},	 {"FX", 0, ID_APPEXIT},    {"FQ", 0, ID_QUIT},

	{"JN", 0, ID_NEXTPAGE},  {"JE", 0, ID_DOWNPAGE}, 
	{"JP", 0, ID_PREVPAGE},  {"JV", 0, ID_UPPAGE},
	{"JT", 0, ID_TOPPAGE},	 {"JB", 0, ID_LASTPAGE},   {"JI", 0, ID_EDITPAGE},

	{"JH", 0, ID_P_HISTORY}, {"JF", 0, ID_FORMERHIST}, {"JL", 0, ID_NEXTHIST},
	{"JQ", 0, ID_QUITHIST},  {"JJ", 0, ID_HYPERTEX},      {"JM", 0, ID_MARKPAGE}, 
	{"JG", 0, ID_GOMARK},    {"JX", 0, ID_EXMARK},     {"JR", 0, ID_MARKRANGE},

	{"J1", 'O', ID_m50PAGE}, {"J2", 'O', ID_m20PAGE},  {"J3", 'O', ID_m10PAGE},
	{"J4", 'O', ID_m5PAGE},	 {"J5", 'O', ID_m2PAGE},
	{"J6", 'O', ID_2PAGE},	 {"J7", 'O', ID_5PAGE},	   {"J8", 'O', ID_10PAGE},
	{"J9", 'O', ID_20PAGE},	 {"J0", 'O', ID_50PAGE},

	{"SF", 0, ID_SEARCH},    {"SU", 0, ID_PRECAND},    {"SD", 0, ID_NEXTCAND},

	{"DM", 'S', ID_MAGNIFY}, {"DR", 'S', ID_REDUCE},   {"DF",'S', ID_FIT},
	{"DL", 'S', ID_FULL},
	{"DB", 'T', ID_BLACKER}, {"DW", 'T', ID_WHITER},   {"DV", 'T', ID_REVERSE},
	{"D1", 'R', ID_SCALE1},	 {"D2", 'R', ID_SCALE2},   {"D3", 'R', ID_SCALE3}, 
	{"D4", 'R', ID_SCALE4},	 {"DG", 'L', ID_LMAGNIFY}, {"DD", 'L', ID_LREDUCE},
	{"DE", 'L', ID_LBIG},	 {"DA", 'L', ID_LLITTLE},  {"DH", 0, ID_MHAND},

	{"VT", 0, ID_TOOLBAR_VIEW},	  {"VS", 0, ID_STATUS_VIEW}, 
	{"VP", 0, ID_SLIDER_VIEW },   {"VR", 0, ID_SCROLLBAR_VIEW}, 
	{"VC", 0, ID_TOOLBAR_CHANGE}, 

	{"HI", 'I', ID_INFO},	    {"HF", 'I', ID_INFO_FONT}, {"HB", 'I', ID_INFO_BUFFER},
	{"HK", 'I', ID_INFO_KEY}, {"HP", 'I', ID_INFO_PARA}, {"HA", 0, ID_ABOUT},

	{"!H", 0, ID_PAGEHEAD}, {"!E", 0, ID_PAGEFOOT},

	{"VW", 0, ID_WARNING_VIEW}, {"DC", 0, ID_COLOR},  {"DP", 0, ID_REPCOLOR},
	{"HH", 0, ID_HELP_CONTENTS},{"FS", 0, ID_SAVEIMG},{"DI", 0, ID_GRAPHIC},
	{"F1", 0, ID_FMENU1},   {"VE", 0, ID_EDITOR_VIEW},{"DT", 0, ID_DOUBLE},
	{"DO", 0, ID_RDOUBLE},    {"DS", 0, ID_CROSS},    {"D6", 0, ID_16PAGE}, 

	{"!U", 0, ID_SCRUP},      {"!D", 0, ID_SCRDW},    {"!L", 0, ID_SCRLF}, 
	{"!R", 0, ID_SCRRT},

	{"DU", 'L', ID_LMEASURE}, {"JS", 0, ID_LASTFILE}, {"PL", 0, ID_LANDSCAPE},
	{"O1", 'C', ID_MACRO1},	  {"O2", 'C', ID_MACRO2},   {"O3", 'C', ID_MACRO3},
	{"O4", 'C', ID_MACRO4},	  {"O5", 'C', ID_MACRO5},

	{"VL", 'I', ID_INF_LARGE}, {"VU", 'I', ID_INF_MEDIUM}, 
	{"VA", 'I', ID_INF_SMALL}, 

	{"NN", 0, ID_PRESENTATION}, 
	{"!P", 0, ID_PRESENTON},     {"!N", 0, ID_PRESENTOFF},
	{"OV", 0, ID_DVIOUTSPECIAL}, {"NP", 'C', ID_COVERSHEET},
	{"NO", 'C', ID_COVERON},
	
	{"N0", 'Y', ID_DEFDEF}, 	{"N1", 'Y', ID_WHITEDEF}, 
	{"N2", 'Y', ID_BLACKDEF},   {"N3", 'Y', ID_WHITEBACK},
	{"N4", 'Y', ID_BLACKBACK}, 

	{"N5", 'V', ID_COVERB},    {"N6", 'V', ID_COVERR},
	{"N7", 'V', ID_COVERL},    {"N8", 'V', ID_COVERBR},
	{"N9", 'V', ID_COVERBL},

	{"NF", 'C', ID_COVEROFF},  {"!S", 0, ID_COVERSUSPEND},
	{"!C", 0, ID_COVERRETURN}, {"!I", 0, ID_INITIALIZE},

	{"!V", 0, ID_TOREVERSE},   {"!W", 0, ID_TONORMAL},
	{"NG", 0, ID_SAVEPRESENT}, {"NL", 'B', ID_USELBUTTON},
	{"NR", 'B', ID_USERBUTTON}, {"VV", 0, ID_REVERSE_MOVEBUTTON},
	{"JU", 0, ID_HEADFOOT},	   {"JD", 0, ID_FOOTHEAD},

	{"!X", 0, ID_LEFTHOME},		{"!Y", 0, ID_RIGHTHOME},
	{"!A", 0, ID_PAINTOFF},		{"!B", 0, ID_PAINTON},
	{"!G", 0, ID_BACKGROUND},	{"OC", 0, ID_SRCSPECIAL},
	{"NE", 0, ID_CUTEDGE},		{"!Z", 0, ID_CUTEDGE1},
	{"!F", 0, ID_DEFIT},		{"HS", 0, ID_INFO_SYS},
	{"DN", 'G', ID_RECTON},		{"DY", 0, ID_VDOUBLE},

	{"NI",'D',ID_DRLINE},		{"NX",'D',ID_DRBOX},
	{"NC",'D',ID_DRERACE}, 		{"ND",'D',ID_DRRED},
	{"NK",'D',ID_DRBLACK},		{"NB",'D',ID_DRBLUE},
	{"NG",'D',ID_DRGREEN},		{"!Q", 0, ID_ONEPAGE},

	{"OD", 0, ID_DIFOPTION},	{"OS",0, ID_OPTION},	
	{"!T", 0, ID_RESCUTEDGE},	{"DX",'G',ID_RECTREC}, 
	{"NT",'D',ID_DTHICK},		{"OP", 0, ID_PREPARA},
	{"!M", 0, ID_WINMAX},		{"FD", 0, ID_DVIPRT},

	{"!J", 0, ID_RELATEDVI},	{"!K", 0, ID_SETSTARTMENU},
	{"V0", 0, ID_FRAME0},		{"!0", 0, ID_STOPOFF},
	{"!1", 0, ID_STOPON},		{"!2", 0, ID_DINOFF},
	{"!3", 0, ID_DINON},

	{"$$", 0, 1}, {"&&", 0, 1}
};

struct KEY_INFO {
	unsigned short int id;
	char *msg;
};


static struct KEY_INFO key_info[] =
{
	{K_JN, "Next Page\t\t: PgDn,"},
	{K_J6, "\t+2\t\t:"},
	{K_J7, "\t+5\t\t: SHIFT+SP, SHIFT+PgDn,"},
	{K_J8, "\t+10\t\t: CTRL+SP, CTRL+PgDn,"},
	{K_J9, "\t+20\t\t:"},
	{K_J0, "\t+50\t\t: CTRL+SHIFT+SP, CTRL+SHIFT+PgDn,"},

	{K_JP, "Previous Page\t\t: PgUp,"},
	{K_J5, "\t-2\t\t:"},
	{K_J4, "\t-5\t\t: SHIFT+BS, SHIFT+PgUp,"},
	{K_J3, "\t-10\t\t: CTRL+BS, CTRL+PgUp,"},
	{K_J2, "\t-20\t\t:"},
	{K_J1, "\t-50\t\t: CTRL+SHIFT+BS, CTRL+SHIFT+PgUp,"},

	{0x1000, "\n"},
	{K_JE, "Head of next page\t: SP, SHIFT+DownArrow,"},
	{K_JV, "Foot of previous page\t: BS, SHIFT+UpArrow,"},
	{K_JT, "Top Page\t\t: CTRL+Home,"},
	{K_JB, "Bottom Page\t\t: CTRL+End,"},
	{K_JD, "Down to next page\t:"},
	{K_JU, "Up to previous page\t:"},

	{0x1000, "\n"},
	{0x1000,"Scroll\t\t\t: Arrow Keys, Left Mouse Botton\n"},
	{K__U, " Scroll up\t\t: Up    Arrow"},
	{K__D, " Scroll down\t\t: Down  Arrow"},
	{K__L, " Scroll left\t\t: Left  Arrow"},
	{K__R, " Scroll right\t\t: Right Arrow"},
	{K__H, "Head of a Page\t\t: Home"},
	{K__E, "Foot of a Page\t\t: End"},
	{K__X, "Left of a Page\t\t:"},
	{K__Y, "Right of a page\t\t:"},

	{0x1000, "\n"},
	{K_JI, "Input Page Number\t:"},
	{0x1000, "  absolute\t\t:    <number>\n"},
	{0x1000, "  relative\t\t:    +<number>, -<number>\n"},
	{0x1000, "  from the bottom\t:    .[<number>]\n"},
	{0x1000, "    by page number\t:        Enter\n"},
	{0x1000, "    by nombre\t\t:        CTRL+Enter, SHIFT+Enter\n"},

	{0x1000, "\n"},
	{K_JH, "Page History list\t:"},
	{K_JF, "Former History\t\t:"},
	{K_JL, "Latter History\t\t:"},
	{K_JQ, "Quit History\t\t:"},
	{K_JM, "Mark page\t\t:"},
	{K_JG, "Goto Mark\t\t:"},
	{K_JX, "Exchange Mark\t\t:"},
	{K_JR, "Mark range\t\t:"},
	{K_FH, "File History list\t: ALT+I,"},
	{K_JS, "Last file\t\t:"},

	{0x1000, "\n"},
	{K_SF, "Dialog for Search\t:"},
	{K_SU, "Upward Search\t\t:"},
	{K_SD, "Downward Search\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Size\n"},
	{K_DM, " Magnify\t\t:"},
	{K_DR, " Reduce\t\t\t:"},
	{K_DF, " Fit\t\t\t:"},
	{K_DL, " Full\t\t\t:"},
	{K__M, "Maximize Window\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Preset\n"},
	{K_D1, " View 1\t\t\t:"},
	{K_D2, " View 2\t\t\t:"},
	{K_D3, " View 3\t\t\t:"},
	{K_D4, " View 4\t\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Contrast\n"},
	{K_DB, " Blacker\t\t:"},
	{K_DW, " Whiter\t\t\t:"},
	{K_DV, " Reverse\t\t:"},
	{K__V, "  To Reverse\t\t:"},
	{K__W, "  To Normal\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Loupe\t\t\t: Right Mouse Botton\n"},
	{K_DG, " Magnify\t\t:"},
	{K_DD, " Reduce\t\t\t:"},
	{K_DE, " Bigger\t\t\t:"},
	{K_DA, " Smaller\t\t:"},
	{K_DU, " Measure\t\t:"},

	{0x1000, "\n"},
	{K_DT, "two pages\t\t:"},
	{K_DO, "rev-two pages\t\t:"},
	{K_DY, "Y-two pages\t\t:"},
	{K_DS, "cross pages\t\t:"},
	{K_D6, "16 pages\t\t:"},
	{K__Q, "one page\t\t:"},

	{0x1000, "\n"},
	{K_PL, "Landscape\t\t:"},
	{K_DN, "Region\t\t\t:"},
	{K_D_, "Recover:\t\t:"},
	{K_DH, "Change Mouse\t\t: ALT+\\,"},
	{K_DI, "Graphics\t\t:"},
	{K_DC, "Color special\t\t:"},
	{K_DP, "Color replace\t\t:"},
	{K__0, "Stop off\t\t:"},
	{K__1, "Stop on\t\t\t:"},

	{0x1000, "\n"},
	{K_JJ, "HyperJump ON/OFF\t:"},
	{0x1000,"HyperJump\t\t: Left Mouse Botton\n"
			"     with inquiry\t:     + CTRL\n\n"},

	{K_FO, "Open File\t\t:"},
	{K_F1, "Open last file\t\t:"},
	{K_FN, "reNew File\t\t:"},
	{K__I, "reNew if necessary\t:"},
	{K_FP, "Print\t\t\t:"},
	{K_FD, "Dviprt\t\t\t:"},
	{K_FS, "Save as Image\t\t:"},
	{K_FX, "Exit & Save\t\t: ALT+X, ALT+F4,"},
	{K_FQ, "Quit\t\t\t:"},

	{0x1000, "\n"},
	{0x1000, "View\n"},
	{K_VT, " Tool bar\t\t:"},
	{K_VS, " Status bar\t\t:"},
	{K_VP, " Page slider\t\t:"},
	{K_VR, " Scroll bar\t\t:"},
	{0x1000, " Erace bars\t\t: [V0]"},
	{K_VV, " Reverse Move Button\t:"},
	{K_VW, " Show Warning\t\t:"},
	{K_VC, " Change Tool Buttons\t:"},
	{K_VE, " Small Editor\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Presentation\n"},
	{K_NN, "On/Off switch\t\t:"},
	{K__P, " Presentation On\t:"},
	{K__N, " Presentation Off\t:"},
	{K_NS, "Save settings\t\t:"},
	{K__A, " Stop Draw\t\t:"},
	{K__B, " Recover Draw\t\t:"},
	{K_NE, "Cut edge On/Off\t\t:"},
	{K__Z, "Cut edge On\t\t:"},
	{K__T, "Cut edge Off\t\t:"},
	{K__F, "Quit Fit/Full\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Mouse Button to proceed\n"},
	{K_NL, " Use left button\t:"},
	{K_NR, " Use right button\t:"},

	{0x1000, "\n"},
	{0x1000, "Presentation type\n"},
	{K_N0, " general screen\t\t:"},
	{K_N1, " white screen\t\t:"},
	{K_N2, " black screen\t\t:"},
	{K_N3, " white back\t\t:"},
	{K_N4, " black back\t\t:"},
	{K__G, " renew background\t:"},
	{K_NI, " Draw line\t\t:"},
	{K_NX, "   box\t\t\t:"},
	{K_NC, "   erace\t\t:"},
	{K_ND, "   red\t\t\t:"},
	{K_NK, "   black\t\t:"},
	{K_NB, "   blue\t\t\t:"},
	{K_NG, "   green\t\t:"},
	{K_NT, "   thick\t\t:"},

	{0x1000, "\n"},
	{0x1000, "Cover sheet\n"},
	{K_NO, " On\t\t\t: Fn5(Presentation)"},
	{K_NF, " Off\t\t\t: Fn6(Presentation)"},
	{K_NP, " On for Pause\t\t: Fn9(Presentation)"},
	{K__S, " Supspend Cover sheet\t: Fn7(Rresentation)"},
	{K__C, " Return to Cover sheet\t: Fn8(Presentation)"},

	{0x1000, "\n"},
	{0x1000, "Cover type\n"},
	{K_N5, "  bottom\t\t:"},
	{K_N6, "  right\t\t\t:"},
	{K_N7, "  left\t\t\t:"},
	{K_N8, "  bottom + right\t:"},
	{K_N9, "  bottom + left\t\t:"},

	{0x1000, "\n"},
	{K_O1, "Macro 1\t\t\t:"},
	{K_O2, "Macro 2\t\t\t:"},
	{K_O3, "Macro 3\t\t\t:"},
	{K_O4, "Macro 4\t\t\t:"},
	{K_O5, "Macro 5\t\t\t:"},

	{0x1000, "\n"},
	{K_OV, "dviout special ON/OFF\t:"},
	{K_OC, "source special ON/OFF\t:"},
	{K__2, "Copy to Editor with CTRL\t:"},
	{K__3, "Copy to Editor without CTRL\t:"},

	{0x1000, "\n"},
	{K_HH, "Online Help\t\t:"},
	{K_HI, "Screen/File Info\t:"},
	{K_HF, "Font Info\t\t:"},
	{K_HB, "Buffer Info\t\t:"},
	{K_HS, "System Info\t\t:"},
	{K_HP, "Parameter Info\t\t:"},
	{K_OD, "Non-default Parameters\t:"},
	{K_OS, "Setup Parameters\t:"},
	{K_OP, "Choose Parameters\t:"},
	{K_HK, "Key table\t\t:"},
	{K_HA, "About dviout\t\t:"},
	{K_NULL, ""}
};



unsigned char org_key_table[MAX_KEYDEF];

unsigned char key_table[MAX_KEYDEF] =
{
//	   @,	A,	 B,	  C,   D,	E,	 F,	  G		+CTRL
	   0,	0,K_JB,K_DC,K_FD,	0,K_SF,K_JG,

//	   H,	I,	 J,	  K,   L,	M,	 N,	  O		+CTRL
	   0,	0,K_JH,   0,K_OP,	0,K_FN,K_FO,

//	   P,	Q,	 R,	  S,   T,	U,	 V,	  W		+CTRL
	K_FP,K_HS,K_SU,K_SD,K_JT,K__0,K__1,	  0,

//	   X,	Y,	 Z,	  [,   \,	],	 ^,	  _		+CTRL
	K_JX,	0,	 0,K_DN,K_OS,	0,	 0,   0,

//	  SP,	!,	 ",   #,   %,   $,   &,   '
	   0,	0,	 0,	  0,   0,	0,	 0,	  0,

//	   (,	),	 *,	  +,	,	-,	 .,	  /
	   0,	0,	 0,	  0,   0,	0,	 0,K_JI,

//	   0,	1,	 2,	  3,   4,	5,	 6,	  7
	   K_DY,K_D1,K_D2,K_D3,K_D4,K_DF,K_DL,K_DT,

//	   8,	9,	 *,	  ;,   <,	=,	 >,	  ?
	   K_DS,K_D6,0,	  0,K_JF,	0,K_JL,	  0,

//	   @,	A,	 B,	  C,   D,	E,	 F,	  G
	   0,	0,	 0,	  0,K_JD,	0,K_JF,	  0,

//	   H,	I,	 J,	  K,   L,	M,	 N,	  O
	   0,	0,	 0,	  0,K_JL,K_JM,K_JN,	  0,

//	   P,	Q,	 R,	  S,   T,	U,	 V,	  W
	K_JP,K_JQ,K_JR,	  0,   0,K_JU,	 0,	  0,

//	   X,	Y,	 Z,	  [,   \,	],	 ^,	  _
	   0,	0,	 0,	  0,   0,	0,	 0,	  0,

//	   `,	a,	 b,	  c,   d,	e,	 f,	  g
	   0,	0,	 0,	  0,K_JD,	0,K_JF,	  0,

//	   h,	i,	 j,	  k,   l,	m,	 n,	  o
	   0,	0,	 0,	  0,K_JL,K_JM,K_JN,	  0,

//	   p,	q,	 r,	  s,   t,	u,	 v,	  w
	K_JP,K_JQ,K_JR,	  0,   0,K_JU,	 0,	  0,

//	   x,	y,	 z,	  {,   |,	},	 ~,
	   0,	0,	 0,	  0,   0,	0,	 0,	  0,

//	  F1,  F2,	F3,	 F4,  F5,  F6,	F7,	 F8,
	  K_HH, 0,K_SD,	  0,   0,	0,	 0,	  0,

//	  F9, F10,	F11, F12
	   0,	0,	 0,	  0,

//	 SF1, SF2, SF3, SF4, SF5, SF6, SF7, SF8,
	 K_O1,K_O2,K_SU,  0,K_O3,K_O4,K_O5,	  0,

//	 SF9, SF10,SF11,SF12,Button,U1, U2,	 U3,
	   0,	0,	 0,	  0,   0,	0,	 0,	  0,

//	  U4,  U5
	   0,	0
};

void PrintKeyTable(char *tmp, int mode)
{
	int pos, len, len0, id;

	if(mode > 0){
		strcpy(tmp, "key=$$");
		len = 6;
	}else
		len = 0;
	for(pos = len0 = 0; pos < MAX_KEYDEF; pos++){
		if((id = key_table[pos]) != 0 || !mode){
			if(!mode && id == org_key_table[pos])
				continue;
			if(len && len - len0 < 80){
				sprintf(tmp+len, ":%c%c=", 
					key_trans[id].key[0], key_trans[id].key[1]);
				len += 4;
			}else if(mode >= 0){
				len0 = len;
				sprintf(tmp+len, (len)?"\nkey=%c%c=":"key=%c%c=", 
					key_trans[id].key[0], key_trans[id].key[1]);
				len += 8;
				if(len == 8)
					len--;
			}else{
				sprintf(tmp+len, "%c%c=", 
					key_trans[id].key[0], key_trans[id].key[1]);
				len += 3;
			}
			if(pos > 0x20 && pos < 0x7f && pos != 0x5c && pos != 0x5e){
				tmp[len++] = pos;
			}else if(pos < 0x20){
				tmp[len++] = '^';
				tmp[len++] = pos + 0x40;
			}else{
				sprintf(tmp+len, "\x5c%2x", pos);
				len += 3;
			}
		}
	}
	tmp[len] = 0;
}

static char NullKey[] =
{
	0x00, 0x20, 'H' - 0x40, 'I' - 0x40, 'M' - 0x40, 0x1f
};

void DefineKeyTable(unsigned char *s)
{
	unsigned char *data;
	int	i, ch, k;
	struct KEY_TRANS *trans;

	data = s;
	while(data[0] && data[1]){
		trans = &(key_trans[0]);
		k = 0;
		do{
			if(trans->key[0] == data[0] && trans->key[1] == data[1]){
				if(*data == '$'){
					for(i = 0; i < MAX_KEYDEF; i++)
						key_table[i] = 0;
					data += 3;
					if(!*(data-1))
						goto end;
					goto nxt;
				}
				data += 2;
				while(1){
					if(!*data || !*++data) goto end;
					if(*data == '\\'){
						if(!*++data) goto err;
						if(*data == '\\' || *data == '^')
							goto dk;
						if(*data == '&' && data[1] ){
							data++;
							i = 0x80 + 12 + 12;
							goto fkey;
						}
						if(*data == '$'){
							i = 0x80+12;
							goto fkey;
						}
						if(*data == '#'){
							i = 0x80;
fkey:						if((ch = *++data) <= 9){
								ch -= '0';
							}else
								ch = (ch | 0x20) - ('a') - 10;
							if(ch <= 0 || ch > 12)
								goto err;
							ch += i;
							goto c_key;
						}
						if((ch = *data++) <= '9')
							ch -= '0';
						else
							ch = (ch | 0x20) - ('a' - 10);
						ch = ch * 16 + *data;
						if(*data <= '9')
							ch -= '0';
						else
							ch = (ch | 0x20) - ('a' - 10);
						if(!*data || ch < 0 || ch >= MAX_KEYDEF)
							goto err;
c_key:					for(i = 0; i < sizeof(NullKey); i++){
							if(NullKey[i] == ch)
								break;
						}
						if(i == sizeof(NullKey))
							key_table[ch] = (unsigned char)k;
					}else if(*data == '^'){
						if(isalpha(data[1]) || (data[1] >= 0x40 && data[1] < 0x60)){
							ch = toupper(*++data) - 0x40;
							goto c_key;
						}
						key_table['^'] = (unsigned char)k;
					}else if(*data < 0x80)
dk:						key_table[*data] = (unsigned char)k;
					if(data[1] == ':'){
						data += 2;
						goto nxt;
					}
				}
			}
			trans++;
			k++;
		}while(trans->key[0] != '&');
err:
	error(ILLEGAL_ARGS, "-key=%s\n", s);
	goto end;
nxt:;
	}
end:;
}
static void ShowKey(int code, char *msg)
{
	int	j;

	if(key_trans[code].key[0] == '!')
		error(C_MSG, "%s [%c%c]", 
			msg, key_trans[code].key[0], key_trans[code].key[1]);
	else{
		error(C_MSG, "%s ALT+%c%c%c [%c%c]", msg, key_trans[code].key[0],
			(key_trans[code].key2)?key_trans[code].key2:' ',
			key_trans[code].key[1],
			key_trans[code].key[0], key_trans[code].key[1]);
	}
	for(j = 0; j < MAX_KEYDEF; j++){
		if(key_table[j] == code){
			if(j < 0x20)
				error(C_MSG, ",  CTRL+%c", j|0x40);
			else if(j == 0x7f)
				error(C_MSG, ",  \\%02x", j);
			else if(j == MAX_KEYDEF - USER_KEY)
				error(C_MSG, ", Button");
			else if(j > MAX_KEYDEF - USER_KEY)
				error(C_MSG, ",  User%c", j	 +	('0' - MAX_KEYDEF + USER_KEY));
			else if(j >= 0x80+12)
				error(C_MSG, ",  SFn%d", j - (0x7f+12));
			else if(j >= 0x80)
				error(C_MSG, ",  Fn%d", j - 0x7f);
			else
				error(C_MSG, ",  %c", j);
		}
	}
	error(C_MSG, "\n");
}

void DisplayKeyInfo(void)
{
	struct KEY_INFO *key;

	for(key = key_info; key->id != K_NULL; key++){
		if(key->id & 0x1000)
			error(C_MSG, "%s", key->msg);
		else
			ShowKey(key->id, key->msg);
	}
	error(DATATITLE, "Key table");
}

static void PrintChar(char *sz_Key, int code)
{
	if(code < 0x20)
		sprintf(sz_Key, "CTRL+%c ",code + 0x40);
	else if(code == 0x20)
		strcpy(sz_Key,	"Space  ");
	else if(code == 0x7f)
		strcpy(sz_Key,	"DEL    ");
	else if(code == MAX_KEYDEF - USER_KEY)
		strcpy(sz_Key,	"Button ");
	else if(code > MAX_KEYDEF - USER_KEY)
		sprintf(sz_Key, "User%1d ", code - (MAX_KEYDEF - USER_KEY)); 
	else if(code >= 0x80+12)
		sprintf(sz_Key, "SFn%2d  ", code - (0x7f+12));
	else if(code >= 0x80)
		sprintf(sz_Key, "Fn%2d   ", code - 0x7f);
	else
		sprintf(sz_Key,"%c      ", code);
}

static void DeTab(char *sz_Key, char *s, int len)
{
	int pos;

	len -= 9;
	for(pos = 0; pos < len; ){
		if(!(sz_Key[pos] = *s++) || sz_Key[pos] == '\n')
			break;
		if(sz_Key[pos++] == '\t'){
			sz_Key[pos-1] = ' ';
			while(pos & 7)
				sz_Key[pos++] = ' ';
		}
	}
	sz_Key[pos] = 0;
}

static void ModifyKeyTable( HWND hDlg, int code, int idx)
{
	int pos;
	char sz_Key[256];

	PrintChar(sz_Key, code);
	if(idx == 0){
		if(key_table[code] == 0)
			return;
		idx = key_table[code];
		key_table[code] = 0;
	}else{
		ModifyKeyTable(hDlg, code, 0);		/* Clear definition */
		key_table[code] = idx;
		sprintf(sz_Key+7, "[%c%c]", 
			key_trans[idx].key[0],key_trans[idx].key[1]);
	}

	SendDlgItemMessage(hDlg, IDC_COMBOBOX1, CB_DELETESTRING, code, 0);
	SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
		CB_INSERTSTRING, code, (LPARAM)sz_Key);
	SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
		CB_SETCURSEL, code, 0);

	for(pos = 0; key_info[pos].id != K_NULL; pos++){
		if(key_info[pos].id == idx){
			ShowKey(idx, key_info[pos].msg );
			SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_DELETESTRING, pos, 0);
			DeTab(sz_Key, GetMessagePtr(), 256);
			ResetMessagePtr();
			SendDlgItemMessage(hDlg, IDC_LISTBOX1, 
				LB_INSERTSTRING, pos, (LPARAM)sz_Key);
			SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_SETCURSEL, pos, 0);
			break;
		}
	}
}

void LoadKeyTable(void)
{
	int i;

	RestoreBinary( key_table, MAX_KEYDEF, "KeyTable", "Key", 0 );
	for(i = 0; i < sizeof(NullKey); i++)
		key_table[NullKey[i]] = 0;
}

unsigned int GetUserKey(int num)
{
	if(num < 0)
		return USER_KEY;
	if(num >= USER_KEY)
		return 0;
	return key_trans[key_table[MAX_KEYDEF-USER_KEY+num]].id;
}

char *GetUserInfo(int idx)
{
	int pos, posd;
	static char toolmsg[32];
	int pt = 0;

	while(key_info[pt].id != K_NULL){
		if(key_trans[key_info[pt].id].id != idx){
			pt++;
			continue;
		}
		pos = (key_info[pt].msg[0] == '\t')?1:0;
		if(key_info[pt].msg[pos] <= ' ')
			return NULL;
		for(posd = 0; posd < 31; ){
			if( (toolmsg[posd++] = key_info[pt].msg[pos++]) < ' '){
				break;
			}
		}
		toolmsg[posd-1] = 0;
		return toolmsg;
	}
	return NULL;
}

LRESULT CALLBACK KeyTabProc( HWND hDlg, UINT message, 
									WPARAM wParam, LPARAM lParam )
{
	void InitTabString(HWND hwnd, char *key, int id);
	void SetTabString(HWND hwnd, char *key, int id);
	void RestoreTabString(HWND hwnd, char *key, int id);
	void ReserveTabString(HWND hwnd, char *key, int id);
#define	INIT_APPLY	0x1000

	int code, idx, pos, ret_val;
	struct KEY_INFO *key;
	char *s;
	char sz_Key[256];
	static char *sz_Org;
	static UINT f_change;
	static DWORD help[] ={
		IDC_KDEF, IDH_KEYDEFINE,
		IDC_KCLEAR, IDH_KEYCLEAR,
		IDC_KSEARCH, IDH_KEYSEARCH,
		ID_ALLCLEAR, IDH_KEYALLCLEAR,
		IDC_LISTBOX1, IDH_KEYFUNCTION,
		IDC_COMBOBOX1,IDH_KEYKEY,
		IDC_DEFAULT, IDH_DEFAULT,
		IDC_MACRO,	IDH_MACRO,
		0, 0
	};
	static HWND hedit;
	extern int f_DlgQuery;

	switch( message )
	{
		case WM_INITDIALOG:
			f_change = INIT_APPLY;
			if(sz_Org)
				GlobalFree(sz_Org);
			InitTabString(hDlg, "macro", IDC_MACRO);
			sz_Org = (char*)HeapAlloc( GetProcessHeap(), 0, MAX_KEYDEF );
			memcpy( sz_Org, key_table, MAX_KEYDEF);
start:		ret_val = TRUE;
cancel:		for(code = 0; code < MAX_KEYDEF; code++){
				PrintChar(sz_Key, code);
				if((idx = key_table[code]) != 0)
					sprintf(sz_Key+7, "[%c%c]",
						key_trans[idx].key[0],key_trans[idx].key[1]);
				SendDlgItemMessage(hDlg, IDC_COMBOBOX1, CB_ADDSTRING, 0,
						(LPARAM)sz_Key);
			}

			for(key = key_info; key->id != K_NULL; key++){
				if(key->id & 0x1000)
					error(C_MSG, "%s", key->msg);
				else
					ShowKey(key->id, key->msg );
				s = GetMessagePtr();
				DeTab(sz_Key, s, 256);
				ResetMessagePtr();
				SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_ADDSTRING, 0,
						(LPARAM)sz_Key);
			}
			SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_SETHORIZONTALEXTENT,
				1024, 0);
			if(f_change & INIT_APPLY)
				f_change = 0;
			return ret_val;

		case WM_COMMAND:
			switch( wParam )
			{
				case IDC_DEFAULT:
					memmove(key_table, org_key_table, MAX_KEYDEF);
					s = GetParaStringDefault("macro");
					if(s)
						SetDlgItemText(hDlg, IDC_MACRO, s);
					goto reset;

				case ID_RESTORE:
					RestoreBinary( key_table, MAX_KEYDEF, "KeyTable", 
						"Key", 0 );
					RestoreTabString(hDlg, "macro", IDC_MACRO);

reset:				SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
						CB_RESETCONTENT, 0, 0L);
					SendDlgItemMessage(hDlg, IDC_LISTBOX1, 
						LB_RESETCONTENT, 0, 0L);
					PropSheet_Changed( GetParent(hDlg), hDlg );
					ApplyOn( hDlg, &f_change );
					f_change |= 1;
					goto start;

				case ID_SAVE:
					ReserveBinary( "KeyTable", "Key", key_table, MAX_KEYDEF );
					ReserveTabString(hDlg, "macro", IDC_MACRO);
					MessageSaved(hDlg);
					break;

				case IDC_KCLEAR:		/* clear def  */
					code = SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
						CB_GETCURSEL, 0, 0L);
					if(code == CB_ERR){
cb_err:					ShowMessage("No key is selected",NULL,
							SM_OKCONT);
						break;
					}
					ModifyKeyTable(hDlg, code, 0);
change:				PropSheet_Changed( GetParent(hDlg), hDlg );
					ApplyOn( hDlg, &f_change );
					f_change |= 1;
					break;

				case ID_ALLCLEAR:
					for(pos = 0; pos < MAX_KEYDEF; pos++)
						key_table[pos] = 0;
					ret_val = TRUE;
clear:				SendDlgItemMessage(hDlg, IDC_COMBOBOX1,CB_RESETCONTENT,
						0, 0);	
					SendDlgItemMessage(hDlg, IDC_LISTBOX1, LB_RESETCONTENT,
						0, 0);
					ApplyOn( hDlg, &f_change );
					f_change |= 1;
					goto cancel;

				case IDC_KDEF:		/* define def */
					code = SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
						CB_GETCURSEL, 0, 0L);
					if(code == CB_ERR)
						goto cb_err;
					for(pos = 0; pos < sizeof(NullKey); pos++){
						if(NullKey[pos] == code){
							ShowMessage("This Key: cannot be selected",NULL,
								SM_OKCONT);
							return FALSE;
						}
					}
					pos = SendDlgItemMessage(hDlg, IDC_LISTBOX1, 
						LB_GETCURSEL, 0, 0L);
					if(pos == LB_ERR){
						ShowMessage("No function is selected", NULL,
							SM_OKCONT);
						break;
					}
					if((idx = key_info[pos].id) & 0x1000){
						ShowMessage("This function cannot be selected",NULL,
							SM_OKCONT);
						break;
					}
					ModifyKeyTable(hDlg, code, idx);
					goto change;

				case IDC_KSEARCH:			// Search
					code = SendDlgItemMessage(hDlg, IDC_COMBOBOX1, 
						CB_GETCURSEL, 0, 0L);
					if(code == CB_ERR)
						goto cb_err;
					if((idx = key_table[code]) != 0){
						for(pos = 0; key_info[pos].id != K_NULL; pos++){
							if(key_info[pos].id == idx){
								SendDlgItemMessage(hDlg, IDC_LISTBOX1, 
									LB_SETCURSEL, pos, 0);
								return FALSE;
							}
						}
					}
					ShowMessage("No function attached to this key",
						NULL, SM_OKCONT);	
					break;
			}
			if(HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_MACRO){
				ApplyOn( hDlg, &f_change );
				f_change |= 1;
			}
			break;

		case WM_HELP:
			ShowCHelp(lParam, help);
			break;

		case WM_NOTIFY:
			switch( ((NMHDR*)lParam)->code ){
				case PSN_HELP:				// HELP
					ShowWinHelp(IDH_PKEY);
					break;

				case PSN_KILLACTIVE:		// lose active
					ReSetFont(hedit);
					break;

//				case PSN_RESET:				// End Prperty Sheet

				case PSN_QUERYCANCEL:		// Cancel
					if(f_change){
skip:					memcpy(key_table, sz_Org, MAX_KEYDEF);
						ApplyOff(hDlg);
						ret_val = f_change = FALSE;
						goto clear;
					}
					break;

				case PSN_APPLY:				// Apply or OK
					if(!f_change)
						break;
					switch(QueryApply(hDlg,IDD_TAB_KEY)){
						case IDYES:			// change the current parameters
							memcpy(sz_Org, key_table, MAX_KEYDEF);
							SetTabString(hDlg, "macro", IDC_MACRO);
							SetButton();
							f_change = FALSE;
							g_bPropertySheetChange = TRUE;
							break;

						case IDCANCEL:		// cancel to apply
							return TRUE;

						case IDNO:			// skip to apply
							goto skip;
					}
					break;

				case PSN_SETACTIVE:
					AdjustPropPage(hDlg);
					hedit = GetDlgItem( hDlg, IDC_MACRO );
					SetFontJE(hedit);
					SetMargin(hedit);
					break;
		}
		break;

		case WM_DESTROY:
			break;
	}
	return FALSE;
}

unsigned int KeyId(char *key)
{
	int	code;

	for(code = 0; key_trans[code].key[0] != '&'; code++){
		if(	 key_trans[code].key[0] == key[0]
		  && key_trans[code].key[1] == key[1] )
		return key_trans[code].id;
	}
	return 0;
}
