On Sun, 17 Jun 2018 15:52:34 -0600, "Todd C. Miller" wrote:

> On Sun, 17 Jun 2018 17:29:31 +0200, Mark Kettenis wrote:
>
> > If folks indeed think that this is a must-have feature, this is
> > certainly a better approach.  I wonder though if the setupterm() call
> > should happen earlier when interactive mode is initialized?
>
> This turns out to be simpler than expected.  Now whenever TERM is
> set (including at startup) it will call setupterm().

Hopefully final diff that better handles unknown term types.  Now
if you set TERM=gobbledegook the old cur_term will be invalidated
and clear-screen will not try to the escape sequence for the old
terminal.

I think this is good enough to commit.

 - todd

Index: bin/ksh/Makefile
===================================================================
RCS file: /cvs/src/bin/ksh/Makefile,v
retrieving revision 1.38
diff -u -p -u -r1.38 Makefile
--- bin/ksh/Makefile    6 Jan 2018 16:28:58 -0000       1.38
+++ bin/ksh/Makefile    16 Jun 2018 22:00:32 -0000
@@ -1,6 +1,9 @@
 #      $OpenBSD: Makefile,v 1.38 2018/01/06 16:28:58 millert Exp $
 
 PROG=  ksh
+DPADD+=        ${LIBCURSES}
+LDADD+=        -lcurses
+
 SRCS=  alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c eval.c \
        exec.c expr.c history.c io.c jobs.c lex.c mail.c main.c \
        misc.c path.c shf.c syn.c table.c trap.c tree.c tty.c var.c \
Index: bin/ksh/edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.65
diff -u -p -u -r1.65 edit.c
--- bin/ksh/edit.c      9 Apr 2018 17:53:36 -0000       1.65
+++ bin/ksh/edit.c      16 Jun 2018 22:09:17 -0000
@@ -138,10 +138,10 @@ x_flush(void)
        shf_flush(shl_out);
 }
 
-void
+int
 x_putc(int c)
 {
-       shf_putc(c, shl_out);
+       return shf_putc(c, shl_out);
 }
 
 void
Index: bin/ksh/edit.h
===================================================================
RCS file: /cvs/src/bin/ksh/edit.h,v
retrieving revision 1.11
diff -u -p -u -r1.11 edit.h
--- bin/ksh/edit.h      26 Jan 2016 17:39:31 -0000      1.11
+++ bin/ksh/edit.h      16 Jun 2018 22:09:27 -0000
@@ -37,7 +37,7 @@ extern X_chars edchars;
 /* edit.c */
 int    x_getc(void);
 void   x_flush(void);
-void   x_putc(int);
+int    x_putc(int);
 void   x_puts(const char *);
 bool   x_mode(bool);
 int    promptlen(const char *, const char **);
Index: bin/ksh/emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 emacs.c
--- bin/ksh/emacs.c     16 Jan 2018 17:17:18 -0000      1.84
+++ bin/ksh/emacs.c     18 Jun 2018 03:30:09 -0000
@@ -21,6 +21,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#ifndef SMALL
+# include <term.h>
+# include <curses.h>
+#endif
 
 #include "sh.h"
 #include "edit.h"
@@ -28,6 +32,7 @@
 static Area    aedit;
 #define        AEDIT   &aedit          /* area for kill ring and macro defns */
 
+#undef CTRL
 #define        CTRL(x)         ((x) == '?' ? 0x7F : (x) & 0x1F)        /* 
ASCII */
 #define        UNCTRL(x)       ((x) == 0x7F ? '?' : (x) | 0x40)        /* 
ASCII */
 
@@ -146,6 +151,7 @@ static int  isu8cont(unsigned char);
 /* proto's for keybindings */
 static int     x_abort(int);
 static int     x_beg_hist(int);
+static int     x_clear_screen(int);
 static int     x_comp_comm(int);
 static int     x_comp_file(int);
 static int     x_complete(int);
