Example #1
0
/*
 * Compare two characters.  The "bc" comes from the buffer.  It has its case
 * folded out. The "pc" is from the pattern.
 */
static int
eq(int bc, int pc, int xcase)
{
	bc = CHARMASK(bc);
	pc = CHARMASK(pc);
	if (bc == pc)
		return (TRUE);
	if (xcase)
		return (FALSE);
	if (ISUPPER(bc))
		return (TOLOWER(bc) == pc);
	if (ISUPPER(pc))
		return (bc == TOLOWER(pc));
	return (FALSE);
}
Example #2
0
File: yank.c Project: sctb/em
/*
 * This function gets characters from the kill buffer. If the character
 * index "n" is off the end, it returns "-1". This lets the caller just
 * scan along until it gets a "-1" back.
 */
int
kremove(int n)
{
	if (n < 0 || n + kstart >= kused)
		return (-1);
	return (CHARMASK(kbufp[n + kstart]));
}
Example #3
0
File: extend.c Project: mbkulik/mg
/*
 * Do the input for local-set-key, global-set-key  and define-key
 * then call remap to do the work.
 */
static int
dobind(KEYMAP *curmap, const char *p, int unbind)
{
	KEYMAP	*pref_map = NULL;
	PF	 funct;
	char	 bprompt[80], *bufp, *pep;
	int	 c, s, n;

	if (macrodef) {
		/*
		 * Keystrokes aren't collected. Not hard, but pretty useless.
		 * Would not work for function keys in any case.
		 */
		ewprintf("Can't rebind key in macro");
		return (FALSE);
	}
	if (inmacro) {
		for (s = 0; s < maclcur->l_used - 1; s++) {
			if (doscan(curmap, c = CHARMASK(maclcur->l_text[s]), &curmap)
			    != NULL) {
				if (remap(curmap, c, NULL, NULL)
				    != TRUE)
					return (FALSE);
			}
		}
		(void)doscan(curmap, c = maclcur->l_text[s], NULL);
		maclcur = maclcur->l_fp;
	} else {
		n = strlcpy(bprompt, p, sizeof(bprompt));
		if (n >= sizeof(bprompt))
			n = sizeof(bprompt) - 1;
		pep = bprompt + n;
		for (;;) {
			ewprintf("%s", bprompt);
			pep[-1] = ' ';
			pep = getkeyname(pep, sizeof(bprompt) -
			    (pep - bprompt), c = getkey(FALSE));
			if (doscan(curmap, c, &curmap) != NULL)
				break;
			*pep++ = '-';
			*pep = '\0';
		}
	}
	if (unbind)
		funct = rescan;
	else {
		if ((bufp = eread("%s to command: ", bprompt, sizeof(bprompt),
		    EFFUNC | EFNEW, bprompt)) == NULL)
			return (ABORT);
		else if (bufp[0] == '\0')
			return (FALSE);
		if (((funct = name_function(bprompt)) == NULL) ?
		    (pref_map = name_map(bprompt)) == NULL : funct == NULL) {
			ewprintf("[No match]");
			return (FALSE);
		}
	}
	return (remap(curmap, c, funct, pref_map));
}
Example #4
0
File: search.c Project: sctb/em
/*
 * This routine does the real work of a backward search.  The pattern is
 * sitting in the external variable "pat".  If found, dot is updated, the
 * window system is notified of the change, and TRUE is returned.  If the
 * string isn't found, FALSE is returned.
 */
int
backsrch(void)
{
	struct line	*clp, *tlp;
	int	 cbo, tbo, c, i, xcase = 0;
	char	*epp, *pp;
	int	 nline, pline;

	for (epp = &pat[0]; epp[1] != 0; ++epp);
	clp = curwp->w_dotp;
	cbo = curwp->w_doto;
	nline = curwp->w_dotline;
	for (i = 0; pat[i]; i++)
		if (ISUPPER(CHARMASK(pat[i])))
			xcase = 1;
	for (;;) {
		if (cbo == 0) {
			clp = lback(clp);
			if (clp == curbp->b_headp)
				return (FALSE);
			nline--;
			cbo = llength(clp) + 1;
		}
		if (--cbo == llength(clp))
			c = CCHR('J');
		else
			c = lgetc(clp, cbo);
		if (eq(c, *epp, xcase) != FALSE) {
			tlp = clp;
			tbo = cbo;
			pp = epp;
			pline = nline;
			while (pp != &pat[0]) {
				if (tbo == 0) {
					tlp = lback(tlp);
					if (tlp == curbp->b_headp)
						goto fail;
					nline--;
					tbo = llength(tlp) + 1;
				}
				if (--tbo == llength(tlp))
					c = CCHR('J');
				else
					c = lgetc(tlp, tbo);
				if (eq(c, *--pp, xcase) == FALSE) {
					nline = pline;
					goto fail;
				}
			}
			curwp->w_dotp = tlp;
			curwp->w_doto = tbo;
			curwp->w_dotline = nline;
			curwp->w_rflag |= WFMOVE;
			return (TRUE);
		}
fail:		;
	}
	/* NOTREACHED */
}
Example #5
0
/*
 * This routine does the real work of a forward search.  The pattern is sitting
 * in the external variable "pat".  If found, dot is updated, the window system
 * is notified of the change, and TRUE is returned.  If the string isn't found,
 * FALSE is returned.
 */
