/* $LynxId: LYKeymap.c,v 1.65 2008/01/08 00:19:25 tom Exp $ */
#include <HTUtils.h>
#include <LYUtils.h>
#include <LYGlobalDefs.h>
#include <LYKeymap.h>
#include <LYCharSets.h> /* for LYlowest_eightbit - kw */
#include <HTAccess.h>
#include <HTFormat.h>
#include <HTAlert.h>
#include <LYStrings.h> /* for USE_KEYMAP stuff - kw */
#include <LYLeaks.h>
#ifdef EXP_KEYBOARD_LAYOUT
#include <jcuken_kb.h>
#include <yawerty_kb.h>
#include <rot13_kb.h>
#endif
#define PUTS(buf) (*target->isa->put_block)(target, buf, strlen(buf))
#ifdef EXP_KEYBOARD_LAYOUT
int current_layout = 0; /* Index into LYKbLayouts[] */
LYKbLayout_t *LYKbLayouts[] =
{
kb_layout_rot13,
kb_layout_jcuken,
kb_layout_yawerty
};
const char *LYKbLayoutNames[] =
{
"ROT13'd keyboard layout",
"JCUKEN Cyrillic, for AT 101-key kbd",
"YAWERTY Cyrillic, for DEC LK201 kbd",
(char *) 0
};
#endif /* EXP_KEYBOARD_LAYOUT */
struct _HTStream {
HTStreamClass *isa;
};
/* * * Tables mapping LynxKeyCodes to LynxActionCodes * * */
/*
* Lynxkeycodes include all single-byte keys as well as codes for function keys
* and some special purposes. See LYStrings.h. Extended lynxkeycode values
* can also contain flags for modifiers and other purposes, but here only the
* base values are mapped to lynxactioncodes. They are called `keystrokes' in
* lynx.cfg.
*
* Lynxactioncodes (confusingly, constants are named LYK_foo and typed as
* LYKeymapCode) specify key `functions', see LYKeymap.h.
*/
/* the character gets 1 added to it before lookup,
* so that EOF maps to 0
*/
/* *INDENT-OFF* */
LYKeymap_t keymap[KEYMAP_SIZE] = {
0,
/* EOF */
LYK_DO_NOTHING, LYK_HOME, LYK_PREV_PAGE, 0,
/* nul */ /* ^A */ /* ^B */ /* ^C */
LYK_ABORT, LYK_END, LYK_NEXT_PAGE, 0,
/* ^D */ /* ^E */ /* ^F */ /* ^G */
LYK_HISTORY, LYK_FASTFORW_LINK, LYK_ACTIVATE, LYK_COOKIE_JAR,
/* bs */ /* ht */ /* nl */ /* ^K */
LYK_REFRESH, LYK_ACTIVATE, LYK_DOWN_TWO, 0,
/* ^L */ /* cr */ /* ^N */ /* ^O */
LYK_UP_TWO, LYK_CHG_CENTER, LYK_RELOAD, LYK_TO_CLIPBOARD,
/* ^P */ /* XON */ /* ^R */ /* ^S */
LYK_TRACE_TOGGLE, LYK_NEXT_DOC, LYK_SWITCH_DTD, LYK_REFRESH,
/* ^T */ /* ^U */ /* ^V */ /* ^W */
#ifdef USE_CACHEJAR
LYK_CACHE_JAR, 0, 0, 0,
/* ^X */ /* ^Y */ /* ^Z */ /* ESC */
#else
0, 0, 0, 0,
/* ^X */ /* ^Y */ /* ^Z */ /* ESC */
#endif
0, 0, 0, 0,
/* ^\ */ /* ^] */ /* ^^ */ /* ^_ */
LYK_NEXT_PAGE, LYK_SHELL, LYK_SOFT_DQUOTES, LYK_TOOLBAR,
/* sp */ /* ! */ /* " */ /* # */
LYK_LAST_LINK, 0, 0, LYK_HISTORICAL,
/* $ */ /* % */ /* & */ /* ' */
LYK_UP_HALF, LYK_DOWN_HALF, LYK_IMAGE_TOGGLE, LYK_NEXT_PAGE,
/* ( */ /* ) */ /* * */ /* + */
LYK_EXTERN_PAGE, LYK_PREV_PAGE, LYK_EXTERN_LINK, LYK_WHEREIS,
/* , */ /* - */ /* . */ /* / */
LYK_F_LINK_NUM, LYK_1, LYK_2, LYK_3,
/* 0 */ /* 1 */ /* 2 */ /* 3 */
LYK_4, LYK_5, LYK_6, LYK_7,
/* 4 */ /* 5 */ /* 6 */ /* 7 */
LYK_8, LYK_9, LYK_COMMAND, LYK_TRACE_LOG,
/* 8 */ /* 9 */ /* : */ /* ; */
LYK_UP_LINK, LYK_INFO, LYK_DOWN_LINK, LYK_HELP,
/* < */ /* = */ /* > */ /* ? */
#ifndef SUPPORT_CHDIR
LYK_RAW_TOGGLE, LYK_ADDRLIST, LYK_PREV_PAGE, LYK_COMMENT,
/* @ */ /* A */ /* B */ /* C */
#else
LYK_RAW_TOGGLE, LYK_ADDRLIST, LYK_PREV_PAGE, LYK_CHDIR,
/* @ */ /* A */ /* B */ /* C */
#endif
LYK_DOWNLOAD, LYK_ELGOTO, LYK_DIRED_MENU, LYK_ECGOTO,
/* D */ /* E */ /* F */ /* G */
#ifdef KANJI_CODE_OVERRIDE
LYK_HELP, LYK_INDEX, LYK_CHG_KCODE, LYK_KEYMAP,
/* H */ /* I */ /* J */ /* K */
#else
LYK_HELP, LYK_INDEX, LYK_JUMP, LYK_KEYMAP,
/* H */ /* I */ /* J */ /* K */
#endif
LYK_LIST, LYK_MAIN_MENU, LYK_PREV, LYK_OPTIONS,
/* L */ /* M */ /* N */ /* O */
LYK_PRINT, LYK_ABORT, LYK_DEL_BOOKMARK, LYK_INDEX_SEARCH,
/* P */ /* Q */ /* R */ /* S */
LYK_TAG_LINK, LYK_PREV_DOC, LYK_VLINKS, 0,
/* T */ /* U */ /* V */ /* W */
LYK_NOCACHE, 0, LYK_INTERRUPT, LYK_INLINE_TOGGLE,
/* X */ /* Y */ /* Z */ /* [ */
LYK_SOURCE, LYK_HEAD, LYK_FIRST_LINK, LYK_CLEAR_AUTH,
/* \ */ /* ] */ /* ^ */ /* _ */
LYK_MINIMAL, LYK_ADD_BOOKMARK, LYK_PREV_PAGE, LYK_COMMENT,
/* ` */ /* a */ /* b */ /* c */
LYK_DOWNLOAD, LYK_EDIT, LYK_DIRED_MENU, LYK_GOTO,
/* d */ /* e */ /* f */ /* g */
LYK_HELP, LYK_INDEX, LYK_JUMP, LYK_KEYMAP,
/* h */ /* i */ /* j */ /* k */
LYK_LIST, LYK_MAIN_MENU, LYK_NEXT, LYK_OPTIONS,
/* l */ /* m */ /* n */ /* o */
LYK_PRINT, LYK_QUIT, LYK_DEL_BOOKMARK, LYK_INDEX_SEARCH,
/* p */ /* q */ /* r */ /* s */
LYK_TAG_LINK, LYK_PREV_DOC, LYK_VIEW_BOOKMARK, 0,
/* t */ /* u */ /* v */ /* w */
LYK_NOCACHE, 0, LYK_INTERRUPT, LYK_SHIFT_LEFT,
/* x */ /* y */ /* z */ /* { */
LYK_LINEWRAP_TOGGLE, LYK_SHIFT_RIGHT, LYK_NESTED_TABLES, LYK_HISTORY,
/* | */ /* } */ /* ~ */ /* del */
/* 80..9F (illegal ISO-8859-1) 8-bit characters. */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 100..10F function key definitions in LYStrings.h */
LYK_PREV_LINK, LYK_NEXT_LINK, LYK_ACTIVATE, LYK_PREV_DOC,
/* UPARROW */ /* DNARROW */ /* RTARROW */ /* LTARROW */
LYK_NEXT_PAGE, LYK_PREV_PAGE, LYK_HOME, LYK_END,
/* PGDOWN */ /* PGUP */ /* HOME */ /* END */
#if (defined(_WINDOWS) || defined(__DJGPP__))
LYK_DWIMHELP, 0, 0, 0,
/* F1*/
#else
LYK_DWIMHELP, LYK_ACTIVATE, LYK_HOME, LYK_END,
/* F1*/ /* Do key */ /* Find key */ /* Select key */
#endif /* _WINDOWS || __DJGPP__ */
LYK_UP_TWO, LYK_DOWN_TWO, LYK_DO_NOTHING, LYK_FASTBACKW_LINK,
/* Insert key */ /* Remove key */ /* DO_NOTHING*/ /* Back tab */
/* 110..18F */
0, 0, 0, 0,
0, 0, 0, 0,
0, LYK_DO_NOTHING, 0, 0,
/* 0x11d: MOUSE_KEY */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
#ifdef DJGPP_KEYHANDLER
0, LYK_ABORT, 0, 0,
/* ALT_X */
#else
0, 0, 0, 0,
#endif /* DJGPP_KEYHANDLER */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 190..20F */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
#if (defined(_WINDOWS) || defined(__DJGPP__) || defined(__CYGWIN__)) && !defined(USE_SLANG) /* PDCurses */
LYK_ABORT, 0, 0, 0,
/* ALT_X */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, LYK_WHEREIS, 0,
/* KP_SLASH */
0, 0, 0, LYK_IMAGE_TOGGLE,
/* KP_* */
LYK_PREV_PAGE, LYK_NEXT_PAGE, 0, 0,
/* KP_- */ /* KP_+ */
#else
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
#endif /* (_WINDOWS || __DJGPP__ || __CYGWIN__) && !USE_SLANG */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 210..28F */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 290...293 */
LYK_CHANGE_LINK, 0, 0, 0,
};
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
/*
* This table is used to override the standard keyboard assignments
* when lynx_edit_mode is in effect and keyboard overrides have been
* allowed at compile time.
*/
LYKeymap_t key_override[KEYMAP_SIZE] = {
0,
/* EOF */
0, 0, 0, 0,
/* nul */ /* ^A */ /* ^B */ /* ^C */
0, 0, 0, 0,
/* ^D */ /* ^E */ /* ^F */ /* ^G */
0, 0, 0, 0,
/* bs */ /* ht */ /* nl */ /* ^K */
0, 0, 0, 0,
/* ^L */ /* cr */ /* ^N */ /* ^O */
0, 0, 0, 0,
/* ^P */ /* XON */ /* ^R */ /* XOFF */
0, LYK_NEXT_DOC, 0, 0,
/* ^T */ /* ^U */ /* ^V */ /* ^W */
0, 0, 0, 0,
/* ^X */ /* ^Y */ /* ^Z */ /* ESC */
0, 0, 0, 0,
/* ^\ */ /* ^] */ /* ^^ */ /* ^_ */
0, 0, 0, 0,
/* sp */ /* ! */ /* " */ /* # */
0, 0, 0, 0,
/* $ */ /* % */ /* & */ /* ' */
0, 0, 0, 0,
/* ( */ /* ) */ /* * */ /* + */
0, 0, LYK_TAG_LINK, 0,
/* , */ /* - */ /* . */ /* / */
0, 0, 0, 0,
/* 0 */ /* 1 */ /* 2 */ /* 3 */
0, 0, 0, 0,
/* 4 */ /* 5 */ /* 6 */ /* 7 */
0, 0, 0, 0,
/* 8 */ /* 9 */ /* : */ /* ; */
0, 0, 0, 0,
/* < */ /* = */ /* > */ /* ? */
#ifndef SUPPORT_CHDIR
0, 0, 0, LYK_CREATE,
/* @ */ /* A */ /* B */ /* C */
#else
0, 0, 0, LYK_CHDIR,
/* @ */ /* A */ /* B */ /* C */
#endif
0, 0, LYK_DIRED_MENU, 0,
/* D */ /* E */ /* F */ /* G */
0, 0, 0, 0,
/* H */ /* I */ /* J */ /* K */
0, LYK_MODIFY, 0, 0,
/* L */ /* M */ /* N */ /* O */
0, 0, LYK_REMOVE, 0,
/* P */ /* Q */ /* R */ /* S */
LYK_TAG_LINK, LYK_UPLOAD, 0, 0,
/* T */ /* U */ /* V */ /* W */
0, 0, 0, 0,
/* X */ /* Y */ /* Z */ /* [ */
0, 0, 0, 0,
/* \ */ /* ] */ /* ^ */ /* _ */
0, 0, 0, LYK_CREATE,
/* ` */ /* a */ /* b */ /* c */
0, 0, LYK_DIRED_MENU, 0,
/* d */ /* e */ /* f */ /* g */
0, 0, 0, 0,
/* h */ /* i */ /* j */ /* k */
0, LYK_MODIFY, 0, 0,
/* l */ /* m */ /* n */ /* o */
0, 0, LYK_REMOVE, 0,
/* p */ /* q */ /* r */ /* s */
LYK_TAG_LINK, LYK_UPLOAD, 0, 0,
/* t */ /* u */ /* v */ /* w */
0, 0, 0, 0,
/* x */ /* y */ /* z */ /* { */
0, 0, 0, 0,
/* | */ /* } */ /* ~ */ /* del */
/* 80..9F (illegal ISO-8859-1) 8-bit characters. */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 100..10F function key definitions in LYStrings.h */
0, 0, 0, 0,
/* UPARROW */ /* DNARROW */ /* RTARROW */ /* LTARROW */
0, 0, 0, 0,
/* PGDOWN */ /* PGUP */ /* HOME */ /* END */
0, 0, 0, 0,
/* F1*/ /* Do key */ /* Find key */ /* Select key */
0, 0, LYK_DO_NOTHING, 0,
/* Insert key */ /* Remove key */ /* DO_NOTHING */ /* Back tab */
/* 110..18F */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 190..20F */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 210..28F */
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 290...293 */
0, 0, 0, 0,
};
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
#define DATA(code, name, doc) { code, name, doc }
/* The order of this array must match the LYKeymapCode enum in LYKeymap.h */
static Kcmd revmap[] = {
DATA(
LYK_UNKNOWN, "UNMAPPED",
NULL ),
DATA(
LYK_COMMAND, "COMMAND",
"prompt for, execute a command" ),
DATA(
LYK_1, "1",
NULL ),
DATA(
LYK_2, "2",
NULL ),
DATA(
LYK_3, "3",
NULL ),
DATA(
LYK_4, "4",
NULL ),
DATA(
LYK_5, "5",
NULL ),
DATA(
LYK_6, "6",
NULL ),
DATA(
LYK_7, "7",
NULL ),
DATA(
LYK_8, "8",
NULL ),
DATA(
LYK_9, "9",
NULL ),
DATA(
LYK_SOURCE, "SOURCE",
"toggle source/presentation for current document" ),
DATA(
LYK_RELOAD, "RELOAD",
"reload the current document" ),
DATA(
LYK_QUIT, "QUIT",
"quit the browser" ),
DATA(
LYK_ABORT, "ABORT",
"quit the browser unconditionally" ),
DATA(
LYK_NEXT_PAGE, "NEXT_PAGE",
"view the next page of the document" ),
DATA(
LYK_PREV_PAGE, "PREV_PAGE",
"view the previous page of the document" ),
DATA(
LYK_UP_TWO, "UP_TWO",
"go back two lines in the document" ),
DATA(
LYK_DOWN_TWO, "DOWN_TWO",
"go forward two lines in the document" ),
DATA(
LYK_UP_HALF, "UP_HALF",
"go back half a page in the document" ),
DATA(
LYK_DOWN_HALF, "DOWN_HALF",
"go forward half a page in the document" ),
DATA(
LYK_REFRESH, "REFRESH",
"refresh the screen to clear garbled text" ),
DATA(
LYK_HOME, "HOME",
"go to the beginning of the current document" ),
DATA(
LYK_END, "END",
"go to the end of the current document" ),
DATA(
LYK_FIRST_LINK, "FIRST_LINK",
"make the first link on the line current" ),
DATA(
LYK_LAST_LINK, "LAST_LINK",
"make the last link on the line current" ),
DATA(
LYK_PREV_LINK, "PREV_LINK",
"make the previous link current" ),
DATA(
LYK_NEXT_LINK, "NEXT_LINK",
"make the next link current" ),
DATA(
LYK_LPOS_PREV_LINK, "LPOS_PREV_LINK",
"make previous link current, same column for input" ),
DATA(
LYK_LPOS_NEXT_LINK, "LPOS_NEXT_LINK",
"make next link current, same column for input" ),
DATA(
LYK_FASTBACKW_LINK, "FASTBACKW_LINK",
"previous link or text area, only stops on links" ),
DATA(
LYK_FASTFORW_LINK, "FASTFORW_LINK",
"next link or text area, only stops on links" ),
DATA(
LYK_UP_LINK, "UP_LINK",
"move up the page to a previous link" ),
DATA(
LYK_DOWN_LINK, "DOWN_LINK",
"move down the page to another link" ),
DATA(
LYK_RIGHT_LINK, "RIGHT_LINK",
"move right to another link" ),
DATA(
LYK_LEFT_LINK, "LEFT_LINK",
"move left to a previous link" ),
DATA(
LYK_HISTORY, "HISTORY",
"display stack of currently-suspended documents" ),
DATA(
LYK_PREV_DOC, "PREV_DOC",
"go back to the previous document" ),
DATA(
LYK_NEXT_DOC, "NEXT_DOC",
"undo going back to the previous document" ),
DATA(
LYK_ACTIVATE, "ACTIVATE",
"go to the document given by the current link" ),
DATA(
LYK_SUBMIT, "MOUSE_SUBMIT",
"DO NOT MAP: follow current link, submit" ),
DATA(
LYK_GOTO, "GOTO",
"go to a document given as a URL" ),
DATA(
LYK_ECGOTO, "ECGOTO",
"edit the current document's URL and go to it" ),
DATA(
LYK_HELP, "HELP",
"display help on using the browser" ),
DATA(
LYK_DWIMHELP, "DWIMHELP",
"display help page that may depend on context" ),
DATA(
LYK_INDEX, "INDEX",
"display an index of potentially useful documents" ),
DATA(
LYK_NOCACHE, "NOCACHE",
"force submission of form or link with no-cache" ),
DATA(
LYK_INTERRUPT, "INTERRUPT",
"interrupt network connection or transmission" ),
DATA(
LYK_MAIN_MENU, "MAIN_MENU",
"return to the first screen (home page)" ),
DATA(
LYK_OPTIONS, "OPTIONS",
"display and change option settings" ),
DATA(
LYK_INDEX_SEARCH, "INDEX_SEARCH",
"allow searching of an index" ),
DATA(
LYK_WHEREIS, "WHEREIS",
"search within the current document" ),
DATA(
LYK_PREV, "PREV",
"search for the previous occurence" ),
DATA(
LYK_NEXT, "NEXT",
"search for the next occurence" ),
DATA(
LYK_COMMENT, "COMMENT",
"send a comment to the author of the current document" ),
DATA(
LYK_EDIT, "EDIT",
"edit the current document or a form's textarea" ),
DATA(
LYK_INFO, "INFO",
"display information on the current document and link" ),
DATA(
LYK_PRINT, "PRINT",
"display choices for printing the current document" ),
DATA(
LYK_ADD_BOOKMARK, "ADD_BOOKMARK",
"add to your personal bookmark list" ),
DATA(
LYK_DEL_BOOKMARK, "DEL_BOOKMARK",
"delete from your personal bookmark list" ),
DATA(
LYK_VIEW_BOOKMARK, "VIEW_BOOKMARK",
"view your personal bookmark list" ),
DATA(
LYK_VLINKS, "VLINKS",
"list links visited during the current Lynx session" ),
DATA(
LYK_SHELL, "SHELL",
"escape from the browser to the system" ),
DATA(
LYK_DOWNLOAD, "DOWNLOAD",
"download the current link to your computer" ),
DATA(
LYK_TRACE_TOGGLE, "TRACE_TOGGLE",
"toggle tracing of browser operations" ),
DATA(
LYK_TRACE_LOG, "TRACE_LOG",
"view trace log if started in the current session" ),
DATA(
LYK_IMAGE_TOGGLE, "IMAGE_TOGGLE",
"toggle handling of all images as links" ),
DATA(
LYK_INLINE_TOGGLE, "INLINE_TOGGLE",
"toggle pseudo-ALTs for inlines with no ALT string" ),
DATA(
LYK_HEAD, "HEAD",
"send a HEAD request for the current document or link" ),
DATA(
LYK_DO_NOTHING, "DO_NOTHING",
NULL ),
DATA(
LYK_TOGGLE_HELP, "TOGGLE_HELP",
"show other commands in the novice help menu" ),
DATA(
LYK_JUMP, "JUMP",
"go directly to a target document or action" ),
DATA(
LYK_KEYMAP, "KEYMAP",
"display the current key map" ),
DATA(
LYK_LIST, "LIST",
"list the references (links) in the current document" ),
DATA(
LYK_TOOLBAR, "TOOLBAR",
"go to Toolbar or Banner in the current document" ),
DATA(
LYK_HISTORICAL, "HISTORICAL",
"toggle historical vs. valid/minimal comment parsing" ),
DATA(
LYK_MINIMAL, "MINIMAL",
"toggle minimal vs. valid comment parsing" ),
DATA(
LYK_SOFT_DQUOTES, "SOFT_DQUOTES",
"toggle valid vs. soft double-quote parsing" ),
DATA(
LYK_RAW_TOGGLE, "RAW_TOGGLE",
"toggle raw 8-bit translations or CJK mode ON or OFF" ),
DATA(
LYK_COOKIE_JAR, "COOKIE_JAR",
"examine the Cookie Jar" ),
DATA(
LYK_F_LINK_NUM, "F_LINK_NUM",
"invoke the 'Follow link (or page) number:' prompt" ),
DATA(
LYK_CLEAR_AUTH, "CLEAR_AUTH",
"clear all authorization info for this session" ),
DATA(
LYK_SWITCH_DTD, "SWITCH_DTD",
"switch between two ways of parsing HTML" ),
DATA(
LYK_ELGOTO, "ELGOTO",
"edit the current link's URL or ACTION and go to it" ),
DATA(
LYK_CHANGE_LINK, "CHANGE_LINK",
"force reset of the current link on the page" ),
DATA(
LYK_DWIMEDIT, "DWIMEDIT",
"use external editor for context-dependent purpose" ),
DATA(
LYK_EDIT_TEXTAREA, "EDITTEXTAREA",
"use an external editor to edit a form's textarea" ),
DATA(
LYK_GROW_TEXTAREA, "GROWTEXTAREA",
"add 5 new blank lines to the bottom of a textarea" ),
DATA(
LYK_INSERT_FILE, "INSERTFILE",
"insert file into a textarea (just above cursorline)" ),
#ifdef EXP_ADDRLIST_PAGE
DATA(
LYK_ADDRLIST, "ADDRLIST",
"like LIST command, but always shows the links' URLs" ),
#endif
#ifdef USE_EXTERNALS
DATA(
LYK_EXTERN_LINK, "EXTERN_LINK",
"run external program with current link" ),
DATA(
LYK_EXTERN_PAGE, "EXTERN_PAGE",
"run external program with current page" ),
#endif
#ifdef VMS
DATA(
LYK_DIRED_MENU, "DIRED_MENU",
"invoke File/Directory Manager, if available" ),
#else
#ifdef DIRED_SUPPORT
DATA(
LYK_DIRED_MENU, "DIRED_MENU",
"display a full menu of file operations" ),
DATA(
LYK_CREATE, "CREATE",
"create a new file or directory" ),
DATA(
LYK_REMOVE, "REMOVE",
"remove a file or directory" ),
DATA(
LYK_MODIFY, "MODIFY",
"modify the name or location of a file or directory" ),
DATA(
LYK_TAG_LINK, "TAG_LINK",
"tag a file or directory for later action" ),
DATA(
LYK_UPLOAD, "UPLOAD",
"upload from your computer to the current directory" ),
DATA(
LYK_INSTALL, "INSTALL",
"install file or tagged files into a system area" ),
#endif /* DIRED_SUPPORT */
DATA(
LYK_CHG_CENTER, "CHANGE_CENTER",
"toggle center alignment in HTML TABLE" ),
#ifdef KANJI_CODE_OVERRIDE
DATA(
LYK_CHG_KCODE, "CHANGE_KCODE",
"Change Kanji code" ),
#endif
#endif /* VMS */
#ifdef SUPPORT_CHDIR
DATA(
LYK_CHDIR, "CHDIR",
"change current directory" ),
#endif
#ifdef USE_CURSES_PADS
DATA(
LYK_SHIFT_LEFT, "SHIFT_LEFT",
"shift the screen left" ),
DATA(
LYK_SHIFT_RIGHT, "SHIFT_RIGHT",
"shift the screen right" ),
DATA(
LYK_LINEWRAP_TOGGLE, "LINEWRAP_TOGGLE",
"toggle linewrap on/off" ),
#endif
#ifdef CAN_CUT_AND_PASTE
DATA(
LYK_PASTE_URL, "PASTE_URL",
"Goto the URL in the clipboard" ),
DATA(
LYK_TO_CLIPBOARD, "TO_CLIPBOARD",
"link's URL to Clip Board" ),
#endif
#ifdef EXP_NESTED_TABLES
DATA(
LYK_NESTED_TABLES, "NESTED_TABLES",
"toggle nested-table parsing on/off" ),
#endif
#ifdef USE_CACHEJAR
DATA(
LYK_CACHE_JAR, "CACHE_JAR",
"examine list of cached documents" ),
#endif
DATA(
LYK_UNKNOWN, NULL,
"" )
};
#undef DATA
static const struct {
int key;
const char *name;
} named_keys[] = {
{ '\t', "<tab>" },
{ '\r', "<return>" },
{ CH_ESC, "ESC" },
{ ' ', "<space>" },
{ '<', "<" },
{ '>', ">" },
{ CH_DEL, "<delete>" },
{ UPARROW, "Up Arrow" },
{ DNARROW, "Down Arrow" },
{ RTARROW, "Right Arrow" },
{ LTARROW, "Left Arrow" },
{ PGDOWN, "Page Down" },
{ PGUP, "Page Up" },
{ HOME, "Home" },
{ END_KEY, "End" },
{ F1, "F1" },
{ DO_KEY, "Do key" },
{ FIND_KEY, "Find key" },
{ SELECT_KEY, "Select key" },
{ INSERT_KEY, "Insert key" },
{ REMOVE_KEY, "Remove key" },
{ DO_NOTHING, "(DO_NOTHING)" },
{ BACKTAB_KEY, "Back Tab" },
{ MOUSE_KEY, "mouse pseudo key" },
};
struct emap {
const char *name;
const int code;
const char *descr;
};
static struct emap ekmap[] = {
{"NOP", LYE_NOP, "Do Nothing"},
{"CHAR", LYE_CHAR, "Insert printable char"},
{"ENTER", LYE_ENTER, "Input complete, return char/lynxkeycode"},
{"TAB", LYE_TAB, "Input complete, return TAB"},
{"STOP", LYE_STOP, "Input deactivated"},
{"ABORT", LYE_ABORT, "Input cancelled"},
{"PASS", LYE_FORM_PASS, "In fields: input complete, or Do Nothing"},
{"DELN", LYE_DELN, "Delete next/curr char"},
{"DELP", LYE_DELP, "Delete prev char"},
{"DELNW", LYE_DELNW, "Delete next word"},
{"DELPW", LYE_DELPW, "Delete prev word"},
{"ERASE", LYE_ERASE, "Erase the line"},
{"BOL", LYE_BOL, "Go to begin of line"},
{"EOL", LYE_EOL, "Go to end of line"},
{"FORW", LYE_FORW, "Cursor forwards"},
{"FORW_RL", LYE_FORW_RL, "Cursor forwards or right link"},
{"BACK", LYE_BACK, "Cursor backwards"},
{"BACK_LL", LYE_BACK_LL, "Cursor backwards or left link"},
{"FORWW", LYE_FORWW, "Word forward"},
{"BACKW", LYE_BACKW, "Word back"},
{"LOWER", LYE_LOWER, "Lower case the line"},
{"UPPER", LYE_UPPER, "Upper case the line"},
{"LKCMD", LYE_LKCMD, "Invoke command prompt"},
{"AIX", LYE_AIX, "Hex 97"},
{"DELBL", LYE_DELBL, "Delete back to BOL"},
{"DELEL", LYE_DELEL, "Delete thru EOL"},
{"SWMAP", LYE_SWMAP, "Switch input keymap"},
{"TPOS", LYE_TPOS, "Transpose characters"},
{"SETM1", LYE_SETM1, "Set modifier 1 flag"},
{"SETM2", LYE_SETM2, "Set modifier 2 flag"},
{"UNMOD", LYE_UNMOD, "Fall back to no-modifier command"},
{"C1CHAR", LYE_C1CHAR, "Insert C1 char if printable"},
{"SETMARK", LYE_SETMARK, "emacs-like set-mark-command"},
{"XPMARK", LYE_XPMARK, "emacs-like exchange-point-and-mark"},
{"KILLREG", LYE_KILLREG, "emacs-like kill-region"},
{"YANK", LYE_YANK, "emacs-like yank"},
#ifdef CAN_CUT_AND_PASTE
{"PASTE", LYE_PASTE, "ClipBoard to Lynx"},
#endif
};
/* *INDENT-ON* */
/*
* Build a list of Lynx's commands, for use in the tab-completion in LYgetstr.
*/
HTList *LYcommandList(void)
{
static HTList *myList = NULL;
if (myList == NULL) {
unsigned j;
myList = HTList_new();
for (j = 0; revmap[j].name != 0; j++) {
if (revmap[j].doc != 0) {
char *data = NULL;
StrAllocCopy(data, revmap[j].name);
HTList_addObject(myList, data);
}
}
}
return myList;
}
/*
* Find the given keycode.
*/
Kcmd *LYKeycodeToKcmd(LYKeymapCode code)
{
unsigned j;
Kcmd *result = 0;
if (code > LYK_UNKNOWN) {
for (j = 0; revmap[j].name != 0; j++) {
if (revmap[j].code == code) {
result = revmap + j;
break;
}
}
}
return result;
}
/*
* Find the given command-name, accepting an abbreviation if it is unique.
*/
Kcmd *LYStringToKcmd(const char *name)
{
unsigned need = strlen(name);
unsigned j;
BOOL exact = FALSE;
Kcmd *result = 0;
Kcmd *maybe = 0;
if (non_empty(name)) {
for (j = 0; revmap[j].name != 0; j++) {
if (!strcasecomp(revmap[j].name, name)) {
result = revmap + j;
break;
} else if (!exact
&& !strncasecomp(revmap[j].name, name, need)) {
if (maybe == 0) {
maybe = revmap + j;
} else {
if (revmap[j].name[need] != 0
&& maybe->name[need] != 0) {
maybe = 0;
exact = TRUE;
}
}
}
}
}
return (result != 0) ? result : maybe;
}
char *LYKeycodeToString(int c,
BOOLEAN upper8)
{
static char buf[30];
unsigned n;
BOOLEAN named = FALSE;
for (n = 0; n < TABLESIZE(named_keys); n++) {
if (named_keys[n].key == c) {
named = TRUE;
strcpy(buf, named_keys[n].name);
break;
}
}
if (!named) {
if (c > ' '
&& c < 0177)
sprintf(buf, "%c", c);
else if (upper8
&& c > ' '
&& c <= 0377
&& c <= LYlowest_eightbit[current_char_set])
sprintf(buf, "%c", c);
else if (c < ' ')
sprintf(buf, "^%c", c | 0100);
else if (c >= 0400)
sprintf(buf, "key-0x%x", c);
else
sprintf(buf, "0x%x", c);
}
return buf;
}
int LYStringToKeycode(char *src)
{
unsigned n;
int key = -1;
int len = strlen(src);
if (len == 1) {
key = *src;
} else if (len == 2 && *src == '^') {
key = src[1] & 0x1f;
} else if (len > 2 && !strncasecomp(src, "0x", 2)) {
char *dst = 0;
key = strtol(src, &dst, 0);
if (!isEmpty(dst))
key = -1;
} else if (len > 6 && !strncasecomp(src, "key-", 4)) {
char *dst = 0;
key = strtol(src + 4, &dst, 0);
if (isEmpty(dst))
key = -1;
}
if (key < 0) {
for (n = 0; n < TABLESIZE(named_keys); n++) {
if (!strcasecomp(named_keys[n].name, src)) {
key = named_keys[n].key;
break;
}
}
}
return key;
}
#define PRETTY_LEN 11
static char *pretty_html(int c)
{
char *src = LYKeycodeToString(c, TRUE);
if (src != 0) {
/* *INDENT-OFF* */
static const struct {
int code;
const char *name;
} table[] = {
{ '<', "<" },
{ '>', ">" },
{ '"', """ },
{ '&', "&" }
};
/* *INDENT-ON* */
static char buf[30];
char *dst = buf;
int adj = 0;
unsigned n;
BOOLEAN found;
while ((c = *src++) != 0) {
found = FALSE;
for (n = 0; n < TABLESIZE(table); n++) {
if (c == table[n].code) {
found = TRUE;
strcpy(dst, table[n].name);
adj += strlen(dst) - 1;
dst += strlen(dst);
break;
}
}
if (!found) {
*dst++ = (char) c;
}
}
adj -= (dst - buf) - PRETTY_LEN;
while (adj-- > 0)
*dst++ = ' ';
*dst = 0;
return buf;
}
return 0;
}
static char *format_binding(LYKeymap_t * table, int i)
{
LYKeymapCode the_key = (LYKeymapCode) table[i];
char *buf = 0;
char *formatted;
Kcmd *rmap = LYKeycodeToKcmd(the_key);
if (rmap != 0
&& rmap->name != 0
&& rmap->doc != 0
&& (formatted = pretty_html(i - 1)) != 0) {
HTSprintf0(&buf, "%-*s %-13s %s\n",
PRETTY_LEN, formatted,
rmap->name,
rmap->doc);
return buf;
}
return 0;
}
/* if both is true, produce an additional line for the corresponding
uppercase key if its binding is different. - kw */
static void print_binding(HTStream *target, int i,
BOOLEAN both)
{
char *buf;
LYKeymapCode lac1 = LYK_UNKNOWN; /* 0 */
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
if (prev_lynx_edit_mode && !no_dired_support &&
(lac1 = (LYKeymapCode) key_override[i]) != LYK_UNKNOWN) {
if ((buf = format_binding(key_override, i)) != 0) {
PUTS(buf);
FREE(buf);
}
} else
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
if ((buf = format_binding(keymap, i)) != 0) {
lac1 = (LYKeymapCode) keymap[i];
PUTS(buf);
FREE(buf);
}
if (!both)
return;
i -= ' '; /* corresponding uppercase key */
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
if (prev_lynx_edit_mode && !no_dired_support && key_override[i]) {
if (key_override[i] != lac1 &&
(buf = format_binding(key_override, i)) != 0) {
PUTS(buf);
FREE(buf);
}
} else
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
if (keymap[i] != lac1 && (buf = format_binding(keymap, i)) != 0) {
PUTS(buf);
FREE(buf);
}
}
/*
* Return lynxactioncode whose name is the string func. returns -1 if not
* found. - kw
*/
int lacname_to_lac(const char *func)
{
Kcmd *mp = LYStringToKcmd(func);
return (mp != 0) ? (int) mp->code : -1;
}
/*
* Return editactioncode whose name is the string func. func must be present
* in the ekmap table. returns -1 if not found. - kw
*/
int lecname_to_lec(const char *func)
{
int i;
struct emap *mp;
if (non_empty(func)) {
for (i = 0, mp = ekmap; (*mp).name != NULL; mp++, i++) {
if (strcmp((*mp).name, func) == 0) {
return (*mp).code;
}
}
}
return (-1);
}
/*
* Return lynxkeycode represented by string src. returns -1 if not valid.
*
* This is simpler than what map_string_to_keysym() does for USE_KEYMAP, but
* compatible with revmap() used for processing KEYMAP options in the
* configuration file. - kw
*/
int lkcstring_to_lkc(const char *src)
{
int c = -1;
if (strlen(src) == 1)
c = *src;
else if (strlen(src) == 2 && *src == '^')
c = src[1] & 037;
else if (strlen(src) >= 2 && isdigit(UCH(*src))) {
if (sscanf(src, "%i", &c) != 1)
return (-1);
#ifdef USE_KEYMAPS
} else {
map_string_to_keysym(src, &c);
#ifndef USE_SLANG
if (c >= 0) {
if ((c & LKC_MASK) > 255 && !(c & LKC_ISLKC))
return (-1); /* Don't accept untranslated curses KEY_* */
else
c &= ~LKC_ISLKC;
}
#endif
#endif
}
if (c == CH_ESC)
escape_bound = 1;
if (c < -1)
return (-1);
else
return c;
}
static int LYLoadKeymap(const char *arg GCC_UNUSED,
HTParentAnchor *anAnchor,
HTFormat format_out,
HTStream *sink)
{
HTFormat format_in = WWW_HTML;
HTStream *target;
char *buf = 0;
int i;
/*
* Set up the stream. - FM
*/
target = HTStreamStack(format_in, format_out, sink, anAnchor);
if (!target || target == NULL) {
HTSprintf0(&buf, CANNOT_CONVERT_I_TO_O,
HTAtom_name(format_in), HTAtom_name(format_out));
HTAlert(buf);
FREE(buf);
return (HT_NOT_LOADED);
}
anAnchor->no_cache = TRUE;
HTSprintf0(&buf, "<html>\n<head>\n<title>%s</title>\n</head>\n<body>\n",
CURRENT_KEYMAP_TITLE);
PUTS(buf);
HTSprintf0(&buf, "<pre>\n");
PUTS(buf);
for (i = 'a' + 1; i <= 'z' + 1; i++) {
print_binding(target, i, TRUE);
}
for (i = 1; i < KEYMAP_SIZE; i++) {
/*
* Don't show CHANGE_LINK if mouse not enabled.
*/
if ((i >= 0200 || i <= ' ' || !isalpha(i - 1)) &&
(LYUseMouse || (keymap[i] != LYK_CHANGE_LINK))) {
print_binding(target, i, FALSE);
}
}
HTSprintf0(&buf, "</pre>\n</body>\n</html>\n");
PUTS(buf);
(*target->isa->_free) (target);
FREE(buf);
return (HT_LOADED);
}
#ifdef GLOBALDEF_IS_MACRO
#define _LYKEYMAP_C_GLOBALDEF_1_INIT { "LYNXKEYMAP", LYLoadKeymap, 0}
GLOBALDEF(HTProtocol, LYLynxKeymap, _LYKEYMAP_C_GLOBALDEF_1_INIT);
#else
GLOBALDEF HTProtocol LYLynxKeymap =
{"LYNXKEYMAP", LYLoadKeymap, 0};
#endif /* GLOBALDEF_IS_MACRO */
/*
* Install func as the mapping for key.
* If for_dired is TRUE, install it in the key_override[] table
* for Dired mode, otherwise in the general keymap[] table.
* If DIRED_SUPPORT or OK_OVERRIDE is not defined, don't do anything
* when for_dired is requested.
* returns lynxkeycode value != 0 if the mapping was made, 0 if not.
*/
int remap(char *key,
const char *func,
BOOLEAN for_dired)
{
Kcmd *mp;
int c;
#if !defined(DIRED_SUPPORT) || !defined(OK_OVERRIDE)
if (for_dired)
return 0;
#endif
if (func == NULL)
return 0;
c = lkcstring_to_lkc(key);
if (c <= -1)
return 0;
else if (c >= 0) {
/* Remapping of key actions is supported only for basic
* lynxkeycodes, without modifiers etc.! If we get somehow
* called for an invalid lynxkeycode, fail or silently ignore
* modifiers. - kw
*/
if (c & (LKC_ISLECLAC | LKC_ISLAC))
return 0;
if ((c & LKC_MASK) != c)
c &= LKC_MASK;
}
if (c + 1 >= KEYMAP_SIZE)
return 0;
if ((mp = LYStringToKcmd(func)) != 0) {
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
if (for_dired)
key_override[c + 1] = mp->code;
else
#endif
keymap[c + 1] = (LYKeymap_t) mp->code;
return (c ? c : (int) LAC_TO_LKC0(mp->code)); /* don't return 0, successful */
}
return 0;
}
typedef struct {
int code;
LYKeymap_t map;
LYKeymap_t save;
} ANY_KEYS;
/*
* Save the given keys in the table, setting them to the map'd value.
*/
static void set_any_keys(ANY_KEYS * table, int size)
{
int j, k;
for (j = 0; j < size; ++j) {
k = table[j].code + 1;
table[j].save = keymap[k];
keymap[k] = table[j].map;
}
}
/*
* Restore the given keys from the table.
*/
static void reset_any_keys(ANY_KEYS * table, int size)
{
int j, k;
for (j = 0; j < size; ++j) {
k = table[j].code + 1;
keymap[k] = table[j].save;
}
}
static ANY_KEYS vms_keys_table[] =
{
{26, LYK_ABORT, 0}, /* control-Z */
{'$', LYK_SHELL, 0},
};
void set_vms_keys(void)
{
set_any_keys(vms_keys_table, TABLESIZE(vms_keys_table));
}
static ANY_KEYS vi_keys_table[] =
{
{'h', LYK_PREV_DOC, 0},
{'j', LYK_NEXT_LINK, 0},
{'k', LYK_PREV_LINK, 0},
{'l', LYK_ACTIVATE, 0},
};
static BOOLEAN did_vi_keys;
void set_vi_keys(void)
{
set_any_keys(vi_keys_table, TABLESIZE(vi_keys_table));
did_vi_keys = TRUE;
}
void reset_vi_keys(void)
{
if (did_vi_keys) {
reset_any_keys(vi_keys_table, TABLESIZE(vi_keys_table));
did_vi_keys = FALSE;
}
}
static ANY_KEYS emacs_keys_table[] =
{
{2, LYK_PREV_DOC, 0}, /* ^B */
{14, LYK_NEXT_LINK, 0}, /* ^N */
{16, LYK_PREV_LINK, 0}, /* ^P */
{6, LYK_ACTIVATE, 0}, /* ^F */
};
static BOOLEAN did_emacs_keys;
void set_emacs_keys(void)
{
set_any_keys(emacs_keys_table, TABLESIZE(emacs_keys_table));
did_emacs_keys = TRUE;
}
void reset_emacs_keys(void)
{
if (did_emacs_keys) {
reset_any_keys(emacs_keys_table, TABLESIZE(emacs_keys_table));
did_emacs_keys = FALSE;
}
}
/*
* Map numbers to functions as labeled on the IBM Enhanced keypad, and save
* their original mapping for reset_numbers_as_arrows(). - FM
*/
static ANY_KEYS number_keys_table[] =
{
{'1', LYK_END, 0},
{'2', LYK_NEXT_LINK, 0},
{'3', LYK_NEXT_PAGE, 0},
{'4', LYK_PREV_DOC, 0},
{'5', LYK_DO_NOTHING, 0},
{'6', LYK_ACTIVATE, 0},
{'7', LYK_HOME, 0},
{'8', LYK_PREV_LINK, 0},
{'9', LYK_PREV_PAGE, 0},
};
static BOOLEAN did_number_keys;
void set_numbers_as_arrows(void)
{
set_any_keys(number_keys_table, TABLESIZE(number_keys_table));
did_number_keys = TRUE;
}
void reset_numbers_as_arrows(void)
{
if (did_number_keys) {
reset_any_keys(number_keys_table, TABLESIZE(number_keys_table));
did_number_keys = FALSE;
}
}
char *key_for_func(int func)
{
static char *buf;
int i;
char *formatted;
if ((i = LYReverseKeymap(func)) >= 0) {
formatted = LYKeycodeToString(i, TRUE);
StrAllocCopy(buf, formatted != 0 ? formatted : "?");
} else if (buf == 0) {
StrAllocCopy(buf, "");
}
return buf;
}
/*
* Given one or two keys as lynxkeycodes, returns an allocated string
* representing the key(s) suitable for statusline messages, or NULL if no
* valid lynxkeycode is passed in (i.e., lkc_first < 0 or some other failure).
* The caller must free the string. - kw
*/
char *fmt_keys(int lkc_first,
int lkc_second)
{
char *buf = NULL;
BOOLEAN quotes = FALSE;
char *fmt_first;
char *fmt_second;
if (lkc_first < 0)
return NULL;
fmt_first = LYKeycodeToString(lkc_first, TRUE);
if (fmt_first && strlen(fmt_first) == 1 && *fmt_first != '\'') {
quotes = TRUE;
}
if (quotes) {
if (lkc_second < 0) {
HTSprintf0(&buf, "'%s'", fmt_first);
return buf;
} else {
HTSprintf0(&buf, "'%s", fmt_first);
}
} else {
StrAllocCopy(buf, fmt_first);
}
if (lkc_second >= 0) {
fmt_second = LYKeycodeToString(lkc_second, TRUE);
if (!fmt_second) {
FREE(buf);
return NULL;
}
HTSprintf(&buf, "%s%s%s",
(((strlen(fmt_second) > 2 && *fmt_second != '<') ||
(strlen(buf) > 2 && buf[strlen(buf) - 1] != '>'))
? " "
: ""),
fmt_second, quotes ? "'" : "");
}
return buf;
}
/*
* This function returns the (int)ch mapped to the LYK_foo value passed to it
* as an argument. It is like LYReverseKeymap, only the order of search is
* different; e.g., small ASCII letters will be returned in preference to
* capital ones. Cf. LYKeyForEditAction, LYEditKeyForAction in LYEditmap.c
* which use the same order to find a best key. In addition, this function
* takes the dired override map into account while LYReverseKeymap doesn't.
* The caller must free the returned string. - kw
*/
#define FIRST_I 97
#define NEXT_I(i,imax) ((i==122) ? 32 : (i==96) ? 123 : (i==126) ? 0 :\
(i==31) ? 256 : (i==imax) ? 127 :\
(i==255) ? (-1) :i+1)
static int best_reverse_keymap(int lac)
{
int i, c;
for (i = FIRST_I; i >= 0; i = NEXT_I(i, KEYMAP_SIZE - 2)) {
#ifdef NOT_ASCII
if (i < 256) {
c = FROMASCII(i);
} else
#endif
c = i;
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
if (lynx_edit_mode && !no_dired_support && lac &&
LKC_TO_LAC(key_override, c) == lac)
return c;
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
if (LKC_TO_LAC(keymap, c) == lac) {
return c;
}
}
return (-1);
}
/*
* This function returns a string representing a key mapped to a LYK_foo
* function, or NULL if not found. The string may represent a pair of keys.
* if context_code is FOR_INPUT, an appropriate binding for use while in the
* (forms) line editor is sought. - kw
*/
char *key_for_func_ext(int lac,
int context_code)
{
int lkc, modkey = -1;
if (context_code == FOR_INPUT) {
lkc = LYEditKeyForAction(lac, &modkey);
if (lkc >= 0) {
if (lkc & (LKC_MOD1 | LKC_MOD2 | LKC_MOD3)) {
return fmt_keys(modkey, lkc & ~(LKC_MOD1 | LKC_MOD2 | LKC_MOD3));
} else {
return fmt_keys(lkc, -1);
}
}
}
lkc = best_reverse_keymap(lac);
if (lkc < 0)
return NULL;
if (context_code == FOR_INPUT) {
modkey = LYKeyForEditAction(LYE_LKCMD);
if (modkey < 0)
return NULL;
return fmt_keys(modkey, lkc);
} else {
return fmt_keys(lkc, -1);
}
}
/*
* This function returns TRUE if the ch is non-alphanumeric and maps to KeyName
* (LYK_foo in the keymap[] array). - FM
*/
BOOLEAN LYisNonAlnumKeyname(int ch,
int KeyName)
{
if (ch < 0 || ch >= KEYMAP_SIZE)
return (FALSE);
if (ch > 0
&& strchr("0123456789\
ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz", ch) != NULL)
return (FALSE);
return (BOOL) (keymap[ch + 1] == KeyName);
}
/*
* This function returns the (int)ch mapped to the LYK_foo value passed to it
* as an argument. - FM
*/
int LYReverseKeymap(int KeyName)
{
int i;
for (i = 1; i < KEYMAP_SIZE; i++) {
if (keymap[i] == KeyName) {
return (i - 1);
}
}
return (-1);
}
#ifdef EXP_KEYBOARD_LAYOUT
int LYSetKbLayout(char *layout_id)
{
int i;
for (i = 0; i < (int) TABLESIZE(LYKbLayoutNames) - 1; i++) {
if (!strcmp(LYKbLayoutNames[i], layout_id)) {
current_layout = i;
return (-1);
}
}
return 0;
}
#endif