Example #1
0
int
getvisrchstr(void)
{
    char *sbuf = halloc(80);
    int sptr = 1, ret = 0, ssbuf = 80;
    int cmd;
    int *obindtab = bindtab;

    if (visrchstr) {
	zsfree(visrchstr);
	visrchstr = NULL;
    }
    clearlist = 1;
    statusline = sbuf;
    sbuf[0] = (visrchsense == -1) ? '?' : '/';
    bindtab = mainbindtab;
    while (sptr) {
	sbuf[sptr] = '_';
	statusll = sptr + 1;
	refresh();
	if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
	    ret = 0;
	    break;
	}
	if(cmd == z_magicspace) {
	    c = ' ';
	    cmd = z_selfinsert;
	}
	switch(cmd) {
	  case z_redisplay:
	    redisplay();
	    break;
	  case z_clearscreen:
	    clearscreen();
	    break;
	  case z_acceptline:
	  case z_vicmdmode:
	    sbuf[sptr] = 0;
	    visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP);
	    ret = 1;
	    sptr = 0;
	    break;
	  case z_backwarddeletechar:
	  case z_vibackwarddeletechar:
	    sptr--;
	    break;
	  case z_backwardkillword:
	  case z_vibackwardkillword:
	    while(sptr != 1 && iblank(sbuf[sptr - 1]))
		sptr--;
	    if(iident(sbuf[sptr - 1]))
		while(sptr != 1 && iident(sbuf[sptr - 1]))
		    sptr--;
	    else
		while(sptr != 1 && !iident(sbuf[sptr - 1]) && !iblank(sbuf[sptr - 1]))
		    sptr--;
	    break;
	  case z_sendstring:
	    sendstring();
	    break;
	  case z_viquotedinsert:
	    sbuf[sptr] = '^';
	    refresh();
	    /* fall through */
	  case z_quotedinsert:
	    if ((c = getkey(0)) == EOF) {
		feep();
		break;
	    }
	    goto ins;
	  case z_selfinsertunmeta:
	    c &= 0x7f;
	    if(c == '\r')
		c = '\n';
	  case z_selfinsert:
	  ins:
	    if(sptr == ssbuf - 1) {
		char *newbuf = halloc(ssbuf *= 2);
		strcpy(newbuf, sbuf);
		statusline = sbuf = newbuf;
	    }
	    sbuf[sptr++] = c;
	    break;
	  default:
	    feep();
	}
    }
    statusline = NULL;
    bindtab = obindtab;
    return ret;
}
Example #2
0
Thingy
executenamedcommand(char *prmt)
{
    Thingy cmd, retval = NULL;
    int l, len, feep = 0, listed = 0, curlist = 0;
    int ols = (listshown && validlist), olll = lastlistlen;
    char *cmdbuf, *ptr;
    char *okeymap = ztrdup(curkeymapname);

    clearlist = 1;
    /* prmt may be constant */
    prmt = ztrdup(prmt);
    l = strlen(prmt);
    cmdbuf = (char *)zhalloc(l + NAMLEN + 2
#ifdef MULTIBYTE_SUPPORT
			     + 2 * MB_CUR_MAX
#endif
			     );
    strcpy(cmdbuf, prmt);
    zsfree(prmt);
    statusline = cmdbuf;
    selectlocalmap(command_keymap);
    selectkeymap("main", 1);
    ptr = cmdbuf += l;
    len = 0;
    for (;;) {
	*ptr = '_';
	ptr[1] = '\0';
	zrefresh();
	if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
	    statusline = NULL;
	    selectkeymap(okeymap, 1);
	    zsfree(okeymap);
	    if ((listshown = ols)) {
		showinglist = -2;
		lastlistlen = olll;
	    } else if (listed)
		clearlist = listshown = 1;

	    retval = NULL;
	    goto done;
	}
	if(cmd == Th(z_clearscreen)) {
	    clearscreen(zlenoargs);
	    if (curlist) {
		int zmultsav = zmult;

		zmult = 1;
		listlist(namedcmdll);
		showinglist = 0;
		zmult = zmultsav;
	    }
	} else if(cmd == Th(z_redisplay)) {
	    redisplay(zlenoargs);
	    if (curlist) {
		int zmultsav = zmult;

		zmult = 1;
		listlist(namedcmdll);
		showinglist = 0;
		zmult = zmultsav;
	    }
	} else if(cmd == Th(z_viquotedinsert)) {
	    *ptr = '^';
	    zrefresh();
	    getfullchar(0);
	    if(LASTFULLCHAR == ZLEEOF || !LASTFULLCHAR || len >= NAMLEN)
		feep = 1;
	    else {
		int ret = zlecharasstring(LASTFULLCHAR, ptr);
		len += ret;
		ptr += ret;
		curlist = 0;
	    }
	} else if(cmd == Th(z_quotedinsert)) {
	    if(getfullchar(0) == ZLEEOF ||
	       !LASTFULLCHAR || len == NAMLEN)
		feep = 1;
	    else {
		int ret = zlecharasstring(LASTFULLCHAR, ptr);
		len += ret;
		ptr += ret;
		curlist = 0;
	    }
	} else if(cmd == Th(z_backwarddeletechar) ||
		  cmd == Th(z_vibackwarddeletechar)) {
	    if (len) {
		ptr = backwardmetafiedchar(cmdbuf, ptr, NULL);
		len = ptr - cmdbuf;
		curlist = 0;
	    }
	} else if(cmd == Th(z_killregion) || cmd == Th(z_backwardkillword) ||
		  cmd == Th(z_vibackwardkillword)) {
	    if (len)
		curlist = 0;
	    while (len) {
		convchar_t cc;
		ptr = backwardmetafiedchar(cmdbuf, ptr, &cc);
		len = ptr - cmdbuf;
		if (cc == ZWC('-'))
		    break;
	    }
	} else if(cmd == Th(z_killwholeline) || cmd == Th(z_vikillline) ||
	    	cmd == Th(z_backwardkillline)) {
	    len = 0;
	    ptr = cmdbuf;
	    if (listed)
		clearlist = listshown = 1;
	    curlist = 0;
	} else if (cmd == Th(z_bracketedpaste)) {
	    char *insert = bracketedstring();
	    size_t inslen = strlen(insert);
	    if (len + inslen > NAMLEN)
		feep = 1;
	    else {
		strcpy(ptr, insert);
		len += inslen;
		ptr += inslen;
		if (listed) {
		    clearlist = listshown = 1;
		    listed = 0;
		} else
		    curlist = 0;
	    }
	    free(insert);
	} else {
	    if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) {
		Thingy r;
		unambiguous:
		*ptr = 0;
		r = rthingy(cmdbuf);
		if (!(r->flags & DISABLED)) {
		    unrefthingy(r);
		    statusline = NULL;
		    selectkeymap(okeymap, 1);
		    zsfree(okeymap);
		    if ((listshown = ols)) {
			showinglist = -2;
			lastlistlen = olll;
		    } else if (listed)
			clearlist = listshown = 1;

		    retval = r;
		    goto done;
		}
		unrefthingy(r);
	    }
	    if(cmd == Th(z_selfinsertunmeta)) {
		fixunmeta();
		cmd = Th(z_selfinsert);
	    }
	    if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist) ||
		cmd == Th(z_expandorcomplete) || cmd == Th(z_completeword) ||
		cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_vicmdmode) ||
		cmd == Th(z_acceptline) || lastchar == ' ' || lastchar == '\t') {
		namedcmdambig = 100;

		namedcmdll = newlinklist();

		*ptr = '\0';
		namedcmdstr = cmdbuf;
		scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0);
		namedcmdstr = NULL;

		if (empty(namedcmdll)) {
		    feep = 1;
		    if (listed)
			clearlist = listshown = 1;
		    curlist = 0;
		} else if (cmd == Th(z_listchoices) ||
		    cmd == Th(z_deletecharorlist)) {
		    int zmultsav = zmult;
		    *ptr = '_';
		    ptr[1] = '\0';
		    zmult = 1;
		    listlist(namedcmdll);
		    listed = curlist = 1;
		    showinglist = 0;
		    zmult = zmultsav;
		} else if (!nextnode(firstnode(namedcmdll))) {
		    strcpy(ptr = cmdbuf, peekfirst(namedcmdll));
		    len = strlen(ptr);
		    ptr += len;
		    if (cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode))
			goto unambiguous;
		} else {
		    strcpy(cmdbuf, peekfirst(namedcmdll));
		    ptr = cmdbuf + namedcmdambig;
		    *ptr = '_';
		    ptr[1] = '\0';
		    if (isset(AUTOLIST) &&
			!(isset(LISTAMBIGUOUS) && namedcmdambig > len)) {
			int zmultsav = zmult;
			if (isset(LISTBEEP))
			    feep = 1;
			zmult = 1;
			listlist(namedcmdll);
			listed = curlist = 1;
			showinglist = 0;
			zmult = zmultsav;
		    }
		    len = namedcmdambig;
		}
	    } else {
		if (len == NAMLEN || cmd != Th(z_selfinsert))
		    feep = 1;
		else {
#ifdef MULTIBYTE_SUPPORT
		    if (!lastchar_wide_valid)
			getrestchar(lastchar, NULL, NULL);
		    if (lastchar_wide == WEOF)
			feep = 1;
		    else
#endif
		    if (ZC_icntrl(LASTFULLCHAR))
			feep = 1;
		    else {
			int ret = zlecharasstring(LASTFULLCHAR, ptr);
			len += ret;
			ptr += ret;
			if (listed) {
			    clearlist = listshown = 1;
			    listed = 0;
			} else
			    curlist = 0;
		    }
		}
	    }
	}
	if (feep)
	    handlefeep(zlenoargs);
	feep = 0;
    }

 done:
    selectlocalmap(NULL);
    return retval;
}
Example #3
0
void
doisearch(int dir)
{
    char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR;
    int sbptr = 0, top_spot = 0, pos, sibuf = 80;
    int nomatch = 0, skip_line = 0, skip_pos = 0;
    int odir = dir, sens = zmult == 1 ? 3 : 1;
    int hl = histline;
    int cmd;
    int *obindtab = bindtab;
    static char *previous_search = NULL;
    static int previous_search_len = 0;

    clearlist = 1;

    strcpy(ibuf, ISEARCH_PROMPT);
    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
    remember_edits();
    s = zle_get_event(hl);
    bindtab = mainbindtab;
    pos = metalen(s, cs);
    for (;;) {
	/* Remember the current values in case search fails (doesn't push). */
	set_isrch_spot(top_spot, hl, pos, cs, sbptr, dir, nomatch);
	if (sbptr == 1 && sbuf[0] == '^') {
	    cs = 0;
    	    nomatch = 0;
	    statusline = ibuf + NORM_PROMPT_POS;
	} else if (sbptr > 0) {
	    char *last_line = s;

	    for (;;) {
		char *t;

		if (skip_pos) {
		    if (dir < 0) {
			if (pos == 0)
			    skip_line = 1;
			else
			    pos -= 1 + (pos != 1 && s[pos-2] == Meta);
		    } else if (sbuf[0] != '^') {
			if (pos >= strlen(s+1))
			    skip_line = 1;
			else
			    pos += 1 + (s[pos] == Meta);
		    } else
			skip_line = 1;
		    skip_pos = 0;
		}
		if (!skip_line && ((sbuf[0] == '^') ?
		    (t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) :
		    (t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) {
		    zle_goto_hist(hl);
		    pos = t - s;
		    cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
	    	    nomatch = 0;
		    statusline = ibuf + NORM_PROMPT_POS;
		    break;
		}
		hl += dir;
		if (!(s = zle_get_event(hl))) {
		    if (sbptr == (int)isrch_spots[top_spot-1].len
		     && (isrch_spots[top_spot-1].flags & ISS_FAILING))
			top_spot--;
		    get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr,
				   &dir, &nomatch);
		    if (!nomatch) {
			feep();
			nomatch = 1;
		    }
		    s = last_line;
		    skip_line = 0;
		    statusline = ibuf;
		    break;
		}
		pos = dir == 1? 0 : strlen(s);
		skip_line = !strcmp(last_line, s);
	    }
	} else {
	    top_spot = 0;
    	    nomatch = 0;
	    statusline = ibuf + NORM_PROMPT_POS;
	}
	sbuf[sbptr] = '_';
	statusll = sbuf - statusline + sbptr + 1;
    ref:
	refresh();
	if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
	    int i;
	    get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch);
	    s = zle_get_event(hl);
	    zle_goto_hist(hl);
	    cs = i;
	    break;
	}
	switch (cmd) {
	case z_clearscreen:
	    clearscreen();
	    goto ref;
	case z_redisplay:
	    redisplay();
	    goto ref;
	case z_vicmdmode:
	    bindtab = (bindtab == mainbindtab) ? altbindtab : mainbindtab;
	    goto ref;
	case z_vibackwarddeletechar:
	case z_backwarddeletechar:
	    if (top_spot)
		get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr,
			       &dir, &nomatch);
	    else
		feep();
	    if (nomatch) {
		statusline = ibuf;
		skip_pos = 1;
	    }
	    s = zle_get_event(hl);
	    if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
		int i = cs;
		zle_goto_hist(hl);
		cs = i;
	    }
	    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
	    continue;
	case z_acceptandhold:
	    acceptandhold();
	    goto brk;
	case z_acceptandinfernexthistory:
	    acceptandinfernexthistory();
	    goto brk;
	case z_acceptlineanddownhistory:
	    acceptlineanddownhistory();
	    goto brk;
	case z_acceptline:
	    acceptline();
	    goto brk;
	case z_historyincrementalsearchbackward:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (dir != -1)
		dir = -1;
	    else
		skip_pos = 1;
	    goto rpt;
	case z_historyincrementalsearchforward:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (dir != 1)
		dir = 1;
	    else
		skip_pos = 1;
	    goto rpt;
	case z_virevrepeatsearch:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    dir = -odir;
	    skip_pos = 1;
	    goto rpt;
	case z_virepeatsearch:
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    dir = odir;
	    skip_pos = 1;
	rpt:
	    if (!sbptr && previous_search_len) {
		if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) {
		    ibuf = hrealloc(ibuf, sibuf, sibuf + previous_search_len);
		    sbuf = ibuf + FIRST_SEARCH_CHAR;
		    sibuf += previous_search_len;
		}
		memcpy(sbuf, previous_search, sbptr = previous_search_len);
	    }
	    memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
	    continue;
	case z_sendstring:
	    sendstring();
	    goto ref;
	case z_viquotedinsert:
	    sbuf[sbptr] = '^';
	    refresh();
	case z_quotedinsert:
	    if ((c = getkey(0)) == EOF) {
		feep();
		continue;
	    }
	    goto ins;
	default:
	    if(cmd == z_selfinsertunmeta) {
		c &= 0x7f;
		if(c == '\r')
		    c = '\n';
	    } else if (cmd == z_magicspace)
		c = ' ';
	    else if (cmd != z_selfinsert) {
		ungetkeycmd();
		if (cmd == z_sendbreak)
		    sbptr = 0;
		goto brk;
	    }
	ins:
	    if (sbptr == PATH_MAX) {
		feep();
		break;
	    }
	    set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch);
	    if (sbptr == sibuf - FIRST_SEARCH_CHAR - 2) {
		ibuf = hrealloc(ibuf, sibuf, sibuf * 2);
		sbuf = ibuf + FIRST_SEARCH_CHAR;
		sibuf *= 2;
	    }
	    sbuf[sbptr++] = c;
	}
    }
  brk:
    if (sbptr) {
	zfree(previous_search, previous_search_len);
	previous_search = zalloc(sbptr);
	memcpy(previous_search, sbuf, previous_search_len = sbptr);
    }
    statusline = NULL;
    bindtab = obindtab;
}
Example #4
0
void
zlecore(void)
{
    Keymap km;
#if !defined(HAVE_POLL) && defined(HAVE_SELECT)
    struct timeval tv;
    fd_set foofd;

    FD_ZERO(&foofd);
#endif

    pushheap();

    /*
     * A widget function may decide to exit the shell.
     * We never exit directly from functions, to allow
     * the shell to tidy up, so we have to test for
     * that explicitly.
     */
    while (!done && !errflag && !exit_pending) {
	UNMETACHECK();

	statusline = NULL;
	vilinerange = 0;
	reselectkeymap();
	selectlocalmap(invicmdmode() && region_active && (km = openkeymap("visual"))
	    ? km : NULL);
	bindk = getkeycmd();
	selectlocalmap(NULL);
	if (bindk) {
	    if (!zlell && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
		lastchar == eofchar) {
		/*
		 * Slight hack: this relies on getkeycmd returning
		 * a value for the EOF character.  However,
		 * undefined-key is fine.  That's necessary because
		 * otherwise we can't distinguish this case from
		 * a ^C.
		 */
		eofsent = 1;
		break;
	    }
	    if (execzlefunc(bindk, zlenoargs, 0)) {
		handlefeep(zlenoargs);
		if (eofsent)
		    break;
	    }
	    handleprefixes();
	    /* for vi mode, make sure the cursor isn't somewhere illegal */
	    if (invicmdmode() && zlecs > findbol() &&
		(zlecs == zlell || zleline[zlecs] == ZWC('\n')))
		DECCS();
	    handleundo();
	} else {
	    errflag |= ERRFLAG_ERROR;
	    break;
	}
#ifdef HAVE_POLL
	if (baud && !(lastcmd & ZLE_MENUCMP)) {
	    struct pollfd pfd;
	    int to = cost * costmult / 1000; /* milliseconds */

	    if (to > 500)
		to = 500;
	    pfd.fd = SHTTY;
	    pfd.events = POLLIN;
	    if (!kungetct && poll(&pfd, 1, to) <= 0)
		zrefresh();
	} else
#else
# ifdef HAVE_SELECT
	if (baud && !(lastcmd & ZLE_MENUCMP)) {
	    FD_SET(SHTTY, &foofd);
	    tv.tv_sec = 0;
	    if ((tv.tv_usec = cost * costmult) > 500000)
		tv.tv_usec = 500000;
	    if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
				    NULL, NULL, &tv) <= 0)
		zrefresh();
	} else
