about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2002-07-01 16:50:41 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2002-07-01 16:50:41 +0000
commit1a1b108b341885da0a70d550384c9ec32a627615 (patch)
treefd8ad7f31204540e6d99bac4ef66a9e1914f2798
parent964f819070c1d506bfcd45e25704ae23c8f09ed4 (diff)
downloadzsh-1a1b108b341885da0a70d550384c9ec32a627615.tar.gz
zsh-1a1b108b341885da0a70d550384c9ec32a627615.tar.xz
zsh-1a1b108b341885da0a70d550384c9ec32a627615.zip
17390: new zle parameters $PREDISPLAY, $POSTDISPLAY
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/zle.yo16
-rw-r--r--Src/Zle/zle_params.c54
-rw-r--r--Src/Zle/zle_refresh.c80
4 files changed, 132 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index b81d847ac..d0d1fc742 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,10 @@
 
 2002-07-01  Peter Stephenson  <pws@csr.com>
 
+	* 17390: Src/Zle/zle_params.c, Src/Zle/zle_refresh.c,
+	Doc/Zsh/zle.yo: $PREDISPLAY and $POSTDISPLAY are used to
+	add text before and after the editable chunk of the zle buffer.
+
 	* 17384: Src/Zle/zle_main.c, Src/Zle/iwidgets.list,
 	Doc/Zsh/zle.yo: new `recursive-edit' widget allows a user-defined
 	widget to pass control back to zle as a subcommand.
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 0cc1b52df..8022a1bdd 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -662,6 +662,22 @@ In a multi-line input at the secondary prompt, this read-only parameter
 contains the contents of the lines before the one the cursor is
 currently in.
 )
+vindex(PREDISPLAY)
+item(tt(PREDISPLAY) (scalar))(
+Text to be displayed before the start of the editable text buffer.  This
+does not have to be a complete line; to display a complete line, a newline
+must be appended explicitly.  Note that the text survives between calls to zle
+and hence must be removed explicitly by assigning an empty value to the
+parameter.
+)
+vindex(POSTDISPLAY)
+item(tt(POSTDISPLAY) (scalar))(
+Text to be displayed after the end of the editable text buffer.  This
+does not have to be a complete line; to display a complete line, a newline
+must be prepended explicitly.  Note that the text survives between calls to
+zle and hence must be removed explicitly by assigning an empty value to the
+parameter.
+)
 vindex(RBUFFER)
 item(tt(RBUFFER) (scalar))(
 The part of the buffer that lies to the right of the cursor position.
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index e2bbdd20b..ef8a98139 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -85,6 +85,10 @@ static struct zleparam {
 	unset_cutbuffer, NULL },
     { "killring", PM_ARRAY, FN(set_killring), FN(get_killring),
 	unset_killring, NULL },
+    { "PREDISPLAY", PM_SCALAR, FN(set_predisplay), FN(get_predisplay),
+	zleunsetfn, NULL },
+    { "POSTDISPLAY", PM_SCALAR, FN(set_postdisplay), FN(get_postdisplay),
+	zleunsetfn, NULL },
     { NULL, 0, NULL, NULL, NULL, NULL }
 };
 
@@ -462,3 +466,53 @@ unset_killring(Param pm, int exp)
 	stdunsetfn(pm, exp);
     }
 }
+
+static void
+set_prepost(unsigned char **textvar, int *lenvar, char *x)
+{
+    if (*lenvar) {
+	zfree(*textvar, *lenvar);
+	*textvar = NULL;
+	*lenvar = 0;
+    }
+    if (x) {
+	unmetafy(x, lenvar);
+	*textvar = (unsigned char *)zalloc(*lenvar);
+	memcpy((char *)*textvar, x, *lenvar);
+	free(x);
+    }
+}
+
+static char *
+get_prepost(unsigned char *text, int len)
+{
+    return metafy((char *)text, len, META_HEAPDUP);
+}
+
+/**/
+static void
+set_predisplay(Param pm, char *x)
+{
+    set_prepost(&predisplay, &predisplaylen, x);
+}
+
+/**/
+static char *
+get_predisplay(Param pm)
+{
+    return get_prepost(predisplay, predisplaylen);
+}
+
+/**/
+static void
+set_postdisplay(Param pm, char *x)
+{
+    set_prepost(&postdisplay, &postdisplaylen, x);
+}
+
+/**/
+static char *
+get_postdisplay(Param pm)
+{
+    return get_prepost(postdisplay, postdisplaylen);
+}
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 17c373732..2223a35f4 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -81,6 +81,16 @@ mod_export int clearlist;
 /**/
 int trashedzle;
 
+/*
+ * Information used by PREDISPLAY and POSTDISPLAY parameters which
+ * add non-editable text to that being displayed.
+ */
+/**/
+unsigned char *predisplay, *postdisplay;
+/**/
+int predisplaylen, postdisplaylen;
+
+
 #ifdef HAVE_SELECT
 /* cost of last update */
 /**/
@@ -278,6 +288,10 @@ zrefresh(void)
 	*sen,			/* pointer to end of the video buffer (eol)  */
 	*scs;			/* pointer to cursor position in real buffer */
     char **qbuf;		/* tmp					     */
+    unsigned char *tmpline;	/* line with added pre/post text */
+    int tmpcs, tmpll;		/* ditto cursor position and line length */
+    int tmpalloced;		/* flag to free tmpline when finished */
+	
 
     /* If this is called from listmatches() (indirectly via trashzle()), and *
      * that was called from the end of zrefresh(), then we don't need to do  *
@@ -286,6 +300,25 @@ zrefresh(void)
     if (inlist)
 	return;
 
+    if (predisplaylen || postdisplaylen) {
+	/* There is extra text to display at the start or end of the line */
+	tmpline = zalloc(ll + predisplaylen + postdisplaylen);
+	if (predisplaylen)
+	    memcpy(tmpline, predisplay, predisplaylen);
+	if (ll)
+	    memcpy(tmpline+predisplaylen, line, ll);
+	if (postdisplaylen)
+	    memcpy(tmpline+predisplaylen+ll, postdisplay, postdisplaylen);
+	tmpcs = cs + predisplaylen;
+	tmpll = predisplaylen + ll + postdisplaylen;
+	tmpalloced = 1;
+    } else {
+	tmpline = line;
+	tmpcs = cs;
+	tmpll = ll;
+	tmpalloced = 0;
+    }
+
     if (clearlist && listshown > 0) {
 	if (tccan(TCCLEAREOD)) {
 	    int ovln = vln, ovcs = vcs;
@@ -392,18 +425,18 @@ zrefresh(void)
    width comparisons can be made with winw, height comparisons with winh */
 
     if (termflags & TERM_SHORT) {
-	singlerefresh();
+	singlerefresh(tmpline, tmpll, tmpcs);
 	goto singlelineout;
     }
 
-    if (cs < 0) {
+    if (tmpcs < 0) {
 #ifdef DEBUG
 	fprintf(stderr, "BUG: negative cursor position\n");
 	fflush(stderr); 
 #endif
-	cs = 0;
+	tmpcs = 0;
     }
-    scs = line + cs;
+    scs = tmpline + tmpcs;
     numscrolls = 0;
 
 /* first, we generate the video line buffers so we know what to put on
@@ -414,9 +447,9 @@ zrefresh(void)
 	*nbuf = (char *)zalloc(winw + 2);
 
     s = (unsigned char *)(nbuf[ln = 0] + lpromptw);
-    t = line;
+    t = tmpline;
     sen = (unsigned char *)(*nbuf + winw);
-    for (; t < line+ll; t++) {
+    for (; t < tmpline+tmpll; t++) {
 	if (t == scs)			/* if cursor is here, remember it */
 	    nvcs = s - (unsigned char *)(nbuf[nvln = ln]);
 
@@ -459,7 +492,7 @@ zrefresh(void)
 	nvln++;
     }
 
-    if (t != line + ll)
+    if (t != tmpline + tmpll)
 	more_end = 1;
 
     if (statusline) {
@@ -646,6 +679,9 @@ individually */
 singlelineout:
     fflush(shout);		/* make sure everything is written out */
 
+    if (tmpalloced)
+	zfree(tmpline, tmpll);
+
     /* if we have a new list showing, note it; if part of the list has been
     overwritten, redisplay it. */
     if (showinglist == -2 || (showinglist > 0 && showinglist < nlnct)) {
@@ -1082,7 +1118,7 @@ redisplay(char **args)
 
 /**/
 static void
-singlerefresh(void)
+singlerefresh(unsigned char *tmpline, int tmpll, int tmpcs)
 {
     char *vbuf, *vp,		/* video buffer and pointer    */
 	**qbuf,			/* tmp			       */
@@ -1093,19 +1129,19 @@ singlerefresh(void)
 
     nlnct = 1;
 /* generate the new line buffer completely */
-    for (vsiz = 1 + lpromptw, t0 = 0; t0 != ll; t0++, vsiz++)
-	if (line[t0] == '\t')
+    for (vsiz = 1 + lpromptw, t0 = 0; t0 != tmpll; t0++, vsiz++)
+	if (tmpline[t0] == '\t')
 	    vsiz = (vsiz | 7) + 1;
-	else if (icntrl(line[t0]))
+	else if (icntrl(tmpline[t0]))
 	    vsiz++;
     vbuf = (char *)zalloc(vsiz);
 
-    if (cs < 0) {
+    if (tmpcs < 0) {
 #ifdef DEBUG
 	fprintf(stderr, "BUG: negative cursor position\n");
 	fflush(stderr); 
 #endif
-	cs = 0;
+	tmpcs = 0;
     }
 
     /* only use last part of prompt */
@@ -1113,25 +1149,25 @@ singlerefresh(void)
     vbuf[lpromptw] = '\0';
     vp = vbuf + lpromptw;
 
-    for (t0 = 0; t0 != ll; t0++) {
-	if (line[t0] == '\t')
+    for (t0 = 0; t0 != tmpll; t0++) {
+	if (tmpline[t0] == '\t')
 	    for (*vp++ = ' '; (vp - vbuf) & 7; )
 		*vp++ = ' ';
-	else if (line[t0] == '\n') {
+	else if (tmpline[t0] == '\n') {
 	    *vp++ = '\\';
 	    *vp++ = 'n';
-	} else if (line[t0] == 0x7f) {
+	} else if (tmpline[t0] == 0x7f) {
 	    *vp++ = '^';
 	    *vp++ = '?';
-	} else if (icntrl(line[t0])) {
+	} else if (icntrl(tmpline[t0])) {
 	    *vp++ = '^';
-	    *vp++ = line[t0] | '@';
+	    *vp++ = tmpline[t0] | '@';
 	} else
-	    *vp++ = line[t0];
-	if (t0 == cs)
+	    *vp++ = tmpline[t0];
+	if (t0 == tmpcs)
 	    nvcs = vp - vbuf - 1;
     }
-    if (t0 == cs)
+    if (t0 == tmpcs)
 	nvcs = vp - vbuf;
     *vp = '\0';