Esempio n. 1
0
/* keep track of enough state to give us a hint as to whether
	we need to redo the visual matches */
static int
need_to_rehilite(void)
{
    /* save static copies of state that affects the search */

    if ((curbp->b_highlight & (HILITE_ON | HILITE_DIRTY)) ==
	(HILITE_ON | HILITE_DIRTY) ||
	tb_length(searchpat) != tb_length(savepat) ||
	(tb_length(searchpat) != 0 &&
	 tb_length(savepat) != 0 &&
	 memcmp(tb_values(searchpat),
		tb_values(savepat),
		tb_length(savepat))) ||
	save_igncase != ignorecase ||
	save_vattr != b_val(curbp, VAL_HILITEMATCH) ||
	save_magic != b_val(curbp, MDMAGIC) ||
	(!hilite_suppressed && save_curbp != curbp)) {
	tb_copy(&savepat, searchpat);
	save_igncase = ignorecase;
	save_vattr = (VIDEO_ATTR) b_val(curbp, VAL_HILITEMATCH);
	save_magic = b_val(curbp, MDMAGIC);
	save_curbp = curbp;
	return TRUE;
    }
    return FALSE;
}
Esempio n. 2
0
static void
promptpattern(const char *prompt)
{
    /* check to see if we are executing a command line */
    if (!clexec) {
	TBUFF *temp = tb_visbuf(tb_values(searchpat), tb_length(searchpat));

	mlforce("%s[%s]: ", prompt, temp ? tb_values(temp) : "");
	tb_free(&temp);
    }
}
Esempio n. 3
0
/* ARGSUSED */
int
scrsearchpat(int f GCC_UNUSED, int n GCC_UNUSED)
{
    int status;
    TBUFF *temp = 0;

    status = readpattern("", &searchpat, &gregexp, EOS, TRUE);
    temp = tb_visbuf(tb_values(searchpat), tb_length(searchpat));
    mlwrite("Search pattern is now %s", temp ? tb_values(temp) : "null");
    tb_free(&temp);
    last_srch_direc = FORWARD;
    return status;
}
Esempio n. 4
0
/*
 * Common function for prompting for shell/pipe command, and for recording the
 * last shell/pipe command so that we can support "!!" convention.
 *
 * Note that for 'pipecmd()', we must retain a leading "!".
 */
static int
ShellPrompt(
TBUFF	**holds,
char	*result,
int	rerun)		/* TRUE/FALSE: spawn, -TRUE: pipecmd */
{
	register int	s;
	register SIZE_T	len;
	static	const char bang[] = SHPIPE_LEFT;
	BUFFER *bp;
	int	cb	= any_changed_buf(&bp),
		fix	= (rerun != -TRUE);
	char	save[NLINE],
		temp[NLINE],
		line[NLINE+1];

	if ((len = tb_length(*holds)) != 0) {
		(void)strncpy(save, tb_values(*holds), len);
	}
	save[len] = EOS;

	/* if it doesn't start with '!', or if that's all it is */
	if (!isShellOrPipe(save) || save[1] == EOS)
		(void)strcpy(save, bang);

	(void)strcpy(line, save);
	if (rerun != TRUE) {
		if (cb != 0) {
		    if (cb > 1) {
			(void)lsprintf(temp, 
				"Warning: %d modified buffers: %s",
				cb, bang);
		    } else {
			(void)lsprintf(temp, 
				"Warning: buffer \"%s\" is modified: %s",
				bp->b_bname, bang);
		    }
		} else {
			(void)lsprintf(temp, "%s%s", 
				rerun == -TRUE ? "" : ": ", bang);
		}

		if ((s = mlreply_no_bs(temp, line+1, NLINE)) != TRUE)
			return s;
	}
	if (line[1] == EOS)
		return FALSE;

	*holds = tb_scopy(holds, line);
	(void)strcpy(result, line+fix);
	return TRUE;
}
Esempio n. 5
0
/*
 * This hack will search for the next occurrence of <searchpat> in the buffer,
 * either forward or backward.  It is called with the status of the prior
 * search attempt, so that it knows not to bother if it didn't work last
 * time.  If we can't find any more matches, "point" is left where it was
 * before.  If we do find a match, "point" will be at the end of the matched
 * string for forward searches and at the beginning of the matched string for
 * reverse searches.
 */
