Patch to support the siteconf feature, from [w3m-dev 04463] on 2012-06-27, provided by AIDA Shinra.
		
			
				
	
	
		
			719 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			719 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id: func.c,v 1.27 2003/09/26 17:59:51 ukai Exp $ */
 | |
| /*
 | |
|  * w3m func.c
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "fm.h"
 | |
| #include "func.h"
 | |
| #include "myctype.h"
 | |
| #include "regex.h"
 | |
| 
 | |
| #include "funcname.c"
 | |
| #include "functable.c"
 | |
| 
 | |
| #define KEYDATA_HASH_SIZE 16
 | |
| static Hash_iv *keyData = NULL;
 | |
| static char keymap_initialized = FALSE;
 | |
| static struct stat sys_current_keymap_file;
 | |
| static struct stat current_keymap_file;
 | |
| 
 | |
| void
 | |
| setKeymap(char *p, int lineno, int verbose)
 | |
| {
 | |
|     unsigned char *map = NULL;
 | |
|     char *s, *emsg;
 | |
|     int c, f;
 | |
| 
 | |
|     s = getQWord(&p);
 | |
|     c = getKey(s);
 | |
|     if (c < 0) {		/* error */
 | |
| 	if (lineno > 0)
 | |
| 	    /* FIXME: gettextize? */
 | |
| 	    emsg = Sprintf("line %d: unknown key '%s'", lineno, s)->ptr;
 | |
| 	else
 | |
| 	    /* FIXME: gettextize? */
 | |
| 	    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)
 | |
| 	    /* FIXME: gettextize? */
 | |
| 	    emsg = Sprintf("line %d: invalid command '%s'", lineno, s)->ptr;
 | |
| 	else
 | |
| 	    /* FIXME: gettextize? */
 | |
| 	    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_MULTI) {
 | |
| 	unsigned char **mmap = NULL;
 | |
| 	int i, j, m = MULTI_KEY(c);
 | |
| 
 | |
| 	if (m & K_ESCD)
 | |
| 	    map = EscDKeymap;
 | |
| 	else if (m & K_ESCB)
 | |
| 	    map = EscBKeymap;
 | |
| 	else if (m & K_ESC)
 | |
| 	    map = EscKeymap;
 | |
| 	else
 | |
| 	    map = GlobalKeymap;
 | |
| 	if (map[m & 0x7F] == FUNCNAME_multimap)
 | |
| 	    mmap = (unsigned char **)getKeyData(m);
 | |
| 	else
 | |
| 	    map[m & 0x7F] = FUNCNAME_multimap;
 | |
| 	if (!mmap) {
 | |
| 	    mmap = New_N(unsigned char *, 4);
 | |
| 	    for (i = 0; i < 4; i++) {
 | |
| 		mmap[i] = New_N(unsigned char, 128);
 | |
| 		for (j = 0; j < 128; j++)
 | |
| 		    mmap[i][j] = FUNCNAME_nulcmd;
 | |
| 	    }
 | |
| 	    mmap[0][ESC_CODE] = FUNCNAME_escmap;
 | |
| 	    mmap[1]['['] = FUNCNAME_escbmap;
 | |
| 	    mmap[1]['O'] = FUNCNAME_escbmap;
 | |
| 	}
 | |
| 	if (keyData == NULL)
 | |
| 	    keyData = newHash_iv(KEYDATA_HASH_SIZE);
 | |
| 	putHash_iv(keyData, m, (void *)mmap);
 | |
| 	if (c & K_ESCD)
 | |
| 	    map = mmap[3];
 | |
| 	else if (c & K_ESCB)
 | |
| 	    map = mmap[2];
 | |
| 	else if (c & K_ESC)
 | |
| 	    map = mmap[1];
 | |
| 	else
 | |
| 	    map = mmap[0];
 | |
|     }
 | |
|     else {
 | |
| 	if (c & K_ESCD)
 | |
| 	    map = EscDKeymap;
 | |
| 	else if (c & K_ESCB)
 | |
| 	    map = EscBKeymap;
 | |
| 	else if (c & K_ESC)
 | |
| 	    map = EscKeymap;
 | |
| 	else
 | |
| 	    map = GlobalKeymap;
 | |
|     }
 | |
|     map[c & 0x7F] = f;
 | |
|     s = getQWord(&p);
 | |
