commit c5ef940b6560f45e3f745865d3b190514b3b9508
parent 27ad998a5c19d4ab2abb23a001b47331af038f73
Author: ukai <ukai>
Date:   Sat,  1 Jun 2002 16:50:16 +0000
[w3m-dev 03200] Re: New configuration option ``keymap_file'' and new command ``DEFINE_KEY''
* fm.h: add <sts/stat.h>, unistd.h>
* fm.h (keymap_file): added
* func.c (keymap_initialized): added
	(current_keymap_file): added
	(setKeymap): added
	(initKeymap): rewrite to use setKeymap()
* funcname.tab (DEFINE_KEY): added
* main.c (MAIN): initKeymap(TRUE)
	(defKey): added
* proto.h (defKey): added
	(setKeymap): added
	(initKeymap): add force param
* rc.c (CMT_KEYMAP_FILE): added
	(params3): add keymap_file
	(sync_with_option): add initKeymap(FALSE)
* doc/README.func (DEFINE_KEY): added
* doc-jp/README.func: (DEFINE_KEY): added
* scripts/w3mhelp.cgi.in: add defKey
* NEWS:
	func: DEFINE_KEY
	rc: keymap_file
From: Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
Diffstat:
11 files changed, 128 insertions(+), 39 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,28 @@
+2002-06-02  Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
+
+	* [w3m-dev 03200] Re: New configuration option ``keymap_file'' and new command ``DEFINE_KEY''
+	* fm.h: add <sts/stat.h>, unistd.h>
+	* fm.h (keymap_file): added
+	* func.c (keymap_initialized): added
+		(current_keymap_file): added
+		(setKeymap): added
+		(initKeymap): rewrite to use setKeymap()
+	* funcname.tab (DEFINE_KEY): added
+	* main.c (MAIN): initKeymap(TRUE)
+		(defKey): added
+	* proto.h (defKey): added
+		(setKeymap): added
+		(initKeymap): add force param
+	* rc.c (CMT_KEYMAP_FILE): added
+		(params3): add keymap_file
+		(sync_with_option): add initKeymap(FALSE)
+	* doc/README.func (DEFINE_KEY): added
+	* doc-jp/README.func: (DEFINE_KEY): added
+	* scripts/w3mhelp.cgi.in: add defKey
+	* NEWS:
+		func: DEFINE_KEY
+		rc: keymap_file
+
 2002-06-02  Hiroaki Shimotsu <shim@d5.bs1.fc.nec.co.jp>
 
 	* [w3m-dev 03196] C-w
diff --git a/NEWS b/NEWS
@@ -1,5 +1,7 @@
 w3m 0.4?
 
+* func: DEFINE_KEY
+* rc: keymap_file
 * rc: use_dictcommand, dictcommand
 * rc: mark_all_pages
 * configure: -mandir
diff --git a/doc-jp/README.func b/doc-jp/README.func
@@ -8,6 +8,7 @@ CENTER_H	
 CENTER_V	カーソルのある行を画面の中央に移動します
 COMMAND		w3mのコマンドを実行します
 COOKIE		クッキー一覧を表示します
+DEFINE_KEY	キー入力とコマンドの対応を定義します
 DELETE_PREVBUF 前のバッファを消去します(主に local-CGI 用)
 DICT_WORD	入力した単語を辞書コマンドで調べます
 DICT_WORD_AT	カーソル位置の単語を辞書コマンドで調べます
diff --git a/doc/README.func b/doc/README.func
@@ -8,6 +8,7 @@ CENTER_H	Move to the center line
 CENTER_V	Move to the center column
 COMMAND		Execute w3m command(s)
 COOKIE		View cookie list
+DEFINE_KEY	Define a binding between a key stroke and a user command
 DELETE_PREVBUF  Delete previous buffer (mainly for local-CGI)
 DICT_WORD	Execute dictionary command (see README.dict)
 DICT_WORD_AT   Execute dictionary command for word at cursor
diff --git a/fm.h b/fm.h
@@ -20,6 +20,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "config.h"
 #include "history.h"
 
@@ -978,6 +980,8 @@ global double image_scale init(100);
 #endif
 global int use_lessopen init(FALSE);
 
