aboutsummaryrefslogtreecommitdiffstats
path: root/func.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--func.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/func.c b/func.c
new file mode 100644
index 0000000..b8c5ee3
--- /dev/null
+++ b/func.c
@@ -0,0 +1,356 @@
+/*
+ * w3m func.c
+ */
+
+#include <stdio.h>
+
+#include "fm.h"
+#include "func.h"
+#include "myctype.h"
+
+#include "funcname.c"
+int w3mNFuncList = 0;
+
+KeyList w3mKeyList = {
+ NULL, 0, 0
+};
+
+void
+initKeymap(void)
+{
+ FILE *kf;
+ Str line;
+ char *p, *s, *emsg;
+ int c;
+ int f;
+ int lineno;
+
+ if (!w3mNFuncList)
+ w3mNFuncList = countFuncList(w3mFuncList);
+
+ if ((kf = fopen(rcFile(KEYMAP_FILE), "rt")) == NULL)
+ return;
+
+ lineno = 0;
+ while (!feof(kf)) {
+ line = Strfgets(kf);
+ lineno++;
+ Strchop(line);
+ Strremovefirstspaces(line);
+ if (line->length == 0)
+ continue;
+ p = line->ptr;
+ s = getWord(&p);
+ if (*s == '#') /* comment */
+ continue;
+ if (strcmp(s, "keymap")) { /* error */
+ emsg = Sprintf("line %d: keymap not found\n", lineno)->ptr;
+ record_err_message(emsg);
+ disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
+ continue;
+ }
+ s = getQWord(&p);
+ c = getKey(s);
+ if (c < 0) { /* error */
+ emsg = Sprintf("line %d: unknown key '%s'\n", lineno, s)->ptr;
+ record_err_message(emsg);
+ disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
+ continue;
+ }
+ s = getWord(&p);
+ f = getFuncList(s, w3mFuncList, w3mNFuncList);
+ if (f < 0) {
+ emsg = Sprintf("line %d: invalid command '%s'\n", lineno, s)->ptr;
+ record_err_message(emsg);
+ disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
+ f = FUNCNAME_nulcmd;
+ }
+ if (c & K_ESCD)
+ EscDKeymap[c ^ K_ESCD] = (f >= 0) ? f : FUNCNAME_nulcmd;
+ else if (c & K_ESCB)
+ EscBKeymap[c ^ K_ESCB] = (f >= 0) ? f : FUNCNAME_nulcmd;
+ else if (c & K_ESC)
+ EscKeymap[c ^ K_ESC] = (f >= 0) ? f : FUNCNAME_nulcmd;
+ else
+ GlobalKeymap[c] = (f >= 0) ? f : FUNCNAME_nulcmd;
+ s = getQWord(&p);
+ addKeyList(&w3mKeyList, c, s);
+ }
+ fclose(kf);
+}
+
+int
+countFuncList(FuncList * list)
+{
+ int i;
+
+ for (i = 0; list->id != NULL; i++, list++);
+ return i;
+}
+
+int
+getFuncList(char *id, FuncList * list, int nlist)
+{
+ int i, is, ie, m;
+
+ if (id == NULL || *id == '\0' || nlist <= 0)
+ return -1;
+
+ is = 0;
+ ie = nlist - 1;
+ while (1) {
+ i = is + (ie - is) / 2;
+ if ((m = strcmp(id, list[i].id)) == 0)
+ return i;
+ else if (is >= ie)
+ return -1;
+ else if (m > 0)
+ is = i + 1;
+ else
+ ie = i - 1;
+ }
+}
+
+int
+getKey(char *s)
+{
+ int c, esc = 0, ctrl = 0;
+
+ if (s == NULL || *s == '\0')
+ return -1;
+
+ if (strcasecmp(s, "UP") == 0) /* ^[[A */
+ return K_ESCB | 'A';
+ else if (strcasecmp(s, "DOWN") == 0) /* ^[[B */
+ return K_ESCB | 'B';
+ else if (strcasecmp(s, "RIGHT") == 0) /* ^[[C */
+ return K_ESCB | 'C';
+ else if (strcasecmp(s, "LEFT") == 0) /* ^[[D */
+ return K_ESCB | 'D';
+
+ if (strncasecmp(s, "ESC-", 4) == 0 ||
+ strncasecmp(s, "ESC ", 4) == 0) { /* ^[ */
+ s += 4;
+ esc = K_ESC;
+ }
+ else if (strncasecmp(s, "M-", 2) == 0 ||
+ strncasecmp(s, "\\E", 2) == 0) { /* ^[ */
+ s += 2;
+ esc = K_ESC;
+ }
+ else if (*s == ESC_CODE) { /* ^[ */
+ s++;
+ esc = K_ESC;
+ }
+ if (strncasecmp(s, "C-", 2) == 0) { /* ^, ^[^ */
+ s += 2;
+ ctrl = 1;
+ }
+ else if (*s == '^') { /* ^, ^[^ */
+ s++;
+ ctrl = 1;
+ }
+ if (!esc && ctrl && *s == '[') { /* ^[ */
+ s++;
+ ctrl = 0;
+ esc = K_ESC;
+ }
+ if (esc && !ctrl) {
+ if (*s == '[' || *s == 'O') { /* ^[[, ^[O */
+ s++;
+ esc = K_ESCB;
+ }
+ if (strncasecmp(s, "C-", 2) == 0) { /* ^[^, ^[[^ */
+ s += 2;
+ ctrl = 1;
+ }
+ else if (*s == '^') { /* ^[^, ^[[^ */
+ s++;
+ ctrl = 1;
+ }
+ }
+
+ if (ctrl) {
+ if (*s >= '@' && *s <= '_') /* ^@ .. ^_ */
+ return esc | (*s - '@');
+ else if (*s >= 'a' && *s <= 'z') /* ^a .. ^z */
+ return esc | (*s - 'a' + 1);
+ else if (*s == '?') /* ^? */
+ return esc | DEL_CODE;
+ else
+ return -1;
+ }
+
+ if (esc == K_ESCB && IS_DIGIT(*s)) {
+ c = (int)(*s - '0');
+ s++;
+ if (IS_DIGIT(*s)) {
+ c = c * 10 + (int)(*s - '0');
+ s++;
+ }
+ if (*s == '~')
+ return K_ESCD | c;
+ else
+ return -1;
+ }
+
+ if (strncasecmp(s, "SPC", 3) == 0) /* ' ' */
+ return esc | ' ';
+ else if (strncasecmp(s, "TAB", 3) == 0) /* ^i */
+ return esc | '\t';
+ else if (strncasecmp(s, "DEL", 3) == 0) /* ^? */
+ return esc | DEL_CODE;
+
+ if (*s == '\\' && *(s + 1) != '\0') {
+ switch (*(s + 1)) {
+ case 'a': /* ^g */
+ return esc | CTRL_G;
+ case 'b': /* ^h */
+ return esc | CTRL_H;
+ case 't': /* ^i */
+ return esc | CTRL_I;
+ case 'n': /* ^j */
+ return esc | CTRL_J;
+ case 'r': /* ^m */
+ return esc | CTRL_M;
+ case 'e': /* ^[ */
+ return esc | ESC_CODE;
+ case '^': /* ^ */
+ return esc | '^';
+ case '\\': /* \ */
+ return esc | '\\';
+ default:
+ return -1;
+ }
+ }
+ if (IS_ASCII(*s)) /* Ascii */
+ return esc | *s;
+ else
+ return -1;
+}
+
+void
+addKeyList(KeyList *list, int key, char *data)
+{
+ KeyListItem *item;
+
+ if (data == NULL || *data == '\0')
+ data = NULL;
+ else
+ data = allocStr(data, 0);
+ item = searchKeyList(list, key);
+ if (item == NULL) {
+ if (data == NULL)
+ return;
+ list->nitem++;
+ if (list->nitem > list->size) {
+ list->size = (list->size >= 2) ? (list->size * 3 / 2) : 2;
+ list->item = New_Reuse(KeyListItem, list->item,
+ list->size * sizeof(KeyListItem));
+ }
+ item = &(list->item[list->nitem - 1]);
+ item->key = key;
+ }
+ item->data = data;
+}
+
+KeyListItem *
+searchKeyList(KeyList *list, int key)
+{
+ int i;
+ KeyListItem *item;
+
+ if (list == NULL)
+ return NULL;
+ for (i = 0, item = list->item; i < list->nitem; i++, item++) {
+ if (key == item->key)
+ return item;
+ }
+ return NULL;
+}
+
+char *
+getWord(char **str)
+{
+ char *p, *s;
+
+ p = *str;
+ SKIP_BLANKS(p);
+ s = p;
+ while (*p != '\0') {
+ if (IS_SPACE(*p)) {
+ *p = '\0';
+ p++;
+ break;
+ }
+ p++;
+ }
+ *str = p;
+ return s;
+}
+
+char *
+getQWord(char **str)
+{
+ char *p, *s, *e;
+ int in_q = 0, in_dq = 0, esc = 0;
+
+ p = *str;
+ while (*p && IS_SPACE(*p))
+ p++;
+ s = p;
+ e = p;
+ while (*p != '\0') {
+ if (esc) {
+ if (in_q) {
+ if (*p != '\\' && *p != '\'') /* '..\\..', '..\'..' */
+ *e++ = '\\';
+ }
+ else if (in_dq) {
+ if (*p != '\\' && *p != '"') /* "..\\..", "..\".." */
+ *e++ = '\\';
+ }
+ else {
+ if (*p != '\\' && *p != '\'' && /* ..\\.., *
+ * ..\'.. */
+ *p != '"' && !IS_SPACE(*p)) /* ..\".., * ..\..
+ */
+ *e++ = '\\';
+ }
+ *e++ = *p;
+ esc = 0;
+ }
+ else if (*p == '\\') {
+ esc = 1;
+ }
+ else if (in_q) {
+ if (*p == '\'')
+ in_q = 0;
+ else
+ *e++ = *p;
+ }
+ else if (in_dq) {
+ if (*p == '"')
+ in_dq = 0;
+ else
+ *e++ = *p;
+ }
+ else if (*p == '\'') {
+ in_q = 1;
+ }
+ else if (*p == '"') {
+ in_dq = 1;
+ }
+ else if (IS_SPACE(*p)) {
+ p++;
+ break;
+ }
+ else {
+ *e++ = *p;
+ }
+ p++;
+ }
+ *e = '\0';
+ *str = p;
+ return s;
+}