# endif
#endif
	    if (!kungetct)
		zrefresh();

	freeheap();
    }

    region_active = 0;
    popheap();
}
Example #5
0
File: zle_vi.c Project: Osse/zsh
static int
getvirange(int wf)
{
    int pos = zlecs, ret = 0;
    int mult1 = zmult, hist1 = histline;
    Thingy k2;

    virangeflag = 1;
    wordflag = wf;
    /* Now we need to execute the movement command, to see where it *
     * actually goes.  virangeflag here indicates to the movement   *
     * function that it should place the cursor at the end of the   *
     * range, rather than where the cursor would actually go if it  *
     * were executed normally.  This makes a difference to some     *
     * commands, but not all.  For example, if searching forward    *
     * for a character, under normal circumstances the cursor lands *
     * on the character.  For a range, the range must include the   *
     * character, so the cursor gets placed after the character if  *
     * virangeflag is set.  vi-match-bracket needs to change the    *
     * value of virangeflag under some circumstances, meaning that  *
     * we need to change the *starting* position.                   */
    zmod.flags &= ~MOD_TMULT;
    do {
	vilinerange = 0;
	prefixflag = 0;
	if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) ||
		k2 == Th(z_sendbreak)) {
	    wordflag = 0;
	    virangeflag = 0;
	    return -1;
	}
	/*
	 * With k2 == bindk, the command key is repeated:
	 * a number of lines is used.  If the function used
	 * returns 1, we fail.
	 */
	if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1))
	    ret = -1;
	if(vichgrepeat)
	    zmult = mult1;
	else
	    zmult = mult1 * zmod.tmult;
    } while(prefixflag && !ret);
    wordflag = 0;
    virangeflag = 0;

    /* It is an error to use a non-movement command to delimit the *
     * range.  We here reject the case where the command modified  *
     * the line, or selected a different history line.             */
    if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) {
	histline = hist1;
	ZS_memcpy(zleline, lastline, zlell = lastll);
	zlecs = pos;
	return -1;
    }

    /* Can't handle an empty file.  Also, if the movement command *
     * failed, or didn't move, it is an error.                    */
    if (!zlell || (zlecs == pos && virangeflag != 2) || ret == -1)
	return -1;

    /* vi-match-bracket changes the value of virangeflag when *
     * moving to the opening bracket, meaning that we need to *
     * change the *starting* position.                        */
    if(virangeflag == -1)
    {
	int origcs = zlecs;
	zlecs = pos;
	INCCS();
	pos = zlecs;
	zlecs = origcs;
    }

    /* Get the range the right way round.  zlecs is placed at the *
     * start of the range, and pos (the return value of this   *
     * function) is the end.                                   */
    if (zlecs > pos) {
	int tmp = zlecs;
	zlecs = pos;
	pos = tmp;
    }

    /* Was it a line-oriented move?  If so, the command will have set *
     * the vilinerange flag.  In this case, entire lines are taken,   *
     * rather than just the sequence of characters delimited by pos   *
     * and zlecs.  The terminating newline is left out of the range,     *
     * which the real command must deal with appropriately.  At this  *
     * point we just need to make the range encompass entire lines.   */
    if(vilinerange) {
	int newcs = findbol();
	zlecs = pos;
	pos = findeol();
	zlecs = newcs;
    }
    return pos;
}
Example #6
0
int
getvirange(int wf)
{
    int k2, t0, startline, endline, obeep;
    int mult1, gotmult1;

    vilinerange = 0;
    startline = findbol();
    endline = findeol();
    /* get arguments for the command, and then the command key */
    mult1 = zmult;
    gotmult1 = gotmult;
    zmult = 1;
    gotmult = 0;
    lastcmd &= ~(ZLE_NEGARG | ZLE_DIGIT);
    while(1) {
	if ((k2 = getkeycmd()) < 0 || k2 == z_sendbreak) {
	    feep();
	    return -1;
	}
	if (!(zlecmds[k2].flags & ZLE_ARG))
	    break;
	(*zlecmds[k2].func) ();
	lastcmd = zlecmds[k2].flags;
    }

    /* double counts, such as in 3d4j, get multiplied, unless we're repeating */
    if(vichgrepeat && gotmult1) {
	zmult = mult1;
	gotmult = 1;
    } else if (gotmult1) {
	zmult *= mult1;
	gotmult = 1;
    }
    /* can't handle an empty file */
    if (!ll) {
	feep();
	return -1;
    }

    /* This bit handles repeated command keys, such as dd.  A number  *
     * of lines is taken as the range.  The current line is included. *
     * If the argument is positive, the lines go downward, otherwise  *
     * vice versa.  The argument gives the number of lines.           */
    if (k2 == bindk) {
	vilinerange = 1;
	if (!zmult) {
	    feep();
	    return -1;
	}
	t0 = cs;
	if (zmult > 0) {
	    while(zmult-- && cs <= ll)
		cs = findeol() + 1;
	    if (zmult != -1) {
		cs = t0;
		feep();
		return -1;
	    }
	    t0 = cs - 1;
	    cs = startline;
	    return t0;
	} else {
	    while(zmult++ && cs >= 0)
		cs = findbol() - 1;
	    if (zmult != 1) {
		cs = t0;
		feep();
		return -1;
	    }
	    cs++;
	    return endline;
	}
    }

    /* Not a movement?!  No, you can't do yd. */
    if (!(zlecmds[k2].flags & ZLE_MOVEMENT)) {
	feep();
	return -1;
    }

    /* Now we need to execute the movement command, to see where it *
     * actually goes.  virangeflag here indicates to the movement   *
     * function that it should place the cursor at the end of the   *
     * range, rather than where the cursor would actually go if it  *
     * were executed normally.  This makes a difference to some     *
     * commands, but not all.  For example, if searching forward    *
     * for a character, under normal circumstances the cursor lands *
     * on the character.  For a range, the range must include the   *
     * character, so the cursor gets placed after the character if  *
     * virangeflag is set.  vi-match-bracket needs to change the    *
     * value of virangeflag under some circumstances, meaning that  *
     * we need to change the *starting* position.                   */
    t0 = cs;
    virangeflag = 1;
    wordflag = wf;
    obeep = opts[BEEP];
    opts[BEEP] = 0;
    (*zlecmds[k2].func) ();
    wordflag = 0;
    opts[BEEP] = obeep;
    if (cs == t0) {
	/* An error occured -- couldn't move.  The movement command didn't *
	 * feep, because we set NO_BEEP for the duration of the command.   */
	feep();
	virangeflag = 0;
	return -1;
    }
    if(virangeflag == -1)
	t0++;
    virangeflag = 0;

    /* get the range the right way round */
    if (cs > t0) {
	int tmp = cs;
	cs = t0;
	t0 = tmp;
    }

    /* Was it a line-oriented move?  In this case, entire lines are taken. *
     * The terminating newline is left out of the range, which the real    *
     * command must deal with appropriately.  At this point we just need   *
     * to make the range encompass entire lines.                           */
    if (zlecmds[k2].flags & ZLE_LINEMOVE) {
	int newcs = findbol();
	cs = t0;
	t0 = findeol();
	cs = newcs;
	vilinerange = 1;
    }
    return t0;
}
Example #7
0
static int
getvirange(int wf)
{
    int pos = zlecs, mpos = mark, ret = 0;
    int visual = region_active; /* movement command might set it */
    int mult1 = zmult, hist1 = histline;
    Thingy k2;

    if (visual) {
	if (!zlell)
	    return -1;
	pos = mark;
	vilinerange = (visual == 2);
	region_active = 0;
    } else {
	virangeflag = 1;
	wordflag = wf;
	mark = -1;
	/* use operator-pending keymap if one exists */
	Keymap km = openkeymap("viopp");
	if (km)
	    selectlocalmap(km);
	/* Now we need to execute the movement command, to see where it *
	 * actually goes.  virangeflag here indicates to the movement   *
	 * function that it should place the cursor at the end of the   *
	 * range, rather than where the cursor would actually go if it  *
	 * were executed normally.  This makes a difference to some     *
	 * commands, but not all.  For example, if searching forward    *
	 * for a character, under normal circumstances the cursor lands *
	 * on the character.  For a range, the range must include the   *
	 * character, so the cursor gets placed after the character if  *
	 * virangeflag is set.                                          */
	zmod.flags &= ~MOD_TMULT;
	do {
	    vilinerange = 0;
	    prefixflag = 0;
	    if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) ||
		    k2 == Th(z_sendbreak)) {
		wordflag = 0;
		virangeflag = 0;
		mark = mpos;
		return -1;
	    }
	    /*
	     * With k2 == bindk, the command key is repeated:
	     * a number of lines is used.  If the function used
	     * returns 1, we fail.
	     */
	    if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1))
		ret = -1;
	    if(vichgrepeat)
		zmult = mult1;
	    else
		zmult = mult1 * zmod.tmult;
	} while(prefixflag && !ret);
	wordflag = 0;
	selectlocalmap(NULL);

	/* It is an error to use a non-movement command to delimit the *
	 * range.  We here reject the case where the command modified  *
	 * the line, or selected a different history line.             */
	if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) {
	    histline = hist1;
	    ZS_memcpy(zleline, lastline, zlell = lastll);
	    zlecs = pos;
	    mark = mpos;
	    virangeflag = 0;
	    return -1;
	}

	/* Can't handle an empty file.  Also, if the movement command *
	 * failed, or didn't move, it is an error.                    */
	if (!zlell || (zlecs == pos && (mark == -1 || mark == zlecs) &&
		    virangeflag != 2) || ret == -1) {
	    mark = mpos;
	    virangeflag = 0;
	    return -1;
	}
	virangeflag = 0;

	/* if the mark has moved, ignore the original cursor position *
	 * and use the mark.                                          */
	if (mark != -1)
	    pos = mark;
    }
    mark = mpos;

    /* Get the range the right way round.  zlecs is placed at the *
     * start of the range, and pos (the return value of this   *
     * function) is the end.                                   */
    if (zlecs > pos) {
	int tmp = zlecs;
	zlecs = pos;
	pos = tmp;
    }

    /* visual selection mode needs to include additional position */
    if (visual == 1 && pos < zlell && invicmdmode())
	INCPOS(pos);

    /* Was it a line-oriented move?  If so, the command will have set *
     * the vilinerange flag.  In this case, entire lines are taken,   *
     * rather than just the sequence of characters delimited by pos   *
     * and zlecs.  The terminating newline is left out of the range,  *
     * which the real command must deal with appropriately.  At this  *
     * point we just need to make the range encompass entire lines.   */
    vilinerange = (zmod.flags & MOD_LINE) ||
	    (vilinerange && !(zmod.flags & MOD_CHAR));
    if (vilinerange) {
	int newcs = findbol();
	lastcol = zlecs - newcs;
	zlecs = pos;
	pos = findeol();
	zlecs = newcs;
    } else if (!visual) {
	/* for a character-wise move don't include a newline at the *
	 * end of the range                                         */
	int prev = pos;
	DECPOS(prev);
	if (zleline[prev] == ZWC('\n'))
	    pos = prev;
    }
    return pos;
}