int
forwsrch(void)
{
	struct line	*clp, *tlp;
	int	 cbo, tbo, c, i, xcase = 0;
	char	*pp;
	int	 nline;

	clp = curwp->w_dotp;
	cbo = curwp->w_doto;
	nline = curwp->w_dotline;
	for (i = 0; pat[i]; i++)
		if (ISUPPER(CHARMASK(pat[i])))
			xcase = 1;
	for (;;) {
		if (cbo == llength(clp)) {
			if ((clp = lforw(clp)) == curbp->b_headp)
				break;
			nline++;
			cbo = 0;
			c = CCHR('J');
		} else
			c = lgetc(clp, cbo++);
		if (eq(c, pat[0], xcase) != FALSE) {
			tlp = clp;
			tbo = cbo;
			pp = &pat[1];
			while (*pp != 0) {
				if (tbo == llength(tlp)) {
					tlp = lforw(tlp);
					if (tlp == curbp->b_headp)
						goto fail;
					tbo = 0;
					c = CCHR('J');
					if (eq(c, *pp++, xcase) == FALSE)
						goto fail;
					nline++;
				} else {
					c = lgetc(tlp, tbo++);
					if (eq(c, *pp++, xcase) == FALSE)
						goto fail;
				}
			}
			curwp->w_dotp = tlp;
			curwp->w_doto = tbo;
			curwp->w_dotline = nline;
			curwp->w_rflag |= WFMOVE;
			return (TRUE);
		}
fail:		;
	}
	return (FALSE);
}
Example #6
0
/*
 * Find the name of a keystroke.  Needs to be changed to handle 8-bit printing
 * characters and function keys better.	 Returns a pointer to the terminating
 * '\0'.  Returns NULL on failure.
 */