+global char *keymap_file init(KEYMAP_FILE);
+
 #ifdef JP_CHARSET
 #define is_kanji(s)    (IS_KANJI1((s)[0])&&IS_KANJI2((s)[1]))
 #define get_mctype(s)  (is_kanji(s)?PC_KANJI:GET_PCTYPE(*(s)))
diff --git a/func.c b/func.c
@@ -14,20 +14,77 @@
 
 #define KEYDATA_HASH_SIZE 16
 static Hash_iv *keyData = NULL;
+static char keymap_initialized;
+static struct stat current_keymap_file;
 
 void
-initKeymap(void)
+setKeymap(char *p, int lineno, int verbose)
+{
+    char *s, *emsg;
+    int c, f;
+
+    s = getQWord(&p);
+    c = getKey(s);
+    if (c < 0) {		/* error */
+	if (lineno > 0)
+	    emsg = Sprintf("line %d: unknown key '%s'", lineno, s)->ptr;
+	else
+	    emsg = Sprintf("defkey: unknown key '%s'", s)->ptr;
+	record_err_message(emsg);
+	if (verbose)
+	    disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
+	return;
+    }
+    s = getWord(&p);
+    f = getFuncList(s);
+    if (f < 0) {
+	if (lineno > 0)
+	    emsg = Sprintf("line %d: invalid command '%s'", lineno, s)->ptr;
+	else
+	    emsg = Sprintf("defkey: invalid command '%s'", s)->ptr;
+	record_err_message(emsg);
+	if (verbose)
+	    disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
+	return;
+    }
+    if (c & K_ESCD)
+	EscDKeymap[c ^ K_ESCD] = f;
+    else if (c & K_ESCB)
+	EscBKeymap[c ^ K_ESCB] = f;
+    else if (c & K_ESC)
+	EscKeymap[c ^ K_ESC] = f;
+    else
+	GlobalKeymap[c] = f;
+    s = getQWord(&p);
+    if (*s) {
+	if (keyData == NULL)
+	    keyData = newHash_iv(KEYDATA_HASH_SIZE);
+	putHash_iv(keyData, c, (void *)s);
+    }
+}
+
+void
+initKeymap(int force)
 {
     FILE *kf;
     Str line;
     char *p, *s, *emsg;
-    int c;
-    int f;
     int lineno;
     int verbose = 1;
+    int fd;
+    struct stat kstat;
     extern int str_to_bool(char *value, int old);
 
-    if ((kf = fopen(rcFile(KEYMAP_FILE), "rt")) == NULL)
+    if (!force && !keymap_initialized)
+	return;
+
+    if ((kf = fopen(rcFile(keymap_file), "rt")) == NULL ||
+	((fd = fileno(kf)) < 0 || fstat(fd, &kstat) ||
+	 (!force && keymap_initialized &&
+	  kstat.st_mtime == current_keymap_file.st_mtime &&
+	  kstat.st_dev == current_keymap_file.st_dev &&
+	  kstat.st_ino == current_keymap_file.st_ino &&
+	  kstat.st_size == current_keymap_file.st_size)))
 	return;
 
     lineno = 0;
@@ -56,40 +113,11 @@ initKeymap(void)
 		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'", lineno, s)->ptr;
-	    record_err_message(emsg);
-	    if (verbose)
-		disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
-	    continue;
-	}
-	s = getWord(&p);
-	f = getFuncList(s);
-	if (f < 0) {
-	    emsg = Sprintf("line %d: invalid command '%s'", lineno, s)->ptr;
-	    record_err_message(emsg);
-	    if (verbose)
-		disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
-	    continue;
-	}
-	if (c & K_ESCD)
-	    EscDKeymap[c ^ K_ESCD] = f;
-	else if (c & K_ESCB)
-	    EscBKeymap[c ^ K_ESCB] = f;
-	else if (c & K_ESC)
-	    EscKeymap[c ^ K_ESC] = f;
-	else
-	    GlobalKeymap[c] = f;
-	s = getQWord(&p);
-	if (*s) {
-	    if (keyData == NULL)
-		keyData = newHash_iv(KEYDATA_HASH_SIZE);
-	    putHash_iv(keyData, c, (void *)s);
-	}
+	setKeymap(p, lineno, verbose);
     }
     fclose(kf);
+    current_keymap_file = kstat;
+    keymap_initialized = TRUE;
 }
 
 int
