/*
 *      Wang PC keyboard handler
 */
#include    "def.h"

extern    char    MSG_sp_key[];
extern    char    MSG_byte_shift[];
extern    char    MSG_back_char[];
extern    char    MSG_quit[];
extern    char    MSG_forw_del_char[];
extern    char    MSG_toggle_swap[];
extern    char    MSG_forw_char[];
extern    char    MSG_abort[];
extern    char    MSG_ins_self[];
extern    char    MSG_back_del_char[];
extern    char    MSG_refresh[];
extern    char    MSG_forw_line[];
extern    char    MSG_back_line[];
extern    char    MSG_quote[];
extern    char    MSG_recall[];
extern    char    MSG_twiddle[];
extern    char    MSG_forw_page[];
extern    char    MSG_kill_region[];
extern    char    MSG_yank[];
extern    char    MSG_down_window[];
extern    char    MSG_ins_toggle[];
extern    char    MSG_display_buffers[];
extern    char    MSG_quit[];
extern    char    MSG_exit_flush_all[];
extern    char    MSG_set_file_name[];
extern    char    MSG_file_insert[];
extern    char    MSG_buf_size_lock[];
extern    char    MSG_flush_all[];
extern    char    MSG_down_window[];
extern    char    MSG_up_window[];
extern    char    MSG_file_read[];
extern    char    MSG_file_save[];
extern    char    MSG_file_visit[];
extern    char    MSG_file_write[];
extern    char    MSG_swap_dot_and_mark[];
extern    char    MSG_shrink_window[];
extern    char    MSG_display_position[];
extern    char    MSG_start_macro[];
extern    char    MSG_end_macro[];
extern    char    MSG_help[];
extern    char    MSG_only_window[];
extern    char    MSG_split_window[];
extern    char    MSG_use_buffer[];
extern    char    MSG_spawn_cli[];
extern    char    MSG_execute_macro[];
extern    char    MSG_goto_line[];
extern    char    MSG_ins_unit[];
extern    char    MSG_kill_buffer[];
extern    char    MSG_load_bindings[];
extern    char    MSG_forw_window[];
extern    char    MSG_back_window[];
extern    char    MSG_view_file[];
extern    char    MSG_enlarge_window[];
extern    char    MSG_ascii_mode[];
extern    char    MSG_binary_mode[];
extern    char    MSG_buffer_name[];
extern    char    MSG_decimal_mode[];
extern    char    MSG_ebcdic_mode[];
extern    char    MSG_hex_mode[];
extern    char    MSG_back_del_unit[];
extern    char    MSG_octal_mode[];
extern    char    MSG_display_version[];
extern    char    MSG_unit_size1[];
extern    char    MSG_unit_size2[];
extern    char    MSG_unit_size4[];
extern    char    MSG_reposition_window[];
extern    char    MSG_set_mark[];
extern    char    MSG_goto_eob[];
extern    char    MSG_goto_bob[];
extern    char    MSG_next_buff[];
extern    char    MSG_prev_buff[];
extern    char    MSG_query_replace[];
extern    char    MSG_display_bindings[];
extern    char    MSG_auto_save[];
extern    char    MSG_back_unit[];
extern    char    MSG_compare[];
extern    char    MSG_forw_del_unit[];
extern    char    MSG_forw_unit[];
extern    char    MSG_link_windows[];
extern    char    MSG_print[];
extern    char    MSG_back_search[];
extern    char    MSG_forw_search[];
extern    char    MSG_back_page[];
extern    char    MSG_copy_region[];
extern    char    MSG_extended_command[];
extern    char    MSG_up_window[];
extern    char    MSG_search_again[];
extern    char    MSG_bind_to_key[];
extern    char    MSG_file_visit_split[];
extern    char    MSG_yank_buffer[];
extern    char    MSG_save_region[];
extern    char    MSG_use_buffer_split[];
extern    char    MSG_no_f_tb[];

#define SPECIAL 0x1F            /* Special keys         */