@@ -202,6 +208,7 @@ static int  x_debug_info(int);
 static const struct x_ftab x_ftab[] = {
        { x_abort,              "abort",                        0 },
        { x_beg_hist,           "beginning-of-history",         0 },
+       { x_clear_screen,       "clear-screen",                 0 },
        { x_comp_comm,          "complete-command",             0 },
        { x_comp_file,          "complete-file",                0 },
        { x_complete,           "complete",                     0 },
@@ -1004,12 +1011,19 @@ x_draw_line(int c)
 {
        x_redraw(-1);
        return KSTD;
+}
 
+static int
+x_clear_screen(int c)
+{
+       x_redraw(-2);
+       return KSTD;
 }
 
-/* Redraw (part of) the line.  If limit is < 0, the everything is redrawn
- * on a NEW line, otherwise limit is the screen column up to which needs
- * redrawing.
+/* Redraw (part of) the line.
+ * A non-negative limit is the screen column up to which needs
+ * redrawing. A limit of -1 redraws on a new line, while a limit
+ * of -2 (attempts to) clear the screen.
  */
 static void
 x_redraw(int limit)
@@ -1018,9 +1032,20 @@ x_redraw(int limit)
        char    *cp;
 
        x_adj_ok = 0;
-       if (limit == -1)
+       if (limit == -2) {
+               int cleared = 0;
+#ifndef SMALL
+               if (cur_term != NULL && clear_screen != NULL) {
+                       if (tputs(clear_screen, 1, x_putc) != ERR)
+                               cleared = 1;
+               }
+#endif
+               if (!cleared)
+                       x_e_putc('\n');
+       }
+       else if (limit == -1)
                x_e_putc('\n');
-       else
+       else if (limit >= 0)
                x_e_putc('\r');
        x_flush();
        if (xbp == xbuf) {
Index: bin/ksh/ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.200
diff -u -p -u -r1.200 ksh.1
--- bin/ksh/ksh.1       30 May 2018 21:20:52 -0000      1.200
+++ bin/ksh/ksh.1       17 Jun 2018 21:58:30 -0000
@@ -1717,6 +1717,10 @@ loops to store the value that is read fr
 The number of seconds since the shell started or, if the parameter has been
 assigned an integer value, the number of seconds since the assignment plus the
 value that was assigned.
+.It Ev TERM
+The user's terminal type.
+If set, it will be used to determine the escape sequence used to
+clear the screen.
 .It Ev TMOUT
 If set to a positive integer in an interactive shell, it specifies the maximum
 number of seconds the shell will wait for input after printing the primary
@@ -4690,6 +4694,11 @@ Moves the cursor to the beginning of the
 Uppercase the first character in the next
 .Ar n
 words, leaving the cursor past the end of the last word.
+.It clear-screen:
+Clears the screen if the
+.Ev TERM
+parameter is set and the terminal supports clearing the screen, then
+reprints the prompt string and the current input line.
 .It comment: ^[#
 If the current line does not begin with a comment character, one is added at
 the beginning of the line and the line is entered (as if return had been
Index: bin/ksh/table.h
===================================================================
RCS file: /cvs/src/bin/ksh/table.h,v
retrieving revision 1.14
diff -u -p -u -r1.14 table.h
--- bin/ksh/table.h     9 Apr 2018 17:53:36 -0000       1.14
+++ bin/ksh/table.h     17 Jun 2018 21:35:49 -0000
@@ -170,6 +170,7 @@ extern const struct builtin shbuiltins [
 #define        V_TMOUT                 16
 #define        V_TMPDIR                17
 #define        V_LINENO                18
+#define        V_TERM                  19
 
 /* values for set_prompt() */
 #define PS1    0               /* command */
Index: bin/ksh/var.c
===================================================================
RCS file: /cvs/src/bin/ksh/var.c,v
retrieving revision 1.68
diff -u -p -u -r1.68 var.c
--- bin/ksh/var.c       13 Apr 2018 18:18:36 -0000      1.68
+++ bin/ksh/var.c       18 Jun 2018 03:32:34 -0000
@@ -11,6 +11,10 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#ifndef SMALL
+# include <term.h>
+# include <curses.h>
+#endif
 
 #include "sh.h"
 
@@ -111,12 +115,13 @@ initvar(void)
                { "SECONDS",            V_SECONDS },
                { "TMOUT",              V_TMOUT },
                { "LINENO",             V_LINENO },
+               { "TERM",               V_TERM },
                { NULL, 0 }
        };
        int i;
        struct tbl *tp;
 
-       ktinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */
+       ktinit(&specials, APERM, 32); /* must be 2^n (currently 19 specials) */
        for (i = 0; names[i].name; i++) {
                tp = ktenter(&specials, names[i].name, hash(names[i].name));
                tp->flag = DEFINED|ISSET;
@@ -1056,6 +1061,18 @@ setspec(struct tbl *vp)
                /* The -1 is because line numbering starts at 1. */
                user_lineno = (unsigned int) intval(vp) - current_lineno - 1;
                vp->flag |= SPECIAL;
+               break;
+       case V_TERM:
+#ifndef SMALL
+               {
+                       int ret;
+
+                       vp->flag &= ~SPECIAL;
+                       if (setupterm(str_val(vp), STDOUT_FILENO, &ret) == ERR)
+                               del_curterm(cur_term);
+                       vp->flag |= SPECIAL;
+               }
+#endif
                break;
        }
 }

Reply via email to