diff --git a/funcname.tab b/funcname.tab
@@ -12,6 +12,7 @@ CENTER_H	ctrCsrH
 CENTER_V	ctrCsrV
 COMMAND		execCmd
 COOKIE		cooLst
+DEFINE_KEY	defKey
 DELETE_PREVBUF	deletePrevBuf
 DICT_WORD	dictword
 DICT_WORD_AT	dictwordat
diff --git a/main.c b/main.c
@@ -724,7 +724,7 @@ MAIN(int argc, char **argv, char **envp)
     if (w3m_backend)
 	backend();
     if (!w3m_dump) {
-	initKeymap();
+	initKeymap(TRUE);
 #ifdef USE_MENU
 	initMenu();
 #endif				/* MENU */
@@ -5091,3 +5091,21 @@ setAlarmEvent(int sec, short status, int cmd, void *data)
     }
 }
 #endif
+
+void
+defKey(void)
+{
+    char *data;
+
+    CurrentKeyData = NULL;	/* not allowed in w3m-control: */
+    data = searchKeyData();
+    if (data == NULL || *data == '\0') {
+	data = inputStrHist("Key definition: ", "", TextHist);
+	if (data == NULL || *data == '\0') {
+	    displayBuffer(Currentbuf, B_NORMAL);
+	    return;
+	}
+    }
+    setKeymap(allocStr(data, -1), -1, TRUE);
+    displayBuffer(Currentbuf, B_NORMAL);
+}
diff --git a/proto.h b/proto.h
@@ -116,6 +116,7 @@ extern void setAlarmEvent(int sec, short status, int cmd, void *data);
 #else
 #define setAlarm nulcmd
 #endif
+extern void defKey(void);
 extern int currentLn(Buffer *buf);
 extern void tmpClearBuffer(Buffer *buf);
 extern char *filename_extension(char *patch, int is_url);
@@ -583,7 +584,8 @@ extern void clearImage(void);
 
 extern char *searchKeyData(void);
 
-extern void initKeymap(void);
+extern void setKeymap(char *p, int lineno, int verbose);
+extern void initKeymap(int force);
 extern int getFuncList(char *id);
 extern int getKey(char *s);
 extern char *getKeyData(int key);
diff --git a/rc.c b/rc.c
@@ -191,6 +191,8 @@ static char *config_file = NULL;
 #define CMT_MIGEMO_COMMAND "Migemoコマンド"
 #endif				/* USE_MIGEMO */
 
+#define CMT_KEYMAP_FILE "keymapファイル"
+
 #else				/* LANG != JA */
 
 
@@ -329,6 +331,8 @@ static char *config_file = NULL;
 #define CMT_MIGEMO_COMMAND "Migemo command"
 #endif				/* USE_MIGEMO */
 
+#define CMT_KEYMAP_FILE "keymap file"
+
 #endif				/* LANG != JA */
 
 #define PI_TEXT    0
@@ -575,6 +579,8 @@ struct param_ptr params3[] = {
      NULL},
     {"decode_cte", P_CHARINT, PI_ONOFF, (void *)&DecodeCTE, CMT_DECODE_CTE,
      NULL},
+    {"keymap_file", P_STRING, PI_TEXT, (void *)&keymap_file, CMT_KEYMAP_FILE,
+     NULL},
     {NULL, 0, 0, NULL, NULL, NULL},
 };
 
@@ -1238,6 +1244,7 @@ sync_with_option(void)
 	AcceptEncoding = acceptableEncoding();
     if (AcceptMedia == NULL || *AcceptMedia == '\0')
 	AcceptMedia = acceptableMimeTypes();
+    initKeymap(FALSE);
 }
 
 void
diff --git a/scripts/w3mhelp.cgi.in b/scripts/w3mhelp.cgi.in
@@ -148,7 +148,7 @@ for $otherlang (@docdirs) {
 
 &show_keymap("Miscellany",
 	     split(" ", "mainMn ldhelp ldOpt cooLst ldHist msgs msToggle
-		wrapToggle setAlarm setOpt setEnv execsh susp qquitfm quitfm"));
+		wrapToggle setAlarm setOpt setEnv execsh susp qquitfm quitfm defKey"));
 
 &show_keymap("Buffer selection mode",
 	     split(" ", "buffer_next buffer_prev buffer_delete buffer_go"));