typedef    struct  key_name_array 
{
	int     key_code;
	char    *func_name_str;
	char    *key_name_str;
}   KEY_NAME_ARRAY;
#if MSDOS
extern  bool    wang_pc;
extern  bool    ibm_pc;
#endif
/*
 * The keyboard's special characters, those things that are prefixed with
 * a 0x1F, are placed into the keyboard tables as KCTRL || 0x80 || x, for some
 * x, i.e. they have both the control and 0x80 bits set, so they won't conflict
 * with anything else on the keyboard.
 */


/*
 * Names for the keys with basic keycode
 * between KFIRST and KLAST (inclusive). This is used by
 * the key name routine in "kbd.c".
 */
#if MSDOS
KEY_NAME_ARRAY wang_keys[] =
{
	KCTRL | 0x80, MSG_bind_to_key, "Indent", 
	    /*  KCTRL | 0x81, NULL, "Page", */
	KCTRL | 0x82, MSG_reposition_window, "Center",
	    /*  KCTRL | 0x83, NULL, "DecTab", */
	/*  KCTRL | 0x84, NULL, "Format", */
	/*  KCTRL | 0x85, NULL, "Merge", */
	/*  KCTRL | 0x86, NULL, "Note", */
	KCTRL | 0x87, MSG_set_mark, "Stop",
	    KCTRL | 0x88, MSG_forw_search, "Search", 
	    KCTRL | 0x89, MSG_yank, "Replace",
	    KCTRL | 0x8A, MSG_copy_region, "Copy",
	    KCTRL | 0x8B, MSG_kill_region, "Move",
	    KCTRL | 0x8C, MSG_extended_command, "Command",
	    KCTRL | 0x8D, MSG_forw_window, "UpDown",
	    /*  KCTRL | 0x8E, NULL, "BlankKey", */
	KCTRL | 0x8F, MSG_goto_line, "GoTo",
	    /*  KCTRL | 0x90, NULL, "Sh-Indent", */
	/*  KCTRL | 0x91, NULL, "Sh-Page", */
	/*  KCTRL | 0x92, NULL, "Sh-Center", */
	/*  KCTRL | 0x93, NULL, "Sh-DecTab", */
	/*  KCTRL | 0x94, NULL, "Sh-Format", */
	/*  KCTRL | 0x95, NULL, "Sh-Merge", */
	/*  KCTRL | 0x96, NULL, "Sh-Note", */
	/*  KCTRL | 0x97, NULL, "Sh-Stop", */
	KCTRL | 0x98, MSG_search_again, "Sh-Search",
	    KCTRL | 0x99, MSG_query_replace, "Sh-Replace",
	    /*  KCTRL | 0x9A, NULL, "Sh-Copy", */
	/*  KCTRL | 0x9B, NULL, "Sh-Move", */
	/*  KCTRL | 0x9C, NULL, "Sh-Command", */
	KCTRL | 0x9D, MSG_split_window, "Sh-UpDown",
	    /*  KCTRL | 0x9E, NULL, "Sh-BlankKey", */
	/*  KCTRL | 0x9F, NULL, "Sh-GoTo", */
	KCTRL | 0xC0, MSG_back_line, "North",
	    KCTRL | 0xC1, MSG_forw_char, "East",
	    KCTRL | 0xC2, MSG_forw_line, "South",
	    KCTRL | 0xC3, MSG_back_char, "West",
	    KCTRL | 0xC4, MSG_byte_shift, "Home",
	    /*  KCTRL | 0xC5, NULL, "Execute", */
	KCTRL | 0xC6, MSG_ins_toggle, "Insert",
	    KCTRL | 0xC7, MSG_forw_del_char, "Delete",
	    KCTRL | 0xC8, MSG_back_page, "PrevPage",
	    KCTRL | 0xC9, MSG_forw_page, "NextPage",
	    /*  KCTRL | 0xCB, NULL, "Erase", */
	/*  KCTRL | 0xCD, NULL, "BackTab", */
	/*  KCTRL | 0xD0, NULL, "Sh-North", */
	KCTRL | 0xD1, MSG_forw_unit, "Sh-East",
	    /*  KCTRL | 0xD2, NULL, "Sh-South", */
	KCTRL | 0xD3, MSG_back_unit, "Sh-West",
	    /*  KCTRL | 0xD4, NULL, "Sh-Home", */
	KCTRL | 0xD5, MSG_execute_macro, "Sh-Execute",
	    /*  KCTRL | 0xD6, NULL, "Sh-Insert", */
	KCTRL | 0xD7, MSG_forw_del_unit, "Sh-Delete",
	    KCTRL | 0xD8, MSG_goto_bob, "Sh-PrevPage",
	    KCTRL | 0xD9, MSG_goto_eob, "Sh-NextPage",
	    /*  KCTRL | 0xDB, NULL, "Sh-Erase", */
	/*  KCTRL | 0xDC, NULL, "Sh-Tab", */
	/*  KCTRL | 0xDD, NULL, "Sh-BackTab", */
	KCTRL | 0xE0, MSG_abort, "Cancel",
	    KMETA | KCTRL | 0xE0, MSG_abort, "Cancel",
	    KCTLX | KCTRL | 0xE0, MSG_abort, "Ctl-X Cancel",
	    KCTRL | 0xE1, MSG_display_bindings, "Help",
	    /*  KCTRL | 0xE2, NULL, "Glossary", */
	KCTRL | 0xE3, MSG_print, "Print",
	    KCTRL | 0xF1, MSG_help, "Sh-Help",
	    /*  KCTRL | 0xF2, NULL, "Sh-Glossary", */
	/*  KCTRL | 0xF3, NULL, "Sh-Print", */
	0, NULL, NULL
};