static int
scanmore(			/* search forward or back for a pattern */
	    TBUFF *patrn,	/* string to scan for */
	    int dir)		/* direction to search */
{
    int sts = FALSE;		/* current search status */

    FreeIfNeeded(gregexp);
    gregexp = regcomp(tb_values(patrn), tb_length(patrn), b_val(curbp, MDMAGIC));
    if (gregexp != 0) {
	ignorecase = window_b_val(curwp, MDIGNCASE);

	sts = scanner(gregexp, (dir < 0) ? REVERSE : FORWARD, FALSE, (int *) 0);
	if (!sts) {
	    kbd_alarm();	/* beep the terminal if we fail */
	}
#if OPT_EXTRA_COLOR
	else {
	    MARK save_MK;
	    int *attrp = lookup_extra_color(XCOLOR_ISEARCH);
	    if (!isEmpty(attrp)) {
		/* clear any existing search-match */
		clear_match_attrs(TRUE, 1);
		/* draw the new search-match */
		regionshape = rgn_EXACT;
		save_MK = MK;
		MK.l = DOT.l;
		MK.o = DOT.o + (C_NUM) tb_length(patrn);
		videoattribute = (VIDEO_ATTR) * attrp;
		videoattribute |= VOWN_MATCHES;
		(void) attributeregion();
		/* fix for clear_match_attrs */
		curbp->b_highlight |= HILITE_ON;
		MK = save_MK;
	    }
	}
#endif
    }
    return (sts);		/* else, don't even try */
}
Esempio n. 6
0
/*
 * readpattern -- read a pattern.  if it is the
 *	search string, recompile it.
 *	pattern not updated if the user types in an empty line.
 */
int
readpattern(const char *prompt,
	    TBUFF **apat,
	    regexp ** srchexpp,
	    int c,
	    int fromscreen)
{
    char temp[NPAT];
    int status;

    TRACE((T_CALLED "readpattern(%s, %s, %p, %d, %d)\n",
	   prompt ? prompt : "",
	   tb_visible(*apat),
	   (void *) srchexpp,
	   c,
	   fromscreen));

    if (fromscreen) {
	if ((status = screen_to_ident(temp, sizeof(temp))) == TRUE) {
	    if (tb_init(apat, EOS) == 0
		|| tb_bappend(apat, temp, strlen(temp)) == 0) {
		status = FALSE;
	    }
	}
	if (status != TRUE)
	    returnCode(status);
    } else {
	/* don't expand #, %, :, and never process backslashes
	   since they're handled by regexp directly for the
	   search pattern, and in delins() for the replacement
	   pattern */
	hst_glue(c);
	/*
	 * kbd_reply() expects a trailing null, to simplify calls from
	 * kbd_string().
	 */
	if (tb_values(*apat) != 0)
	    tb_append(apat, EOS);
	status = kbd_reply(prompt, apat,
			   eol_history, c,
			   KBD_EXPPAT | KBD_0CHAR,
			   no_completion);
	if (tb_length(*apat) != 0)
	    tb_unput(*apat);	/* trim the trailing null */
    }
    if (status == TRUE) {
	if (srchexpp) {		/* compile it */
	    beginDisplay();
	    FreeIfNeeded(*srchexpp);
	    endofDisplay();
	    *srchexpp = regcomp(tb_values(*apat),
				tb_length(*apat),
				b_val(curbp, MDMAGIC));
	    if (!*srchexpp)
		returnCode(FALSE);
	}
    } else if (status == FALSE && tb_length(*apat) != 0) {	/* Old one */
	status = TRUE;
    }

    returnCode(status);
}
Esempio n. 7
0
/* For the "operator" commands -- the following command is a motion, or
 *  the operator itself is repeated.  All operate on regions.
 */