char *
getkeyname(char *cp, size_t len, int k)
{
	const char	*np;
	size_t		 copied;

	if (k < 0)
		k = CHARMASK(k);	/* sign extended char */
	switch (k) {
	case CCHR('@'):
		np = "C-SPC";
		break;
	case CCHR('I'):
		np = "TAB";
		break;
	case CCHR('M'):
		np = "RET";
		break;
	case CCHR('['):
		np = "ESC";
		break;
	case ' ':
		np = "SPC";
		break;		/* yuck again */
	case CCHR('?'):
		np = "DEL";
		break;
	default:
#ifdef	FKEYS
#ifndef MONA
		if (k >= KFIRST && k <= KLAST &&
		    (np = keystrings[k - KFIRST]) != NULL)
			break;
#endif
#endif
		if (k > CCHR('?')) {
			*cp++ = '0';
			*cp++ = ((k >> 6) & 7) + '0';
			*cp++ = ((k >> 3) & 7) + '0';
			*cp++ = (k & 7) + '0';
			*cp = '\0';
			return (cp);
		} else if (k < ' ') {
Example #7
0
File: extend.c Project: mbkulik/mg
/*
 * excline - run a line from a load file or eval-expression.  If FKEYS is
 * defined, duplicate functionality of dobind so function key values don't
 * have to fit in type char.
 */
int
excline(char *line)
{
	PF	 fp;
	struct line	*lp, *np;
	int	 status, c, f, n;
	char	*funcp, *tmp;
	char	*argp = NULL;
	long	 nl;
#ifdef	FKEYS
	int	 bind;
	KEYMAP	*curmap;
#define BINDARG		0  /* this arg is key to bind (local/global set key) */
#define	BINDNO		1  /* not binding or non-quoted BINDARG */
#define BINDNEXT	2  /* next arg " (define-key) */
#define BINDDO		3  /* already found key to bind */
#define BINDEXT		1  /* space for trailing \0 */
#else /* FKEYS */
#define BINDEXT		0
#endif /* FKEYS */

	lp = NULL;

	if (macrodef || inmacro) {
		ewprintf("Not now!");
		return (FALSE);
	}
	f = 0;
	n = 1;
	funcp = skipwhite(line);
	if (*funcp == '\0')
		return (TRUE);	/* No error on blank lines */
	line = parsetoken(funcp);
	if (*line != '\0') {
		*line++ = '\0';
		line = skipwhite(line);
		if (ISDIGIT(*line) || *line == '-') {
			argp = line;
			line = parsetoken(line);
		}
	}
	if (argp != NULL) {
		f = FFARG;
		nl = strtol(argp, &tmp, 10);
		if (*tmp != '\0')
			return (FALSE);
		if (nl >= INT_MAX || nl <= INT_MIN)
			return (FALSE);
		n = (int)nl;
	}
	if ((fp = name_function(funcp)) == NULL) {
		ewprintf("Unknown function: %s", funcp);
		return (FALSE);
	}
#ifdef	FKEYS
	if (fp == bindtokey || fp == unbindtokey) {
		bind = BINDARG;
		curmap = fundamental_map;
	} else if (fp == localbind || fp == localunbind) {
		bind = BINDARG;
		curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
	} else if (fp == redefine_key)
		bind = BINDNEXT;
	else
		bind = BINDNO;
#endif /* FKEYS */
	/* Pack away all the args now... */
	if ((np = lalloc(0)) == FALSE)
		return (FALSE);
	np->l_fp = np->l_bp = maclcur = np;
	while (*line != '\0') {
		argp = skipwhite(line);
		if (*argp == '\0')
			break;
		line = parsetoken(argp);
		if (*argp != '"') {
			if (*argp == '\'')
				++argp;
			if ((lp = lalloc((int) (line - argp) + BINDEXT)) ==
			    NULL) {
				status = FALSE;
				goto cleanup;
			}
			bcopy(argp, ltext(lp), (int)(line - argp));
#ifdef	FKEYS
			/* don't count BINDEXT */
			lp->l_used--;
			if (bind == BINDARG)
				bind = BINDNO;
#endif /* FKEYS */
		} else {
			/* quoted strings are special */
			++argp;
#ifdef	FKEYS
			if (bind != BINDARG) {
#endif /* FKEYS */
				lp = lalloc((int)(line - argp) + BINDEXT);
				if (lp == NULL) {
					status = FALSE;
					goto cleanup;
				}
				lp->l_used = 0;
#ifdef	FKEYS
			} else
				key.k_count = 0;
#endif /* FKEYS */
			while (*argp != '"' && *argp != '\0') {
				if (*argp != '\\')
					c = *argp++;
				else {
					switch (*++argp) {
					case 't':
					case 'T':
						c = CCHR('I');
						break;
					case 'n':
					case 'N':
						c = CCHR('J');
						break;
					case 'r':
					case 'R':
						c = CCHR('M');
						break;
					case 'e':
					case 'E':
						c = CCHR('[');
						break;
					case '^':
						/*
						 * split into two statements
						 * due to bug in OSK cpp
						 */
						c = CHARMASK(*++argp);
						c = ISLOWER(c) ?
						    CCHR(TOUPPER(c)) : CCHR(c);
						break;
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
						c = *argp - '0';
						if (argp[1] <= '7' &&
						    argp[1] >= '0') {
							c <<= 3;
							c += *++argp - '0';
							if (argp[1] <= '7' &&
							    argp[1] >= '0') {
								c <<= 3;
								c += *++argp
								    - '0';
							}
						}
						break;
#ifdef	FKEYS
					case 'f':
					case 'F':
						c = *++argp - '0';
						if (ISDIGIT(argp[1])) {
							c *= 10;
							c += *++argp - '0';
						}
						c += KFIRST;
						break;
#endif /* FKEYS */
					default:
						c = CHARMASK(*argp);
						break;
					}
					argp++;
				}
#ifdef	FKEYS
				if (bind == BINDARG)
					key.k_chars[key.k_count++] = c;
				else
#endif /* FKEYS */
					lp->l_text[lp->l_used++] = c;
			}
			if (*line)
				line++;
		}
#ifdef	FKEYS
		switch (bind) {
		case BINDARG:
			bind = BINDDO;
			break;
		case BINDNEXT:
			lp->l_text[lp->l_used] = '\0';
			if ((curmap = name_map(lp->l_text)) == NULL) {
				ewprintf("No such mode: %s", lp->l_text);
				status = FALSE;
				free(lp);
				goto cleanup;
			}
			free(lp);
			bind = BINDARG;
			break;
		default:
#endif /* FKEYS */
			lp->l_fp = np->l_fp;
			lp->l_bp = np;
			np->l_fp = lp;
			np = lp;
#ifdef	FKEYS
		}
#endif /* FKEYS */
	}
#ifdef	FKEYS
	switch (bind) {
	default:
		ewprintf("Bad args to set key");
		status = FALSE;
		break;
	case BINDDO:
		if (fp != unbindtokey && fp != localunbind) {
			lp->l_text[lp->l_used] = '\0';
			status = bindkey(&curmap, lp->l_text, key.k_chars,
			    key.k_count);
		} else
			status = bindkey(&curmap, NULL, key.k_chars,
			    key.k_count);
		break;
	case BINDNO:
#endif /* FKEYS */
		inmacro = TRUE;
		maclcur = maclcur->l_fp;
		status = (*fp)(f, n);
		inmacro = FALSE;
#ifdef	FKEYS
	}
#endif /* FKEYS */
cleanup:
	lp = maclcur->l_fp;
	while (lp != maclcur) {
		np = lp->l_fp;
		free(lp);
		lp = np;
	}
	free(lp);
	return (status);
}
Example #8
0
/*
 * Incremental Search.
 *	dir is used as the initial direction to search.
 *	^S	switch direction to forward
 *	^R	switch direction to reverse
 *	^Q	quote next character (allows searching for ^N etc.)
 *	<ESC>	exit from Isearch
 *	<DEL>	undoes last character typed. (tricky job to do this correctly).
 *	other ^ exit search, don't set mark
 *	else	accumulate into search string
 */
static int
isearch(int dir)
{
	struct line	*clp;		/* Saved line pointer */
	int		 c;
	int		 cbo;		/* Saved offset */
	int		 success;
	int		 pptr;
	int		 firstc;
	int		 xcase;
	int		 i;
	char		 opat[NPAT];
	int		 cdotline;	/* Saved line number */

#ifndef NO_MACRO
	if (macrodef) {
		ewprintf("Can't isearch in macro");
		return (FALSE);
	}
#endif /* !NO_MACRO */
	for (cip = 0; cip < NSRCH; cip++)
		cmds[cip].s_code = SRCH_NOPR;

	(void)strlcpy(opat, pat, sizeof(opat));
	cip = 0;
	pptr = -1;
	clp = curwp->w_dotp;
	cbo = curwp->w_doto;
	cdotline = curwp->w_dotline;
	is_lpush();
	is_cpush(SRCH_BEGIN);
	success = TRUE;
	is_prompt(dir, TRUE, success);

	for (;;) {
		update();

		switch (c = getkey(FALSE)) {
		case CCHR('['):
			/*
			 * If new characters come in the next 300 msec,
			 * we can assume that they belong to a longer
			 * escaped sequence so we should ungetkey the
			 * ESC to avoid writing out garbage.
			 */
			if (ttwait(300) == FALSE)
				ungetkey(c);
			srch_lastdir = dir;
			curwp->w_markp = clp;
			curwp->w_marko = cbo;
			curwp->w_markline = cdotline;
			ewprintf("Mark set");
			return (TRUE);
		case CCHR('G'):
			if (success != TRUE) {
				while (is_peek() == SRCH_ACCM)
					is_undo(&pptr, &dir);
				success = TRUE;
				is_prompt(dir, pptr < 0, success);
				break;
			}
			curwp->w_dotp = clp;
			curwp->w_doto = cbo;
			curwp->w_dotline = cdotline;
			curwp->w_rflag |= WFMOVE;
			srch_lastdir = dir;
			(void)ctrlg(FFRAND, 0);
			(void)strlcpy(pat, opat, sizeof(pat));
			return (ABORT);
		case CCHR('S'):
			if (dir == SRCH_BACK) {
				dir = SRCH_FORW;
				is_lpush();
				is_cpush(SRCH_FORW);
				success = TRUE;
			}
			if (success == FALSE && dir == SRCH_FORW) {
				/* wrap the search to beginning */
				curwp->w_dotp = bfirstlp(curbp);
				curwp->w_doto = 0;
				curwp->w_dotline = 1;
				if (is_find(dir) != FALSE) {
					is_cpush(SRCH_MARK);
					success = TRUE;
				}
				ewprintf("Overwrapped I-search: %s", pat);
				break;
			}

			is_lpush();
			pptr = strlen(pat);
			(void)forwchar(FFRAND, 1);
			if (is_find(SRCH_FORW) != FALSE)
				is_cpush(SRCH_MARK);
			else {
				(void)backchar(FFRAND, 1);
				ttbeep();
				success = FALSE;
				ewprintf("Failed I-search: %s", pat);
			}
			is_prompt(dir, pptr < 0, success);
			break;
		case CCHR('R'):
			if (dir == SRCH_FORW) {
				dir = SRCH_BACK;
				is_lpush();
				is_cpush(SRCH_BACK);
				success = TRUE;
			}
			if (success == FALSE && dir == SRCH_BACK) {
				/* wrap the search to end */
				curwp->w_dotp = blastlp(curbp);
				curwp->w_doto = llength(curwp->w_dotp);
				curwp->w_dotline = curwp->w_bufp->b_lines;
				if (is_find(dir) != FALSE) {
					is_cpush(SRCH_MARK);
					success = TRUE;
				}
				ewprintf("Overwrapped I-search: %s", pat);
				break;
			}
			is_lpush();
			pptr = strlen(pat);
			(void)backchar(FFRAND, 1);
			if (is_find(SRCH_BACK) != FALSE)
				is_cpush(SRCH_MARK);
			else {
				(void)forwchar(FFRAND, 1);
				ttbeep();
				success = FALSE;
			}
			is_prompt(dir, pptr < 0, success);
			break;
		case CCHR('W'):
			/* add the rest of the current word to the pattern */
			clp = curwp->w_dotp;
			cbo = curwp->w_doto;
			firstc = 1;
			if (pptr == -1)
				pptr = 0;
			if (dir == SRCH_BACK) {
				/* when isearching backwards, cbo is the start of the pattern */
				cbo += pptr;
			}

			/* if the search is case insensitive, add to pattern using lowercase */
			xcase = 0;
			for (i = 0; pat[i]; i++)
				if (ISUPPER(CHARMASK(pat[i])))
					xcase = 1;

			while (cbo < llength(clp)) {
				c = lgetc(clp, cbo++);
				if ((!firstc && !isalnum(c)))
					break;

				if (pptr == NPAT - 1) {
					ttbeep();
					break;
				}
				firstc = 0;
				if (!xcase && ISUPPER(c))
					c = TOLOWER(c);

				pat[pptr++] = c;
				pat[pptr] = '\0';
				/* cursor only moves when isearching forwards */
				if (dir == SRCH_FORW) {
					curwp->w_doto = cbo;
					curwp->w_rflag |= WFMOVE;
					update();
				}
			}
			is_prompt(dir, pptr < 0, success);
			break;
		case CCHR('H'):
		case CCHR('?'):
			is_undo(&pptr, &dir);
			if (is_peek() != SRCH_ACCM)
				success = TRUE;
			is_prompt(dir, pptr < 0, success);
			break;
		case CCHR('\\'):
		case CCHR('Q'):
			c = (char)getkey(FALSE);
			goto addchar;
		case CCHR('M'):
			c = CCHR('J');
			goto addchar;
		default:
			if (ISCTRL(c)) {
				ungetkey(c);
				curwp->w_markp = clp;
				curwp->w_marko = cbo;
				curwp->w_markline = cdotline;
				ewprintf("Mark set");
				curwp->w_rflag |= WFMOVE;
				return (TRUE);
			}
			/* FALLTHRU */
		case CCHR('I'):
		case CCHR('J'):
	addchar:
			if (pptr == -1)
				pptr = 0;
			if (pptr == 0)
				success = TRUE;
			if (pptr == NPAT - 1)
				ttbeep();
			else {
				pat[pptr++] = c;
				pat[pptr] = '\0';
			}
			is_lpush();
			if (success != FALSE) {
				if (is_find(dir) != FALSE)
					is_cpush(c);
				else {
					success = FALSE;
					ttbeep();
					is_cpush(SRCH_ACCM);
				}
			} else
				is_cpush(SRCH_ACCM);
			is_prompt(dir, FALSE, success);
		}
	}
	/* NOTREACHED */
}