KEY_NAME_ARRAY  ibm_keys[] =
{
	KCTLX | 0x80 | 0x3B, MSG_display_bindings, "F1",
	    KCTLX | 0x80 | 0x3C, MSG_set_mark, "F2",
	    KCTLX | 0x80 | 0x3D, MSG_forw_search, "F3",
	    KCTLX | 0x80 | 0x3E, MSG_search_again, "F4",
	    KCTLX | 0x80 | 0x3F, MSG_query_replace, "F5",
	    KCTLX | 0x80 | 0x40, MSG_yank, "F6",
	    KCTLX | 0x80 | 0x41, MSG_copy_region, "F7",
	    KCTLX | 0x80 | 0x42, MSG_kill_region, "F8",
	    KCTLX | 0x80 | 0x43, MSG_goto_line, "F9",
	    KCTLX | 0x80 | 0x44, MSG_abort, "F10",
	    KCTLX | 0x80 | 0x54, MSG_help, "Sh-F1",
	    KCTLX | 0x80 | 0x55, MSG_file_read, "Sh-F2",
	    KCTLX | 0x80 | 0x56, MSG_file_save, "Sh-F3",
	    KCTLX | 0x80 | 0x57, MSG_file_visit, "Sh-F4",
	    KCTLX | 0x80 | 0x58, MSG_file_write, "Sh-F5",
	    KCTLX | 0x80 | 0x59, MSG_flush_all, "Sh-F6",
	    KCTLX | 0x80 | 0x5A, MSG_set_file_name, "Sh-F7",
	    KCTLX | 0x80 | 0x5B, MSG_file_insert, "Sh-F8",
	    KCTLX | 0x80 | 0x5C, MSG_exit_flush_all, "Sh-F9",
	    KCTLX | 0x80 | 0x5D, MSG_quit, "Sh-F10",
	    KCTLX | 0x80 | 0x5E, MSG_display_buffers, "Ctl-F1",
	    KCTLX | 0x80 | 0x5F, MSG_use_buffer, "Ctl-F2",
	    KCTLX | 0x80 | 0x60, MSG_kill_buffer, "Ctl-F3",
	    KCTLX | 0x80 | 0x61, MSG_next_buff, "Ctl-F4",
	    KCTLX | 0x80 | 0x62, MSG_prev_buff, "Ctl-F5",
	    KCTLX | 0x80 | 0x63, MSG_yank_buffer, "Ctl-F6",
	    KCTLX | 0x80 | 0x64, MSG_set_file_name, "Ctl-F7",
	    KCTLX | 0x80 | 0x65, MSG_file_insert, "Ctl-F8",
	    KCTLX | 0x80 | 0x66, MSG_exit_flush_all, "Ctl-F9",
	    KCTLX | 0x80 | 0x67, MSG_quit, "Ctl-F10",
	    KCTLX | 0x80 | 0x48, MSG_back_line, "North",
	    KCTLX | 0x80 | 0x4D, MSG_forw_char, "East",
	    KCTLX | 0x80 | 0x74, MSG_forw_unit, "Ctl-East",
	    KCTLX | 0x80 | 0x50, MSG_forw_line, "South",
	    KCTLX | 0x80 | 0x4B, MSG_back_char, "West",
	    KCTLX | 0x80 | 0x73, MSG_back_unit, "Ctl-West",
	    KCTLX | 0x80 | 0x49, MSG_back_page, "PageDown",
	    KCTLX | 0x80 | 0x47, MSG_goto_bob, "Home",
	    KCTLX | 0x80 | 0x51, MSG_forw_page, "PageUp",
	    KCTLX | 0x80 | 0x4F, MSG_goto_eob, "End",
	    KCTLX | 0x80 | 0x52, MSG_ins_toggle, "Insert",
	    KCTLX | 0x80 | 0x53, MSG_forw_del_char, "Delete",
	    KCTLX | 0x80 | 0x76, MSG_forw_window, "Ctl-PageDown",
	    KCTLX | 0x80 | 0x84, MSG_back_window, "Ctl-PageUp",
	    KCTLX | 0x80 | 0x72, MSG_print, "Ctl-Print",
	    KCTLX | 0x80 | 0x0F, MSG_forw_unit, "Sh-Tab",
	    0, NULL, NULL
};
#endif
/*
 * Read in a key, doing the low level mapping
 * of ASCII code to 11 bit code.  This level deals with
 * mapping the special keys into their spots in the C1
 * control area.  The C0 controls go right through, and
 * get remapped by "getkey".
 */