int
vile_op(int f, int n, OpsFunc fn, const char *str)
{
    int c = 0;
    int thiskey;
    int status;
    const CMDFUNC *cfp;		/* function to execute */
    const CMDFUNC *save_cmd_motion = cmd_motion;
    BUFFER *ourbp;
#if OPT_MOUSE
    WINDOW *wp0 = curwp;
#endif

    TRACE((T_CALLED "vile_op(%s)\n", str));

    doingopcmd = TRUE;

    pre_op_dot = DOT;
    ourbp = curbp;

    if (havemotion != NULL) {
	cfp = havemotion;
	havemotion = NULL;
    } else {
	TBUFF *tok = 0;

	mlwrite("%s operation pending...", str);
	(void) update(FALSE);

	/* get the next command from the keyboard */
	/* or a command line, as approp. */
	if (clexec) {
	    char *value = mac_unquotedarg(&tok);	/* get the next token */
	    if (value != 0 && strcmp(value, "lines"))
		cfp = engl2fnc(value);
	    else
		cfp = &f_godotplus;
	} else {
	    thiskey = lastkey;
	    c = kbd_seq();

#if OPT_MOUSE
	    if (curwp != wp0) {
		unkeystroke(c);
		doingopcmd = FALSE;
		returnCode(FALSE);
	    }
#endif
	    /* allow second chance for entering counts */
	    do_repeats(&c, &f, &n);

	    if (thiskey == lastkey)
		cfp = &f_godotplus;
	    else
		cfp = DefaultKeyBinding(c);

	}
	if (cfp != 0) {
	    mlerase();
	} else {
	    if (!clexec) {
		char temp[NSTRING];
		lsprintf(temp, "(%d)", c);
		tb_scopy(&tok, temp);
	    }
	    (void) no_such_function(tb_values(tok));
	}
	tb_free(&tok);
    }

    if (!cfp) {
	status = FALSE;
    } else if ((cfp->c_flags & MOTION) == 0) {
	kbd_alarm();
	status = ABORT;
    } else {
	/* motion is interpreted as affecting full lines */
	if (regionshape == rgn_EXACT) {
	    if (cfp->c_flags & FL)
		regionshape = rgn_FULLLINE;
	    if (cfp->c_flags & VL_RECT)
		regionshape = rgn_RECTANGLE;
	}

	/* and execute the motion */
	if ((status = execute(cfp, f, n)) == TRUE) {
	    post_op_dot = DOT;
	} else {
	    mlforce("[Motion failed]");
	    status = FALSE;
	}
    }

    if (status == TRUE) {
	opcmd = 0;

	MK = pre_op_dot;

	/* we've successfully set up a region */
	if (!fn) {		/* be defensive */
	    mlforce("BUG -- null func pointer in operator");
	    status = FALSE;
	} else if (fn == user_operator) {
	    swapmark();
	    cmd_motion = cfp;
	    status = dobuf(find_b_name(str), 1, f ? n : 1);
	} else {
	    status = (fn) ();
	}

	if (ourbp == curbp)	/* in case the func switched buffers on us */
	    swapmark();

	if (regionshape == rgn_FULLLINE)
	    (void) firstnonwhite(FALSE, 1);
    }

    regionshape = rgn_EXACT;
    doingopcmd = FALSE;
    haveregion = FALSE;
    cmd_motion = save_cmd_motion;

    returnCode(status);
}
Esempio n. 8
0
/*
 * This is invoked as a wrapper for 'kbd_putc()'.  It writes to the Messages
 * scratch buffer, and also to the message line.  If the Messages buffer isn't
 * visible, it is automatically popped up when a new message line is begun.
 * Since it's a scratch buffer, popping it down destroys it.
 */
