119304Speter/*-
219304Speter * Copyright (c) 1992, 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
819304Speter */
919304Speter
1019304Speter#include "config.h"
1119304Speter
1219304Speter#ifndef lint
13254225Speterstatic const char sccsid[] = "$Id: ex_map.c,v 10.11 2001/06/25 15:19:17 skimo Exp $";
1419304Speter#endif /* not lint */
1519304Speter
1619304Speter#include <sys/types.h>
1719304Speter#include <sys/queue.h>
18254225Speter#include <sys/time.h>
1919304Speter
2019304Speter#include <bitstring.h>
2119304Speter#include <ctype.h>
2219304Speter#include <limits.h>
2319304Speter#include <stdio.h>
2419304Speter#include <stdlib.h>
2519304Speter#include <string.h>
2619304Speter
2719304Speter#include "../common/common.h"
2819304Speter
2919304Speter/*
3019304Speter * ex_map -- :map[!] [input] [replacement]
3119304Speter *	Map a key/string or display mapped keys.
3219304Speter *
3319304Speter * Historical note:
3419304Speter *	Historic vi maps were fairly bizarre, and likely to differ in
3519304Speter *	very subtle and strange ways from this implementation.  Two
3619304Speter *	things worth noting are that vi would often hang or drop core
3719304Speter *	if the map was strange enough (ex: map X "xy$@x^V), or, simply
3819304Speter *	not work.  One trick worth remembering is that if you put a
3919304Speter *	mark at the start of the map, e.g. map X mx"xy ...), or if you
4019304Speter *	put the map in a .exrc file, things would often work much better.
4119304Speter *	No clue why.
4219304Speter *
4319304Speter * PUBLIC: int ex_map __P((SCR *, EXCMD *));
4419304Speter */
4519304Speterint
46254225Speterex_map(SCR *sp, EXCMD *cmdp)
4719304Speter{
4819304Speter	seq_t stype;
4919304Speter	CHAR_T *input, *p;
5019304Speter
5119304Speter	stype = FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND;
5219304Speter
5319304Speter	switch (cmdp->argc) {
5419304Speter	case 0:
5519304Speter		if (seq_dump(sp, stype, 1) == 0)
5619304Speter			msgq(sp, M_INFO, stype == SEQ_INPUT ?
5719304Speter			    "132|No input map entries" :
5819304Speter			    "133|No command map entries");
5919304Speter		return (0);
6019304Speter	case 2:
6119304Speter		input = cmdp->argv[0]->bp;
6219304Speter		break;
6319304Speter	default:
6419304Speter		abort();
6519304Speter	}
6619304Speter
6719304Speter	/*
6819304Speter	 * If the mapped string is #[0-9]* (and wasn't quoted) then store the
6919304Speter	 * function key mapping.  If the screen specific routine has been set,
7019304Speter	 * call it as well.  Note, the SEQ_FUNCMAP type is persistent across
7119304Speter	 * screen types, maybe the next screen type will get it right.
7219304Speter	 */
7319304Speter	if (input[0] == '#' && isdigit(input[1])) {
7419304Speter		for (p = input + 2; isdigit(*p); ++p);
7519304Speter		if (p[0] != '\0')
7619304Speter			goto nofunc;
7719304Speter
7819304Speter		if (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
7919304Speter		    cmdp->argv[1]->bp, cmdp->argv[1]->len, stype,
8019304Speter		    SEQ_FUNCMAP | SEQ_USERDEF))
8119304Speter			return (1);
8219304Speter		return (sp->gp->scr_fmap == NULL ? 0 :
8319304Speter		    sp->gp->scr_fmap(sp, stype, input, cmdp->argv[0]->len,
8419304Speter		    cmdp->argv[1]->bp, cmdp->argv[1]->len));
8519304Speter	}
8619304Speter
8719304Speter	/* Some single keys may not be remapped in command mode. */
8819304Speternofunc:	if (stype == SEQ_COMMAND && input[1] == '\0')
8919304Speter		switch (KEY_VAL(sp, input[0])) {
9019304Speter		case K_COLON:
9119304Speter		case K_ESCAPE:
9219304Speter		case K_NL:
9319304Speter			msgq(sp, M_ERR,
9419304Speter			    "134|The %s character may not be remapped",
9519304Speter			    KEY_NAME(sp, input[0]));
9619304Speter			return (1);
9719304Speter		}
9819304Speter	return (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
9919304Speter	    cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_USERDEF));
10019304Speter}
10119304Speter
10219304Speter/*
10319304Speter * ex_unmap -- (:unmap[!] key)
10419304Speter *	Unmap a key.
10519304Speter *
10619304Speter * PUBLIC: int ex_unmap __P((SCR *, EXCMD *));
10719304Speter */
10819304Speterint
109254225Speterex_unmap(SCR *sp, EXCMD *cmdp)
11019304Speter{
11119304Speter	if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
11219304Speter	    FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) {
113254225Speter		msgq_wstr(sp, M_INFO,
11419304Speter		    cmdp->argv[0]->bp, "135|\"%s\" isn't currently mapped");
11519304Speter		return (1);
11619304Speter	}
11719304Speter	return (0);
11819304Speter}
119