static int  unkey = KRANDOM;    /* jam - for ungetkey */
void ungetkey (k)
{
	unkey = k;
}

int     getkbd ()
{
	register int    c;

	if (unkey == KRANDOM)       /* jam */
		c = ttgetc ();
	else
	{
		c = unkey;
		unkey = KRANDOM;
	}
	if (c == SPECIAL)
	{
		c = ttgetc ();
		if ((c == 0xCD) || (c == 0xDD))/* Backtab is meta */
			return (METACH);
		return (c | KCTRL);
	}
	if (c == 0)
	{
		c = ttgetc ();
		return (c | 0x80 | KCTLX);
	}
	return (c);
}


/*
 * Terminal specific keymap initialization.
 * Attach the special keys to the appropriate built
 * in functions.
 * As is the case of all the keymap routines, errors
 * are very fatal.
 */
void ttykeymapinit ()
{
#if MSDOS
	KEY_NAME_ARRAY  *ptr;
	int     i;
	char    buf[NCOL];
	if (wang_pc)
		ptr = wang_keys;

	if (ibm_pc)
		ptr = ibm_keys;

	if (!wang_pc && !ibm_pc)
		return;

	i = 0;
	while (ptr -> key_code != 0)
	{
		if (ptr -> func_name_str != NULL)
			keydup (ptr -> key_code, ptr -> func_name_str);
		ptr++;
		i++;
	}
	sprintf (buf, MSG_sp_key, i);
	writ_echo (buf);
#endif
}
/* 
*   Search key name array for given key code.
*   return pointer to key name.
*/
char    *keystrings (key)
int     key;
{
#if MSDOS
	KEY_NAME_ARRAY  *ptr;

	if (wang_pc)
		ptr = wang_keys;

	if (ibm_pc)
		ptr = ibm_keys;

	if (!wang_pc && !ibm_pc)
		return(NULL);

	while (ptr -> key_code != 0)
	{
		if (key == ptr -> key_code)
		{
			return (ptr -> key_name_str);
		}
		ptr++;
	}
#endif
	return (NULL);
}