int
msg_putc(int c)
{
    BUFFER *savebp = curbp;
    WINDOW *savewp = curwp;
    MARK savemk;
    int saverow = ttrow;
    int savecol = ttcol;
    register BUFFER *bp;
    register WINDOW *wp;

    if ((bp = create_msgs()) == 0)
	return TRUE;

    savemk = DOT;
    beginDisplay();
    /*
     * Modify the current-buffer state as unobtrusively as possible (i.e.,
     * don't modify the buffer order, and don't make the buffer visible if
     * it isn't already!).  To use the 'bputc()' logic, though, we've got
     * to have a window, even if it's not real.
     */
    curbp = bp;
    if ((wp = bp2any_wp(bp)) == NULL) {
	static WINDOW dummy;
	wp = &dummy;
	wp->w_bufp = bp;
    }
    curwp = wp;
    DOT.l = lback(buf_head(bp));
    DOT.o = llength(DOT.l);

    /*
     * Write into the [Messages]-buffer
     */
#if OPT_TRACE
    if (c == '\n') {
	static TBUFF *ss;
	int len = (DOT.o > 0) ? DOT.o : 1;
	if (tb_init(&ss, EOS) != 0
	    && tb_bappend(&ss,
			  (DOT.o > 0) ? lvalue(DOT.l) : "?",
			  (size_t) len) != 0
	    && tb_append(&ss, EOS) != 0) {
	    TRACE(("msg:%s\n",
		   visible_buff(tb_values(ss),
				(int) tb_length(ss) - 1, TRUE)));
	}
    }
#endif
    if ((c != '\n') || (DOT.o > 0)) {
	bputc(c);
	b_clr_changed(bp);
    }

    /* Finally, restore the original current-buffer and write the character
     * to the message line.
     */
    curbp = savebp;
    curwp = savewp;
    if (savewp)
	DOT = savemk;
    movecursor(saverow, savecol);
    if (c != '\n') {
	if (sgarbf) {
	    mlsavec(c);
	} else {
	    kbd_putc(c);
	}
    }
    endofDisplay();

    return TRUE;
}
Esempio n. 9
0
int
attributeregion(void)
{
    BUFFER *bp = curbp;
    int status;
    REGION region;
    AREGION *arp;

    if ((status = getregion(bp, &region)) == TRUE) {
	if (apply_attribute()) {
	    if (add_line_attrib(bp, &region, regionshape, videoattribute,
#if OPT_HYPERTEXT
				hypercmd
#else
				0
#endif
		)) {
		return TRUE;
	    }

	    /* add new attribute-region */
	    if ((arp = alloc_AREGION()) == NULL) {
		return FALSE;
	    }
	    arp->ar_region = region;
	    arp->ar_vattr = videoattribute;	/* include ownership */
	    arp->ar_shape = regionshape;
#if OPT_HYPERTEXT
	    arp->ar_hypercmd = 0;
	    if (tb_length(hypercmd) && *tb_values(hypercmd)) {
#if OPT_EXTRA_COLOR
		if (tb_length(hypercmd) > 4
		    && !memcmp(tb_values(hypercmd), "view ", (size_t) 4)) {
		    int *newVideo = lookup_extra_color(XCOLOR_HYPERTEXT);
		    if (!isEmpty(newVideo)) {
			arp->ar_vattr = (VIDEO_ATTR) * newVideo;
		    }
		}
#endif
		arp->ar_hypercmd = strmalloc(tb_values(hypercmd));
		tb_init(&hypercmd, 0);
	    }
#endif
	    attach_attrib(bp, arp);
	} else {		/* purge attributes in this region */
	    L_NUM rls = line_no(bp, region.r_orig.l);
	    L_NUM rle = line_no(bp, region.r_end.l);
	    C_NUM ros = region.r_orig.o;
	    C_NUM roe = region.r_end.o;
	    AREGION **pp;
	    AREGION **qq;
	    AREGION *p, *n;
	    int owner;

	    owner = VOWNER(videoattribute);

	    purge_line_attribs(bp, &region, regionshape, owner);

	    pp = &(bp->b_attribs);

	    for (p = *pp; p != 0; pp = qq, p = *pp) {
		L_NUM pls, ple;
		C_NUM pos, poe;

		if (interrupted())
		    return FALSE;

		qq = &(p->ar_next);

		if (owner != 0 && owner != VOWNER(p->ar_vattr))
		    continue;

		pls = line_no(bp, p->ar_region.r_orig.l);
		ple = line_no(bp, p->ar_region.r_end.l);
		pos = p->ar_region.r_orig.o;
		poe = p->ar_region.r_end.o;

		/* Earlier the overlapping region check was made based only
		 * on line numbers and so was right only for FULLINES shape
		 * changed it to be correct for rgn_EXACT and rgn_RECTANGLE also
		 * -kuntal 9/13/98
		 */
		/*
		 * check for overlap:
		 * for any shape of region 'p' things are fine as long as
		 * 'region' is above or below it
		 */
		if (ple < rls || pls > rle)
		    continue;
		/*
		 * for rgn_EXACT 'p' region
		 */
		if (p->ar_shape == rgn_EXACT) {
		    if (ple == rls && poe - 1 < ros)
			continue;
		    if (pls == rle && pos > roe)
			continue;
		}
		/*
		 * for rgn_RECTANGLE 'p' region
		 */
		if (p->ar_shape == rgn_RECTANGLE)
		    if (poe < ros || pos > roe)
			continue;

		/*
		 * FIXME: this removes the whole of an overlapping region;
		 * we really only want to remove the overlapping portion...
		 */

		/*
		 * we take care of this fix easily as long as neither of
		 * 'p' or 'region' are rgn_RECTANGLE. we will need to create
		 * at the most one new region in case 'region' is
		 * completely contained within 'p'
		 */
		if (p->ar_shape != rgn_RECTANGLE && regionshape != rgn_RECTANGLE) {
		    if ((rls > pls) || (rls == pls && ros > pos)) {
			p->ar_shape = rgn_EXACT;
			if ((rle < ple) || (rle == ple && roe < poe)) {
			    /* open a new region */
			    if ((n = alloc_AREGION()) == NULL) {
				return FALSE;
			    }
			    n->ar_region = p->ar_region;
			    n->ar_vattr = p->ar_vattr;
			    n->ar_shape = p->ar_shape;
#if OPT_HYPERTEXT
			    n->ar_hypercmd = p->ar_hypercmd;
#endif
			    n->ar_region.r_orig.l = (region.r_end.l);
			    n->ar_region.r_orig.o = (region.r_end.o);
			    attach_attrib(bp, n);
			}
			p->ar_region.r_end.l = (region.r_orig.l);
			p->ar_region.r_end.o = (region.r_orig.o);
			curwp->w_flag |= WFHARD;
			continue;
		    } else if ((rle < ple) || (rle == ple && roe < poe)) {
			p->ar_region.r_orig.l = (region.r_end.l);
			p->ar_region.r_orig.o = (region.r_end.o);
			curwp->w_flag |= WFHARD;
			continue;
		    }
		}

		free_attrib2(bp, pp);
		qq = pp;
	    }
	}
    }
    return status;
}
Esempio n. 10
0
/* Return comma-delimited list of "interesting" options. */
static char *
cfgopts(void)
{
    static const char *opts[] =
    {
#if !OPT_SHELL
	"noshell",
#endif
#if SYS_WINNT && defined(VILE_OLE)
	"oleauto",
#endif
#if OPT_HYPERTEXT
	"hypertext",
#endif
#if OPT_LOCALE
	"locale",
#endif
#if OPT_ICONV_FUNCS
	"iconv",
#endif
#if OPT_MULTIBYTE
	"multibyte",
#endif
#if OPT_PERL
	"perl",
#endif
#if DISP_ANSI
	"ansi",
#endif
#if DISP_BORLAND
	"borland",
#endif
#if DISP_CURSES
	"curses",
#endif
#if DISP_NTCONS
	"ntcons",
#endif
#if DISP_NTWIN
	"ntwin",
#endif
#if DISP_TERMCAP
# if USE_TERMINFO
	"terminfo",
# else
	"termcap",
# endif
#endif
#if DISP_VIO
	"os2vio",
#endif
#if DISP_VMSVT
	"vmsvt",
#endif
#if DISP_X11
# if MOTIF_WIDGETS
	"motif",
# endif
# if ATHENA_WIDGETS
	"athena",
#  ifdef HAVE_LIB_XAW
	"xaw",
#  endif
#  ifdef HAVE_LIB_XAW3D
	"xaw3d",
#  endif
#  ifdef HAVE_LIB_NEXTAW
	"nextaw",
#  endif
# endif
#endif
	NULL			/* End of list marker */
    };
    static TBUFF *optstring;

    if (optstring == 0) {
	const char **lclopt;

	optstring = tb_init(&optstring, EOS);
	for (lclopt = opts; *lclopt; lclopt++) {
	    if (tb_length(optstring))
		optstring = tb_append(&optstring, ',');
	    optstring = tb_sappend(&optstring, *lclopt);
	}
	optstring = tb_append(&optstring, EOS);
    }
    return tb_values(optstring);
}
Esempio n. 11
0
/* ARGSUSED */
static int
isearch(int f GCC_UNUSED, int n)
{
    static TBUFF *pat_save = 0;	/* Saved copy of the old pattern str */

    int status;			/* Search status */
    register int cpos;		/* character number in search string */
    register int c;		/* current input character */
    MARK curpos, curp;		/* Current point on entry */
    int init_direction;		/* The initial search direction */

    /* Initialize starting conditions */

    cmd_reexecute = -1;		/* We're not re-executing (yet?) */
    itb_init(&cmd_buff, EOS);	/* Init the command buffer */
    /* Save the old pattern string */
    (void) tb_copy(&pat_save, searchpat);
    curpos = DOT;		/* Save the current pointer */
    init_direction = n;		/* Save the initial search direction */

    ignorecase = window_b_val(curwp, MDIGNCASE);

    scanboundry(FALSE, DOT, FORWARD);	/* keep scanner() finite */

    /* This is a good place to start a re-execution: */

  start_over:

    /* ask the user for the text of a pattern */
    promptpattern("ISearch: ");

    status = TRUE;		/* Assume everything's cool */

    /*
     * Get the first character in the pattern.  If we get an initial
     * Control-S or Control-R, re-use the old search string and find the
     * first occurrence
     */

    c = kcod2key(get_char());	/* Get the first character */
    if ((c == IS_FORWARD) ||
	(c == IS_REVERSE)) {	/* Reuse old search string? */
	for (cpos = 0; cpos < (int) tb_length(searchpat); ++cpos)
	    echochar(tb_values(searchpat)[cpos]);	/* and re-echo the string */
	curp = DOT;
	if (c == IS_REVERSE) {	/* forward search? */
	    n = -1;		/* No, search in reverse */
	    last_srch_direc = REVERSE;
	    backchar(TRUE, 1);	/* Be defensive about EOB */
	} else {
	    n = 1;		/* Yes, search forward */
	    last_srch_direc = FORWARD;
	    forwchar(TRUE, 1);
	}
	unget_char();
	status = scanmore(searchpat, n);	/* Do the search */
	if (status != TRUE)
	    DOT = curp;
	c = kcod2key(get_char());	/* Get another character */
    } else {
	tb_init(&searchpat, EOS);
    }
    /* Top of the per character loop */

    for_ever {			/* ISearch per character loop */
	/* Check for special characters, since they might change the
	 * search to be done
	 */

	if (ABORTED(c) || c == '\r')	/* search aborted? */
	    return (TRUE);	/* end the search */

	if (isbackspace(c))
	    c = '\b';

	if (c == quotec)	/* quote character? */
	    c = kcod2key(get_char());	/* Get the next char */

	switch (c) {		/* dispatch on the input char */
	case IS_REVERSE:	/* If backward search */
	case IS_FORWARD:	/* If forward search */
	    curp = DOT;
	    if (c == IS_REVERSE) {	/* forward search? */
		last_srch_direc = REVERSE;
		n = -1;		/* No, search in reverse */
		backchar(TRUE, 1);	/* Be defensive about
					 * EOB */
	    } else {
		n = 1;		/* Yes, search forward */
		last_srch_direc = FORWARD;
		forwchar(TRUE, 1);
	    }
	    status = scanmore(searchpat, n);	/* Do the search */
	    if (status != TRUE)
		DOT = curp;
	    c = kcod2key(get_char());	/* Get the next char */
	    continue;		/* Go continue with the search */

	case '\t':		/* Generically allowed */
	case '\n':		/* controlled characters */
	    break;		/* Make sure we use it */

	case '\b':		/* or if a Rubout: */
	    if (itb_length(cmd_buff) <= 1)	/* Anything to delete? */
		return (TRUE);	/* No, just exit */
	    unget_char();
	    DOT = curpos;	/* Reset the pointer */
	    n = init_direction;	/* Reset the search direction */
	    (void) tb_copy(&searchpat, pat_save);
	    /* Restore the old search str */
	    cmd_reexecute = 0;	/* Start the whole mess over */
	    goto start_over;	/* Let it take care of itself */

	    /* Presumably a quasi-normal character comes here */

	default:		/* All other chars */
	    if (!isPrint(c)) {	/* Is it printable? */
		/* Nope. */
		unkeystroke(c);	/* Re-eat the char */
		return (TRUE);	/* And return the last status */
	    }
	}			/* Switch */

	/* I guess we got something to search for, so search for it */

	tb_append(&searchpat, c);	/* put the char in the buffer */
	echochar(c);		/* Echo the character */
	if (!status) {		/* If we lost last time */
	    kbd_alarm();	/* Feep again */
	} else			/* Otherwise, we must have won */
	    status = scanmore(searchpat, n);	/* or find the next
						   * match */
	c = kcod2key(get_char());	/* Get the next char */
    }				/* for_ever */
}