|     if (*s) {
 | |
| 	if (keyData == NULL)
 | |
| 	    keyData = newHash_iv(KEYDATA_HASH_SIZE);
 | |
| 	putHash_iv(keyData, c, (void *)s);
 | |
|     }
 | |
|     else if (getKeyData(c))
 | |
| 	putHash_iv(keyData, c, NULL);
 | |
| }
 | |
| 
 | |
| static void
 | |
| interpret_keymap(FILE * kf, struct stat *current, int force)
 | |
| {
 | |
|     int fd;
 | |
|     struct stat kstat;
 | |
|     Str line;
 | |
|     char *p, *s, *emsg;
 | |
|     int lineno;
 | |
| #ifdef USE_M17N
 | |
|     wc_ces charset = SystemCharset;
 | |
| #endif
 | |
|     int verbose = 1;
 | |
|     extern int str_to_bool(char *value, int old);
 | |
| 
 | |
|     if ((fd = fileno(kf)) < 0 || fstat(fd, &kstat) ||
 | |
| 	(!force &&
 | |
| 	 kstat.st_mtime == current->st_mtime &&
 | |
| 	 kstat.st_dev == current->st_dev &&
 | |
| 	 kstat.st_ino == current->st_ino && kstat.st_size == current->st_size))
 | |
| 	return;
 | |
|     *current = kstat;
 | |
| 
 | |
|     lineno = 0;
 | |
|     while (!feof(kf)) {
 | |
| 	line = Strfgets(kf);
 | |
| 	lineno++;
 | |
| 	Strchop(line);
 | |
| 	Strremovefirstspaces(line);
 | |
| 	if (line->length == 0)
 | |
| 	    continue;
 | |
| #ifdef USE_M17N
 | |
| 	line = wc_Str_conv(line, charset, InnerCharset);
 | |
| #endif
 | |
| 	p = line->ptr;
 | |
| 	s = getWord(&p);
 | |
| 	if (*s == '#')		/* comment */
 | |
| 	    continue;
 | |
| 	if (!strcmp(s, "keymap")) ;
 | |
| #ifdef USE_M17N
 | |
| 	else if (!strcmp(s, "charset") || !strcmp(s, "encoding")) {
 | |
| 	    s = getQWord(&p);
 | |
| 	    if (*s)
 | |
| 		charset = wc_guess_charset(s, charset);
 | |
| 	    continue;
 | |
| 	}
 | |
| #endif
 | |
| 	else if (!strcmp(s, "verbose")) {
 | |
| 	    s = getWord(&p);
 | |
| 	    if (*s)
 | |
| 		verbose = str_to_bool(s, verbose);
 | |
| 	    continue;
 | |
| 	}
 | |
| 	else {			/* error */
 | |
| 	    emsg = Sprintf("line %d: syntax error '%s'", lineno, s)->ptr;
 | |
| 	    record_err_message(emsg);
 | |
| 	    if (verbose)
 | |
| 		disp_message_nsec(emsg, FALSE, 1, TRUE, FALSE);
 | |
| 	    continue;
 | |
| 	}
 | |
| 	setKeymap(p, lineno, verbose);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| initKeymap(int force)
 | |
| {
 | |
|     FILE *kf;
 | |
| 
 | |
|     if ((kf = fopen(confFile(KEYMAP_FILE), "rt")) != NULL) {
 | |
| 	interpret_keymap(kf, &sys_current_keymap_file,
 | |
| 			 force || !keymap_initialized);
 | |
| 	fclose(kf);
 | |
|     }
 | |
|     if ((kf = fopen(rcFile(keymap_file), "rt")) != NULL) {
 | |
| 	interpret_keymap(kf, ¤t_keymap_file,
 | |
| 			 force || !keymap_initialized);
 | |
| 	fclose(kf);
 | |
|     }
 | |
|     keymap_initialized = TRUE;
 | |
| }
 | |
| 
 | |
| int
 | |
| getFuncList(char *id)
 | |
| {
 | |
|     return getHash_si(&functable, id, -1);
 | |
| }
 | |
| 
 | |
| char *
 | |
| getKeyData(int key)
 | |
| {
 | |
|     if (keyData == NULL)
 | |
| 	return NULL;
 | |
|     return (char *)getHash_iv(keyData, key, NULL);
 | |
| }
 | |
| 
 | |
| static int
 | |
| getKey2(char **str)
 | |
| {
 | |
|     char *s = *str;
 | |
|     int c, esc = 0, ctrl = 0;
 | |
| 
 | |
|     if (s == NULL || *s == '\0')
 | |
| 	return -1;
 | |
| 
 | |
|     if (strcasecmp(s, "UP") == 0) {	/* ^[[A */
 | |
| 	*str = s + 2;
 | |
| 	return K_ESCB | 'A';
 | |
|     }
 | |
|     else if (strcasecmp(s, "DOWN") == 0) {	/* ^[[B */
 | |
| 	*str = s + 4;
 | |
| 	return K_ESCB | 'B';
 | |
|     }
 | |
|     else if (strcasecmp(s, "RIGHT") == 0) {	/* ^[[C */
 | |
| 	*str = s + 5;
 | |
| 	return K_ESCB | 'C';
 | |
|     }
 | |
|     else if (strcasecmp(s, "LEFT") == 0) {	/* ^[[D */
 | |
| 	*str = s + 4;
 | |
| 	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 + 1)) {	/* ^, ^[^ */
 | |
| 	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 + 1)) {	/* ^[^, ^[[^ */
 | |
| 	    s++;
 | |
| 	    ctrl = 1;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (ctrl) {
 | |
| 	*str = s + 1;
 | |
| 	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++;
 | |
| 	}
 | |
| 	*str = s + 1;
 | |
| 	if (*s == '~')
 | |
| 	    return K_ESCD | c;
 | |
| 	else
 | |
| 	    return -1;
 | |
|     }
 | |
| 
 | |
|     if (strncasecmp(s, "SPC", 3) == 0) {	/* ' ' */
 | |
| 	*str = s + 3;
 | |
| 	return esc | ' ';
 | |
|     }
 | |
|     else if (strncasecmp(s, "TAB", 3) == 0) {	/* ^i */
 | |
| 	*str = s + 3;
 | |
| 	return esc | '\t';
 | |
|     }
 | |
|     else if (strncasecmp(s, "DEL", 3) == 0) {	/* ^? */
 | |
| 	*str = s + 3;
 | |
| 	return esc | DEL_CODE;
 | |
|     }
 | |
| 
 | |
|     if (*s == '\\' && *(s + 1) != '\0') {
 | |
| 	s++;
 | |
| 	*str = s + 1;
 | |
| 	switch (*s) {
 | |
| 	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;
 | |
| 	}
 | |
|     }
 | |
|     *str = s + 1;
 | |
|     if (IS_ASCII(*s))		/* Ascii */
 | |
| 	return esc | *s;
 | |
|     else
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| int
 | |
| getKey(char *s)
 | |
| {
 | |
|     int c, c2;
 | |
| 
 | |
|     c = getKey2(&s);
 | |
|     if (c < 0)
 | |
| 	return -1;
 | |
|     if (*s == ' ' || *s == '-')
 | |
| 	s++;
 | |
|     if (*s) {
 | |
| 	c2 = getKey2(&s);
 | |
| 	if (c2 < 0)
 | |
| 	    return -1;
 | |
| 	c = K_MULTI | (c << 16) | c2;
 | |
|     }
 | |
|     return c;
 | |
| }
 | |
| 
 | |
| char *
 | |
| getWord(char **str)
 | |
| {
 | |
|     char *p, *s;
 | |
| 
 | |
|     p = *str;
 | |
|     SKIP_BLANKS(p);
 | |
|     for (s = p; *p && !IS_SPACE(*p) && *p != ';'; p++) ;
 | |
|     *str = p;
 | |
|     return Strnew_charp_n(s, p - s)->ptr;
 | |
| }
 | |
| 
 | |
| char *
 | |
| getQWord(char **str)
 | |
| {
 | |
|     Str tmp = Strnew();
 | |
|     char *p;
 | |
|     int in_q = 0, in_dq = 0, esc = 0;
 | |
| 
 | |
|     p = *str;
 | |
|     SKIP_BLANKS(p);
 | |
|     for (; *p; p++) {
 | |
| 	if (esc) {
 | |
| 	    if (in_q) {
 | |
| 		if (*p != '\\' && *p != '\'')	/* '..\\..', '..\'..' */
 | |
| 		    Strcat_char(tmp, '\\');
 | |
| 	    }
 | |
| 	    else if (in_dq) {
 | |
| 		if (*p != '\\' && *p != '"')	/* "..\\..", "..\".." */
 | |
| 		    Strcat_char(tmp, '\\');
 | |
| 	    }
 | |
| 	    else {
 | |
| 		if (*p != '\\' && *p != '\'' &&	/* ..\\.., ..\'.. */
 | |
| 		    *p != '"' && !IS_SPACE(*p))	/* ..\".., ..\.. */
 | |
| 		    Strcat_char(tmp, '\\');
 | |
| 	    }
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	    esc = 0;
 | |
| 	}
 | |
| 	else if (*p == '\\') {
 | |
| 	    esc = 1;
 | |
| 	}
 | |
| 	else if (in_q) {
 | |
| 	    if (*p == '\'')
 | |
| 		in_q = 0;
 | |
| 	    else
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
| 	else if (in_dq) {
 | |
| 	    if (*p == '"')
 | |
| 		in_dq = 0;
 | |
| 	    else
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
| 	else if (*p == '\'') {
 | |
| 	    in_q = 1;
 | |
| 	}
 | |
| 	else if (*p == '"') {
 | |
| 	    in_dq = 1;
 | |
| 	}
 | |
| 	else if (IS_SPACE(*p) || *p == ';') {
 | |
| 	    break;
 | |
| 	}
 | |
| 	else {
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     *str = p;
 | |
|     return tmp->ptr;
 | |
| }
 | |
| 
 | |
| /* This extracts /regex/i or m@regex@i from the given string.
 | |
|  * Then advances *str to the end of regex.
 | |
|  * If the input does not seems to be a regex, this falls back to getQWord().
 | |
|  * 
 | |
|  * Returns a word (no matter whether regex or not) in the give string.
 | |
|  * If regex_ret is non-NULL, compiles the regex and stores there.
 | |
|  *
 | |
|  * XXX: Actually this is unrelated to func.c.
 | |
|  */
 | |
| char *
 | |
| getRegexWord(const char **str, Regex **regex_ret)
 | |
| {
 | |
|     char *word = NULL;
 | |
|     const char *p, *headp, *bodyp, *tailp;
 | |
|     char delimiter;
 | |
|     int esc;
 | |
|     int igncase = 0;
 | |
| 
 | |
|     p = *str;
 | |
|     SKIP_BLANKS(p);
 | |
|     headp = p;
 | |
| 
 | |
|     /* Get the opening delimiter */
 | |
|     if (p[0] == 'm' && IS_PRINT(p[1]) && !IS_ALNUM(p[1]) && p[1] != '\\') {
 | |
| 	delimiter = p[1];
 | |
| 	p += 2;
 | |
|     }
 | |
|     else if (p[0] == '/') {
 | |
| 	delimiter = '/';
 | |
| 	p += 1;
 | |
|     }
 | |
|     else {
 | |
| 	goto not_regex;
 | |
|     }
 | |
|     bodyp = p;
 | |
| 
 | |
|     /* Scan the end of the expression */
 | |
|     for (esc = 0; *p; ++p) {
 | |
| 	if (esc) {
 | |
| 	    esc = 0;
 | |
| 	} else {
 | |
| 	    if (*p == delimiter)
 | |
| 		break;
 | |
| 	    else if (*p == '\\')
 | |
| 		esc = 1;
 | |
| 	}
 | |
|     }
 | |
|     if (!*p && *headp == '/')
 | |
| 	goto not_regex;
 | |
|     tailp = p;
 | |
| 
 | |
|     /* Check the modifiers */
 | |
|     if (*p == delimiter) {
 | |
| 	while (*++p && !IS_SPACE(*p)) {
 | |
| 	    switch (*p) {
 | |
| 	    case 'i':
 | |
| 		igncase = 1;
 | |
| 		break;
 | |
| 	    }
 | |
| 	    /* ignore unknown modifiers */
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     /* Save the expression */
 | |
|     word = allocStr(headp, p - headp);
 | |
| 
 | |
|     /* Compile */
 | |
|     if (regex_ret) {
 | |
| 	if (*tailp == delimiter)
 | |
| 	    word[tailp - headp] = 0;
 | |
| 	*regex_ret = newRegex(word + (bodyp - headp), igncase, NULL, NULL);
 | |
| 	if (*tailp == delimiter)
 | |
| 	    word[tailp - headp] = delimiter;
 | |
|     }
 | |
|     goto last;
 | |
| 
 | |
| not_regex:
 | |
|     p = headp;
 | |
|     word = getQWord((char **)&p);
 | |
|     if (regex_ret)
 | |
| 	*regex_ret = NULL;
 | |
| 
 | |
| last:
 | |
|     *str = p;
 | |
|     return word;
 | |
| }
 | |
| 
 | |
| #ifdef USE_MOUSE
 | |
| static MouseAction default_mouse_action = {
 | |
|     NULL,
 | |
|     "<=UpDn",
 | |
|     0, 6, FALSE, 0, 0,
 | |
|     {{movMs, NULL}, {backBf, NULL}, {menuMs, NULL}},	/* default */
 | |
|     {{NULL, NULL}, {NULL, NULL}, {NULL, NULL}},	/* anchor */
 | |
|     {{followA, NULL}, {NULL, NULL}, {NULL, NULL}},	/* active */
 | |
|     {{tabMs, NULL}, {closeTMs, NULL}, {NULL, NULL}},	/* tab */
 | |
|     {NULL, NULL, NULL},		/* menu */
 | |
|     {NULL, NULL, NULL}		/* lastline */
 | |
| };
 | |
| static MouseActionMap default_lastline_action[6] = {
 | |
|     {backBf, NULL},
 | |
|     {backBf, NULL},
 | |
|     {pgBack, NULL},
 | |
|     {pgBack, NULL},
 | |
|     {pgFore, NULL},
 | |
|     {pgFore, NULL}
 | |
| };
 | |
| 
 | |
| static void
 | |
| setMouseAction0(char **str, int *width, MouseActionMap ** map, char *p)
 | |
| {
 | |
|     char *s;
 | |
|     int b, w, x;
 | |
| 
 | |
|     s = getQWord(&p);
 | |
|     if (!*s) {
 | |
| 	*str = NULL;
 | |
| 	width = 0;
 | |
| 	for (b = 0; b < 3; b++)
 | |
| 	    map[b] = NULL;
 | |
| 	return;
 | |
|     }
 | |
|     w = *width;
 | |
|     *str = s;
 | |
|     *width = get_strwidth(s);
 | |
|     if (*width >= LIMIT_MOUSE_MENU)
 | |
| 	*width = LIMIT_MOUSE_MENU;
 | |
|     if (*width <= w)
 | |
| 	return;
 | |
|     for (b = 0; b < 3; b++) {
 | |
| 	if (!map[b])
 | |
| 	    continue;
 | |
| 	map[b] = New_Reuse(MouseActionMap, map[b], *width);
 | |
| 	for (x = w + 1; x < *width; x++) {
 | |
| 	    map[b][x].func = NULL;
 | |
| 	    map[b][x].data = NULL;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| setMouseAction1(MouseActionMap ** map, int width, char *p)
 | |
| {
 | |
|     char *s;
 | |
|     int x, x2, f;
 | |
| 
 | |
|     if (!*map) {
 | |
| 	*map = New_N(MouseActionMap, width);
 | |
| 	for (x = 0; x < width; x++) {
 | |
| 	    (*map)[x].func = NULL;
 | |
| 	    (*map)[x].data = NULL;
 | |
| 	}
 | |
|     }
 | |
|     s = getWord(&p);
 | |
|     x = atoi(s);
 | |
|     if (!(IS_DIGIT(*s) && x >= 0 && x < width))
 | |
| 	return;			/* error */
 | |
|     s = getWord(&p);
 | |
|     x2 = atoi(s);
 | |
|     if (!(IS_DIGIT(*s) && x2 >= 0 && x2 < width))
 | |
| 	return;			/* error */
 | |
|     s = getWord(&p);
 | |
|     f = getFuncList(s);
 | |
|     s = getQWord(&p);
 | |
|     if (!*s)
 | |
| 	s = NULL;
 | |
|     for (; x <= x2; x++) {
 | |
| 	(*map)[x].func = (f >= 0) ? w3mFuncList[f].func : NULL;
 | |
| 	(*map)[x].data = s;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| setMouseAction2(MouseActionMap * map, char *p)
 | |
| {
 | |
|     char *s;
 | |
|     int f;
 | |
| 
 | |
|     s = getWord(&p);
 | |
|     f = getFuncList(s);
 | |
|     s = getQWord(&p);
 | |
|     if (!*s)
 | |
| 	s = NULL;
 | |
|     map->func = (f >= 0) ? w3mFuncList[f].func : NULL;
 | |
|     map->data = s;
 | |
| }
 | |
| 
 | |
| static void
 | |
| interpret_mouse_action(FILE * mf)
 | |
| {
 | |
|     Str line;
 | |
|     char *p, *s;
 | |
|     int b;
 | |
| 
 | |
|     while (!feof(mf)) {
 | |
| 	line = Strfgets(mf);
 | |
| 	Strchop(line);
 | |
| 	Strremovefirstspaces(line);
 | |
| 	if (line->length == 0)
 | |
| 	    continue;
 | |
| 	p = conv_from_system(line->ptr);
 | |
| 	s = getWord(&p);
 | |
| 	if (*s == '#')		/* comment */
 | |
| 	    continue;
 | |
| 	if (!strcmp(s, "menu")) {
 | |
| 	    setMouseAction0(&mouse_action.menu_str, &mouse_action.menu_width,
 | |
| 			    mouse_action.menu_map, p);
 | |
| 	    continue;
 | |
| 	}
 | |
| 	else if (!strcmp(s, "lastline")) {
 | |
| 	    setMouseAction0(&mouse_action.lastline_str,
 | |
| 			    &mouse_action.lastline_width,
 | |
| 			    mouse_action.lastline_map, p);
 | |
| 	    continue;
 | |
| 	}
 | |
| 	if (strcmp(s, "button"))
 | |
| 	    continue;		/* error */
 | |
| 	s = getWord(&p);
 | |
| 	b = atoi(s) - 1;
 | |
| 	if (!(b >= 0 && b <= 2))
 | |
| 	    continue;		/* error */
 | |
| 	SKIP_BLANKS(p);
 | |
| 	if (IS_DIGIT(*p))
 | |
| 	    s = "menu";
 | |
| 	else
 | |
| 	    s = getWord(&p);
 | |
| 	if (!strcasecmp(s, "menu")) {
 | |
| 	    if (!mouse_action.menu_str)
 | |
| 		continue;
 | |
| 	    setMouseAction1(&mouse_action.menu_map[b], mouse_action.menu_width,
 | |
| 			    p);
 | |
| 	}
 | |
| 	else if (!strcasecmp(s, "lastline")) {
 | |
| 	    if (!mouse_action.lastline_str)
 | |
| 		continue;
 | |
| 	    setMouseAction1(&mouse_action.lastline_map[b],
 | |
| 			    mouse_action.lastline_width, p);
 | |
| 	}
 | |
| 	else if (!strcasecmp(s, "default"))
 | |
| 	    setMouseAction2(&mouse_action.default_map[b], p);
 | |
| 	else if (!strcasecmp(s, "anchor"))
 | |
| 	    setMouseAction2(&mouse_action.anchor_map[b], p);
 | |
| 	else if (!strcasecmp(s, "active"))
 | |
| 	    setMouseAction2(&mouse_action.active_map[b], p);
 | |
| 	else if (!strcasecmp(s, "tab"))
 | |
| 	    setMouseAction2(&mouse_action.tab_map[b], p);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| initMouseAction(void)
 | |
| {
 | |
|     FILE *mf;
 | |
| 
 | |
|     bcopy((void *)&default_mouse_action, (void *)&mouse_action,
 | |
| 	  sizeof(default_mouse_action));
 | |
|     mouse_action.lastline_map[0] = New_N(MouseActionMap, 6);
 | |
|     bcopy((void *)&default_lastline_action,
 | |
| 	  (void *)mouse_action.lastline_map[0],
 | |
| 	  sizeof(default_lastline_action));
 | |
|     {
 | |
| #ifdef USE_M17N
 | |
| 	int w = 0;
 | |
| 	char **symbol = get_symbol(DisplayCharset, &w);
 | |
| #else
 | |
| 	char **symbol = get_symbol();
 | |
| #endif
 | |
| 	mouse_action.lastline_str =
 | |
| 	    Strnew_charp(symbol[N_GRAPH_SYMBOL + 13])->ptr;
 | |
|     }
 | |
| 
 | |
|     if ((mf = fopen(confFile(MOUSE_FILE), "rt")) != NULL) {
 | |
| 	interpret_mouse_action(mf);
 | |
| 	fclose(mf);
 | |
|     }
 | |
|     if ((mf = fopen(rcFile(MOUSE_FILE), "rt")) != NULL) {
 | |
| 	interpret_mouse_action(mf);
 | |
| 	fclose(mf);
 | |
|     }
 | |
| }
 | |
| #endif
 |