summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--Src/Zle/complist.c31
-rw-r--r--Src/Zle/zle.h24
-rw-r--r--Src/Zle/zle_hist.c528
-rw-r--r--Src/Zle/zle_main.c17
-rw-r--r--Src/Zle/zle_misc.c92
-rw-r--r--Src/Zle/zle_move.c138
-rw-r--r--Src/Zle/zle_refresh.c9
-rw-r--r--Src/Zle/zle_thingy.c11
-rw-r--r--Src/Zle/zle_utils.c51
-rw-r--r--Src/Zle/zle_vi.c3
-rw-r--r--Src/Zle/zle_word.c1
-rw-r--r--Src/utils.c81
-rw-r--r--Src/zsh.h11
14 files changed, 652 insertions, 355 deletions
diff --git a/ChangeLog b/ChangeLog
index 7a9c913ea..f14780fea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2008-04-20 Peter Stephenson <p.w.stephenson@ntlworld.com>
-
+
+ * 24853: Src/utils.c, Src/zsh.h, Src/Zle/complist.c,
+ Src/Zle/zle.h, Src/Zle/zle_hist.c, Src/Zle/zle_main.c,
+ Src/Zle/zle_misc.c, Src/Zle/zle_move.c, Src/Zle/zle_refresh.c,
+ Src/Zle/zle_thingy.c, Src/Zle/zle_utils.c, Src/Zle/zle_vi.c,
+ Src/Zle/zle_word.c: use metafied strings for inner loops
+ involving history, with consequent changes for similar code
+ such as execute-name-command, plus some utility functions.
+
* 24852: Src/zle_main.c (Jun T.), Src/Zle/zle_vi.c: more
combining chars fallout.
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index f441ae530..651a5103c 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -2432,7 +2432,7 @@ domenuselect(Hookdef dummy, Chdata dat)
}
first = 0;
if (mode == MM_INTER)
- statusline = stringaszleline(status, 0, &statusll, NULL, NULL);
+ statusline = status;
else if (mode) {
int l = sprintf(status, "%s%sisearch%s: ",
((msearchstate & MS_FAILED) ? "failed " : ""),
@@ -2441,17 +2441,12 @@ domenuselect(Hookdef dummy, Chdata dat)
strncat(status, msearchstr, MAX_STATUS - l - 1);
- statusline = stringaszleline(status, 0, &statusll, NULL, NULL);
+ statusline = status;
} else {
statusline = NULL;
- statusll = 0;
}
zrefresh();
- if (statusline) {
- free(statusline);
- statusline = NULL;
- statusll = 0;
- }
+ statusline = NULL;
inselect = 1;
if (noselect) {
broken = 1;
@@ -2622,12 +2617,10 @@ domenuselect(Hookdef dummy, Chdata dat)
if (nmatches < 1 || !minfo.cur || !*(minfo.cur)) {
nolist = 1;
if (mode == MM_INTER) {
- statusline = stringaszleline(status, 0,
- &statusll, NULL, NULL);
+ statusline = status;
} else {
/* paranoia */
statusline = NULL;
- statusll = 0;
}
if (nmessages) {
showinglist = -2;
@@ -2645,11 +2638,7 @@ domenuselect(Hookdef dummy, Chdata dat)
zrefresh();
showinglist = clearlist = 0;
}
- if (statusline) {
- free(statusline);
- statusline = NULL;
- statusll = 0;
- }
+ statusline = NULL;
goto getk;
}
@@ -2763,19 +2752,13 @@ domenuselect(Hookdef dummy, Chdata dat)
if (nolist) {
if (mode == MM_INTER) {
- statusline = stringaszleline(status, 0,
- &statusll, NULL, NULL);
+ statusline = status;
} else {
/* paranoia */
statusline = NULL;
- statusll = 0;
}
zrefresh();
- if (statusline) {
- free(statusline);
- statusline = NULL;
- statusll = 0;
- }
+ statusline = NULL;
goto getk;
}
if (mode)
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index bed5888cb..a91d84400 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -74,10 +74,22 @@ typedef wint_t ZLE_INT_T;
#define LASTFULLCHAR lastchar_wide
#define LASTFULLCHAR_T ZLE_INT_T
-/* We may need to handle combining character alignment */
+/*
+ * We may need to handle combining character alignment.
+ * The following fix up the position of the cursor so that it
+ * never ends up over a zero-width punctuation character following
+ * an alphanumeric character. The first is used if we were
+ * moving the cursor left, the second if we were moving right or
+ * if something under the cursor may have changed.
+ */
#define CCLEFT() alignmultiwordleft(&zlecs, 1)
#define CCRIGHT() alignmultiwordright(&zlecs, 1)
/*
+ * Same for any other position
+ */
+#define CCLEFTPOS(pos) alignmultiwordleft(&pos, 1)
+#define CCRIGHTPOS(pos) alignmultiwordright(&pos, 1)
+/*
* Increment or decrement the cursor position, skipping over
* combining characters.
*/
@@ -151,6 +163,8 @@ static inline int ZS_strncmp(ZLE_STRING_T s1, ZLE_STRING_T s2, size_t l)
/* Combining character alignment: none in this mode */
#define CCLEFT()
#define CCRIGHT()
+#define CCLEFTPOS()
+#define CCRIGHTPOS()
/*
* Increment or decrement the cursor position: simple in this case.
*/
@@ -235,7 +249,13 @@ struct modifier {
#define CUT_FRONT (1<<0) /* Text goes in front of cut buffer */
#define CUT_REPLACE (1<<1) /* Text replaces cut buffer */
-#define CUT_RAW (1<<2) /* Raw character counts (not used in cut itself) */
+#define CUT_RAW (1<<2) /*
+ * Raw character counts (not used in cut itself).
+ * This is used when the values are offsets
+ * into the zleline array rather than numbers
+ * of visible characters directly input by
+ * the user.
+ */
/* undo system */
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index 066750e23..9d65b3516 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -54,8 +54,9 @@ int previous_search_len = 0;
struct zle_text {
- ZLE_STRING_T text;
- int len;
+ /* Metafied, NULL-terminated string */
+ char *text;
+ /* 1 if we have allocated space for text */
int alloced;
};
@@ -67,30 +68,18 @@ struct zle_text {
* Each use of this must have a matching zletextfree() in order
* to free up the allocated line, if any. (N.B.: each use *of
* the function*, not just each use of a struct zle_text.)
- *
- * TODO: This is quite inefficient. We could convert zlinecmp and
- * zlinefind to take a metafied string as input and acquire a (wide)
- * character from it whenever needed, which would also require storing
- * zle_text as a metafied string in remember_edits(). However, the
- * following is good enough for now (although searching a really huge
- * history might not be so much fun).
*/
static void
zletext(Histent ent, struct zle_text *zt)
{
- char *duptext;
-
if (ent->zle_text) {
zt->text = ent->zle_text;
- zt->len = ent->zle_len;
zt->alloced = 0;
return;
}
- duptext = ztrdup(ent->node.nam);
- zt->text = stringaszleline(duptext, 0, &zt->len, NULL, NULL);
- zsfree(duptext);
+ zt->text = ztrdup(ent->node.nam);
zt->alloced = 1;
}
@@ -111,14 +100,15 @@ remember_edits(void)
{
Histent ent = quietgethist(histline);
if (ent) {
- if (!ent->zle_text || ent->zle_len != zlell ||
- ZS_memcmp(ent->zle_text, zleline, zlell) != 0) {
+ char *line =
+ zlemetaline ? zlemetaline :
+ zlelineasstring(zleline, zlell, 0, NULL, NULL, 0);
+ if (!ent->zle_text || strcmp(line, ent->zle_text) != 0) {
if (ent->zle_text)
free(ent->zle_text);
- ent->zle_text = zalloc(zlell * ZLE_CHAR_SIZE);
- ent->zle_len = zlell;
- ZS_memcpy(ent->zle_text, zleline, zlell);
- }
+ ent->zle_text = zlemetaline ? ztrdup(line) : line;
+ } else if (!zlemetaline)
+ free(line);
}
}
@@ -132,7 +122,6 @@ forget_edits(void)
if (he->zle_text) {
free(he->zle_text);
he->zle_text = NULL;
- he->zle_len = 0;
}
}
}
@@ -150,65 +139,99 @@ forget_edits(void)
*/
static int
-zlinecmp(ZLE_STRING_T histp, int histl, ZLE_STRING_T inputp, int inputl)
+zlinecmp(const char *histp, const char *inputp)
{
- int cnt;
+ const char *hptr = histp, *iptr = inputp;
+#ifdef MULTIBYTE_SUPPORT
+ mbstate_t hstate, istate;
+#endif
- if (histl < inputl) {
- /* Not identical, second string is not a prefix. */
- return 3;
+ while (*hptr == *iptr) {
+ hptr++;
+ iptr++;
}
- if (!ZS_memcmp(histp, inputp, inputl)) {
- /* Common prefix is identical */
- /* If lines are identical return 0 */
- if (histl == inputl)
+ if (!*iptr) {
+ if (!*hptr) {
+ /* strings are the same */
return 0;
- /* Second string is a prefix of the first */
- return -1;
+ } else {
+ /* inputp is a prefix */
+ return -1;
+ }
}
- for (cnt = inputl; cnt; cnt--) {
- if ((ZLE_INT_T)*inputp++ != ZC_tolower(*histp++))
+#ifdef MULTIBYTE_SUPPORT
+ memset(&hstate, 0, sizeof(hstate));
+ memset(&istate, 0, sizeof(istate));
+#endif
+
+ /* look for lower case versions */
+ while (*histp && *inputp) {
+#ifdef MULTIBYTE_SUPPORT
+ wint_t hwc, iwc;
+ int hlen, ilen;
+
+ hlen = mb_metacharlenconv_r(histp, &hwc, &hstate);
+ ilen = mb_metacharlenconv_r(inputp, &iwc, &istate);
+
+ if (hwc == WEOF || iwc == WEOF) {
+ /* can't convert, compare input characters */
+ if (ilen != hlen || memcmp(histp, inputp, hlen) != 0)
+ return 3;
+ } else if (towlower(hwc) != iwc)
return 3;
+
+ histp += hlen;
+ inputp += ilen;
+#else
+ if (tulower(*histp++) != *inputp++)
+ return 3;
+#endif
}
- /* Is second string is lowercase version of first? */
- if (histl == inputl)
- return 1;
- /* Second string is lowercase prefix of first */
- return 2;
+ if (!*inputp) {
+ /* one string finished, if it's the input... */
+ if (!*histp)
+ return 1; /* ...same, else */
+ else
+ return 2; /* ...prefix */
+ }
+ /* Different */
+ return 3;
}
/*
- * Search for needle in haystack. Haystack and needle are ZLE strings
- * of the indicated length. Start the search at position
- * pos in haystack. Search forward if dir > 0, otherwise search
- * backward. sens is used to test against the return value of linecmp.
+ * Search for needle in haystack. Haystack and needle are metafied strings.
+ * Start the search at position pos in haystack.
+ * Search forward if dir > 0, otherwise search backward.
+ * sens is used to test against the return value of linecmp.
+ *
+ * Return the pointer to the location in haystack found, else NULL.
+ *
+ * We assume we'll only find needle at some sensible position in a multibyte
+ * string, so we don't bother calculating multibyte character lengths for
+ * incrementing and decrementing the search position.
*/
-static ZLE_STRING_T
-zlinefind(ZLE_STRING_T haystack, int haylen, int pos,
- ZLE_STRING_T needle, int needlen, int dir, int sens)
+static char *
+zlinefind(char *haystack, int pos, char *needle, int dir, int sens)
{
- ZLE_STRING_T s = haystack + pos;
- int slen = haylen - pos;
+ char *s = haystack + pos;
if (dir > 0) {
- while (slen) {
- if (zlinecmp(s, slen, needle, needlen) < sens)
+ while (*s) {
+ if (zlinecmp(s, needle) < sens)
return s;
s++;
- slen--;
}
} else {
for (;;) {
- if (zlinecmp(s, slen, needle, needlen) < sens)
+ if (zlinecmp(s, needle) < sens)
return s;
if (s == haystack)
break;
s--;
- slen++;
}
}
@@ -257,7 +280,7 @@ upline(void)
if ((zlecs += lastcol) >= x) {
zlecs = x;
if (zlecs > findbol() && invicmdmode())
- zlecs--;
+ DECCS();
}
}
return n;
@@ -341,7 +364,7 @@ downline(void)
if ((zlecs += lastcol) >= x) {
zlecs = x;
if (zlecs > findbol() && invicmdmode())
- zlecs--;
+ DECCS();
}
}
return n;
@@ -421,16 +444,26 @@ downhistory(UNUSED(char **args))
return 0;
}
-static int histpos, srch_hl, srch_cs = -1;
-static ZLE_STRING_T srch_str;
+/*
+ * Values remembered for history searches to enable repetition.
+ * srch_hl remembers the old value of histline, to see if it's changed
+ * since the last search.
+ * srch_cs remembers the old value of zlecs for the same purpose (it is
+ * not use for any other purpose, i.e. does not need to be a valid
+ * index into anything).
+ * srch_str is the metafied search string, as extracted from the start
+ * of zleline.
+ */
+static int srch_hl, srch_cs = -1;
+static char *srch_str;
/**/
int
historysearchbackward(char **args)
{
Histent he;
- int n = zmult, hp;
- ZLE_STRING_T str;
+ int n = zmult, histpos;
+ char *str;
struct zle_text zt;
if (zmult < 0) {
@@ -440,46 +473,45 @@ historysearchbackward(char **args)
zmult = n;
return ret;
}
- if (*args)
- str = stringaszleline(*args, 0, &hp, NULL, NULL);
- else {
+ if (*args) {
+ str = *args;
+ } else {
+ char *line = zlelineasstring(zleline, zlell, 0, NULL, NULL, 0);
if (histline == curhist || histline != srch_hl || zlecs != srch_cs ||
- mark != 0 || ZS_memcmp(srch_str, zleline, histpos) != 0) {
- zfree(srch_str, histpos);
- for (histpos = 0; histpos < zlell && !ZC_iblank(zleline[histpos]); histpos++) ;
+ mark != 0 || strncmp(srch_str, line, histpos) != 0) {
+ free(srch_str);
+ for (histpos = 0; histpos < zlell && !ZC_iblank(zleline[histpos]);
+ histpos++)
+ ;
if (histpos < zlell)
histpos++;
- srch_str = zalloc(histpos * ZLE_CHAR_SIZE);
- ZS_memcpy(srch_str, zleline, histpos);
+ /* ensure we're not on a combining character */
+ CCRIGHTPOS(histpos);
+ /* histpos from now on on is an index into the metafied string */
+ srch_str = zlelineasstring(zleline, histpos, 0, NULL, NULL, 0);
}
+ free(line);
str = srch_str;
- hp = histpos;
}
- if (!(he = quietgethist(histline))) {
- if (*args)
- free(str);
+ if (!(he = quietgethist(histline)))
return 1;
- }
+
while ((he = movehistent(he, -1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->node.flags & HIST_DUP)
continue;
zletext(he, &zt);
- if (zlinecmp(zt.text, zt.len, str, hp) < 0 &&
- (*args || zlell != zt.len || ZS_memcmp(zt.text, str, zlell))) {
+ if (zlinecmp(zt.text, str) < 0 &&
+ (*args || strcmp(zt.text, str) != 0)) {
if (--n <= 0) {
zle_setline(he);
srch_hl = histline;
srch_cs = zlecs;
- if (*args)
- free(str);
zletextfree(&zt);
return 0;
}
}
zletextfree(&zt);
}
- if (*args)
- free(str);
return 1;
}
@@ -488,8 +520,8 @@ int
historysearchforward(char **args)
{
Histent he;
- int n = zmult, hp;
- ZLE_STRING_T str;
+ int n = zmult, histpos;
+ char *str;
struct zle_text zt;
if (zmult < 0) {
@@ -499,46 +531,43 @@ historysearchforward(char **args)
zmult = n;
return ret;
}
- if (*args)
- str = stringaszleline(*args, 0, &hp, NULL, NULL);
- else {
+ if (*args) {
+ str = *args;
+ } else {
+ char *line = zlelineasstring(zleline, zlell, 0, NULL, NULL, 0);
if (histline == curhist || histline != srch_hl || zlecs != srch_cs ||
- mark != 0 || ZS_memcmp(srch_str, zleline, histpos) != 0) {
- zfree(srch_str, histpos * ZLE_CHAR_SIZE);
- for (histpos = 0; histpos < zlell && !ZC_iblank(zleline[histpos]); histpos++) ;
+ mark != 0 || strncmp(srch_str, line, histpos) != 0) {
+ free(srch_str);
+ for (histpos = 0; histpos < zlell && !ZC_iblank(zleline[histpos]);
+ histpos++)
+ ;
if (histpos < zlell)
histpos++;
- srch_str = zalloc(histpos * ZLE_CHAR_SIZE);
- ZS_memcpy(srch_str, zleline, histpos);
+ CCRIGHT();
+ srch_str = zlelineasstring(zleline, histpos, 0, NULL, NULL, 0);
}
+ free(line);
str = srch_str;
- hp = histpos;
}
- if (!(he = quietgethist(histline))) {
- if (*args)
- free(str);
+ if (!(he = quietgethist(histline)))
return 1;
- }
+
while ((he = movehistent(he, 1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->node.flags & HIST_DUP)
continue;
zletext(he, &zt);
- if (zlinecmp(zt.text, zt.len, str, hp) < (he->histnum == curhist) &&
- (*args || zlell != zt.len || ZS_memcmp(zt.text, str, zlell))) {
+ if (zlinecmp(zt.text, str) < (he->histnum == curhist) &&
+ (*args || strcmp(zt.text, str) != 0)) {
if (--n <= 0) {
zle_setline(he);
srch_hl = histline;
srch_cs = zlecs;
- if (*args)
- free(str);
zletextfree(&zt);
return 0;
}
}
zletextfree(&zt);
}
- if (*args)
- free(str);
return 1;
}
@@ -741,29 +770,21 @@ insertlastword(char **args)
void
zle_setline(Histent he)
{
+ int remetafy;
+ if (zlemetaline) {
+ unmetafy_line();
+ remetafy = 1;
+ } else
+ remetafy = 0;
remember_edits();
mkundoent();
histline = he->histnum;
- if (he->zle_text) {
- /*
- * Optimise out conversion to metafied string and back.
- * Remember convention of extra 2 characters spare.
- */
- free(zleline);
- linesz = zlell = he->zle_len;
- zleline = zalloc((zlell + 2) * ZLE_CHAR_SIZE);
- ZS_memcpy(zleline, he->zle_text, zlell);
-
- if ((zlecs = zlell) && invicmdmode())
- DECCS();
- } else {
- setline(he->node.nam, ZSL_COPY|ZSL_TOEND);
- }
- /* Move right if we're on a zero-width combining character */
- CCRIGHT();
+ setline(he->zle_text ? he->zle_text : he->node.nam, ZSL_COPY|ZSL_TOEND);
setlastline();
clearlist = 1;
+ if (remetafy)
+ metafy_line();
}
/**/
@@ -783,6 +804,8 @@ int
zle_goto_hist(int ev, int n, int skipdups)
{
Histent he = quietgethist(ev);
+ char *line = zlelineasstring(zleline, zlell, 0, NULL, NULL, 1);
+
if (!he || !(he = movehistent(he, n, hist_skip_flags)))
return 1;
if (skipdups && n) {
@@ -793,7 +816,7 @@ zle_goto_hist(int ev, int n, int skipdups)
int ret;
zletext(he, &zt);
- ret = zlinecmp(zt.text, zt.len, zleline, zlell);
+ ret = zlinecmp(zt.text, line);
zletextfree(&zt);
if (ret)
break;
@@ -961,7 +984,7 @@ get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int
*nomatch = (isrch_spots[num].flags & ISS_FAILING);
}
-#define ISEARCH_PROMPT ZWS("failing XXX-i-search: ")
+#define ISEARCH_PROMPT "failing XXX-i-search: "
#define NORM_PROMPT_POS 8
#define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14)
@@ -969,17 +992,18 @@ get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int
static void
doisearch(char **args, int dir)
{
- ZLE_STRING_T ibuf = zhalloc(80 * ZLE_CHAR_SIZE);
- ZLE_STRING_T sbuf = ibuf + FIRST_SEARCH_CHAR;
- ZLE_STRING_T last_line = NULL;
+ char *ibuf = zhalloc(80);
+ char *sbuf = ibuf + FIRST_SEARCH_CHAR;
+ char *last_line = NULL;
struct zle_text zt;
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, savekeys = -1, feep = 0, last_len;
+ int hl = histline, savekeys = -1, feep = 0;
Thingy cmd;
char *okeymap;
Histent he;
+ ZleIntFunc exitfn = (ZleIntFunc)0;
if (!(he = quietgethist(hl)))
return;
@@ -994,18 +1018,21 @@ doisearch(char **args, int dir)
ungetbytes(arg, len);
}
- ZS_strcpy(ibuf, ISEARCH_PROMPT);
- ZS_memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? ZWS("fwd") : ZWS("bck"), 3);
- remember_edits();
+ strcpy(ibuf, ISEARCH_PROMPT);
+ /* careful with fwd/bck: we don't want the NULL copied */
+ memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
okeymap = ztrdup(curkeymapname);
- zletext(he, &zt);
selectkeymap("main", 1);
- pos = zlecs;
+
+ metafy_line();
+ remember_edits();
+ zletext(he, &zt);
+ pos = zlemetacs;
for (;;) {
/* Remember the current values in case search fails (doesn't push). */
- set_isrch_spot(top_spot, hl, pos, zlecs, sbptr, dir, nomatch);
- if (sbptr == 1 && sbuf[0] == ZWC('^')) {
- zlecs = 0;
+ set_isrch_spot(top_spot, hl, pos, zlemetacs, sbptr, dir, nomatch);
+ if (sbptr == 1 && sbuf[0] == '^') {
+ zlemetacs = 0;
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
} else if (sbptr > 0) {
@@ -1016,21 +1043,28 @@ doisearch(char **args, int dir)
*/
if (last_line)
free(last_line);
- last_line = zalloc(zt.len * ZLE_CHAR_SIZE);
- ZS_memcpy(last_line, zt.text, zt.len);
- last_len = zt.len;
+ last_line = ztrdup(zt.text);
for (;;) {
- ZLE_STRING_T t;
-
+ char *t;
+
+ /*
+ * If instructed, move past a match position:
+ * backwards if searching backwards (skipping
+ * the line if we're at the start), forwards
+ * if searching forwards (skipping a line if we're
+ * at the end).
+ */
if (skip_pos) {
if (dir < 0) {
if (pos == 0)
skip_line = 1;
else
- pos -= 1;
- } else if (sbuf[0] != ZWC('^')) {
- if (pos >= zt.len - 1)
+ pos = backwardmetafiedchar(zlemetaline,
+ zlemetaline + pos,
+ NULL) - zlemetaline;
+ } else if (sbuf[0] != '^') {
+ if (pos >= strlen(zt.text) - 1)
skip_line = 1;
else
pos += 1;
@@ -1038,25 +1072,33 @@ doisearch(char **args, int dir)
skip_line = 1;
skip_pos = 0;
}
- if (!skip_line && ((sbuf[0] == ZWC('^')) ?
- (t = zlinecmp(zt.text, zt.len, sbuf + 1, sbptr - 1) < sens
- ? zt.text : NULL) :
- (t = zlinefind(zt.text, zt.len, pos, sbuf,
- sbptr, dir, sens)))) {
+ /*
+ * First search for a(nother) match within the
+ * current line, unless we've been told to skip it.
+ */
+ sbuf[sbptr] = '\0';
+ if (!skip_line && ((sbuf[0] == '^') ?
+ (t = (zlinecmp(zt.text, sbuf + 1) < sens
+ ? zt.text : NULL)) :
+ (t = zlinefind(zt.text, pos, sbuf, dir, sens)))) {
zle_setline(he);
pos = t - zt.text;
- zlecs = pos +
- (dir == 1 ? sbptr - (sbuf[0] == ZWC('^')) : 0);
+ zlemetacs = pos +
+ (dir == 1 ? sbptr - (sbuf[0] == '^') : 0);
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
break;
}
+ /*
+ * If not found within that line, move through
+ * the history to try again.
+ */
if (!(zlereadflags & ZLRF_HISTORY)
|| !(he = movehistent(he, dir, hist_skip_flags))) {
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, &zlecs, &sbptr,
+ get_isrch_spot(top_spot, &hl, &pos, &zlemetacs, &sbptr,
&dir, &nomatch);
if (!nomatch) {
feep = 1;
@@ -1072,18 +1114,18 @@ doisearch(char **args, int dir)
hl = he->histnum;
zletextfree(&zt);
zletext(he, &zt);
- pos = (dir == 1) ? 0 : zt.len;
- skip_line = isset(HISTFINDNODUPS) ? !!(he->node.flags & HIST_DUP)
- : (zt.len == last_len &&
- !ZS_memcmp(zt.text, last_line, zt.len));
+ pos = (dir == 1) ? 0 : strlen(zt.text);
+ skip_line = isset(HISTFINDNODUPS)
+ ? !!(he->node.flags & HIST_DUP)
+ : !strcmp(zt.text, last_line);
}
} else {
top_spot = 0;
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
}
- sbuf[sbptr] = ZWC('_');
- statusll = sbuf - statusline + sbptr + 1;
+ sbuf[sbptr] = '_';
+ sbuf[sbptr+1] = '\0';
ref:
zrefresh();
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
@@ -1093,7 +1135,7 @@ doisearch(char **args, int dir)
zle_setline(he);
zletextfree(&zt);
zletext(he, &zt);
- zlecs = i;
+ zlemetacs = i;
break;
}
if(cmd == Th(z_clearscreen)) {
@@ -1109,7 +1151,7 @@ doisearch(char **args, int dir)
} else if(cmd == Th(z_vibackwarddeletechar) ||
cmd == Th(z_backwarddeletechar)) {
if (top_spot)
- get_isrch_spot(--top_spot, &hl, &pos, &zlecs, &sbptr,
+ get_isrch_spot(--top_spot, &hl, &pos, &zlemetacs, &sbptr,
&dir, &nomatch);
else
feep = 1;
@@ -1120,67 +1162,66 @@ doisearch(char **args, int dir)
he = quietgethist(hl);
zletextfree(&zt);
zletext(he, &zt);
- if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == ZWC('^'))) {
- int i = zlecs;
+ if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
+ int i = zlemetacs;
zle_setline(he);
- zlecs = i;
+ zlemetacs = i;
}
- ZS_memcpy(ibuf + NORM_PROMPT_POS,
- (dir == 1) ? ZWS("fwd") : ZWS("bck"), 3);
+ memcpy(ibuf + NORM_PROMPT_POS,
+ (dir == 1) ? "fwd" : "bck", 3);
continue;
} else if(cmd == Th(z_acceptandhold)) {
- acceptandhold(zlenoargs);
+ exitfn = acceptandhold;
break;
} else if(cmd == Th(z_acceptandinfernexthistory)) {
- acceptandinfernexthistory(zlenoargs);
+ exitfn = acceptandinfernexthistory;
break;
} else if(cmd == Th(z_acceptlineanddownhistory)) {
- acceptlineanddownhistory(zlenoargs);
+ exitfn = acceptlineanddownhistory;
break;
} else if(cmd == Th(z_acceptline)) {
- acceptline(zlenoargs);
+ exitfn = acceptline;
break;
} else if(cmd == Th(z_historyincrementalsearchbackward)) {
- set_isrch_spot(top_spot++, hl, pos, zlecs, sbptr, dir, nomatch);
+ set_isrch_spot(top_spot++, hl, pos, zlemetacs, sbptr, dir, nomatch);
if (dir != -1)
dir = -1;
else
skip_pos = 1;
goto rpt;
} else if(cmd == Th(z_historyincrementalsearchforward)) {
- set_isrch_spot(top_spot++, hl, pos, zlecs, sbptr, dir, nomatch);
+ set_isrch_spot(top_spot++, hl, pos, zlemetacs, sbptr, dir, nomatch);
if (dir != 1)
dir = 1;
else
skip_pos = 1;
goto rpt;
} else if(cmd == Th(z_virevrepeatsearch)) {
- set_isrch_spot(top_spot++, hl, pos, zlecs, sbptr, dir, nomatch);
+ set_isrch_spot(top_spot++, hl, pos, zlemetacs, sbptr, dir, nomatch);
dir = -odir;
skip_pos = 1;
goto rpt;
} else if(cmd == Th(z_virepeatsearch)) {
- set_isrch_spot(top_spot++, hl, pos, zlecs, sbptr, dir, nomatch);
+ set_isrch_spot(top_spot++, hl, pos, zlemetacs, 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((char *)ibuf, sibuf * ZLE_CHAR_SIZE,
- (sibuf + previous_search_len)
- * ZLE_CHAR_SIZE);
+ ibuf = hrealloc((char *)ibuf, sibuf,
+ (sibuf + previous_search_len));
sbuf = ibuf + FIRST_SEARCH_CHAR;
sibuf += previous_search_len;
}
- ZS_memcpy(sbuf, previous_search, sbptr = previous_search_len);
+ memcpy(sbuf, previous_search, sbptr = previous_search_len);
}
- ZS_memcpy(ibuf + NORM_PROMPT_POS,
- (dir == 1) ? ZWS("fwd") : ZWS("bck"), 3);
+ memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
continue;
} else if(cmd == Th(z_viquotedinsert) ||
cmd == Th(z_quotedinsert)) {
if(cmd == Th(z_viquotedinsert)) {
- sbuf[sbptr] = ZWC('^');
+ sbuf[sbptr] = '^';
+ sbuf[sbptr+1] = '\0';
zrefresh();
}
if (getfullchar(0) == ZLEEOF)
@@ -1213,10 +1254,13 @@ doisearch(char **args, int dir)
feep = 1;
continue;
}
- set_isrch_spot(top_spot++, hl, pos, zlecs, sbptr, dir, nomatch);
- if (sbptr >= sibuf - FIRST_SEARCH_CHAR - 2) {
- ibuf = hrealloc((char *)ibuf, sibuf * ZLE_CHAR_SIZE,
- sibuf * 2 * ZLE_CHAR_SIZE);
+ set_isrch_spot(top_spot++, hl, pos, zlemetacs, sbptr, dir, nomatch);
+ if (sbptr >= sibuf - FIRST_SEARCH_CHAR - 2
+#ifdef MULTIBYTE_SUPPORT
+ - 2 * MB_CUR_MAX
+#endif
+ ) {
+ ibuf = hrealloc(ibuf, sibuf, sibuf * 2);
sbuf = ibuf + FIRST_SEARCH_CHAR;
sibuf *= 2;
}
@@ -1224,7 +1268,7 @@ doisearch(char **args, int dir)
* We've supposedly arranged above that lastchar_wide is
* always valid at this point.
*/
- sbuf[sbptr++] = LASTFULLCHAR;
+ sbptr += zlecharasstring(LASTFULLCHAR, sbuf + sbptr);
}
if (feep)
handlefeep(zlenoargs);
@@ -1232,10 +1276,13 @@ doisearch(char **args, int dir)
}
if (sbptr) {
zfree(previous_search, previous_search_len);
- previous_search = zalloc(sbptr * ZLE_CHAR_SIZE);
- ZS_memcpy(previous_search, sbuf, previous_search_len = sbptr);
+ previous_search = zalloc(sbptr);
+ memcpy(previous_search, sbuf, previous_search_len = sbptr);
}
statusline = NULL;
+ unmetafy_line();
+ if (exitfn)
+ exitfn(zlenoargs);
selectkeymap(okeymap, 1);
zsfree(okeymap);
/*
@@ -1252,17 +1299,20 @@ doisearch(char **args, int dir)
static Histent
infernexthist(Histent he, UNUSED(char **args))
{
+ metafy_line();
for (he = movehistent(he, -2, HIST_FOREIGN);
he; he = movehistent(he, -1, HIST_FOREIGN)) {
struct zle_text zt;
zletext(he, &zt);
- if (!zlinecmp(zt.text, zt.len, zleline, zlell)) {
+ if (!zlinecmp(zt.text, zlemetaline)) {
+ unmetafy_line();
zletextfree(&zt);
return movehistent(he, 1, HIST_FOREIGN);
}
zletextfree(&zt);
}
+ unmetafy_line();
return NULL;
}
@@ -1321,7 +1371,7 @@ static int visrchsense;
static int
getvisrchstr(void)
{
- ZLE_STRING_T sbuf = zhalloc(80 * ZLE_CHAR_SIZE);
+ char *sbuf = zhalloc(80);
int sptr = 1, ret = 0, ssbuf = 80, feep = 0;
Thingy cmd;
char *okeymap = ztrdup(curkeymapname);
@@ -1337,11 +1387,11 @@ getvisrchstr(void)
}
clearlist = 1;
statusline = sbuf;
- sbuf[0] = (visrchsense == -1) ? ZWC('?') : ZWC('/');
+ sbuf[0] = (visrchsense == -1) ? '?' : '/';
selectkeymap("main", 1);
while (sptr) {
- sbuf[sptr] = ZWC('_');
- statusll = sptr + 1;
+ sbuf[sptr] = '_';
+ sbuf[sptr] = '\0';
zrefresh();
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
ret = 0;
@@ -1357,32 +1407,52 @@ getvisrchstr(void)
clearscreen(zlenoargs);
} else if(cmd == Th(z_acceptline) ||
cmd == Th(z_vicmdmode)) {
- int newlen;
- sbuf[sptr] = ZWC('\0');
- visrchstr = zlelineasstring(sbuf+1, sptr-1, 0, &newlen, NULL, 0);
- if (!newlen) {
- zsfree(visrchstr);
+ if (sptr) {
+ sbuf[sptr] = ZWC('\0');
+ visrchstr = ztrdup(sbuf+1);
+ } else {
visrchstr = ztrdup(vipenultsrchstr);
}
ret = 1;
sptr = 0;
} else if(cmd == Th(z_backwarddeletechar) ||
- cmd == Th(z_vibackwarddeletechar)) {
- sptr--;
+ cmd == Th(z_vibackwarddeletechar)) {
+ sptr = backwardmetafiedchar(sbuf+1, sbuf+sptr, NULL) - sbuf;
} else if(cmd == Th(z_backwardkillword) ||
- cmd == Th(z_vibackwardkillword)) {
- while(sptr != 1 && ZC_iblank(sbuf[sptr - 1]))
- sptr--;
- if(ZC_iident(sbuf[sptr - 1]))
- while(sptr != 1 && ZC_iident(sbuf[sptr - 1]))
- sptr--;
- else
- while(sptr != 1 && !ZC_iident(sbuf[sptr - 1]) &&
- !ZC_iblank(sbuf[sptr - 1]))
- sptr--;
+ cmd == Th(z_vibackwardkillword)) {
+ convchar_t cc;
+ char *newpos;
+ while (sptr != 1) {
+ newpos = backwardmetafiedchar(sbuf+1, sbuf+sptr, &cc);
+ if (!ZC_iblank(cc))
+ break;
+ sptr = newpos - sbuf;
+ }
+ if (sptr > 1) {
+ newpos = backwardmetafiedchar(sbuf+1, sbuf+sptr, &cc);
+ if (ZC_iident(cc)) {
+ for (;;) {
+ sptr = newpos - sbuf;
+ if (sptr == 1)
+ break;
+ newpos = backwardmetafiedchar(sbuf+1, sbuf+sptr, &cc);
+ if (!ZC_iident(cc))
+ break;
+ }
+ } else {
+ for (;;) {
+ sptr = newpos - sbuf;
+ if (sptr == 1)
+ break;
+ newpos = backwardmetafiedchar(sbuf+1, sbuf+sptr, &cc);
+ if (ZC_iident(cc) || ZC_iblank(cc))
+ break;
+ }
+ }
+ }
} else if(cmd == Th(z_viquotedinsert) || cmd == Th(z_quotedinsert)) {
if(cmd == Th(z_viquotedinsert)) {
- sbuf[sptr] = ZWC('^');
+ sbuf[sptr] = '^';
zrefresh();
}
if (getfullchar(0) == ZLEEOF)
@@ -1405,12 +1475,11 @@ getvisrchstr(void)
}
ins:
if (sptr == ssbuf - 1) {
- ZLE_STRING_T newbuf =
- (ZLE_STRING_T) zhalloc((ssbuf *= 2) * ZLE_CHAR_SIZE);
- ZS_strcpy(newbuf, sbuf);
+ char *newbuf = (char *)zhalloc((ssbuf *= 2));
+ strcpy(newbuf, sbuf);
statusline = sbuf = newbuf;
}
- sbuf[sptr++] = LASTFULLCHAR;
+ sptr += zlecharasstring(LASTFULLCHAR, sbuf + sptr);
} else {
feep = 1;
}
@@ -1471,8 +1540,6 @@ int
virepeatsearch(UNUSED(char **args))
{
Histent he;
- ZLE_STRING_T srcstr;
- int srclen;
int n = zmult;
struct zle_text zt;
@@ -1482,28 +1549,26 @@ virepeatsearch(UNUSED(char **args))
n = -n;
visrchsense = -visrchsense;
}
- srcstr = stringaszleline(visrchstr, 0, &srclen, NULL, NULL);
if (!(he = quietgethist(histline)))
return 1;
+ metafy_line();
while ((he = movehistent(he, visrchsense, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->node.flags & HIST_DUP)
continue;
zletext(he, &zt);
- if (zlinecmp(zt.text, zt.len, zleline, zlell) &&
- (*visrchstr == '^'?
- (zt.len == srclen - 1 &&
- ZS_memcmp(zt.text, srcstr + 1, zt.len) == 0) :
- zlinefind(zt.text, zt.len, 0, srcstr, srclen, 1, 1) != 0)) {
+ if (zlinecmp(zt.text, zlemetaline) &&
+ (*visrchstr == '^' ? strpfx(zt.text, visrchstr + 1) :
+ zlinefind(zt.text, 0, visrchstr, 1, 1) != 0)) {
if (--n <= 0) {
+ unmetafy_line();
zletextfree(&zt);
zle_setline(he);
- free(srcstr);
return 0;
}
}
zletextfree(&zt);
}
- free(srcstr);
+ unmetafy_line();
return 1;
}
@@ -1540,13 +1605,20 @@ historybeginningsearchbackward(char **args)
}
if (!(he = quietgethist(histline)))
return 1;
+ metafy_line();
while ((he = movehistent(he, -1, hist_skip_flags))) {
+ int tst;
+ char sav;
if (isset(HISTFINDNODUPS) && he->node.flags & HIST_DUP)
continue;
zletext(he, &zt);
- if (zlinecmp(zt.text, zt.len, zleline, zlecs) < 0 &&
- zlinecmp(zt.text, zt.len, zleline, zlell)) {
+ sav = zlemetaline[zlemetacs];
+ zlemetaline[zlemetacs] = '\0';
+ tst = zlinecmp(zt.text, zlemetaline);
+ zlemetaline[zlemetacs] = sav;
+ if (tst < 0 && zlinecmp(zt.text, zlemetaline)) {
if (--n <= 0) {
+ unmetafy_line();
zletextfree(&zt);
zle_setline(he);
zlecs = cpos;
@@ -1556,6 +1628,7 @@ historybeginningsearchbackward(char **args)
}
zletextfree(&zt);
}
+ unmetafy_line();
return 1;
}
@@ -1580,14 +1653,20 @@ historybeginningsearchforward(char **args)
}
if (!(he = quietgethist(histline)))
return 1;
+ metafy_line();
while ((he = movehistent(he, 1, hist_skip_flags))) {
+ char sav;
+ int tst;
if (isset(HISTFINDNODUPS) && he->node.flags & HIST_DUP)
continue;
zletext(he, &zt);
- if (zlinecmp(zt.text, zt.len, zleline, zlecs) <
- (he->histnum == curhist) &&
- zlinecmp(zt.text, zt.len, zleline, zlell)) {
+ sav = zlemetaline[zlemetacs];
+ zlemetaline[zlemetacs] = '\0';
+ tst = zlinecmp(zt.text, zlemetaline) < (he->histnum == curhist);
+ zlemetaline[zlemetacs] = sav;
+ if (tst && zlinecmp(zt.text, zlemetaline)) {
if (--n <= 0) {
+ unmetafy_line();
zletextfree(&zt);
zle_setline(he);
zlecs = cpos;
@@ -1597,5 +1676,6 @@ historybeginningsearchforward(char **args)
}
zletextfree(&zt);
}
+ unmetafy_line();
return 1;
}
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 713221d0d..280460f81 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -143,12 +143,10 @@ mod_export int lastcmd;
/**/
mod_export Widget compwidget;
-/* the status line, and its length */
+/* the status line, a null-terminated metafied string */
/**/
-mod_export ZLE_STRING_T statusline;
-/**/
-mod_export int statusll;
+mod_export char *statusline;
/* The current history line and cursor position for the top line *
* on the buffer stack. */
@@ -1240,12 +1238,16 @@ zleread(char **lp, char **rp, int flags, int context)
int
execzlefunc(Thingy func, char **args, int set_bindk)
{
- int r = 0, ret = 0;
+ int r = 0, ret = 0, remetafy = 0;
Widget w;
Thingy save_bindk = bindk;
if (set_bindk)
bindk = func;
+ if (zlemetaline) {
+ unmetafy_line();
+ remetafy = 1;
+ }
if(func->flags & DISABLED) {
/* this thingy is not the name of a widget */
@@ -1350,6 +1352,8 @@ execzlefunc(Thingy func, char **args, int set_bindk)
* directly.
*/
CCRIGHT();
+ if (remetafy)
+ metafy_line();
return ret;
}
@@ -1632,8 +1636,7 @@ describekeybriefly(UNUSED(char **args))
if (statusline)
return 1;
clearlist = 1;
- statusline = ZWS("Describe key briefly: _");
- statusll = ZS_strlen(statusline);
+ statusline = "Describe key briefly: _";
zrefresh();
seq = getkeymapcmd(curkeymap, &func, &str);
statusline = NULL;
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index db2d4acce..fd3ab37a9 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -914,24 +914,27 @@ executenamedcommand(char *prmt)
Thingy cmd;
int l, len, feep = 0, listed = 0, curlist = 0;
int ols = (listshown && validlist), olll = lastlistlen;
- ZLE_STRING_T cmdbuf, ptr, zprmt;
+ char *cmdbuf, *ptr;
char *okeymap = ztrdup(curkeymapname);
clearlist = 1;
/* prmt may be constant */
prmt = ztrdup(prmt);
- zprmt = stringaszleline(prmt, 0, &l, NULL, NULL);
- cmdbuf = zhalloc((l + NAMLEN + 2) * ZLE_CHAR_SIZE);
- ZS_memcpy(cmdbuf, zprmt, l);
- free(zprmt);
+ l = strlen(prmt);
+ cmdbuf = (char *)zhalloc(l + NAMLEN + 2 +
+#ifdef MULTIBYTE_SUPPORT
+ 2 * MB_CUR_MAX
+#endif
+ );
+ strcpy(cmdbuf, prmt);
zsfree(prmt);
statusline = cmdbuf;
selectkeymap("main", 1);
ptr = cmdbuf += l;
len = 0;
for (;;) {
- *ptr = ZWC('_');
- statusll = l + len + 1;
+ *ptr = '_';
+ ptr[1] = '\0';
zrefresh();
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
statusline = NULL;
@@ -966,31 +969,45 @@ executenamedcommand(char *prmt)
zmult = zmultsav;
}
} else if(cmd == Th(z_viquotedinsert)) {
- *ptr = ZWC('^');
+ *ptr = '^';
zrefresh();
getfullchar(0);
- if(LASTFULLCHAR == ZLEEOF || !LASTFULLCHAR || len == NAMLEN)
+ if(LASTFULLCHAR == ZLEEOF || !LASTFULLCHAR || len >= NAMLEN)
feep = 1;
else {
- *ptr++ = LASTFULLCHAR, len++, curlist = 0;
+ 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 {
- *ptr++ = LASTFULLCHAR, len++, curlist = 0;
+ int ret = zlecharasstring(LASTFULLCHAR, ptr);
+ len += ret;
+ ptr += ret;
+ curlist = 0;
}
} else if(cmd == Th(z_backwarddeletechar) ||
- cmd == Th(z_vibackwarddeletechar)) {
+ cmd == Th(z_vibackwarddeletechar)) {
if (len) {
- len--, ptr--, curlist = 0;
+ 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 && (len--, *--ptr != ZWC('-')));
+ 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;
@@ -1003,10 +1020,7 @@ executenamedcommand(char *prmt)
Thingy r;
unambiguous:
*ptr = 0;
- namedcmdstr = zlelineasstring(cmdbuf, len, 0, NULL, NULL, 0);
- r = rthingy(namedcmdstr);
- free(namedcmdstr);
- namedcmdstr = NULL;
+ r = rthingy(cmdbuf);
if (!(r->flags & DISABLED)) {
unrefthingy(r);
statusline = NULL;
@@ -1033,9 +1047,9 @@ executenamedcommand(char *prmt)
namedcmdll = newlinklist();
- namedcmdstr = zlelineasstring(cmdbuf, len, 0, NULL, NULL, 0);
+ *ptr = '\0';
+ namedcmdstr = cmdbuf;
scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0);
- free(namedcmdstr);
namedcmdstr = NULL;
if (empty(namedcmdll)) {
@@ -1046,39 +1060,29 @@ executenamedcommand(char *prmt)
} else if (cmd == Th(z_listchoices) ||
cmd == Th(z_deletecharorlist)) {
int zmultsav = zmult;
- *ptr = ZWC('_');
- statusll = l + len + 1;
+ *ptr = '_';
+ ptr[1] = '\0';
zmult = 1;
listlist(namedcmdll);
listed = curlist = 1;
showinglist = 0;
zmult = zmultsav;
} else if (!nextnode(firstnode(namedcmdll))) {
- char *peekstr = ztrdup(peekfirst(namedcmdll));
- ZLE_STRING_T ztmp = stringaszleline(peekstr, 0, &len,
- NULL, NULL);
- zsfree(peekstr);
- ZS_memcpy(ptr = cmdbuf, ztmp, len);
+ strcpy(ptr = cmdbuf, peekfirst(namedcmdll));
+ len = strlen(ptr);
ptr += len;
- free(ztmp);
- if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode))
+ if (cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode))
goto unambiguous;
} else {
- int ltmp;
- char *peekstr = ztrdup(peekfirst(namedcmdll));
- ZLE_STRING_T ztmp = stringaszleline(peekstr, 0, &ltmp,
- NULL, NULL);
- zsfree(peekstr);
- ZS_memcpy(cmdbuf, ztmp, ltmp);
- free(ztmp);
+ strcpy(cmdbuf, peekfirst(namedcmdll));
ptr = cmdbuf + namedcmdambig;
- *ptr = ZWC('_');
+ *ptr = '_';
+ ptr[1] = '\0';
if (isset(AUTOLIST) &&
!(isset(LISTAMBIGUOUS) && namedcmdambig > len)) {
int zmultsav = zmult;
if (isset(LISTBEEP))
feep = 1;
- statusll = l + namedcmdambig + 1;
zmult = 1;
listlist(namedcmdll);
listed = curlist = 1;
@@ -1100,8 +1104,16 @@ executenamedcommand(char *prmt)
#endif
if (ZC_icntrl(LASTFULLCHAR))
feep = 1;
- else
- *ptr++ = LASTFULLCHAR, len++, curlist = 0;
+ else {
+ int ret = zlecharasstring(LASTFULLCHAR, ptr);
+ len += ret;
+ ptr += ret;
+ if (listed) {
+ clearlist = listshown = 1;
+ listed = 0;
+ } else
+ curlist = 0;
+ }
}
}
}
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 4568e2696..5bfe8ffcb 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -158,6 +158,144 @@ decpos(int *pos)
}
#endif
+
+/* Size of buffer in the following function */
+#define BMC_BUFSIZE MB_CUR_MAX
+/*
+ * For a metafied string that starts at "start" and where the
+ * current position is "ptr", go back one full character,
+ * taking account of combining characters if necessary.
+ */
+
+/**/
+char *
+backwardmetafiedchar(char *start, char *ptr, convchar_t *retchr)
+{
+#ifdef MULTIBYTE_SUPPORT
+ int charlen = 0;
+ char *last = NULL, *bufptr, *endptr = ptr;
+ convchar_t lastc;
+ mbstate_t mbs;
+ size_t ret;
+ wchar_t wc;
+ VARARR(char, buf, BMC_BUFSIZE);
+
+ bufptr = buf + BMC_BUFSIZE;
+ while (ptr > start) {
+ ptr--;
+ /*
+ * Scanning backwards we're not guaranteed ever to find a
+ * valid character. If we've looked as far as we should
+ * need to, give up.
+ */
+ if (bufptr-- == buf)
+ break;
+ charlen++;
+ if (ptr > start && ptr[-1] == Meta)
+ *bufptr = *ptr-- ^ 32;
+ else
+ *bufptr = *ptr;
+
+ /* we always need to restart the character from scratch */
+ memset(&mbs, 0, sizeof(mbs));
+ ret = mbrtowc(&wc, bufptr, charlen, &mbs);
+ if (ret == 0) {
+ /* NULL: unlikely, but handle anyway. */
+ if (last) {
+ if (retchr)
+ *retchr = lastc;
+ return last;
+ } else {
+ if (retchr)
+ *retchr = wc;
+ return ptr;
+ }
+ }
+ if (ret >= 0) {
+ if (ret < charlen) {
+ /* The last character didn't convert, so use it raw. */
+ break;
+ }
+ if (!isset(COMBININGCHARS)) {
+ if (retchr)
+ *retchr = wc;
+ return ptr;
+ }
+ /* HERE: test for combining char, fix when test changes */
+ if (!iswpunct(wc) || wcwidth(wc) != 0) {
+ /* not a combining character... */
+ if (last) {
+ /*
+ * ... but we were looking for a suitable base character,
+ * test it.
+ */
+ /* HERE this test will change too */
+ if (iwsalnum(wc) && wcwidth(wc) > 0) {
+ /*
+ * Yes, this will do.
+ */
+ if (retchr)
+ *retchr = wc;
+ return ptr;
+ } else {
+ /* No, just return the first character we found */
+ if (retchr)
+ *retchr = lastc;
+ return last;
+ }
+ }
+ /* This is the first character, so just return it. */
+ if (retchr)
+ *retchr = wc;
+ return ptr;
+ }
+ if (!last) {
+ /* still looking for the character immediately before ptr */
+ last = ptr;
+ }
+ /* searching for base character of combining character */
+ charlen = 0;
+ bufptr = buf + BMC_BUFSIZE;
+ }
+ /*
+ * Else keep scanning this character even if MB_INVALID: we can't
+ * expect MB_INCOMPLETE to work when moving backwards.
+ */
+ }
+ /*
+ * Found something we didn't like, was there a good character
+ * immediately before ptr?
+ */
+ if (last) {
+ if (retchr)
+ *retchr = lastc;
+ return last;
+ }
+ /*
+ * No, we couldn't find any good character, so just treat
+ * the last unmetafied byte we found as a character.
+ */
+#endif
+ if (endptr > start) {
+ if (endptr > start - 1 && endptr[-2] == Meta)
+ {
+ if (retchr)
+ *retchr = (convchar_t)(endptr[-1] ^ 32);
+ return endptr - 2;
+ }
+ else
+ {
+ if (retchr)
+ *retchr = (convchar_t)endptr[-1];
+ return endptr - 1;
+ }
+ }
+ if (retchr)
+ *retchr = (convchar_t)0;
+ return endptr;
+}
+
+
/**/
int
beginningofline(char **args)
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 89bf30d9a..b9e5723c9 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1387,11 +1387,15 @@ zrefresh(void)
more_end = 1;
if (statusline) {
+ int outll, outsz;
+ ZLE_STRING_T outputline =
+ stringaszleline(statusline, 0, &outll, &outsz, NULL);
+
rpms.tosln = rpms.ln + 1;
nbuf[rpms.ln][winw + 1] = zr_zr; /* text not wrapped */
snextline(&rpms);
- u = statusline;
- for (; u < statusline + statusll; u++) {
+ u = outputline;
+ for (; u < outputline + outll; u++) {
#ifdef MULTIBYTE_SUPPORT
if (iswprint(*u)) {
int width = wcwidth(*u);
@@ -1449,6 +1453,7 @@ zrefresh(void)
*/
snextline(&rpms);
}
+ zfree(outputline, outsz);
}
*rpms.s = zr_zr;
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index fb0dbb092..f712e1750 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -406,16 +406,15 @@ bin_zle_list(UNUSED(char *name), char **args, Options ops, UNUSED(char func))
static int
bin_zle_refresh(UNUSED(char *name), char **args, Options ops, UNUSED(char func))
{
- ZLE_STRING_T s = statusline;
- int sl = statusll, ocl = clearlist;
+ char *s = statusline;
+ int ocl = clearlist;
if (!zleactive)
return 1;
statusline = NULL;
- statusll = 0;
if (*args) {
if (**args)
- statusline = stringaszleline(*args, 0, &statusll, NULL, NULL);
+ statusline = *args;
if (*++args) {
LinkList l = newlinklist();
int zmultsav = zmult;
@@ -439,12 +438,8 @@ bin_zle_refresh(UNUSED(char *name), char **args, Options ops, UNUSED(char func))
}
zrefresh();
- if (statusline)
- free(statusline);
-
clearlist = ocl;
statusline = s;
- statusll = sl;
return 0;
}
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 7d29bd649..06c6ebd09 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -106,6 +106,54 @@ zleaddtoline(int chr)
}
/*
+ * Convert a line editor character to a possibly multibyte character
+ * in a metafied string. To be safe buf should have space for at least
+ * 2 * MB_CUR_MAX chars for multibyte mode and 2 otherwise. Returns the
+ * length of the string added.
+ */
+
+/**/
+int
+zlecharasstring(ZLE_CHAR_T inchar, char *buf)
+{
+#ifdef MULTIBYTE_SUPPORT
+ size_t ret;
+ char *ptr;
+
+ ret = wctomb(buf, inchar);
+ if (ret <= 0) {
+ /* Ick. */
+ buf[0] = '?';
+ return 1;
+ }
+ ptr = buf + ret - 1;
+ for (;;) {
+ if (imeta(*ptr)) {
+ char *ptr2 = buf + ret - 1;
+ for (;;) {
+ ptr2[1] = ptr2[0];
+ if (ptr2 == ptr)
+ break;
+ ptr2--;
+ }
+ *ptr = Meta;
+ ret++;
+ }
+
+ if (ptr == buf)
+ return ret;
+ ptr--;
+ }
+#else
+ if (imeta(inchar)) {
+ buf[0] = Meta;
+ buf[1] = inchar ^ 32;
+ } else
+ buf[0] = inchar;
+#endif
+}
+
+/*
* Input a line in internal zle format, possibly using wide characters,
* possibly not, together with its length and the cursor position.
* The length must be accurate and includes all characters (no NULL
@@ -621,7 +669,7 @@ void
setline(char *s, int flags)
{
char *scp;
-
+
if (flags & ZSL_COPY)
scp = ztrdup(s);
else
@@ -639,7 +687,6 @@ setline(char *s, int flags)
else if (zlecs > zlell)
zlecs = zlell;
CCRIGHT();
-
if (flags & ZSL_COPY)
free(scp);
}
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index b8c3936d4..b8215454f 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -853,8 +853,7 @@ vicapslockpanic(UNUSED(char **args))
{
clearlist = 1;
zbeep();
- statusline = ZWS("press a lowercase key to continue");
- statusll = ZS_strlen(statusline);
+ statusline = "press a lowercase key to continue";
zrefresh();
while (!ZC_ilower(getfullchar(0)));
statusline = NULL;
diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c
index 83f7a4ece..368079053 100644
--- a/Src/Zle/zle_word.c
+++ b/Src/Zle/zle_word.c
@@ -185,7 +185,6 @@ viforwardwordend(char **args)
return ret;
}
while (n--) {
- /* HERE: the zlecs + 1 here is suspect */
int pos;
while (zlecs != zlell) {
pos = zlecs;
diff --git a/Src/utils.c b/Src/utils.c
index 21a3a0c34..59a496fcf 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3968,6 +3968,50 @@ nicedup(const char *s, int heap)
/*
+ * The guts of mb_metacharlenconv(). This version assumes we are
+ * processing a true multibyte character string without tokens, and
+ * takes the shift state as an argument.
+ */
+
+/**/
+mod_export int
+mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
+{
+ size_t ret = MB_INVALID;
+ char inchar;
+ const char *ptr;
+ wchar_t wc;
+
+ for (ptr = s; *ptr; ) {
+ if (*ptr == Meta) {
+ inchar = *++ptr ^ 32;
+ DPUTS(!*ptr,
+ "BUG: unexpected end of string in mb_metacharlen()\n");
+ } else
+ inchar = *ptr;
+ ptr++;
+ ret = mbrtowc(&wc, &inchar, 1, mbsp);
+
+ if (ret == MB_INVALID)
+ break;
+ if (ret == MB_INCOMPLETE)
+ continue;
+ if (wcp)
+ *wcp = wc;
+ return ptr - s;
+ }
+
+ if (wcp)
+ *wcp = WEOF;
+ /* No valid multibyte sequence */
+ memset(mbsp, 0, sizeof(*mbsp));
+ if (ptr > s) {
+ return 1 + (*s == Meta); /* Treat as single byte character */
+ } else
+ return 0; /* Probably shouldn't happen */
+}
+
+/*
* Length of metafied string s which contains the next multibyte
* character; single (possibly metafied) character if string is not null
* but character is not valid (e.g. possibly incomplete at end of string).
@@ -3982,11 +4026,6 @@ nicedup(const char *s, int heap)
mod_export int
mb_metacharlenconv(const char *s, wint_t *wcp)
{
- char inchar;
- const char *ptr;
- size_t ret;
- wchar_t wc;
-
if (!isset(MULTIBYTE)) {
/* treat as single byte, possibly metafied */
if (wcp)
@@ -4009,37 +4048,7 @@ mb_metacharlenconv(const char *s, wint_t *wcp)
return 1;
}
- ret = MB_INVALID;
- for (ptr = s; *ptr; ) {
- if (*ptr == Meta) {
- inchar = *++ptr ^ 32;
-#ifdef DEBUG
- if (!*ptr)
- fprintf(stderr,
- "BUG: unexpected end of string in mb_metacharlen()\n");
-#endif
- } else
- inchar = *ptr;
- ptr++;
- ret = mbrtowc(&wc, &inchar, 1, &mb_shiftstate);
-
- if (ret == MB_INVALID)
- break;
- if (ret == MB_INCOMPLETE)
- continue;
- if (wcp)
- *wcp = wc;
- return ptr - s;
- }
-
- if (wcp)
- *wcp = WEOF;
- /* No valid multibyte sequence */
- memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
- if (ptr > s) {
- return 1 + (*s == Meta); /* Treat as single byte character */
- } else
- return 0; /* Probably shouldn't happen */
+ return mb_metacharlenconv_r(s, wcp, &mb_shiftstate);
}
/*
diff --git a/Src/zsh.h b/Src/zsh.h
index 67e4c0c31..f91d27680 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1606,12 +1606,11 @@ struct histent {
Histent up; /* previous line (moving upward) */
Histent down; /* next line (moving downward) */
-#ifdef MULTIBYTE_SUPPORT /* (Note: must match ZLE_STRING_T!) */
- wchar_t *zle_text; /* the edited history line */
-#else
- char *zle_text; /* the edited history line */
-#endif
- int zle_len; /* length of zle_text */
+ char *zle_text; /* the edited history line,
+ * a metafied, NULL-terminated string,
+ * i.e the same format as the original
+ * entry
+ */
time_t stim; /* command started time (datestamp) */
time_t ftim; /* command finished time */
short *words; /* Position of words in history */