qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs TODO.org display.h qe.h shell.c archive....


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs TODO.org display.h qe.h shell.c archive....
Date: Fri, 21 Apr 2017 10:44:15 -0400 (EDT)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        17/04/21 10:44:15

Modified files:
        .              : TODO.org display.h qe.h shell.c archive.c 
                         latex-mode.c qeconfig.h tty.c buffer.c qe.c 
                         search.c 

Log message:
        shell: major improvements in tty emulator
        terminal emulator:
        - add EditState.cols and EditState.rows: window dimensions in characters
        - pass target window to new_shell_buffer()
        - use window size for shell terminal emulator initial screen size
        - set COLUMNS and LINES environment variables for child processes
        - factorize emulator character output
        - increase number of CSI arguments
        - simplify and improve CSI m argument processing including
          multiple argument sequences
        - minimal support for `:` as argument separator eg:
          \033[38;5;128:128:128m
        - support erase line vt100 command:
          \033[K, \033[0K erase end of line
          \033[1K         erase beginning of line
          \033[2K         erase complete line
        debugging:
        - pass string argument to set-trace: on, off or list of trace indicators
        - remove doctor command
        - add QE_TRACE_EMULATE for emulator trace messages
        - fix incorrect uses of eb_delete()

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/TODO.org?cvsroot=qemacs&r1=1.37&r2=1.38
http://cvs.savannah.gnu.org/viewcvs/qemacs/display.h?cvsroot=qemacs&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.255&r2=1.256
http://cvs.savannah.gnu.org/viewcvs/qemacs/shell.c?cvsroot=qemacs&r1=1.127&r2=1.128
http://cvs.savannah.gnu.org/viewcvs/qemacs/archive.c?cvsroot=qemacs&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/qemacs/latex-mode.c?cvsroot=qemacs&r1=1.56&r2=1.57
http://cvs.savannah.gnu.org/viewcvs/qemacs/qeconfig.h?cvsroot=qemacs&r1=1.67&r2=1.68
http://cvs.savannah.gnu.org/viewcvs/qemacs/tty.c?cvsroot=qemacs&r1=1.81&r2=1.82
http://cvs.savannah.gnu.org/viewcvs/qemacs/buffer.c?cvsroot=qemacs&r1=1.113&r2=1.114
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.274&r2=1.275
http://cvs.savannah.gnu.org/viewcvs/qemacs/search.c?cvsroot=qemacs&r1=1.14&r2=1.15

Patches:
Index: TODO.org
===================================================================
RCS file: /sources/qemacs/qemacs/TODO.org,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- TODO.org    18 Apr 2017 09:14:55 -0000      1.37
+++ TODO.org    21 Apr 2017 14:44:14 -0000      1.38
@@ -1,11 +1,15 @@
 ; TODO list for qemacs
 ;
 ; Author: Charles Gordon
-; Updated: 2017-04-17
+; Updated: 2017-04-21
 
 * Recent bugs and ideas
 
 ** basic: backspace delete hacking tabs
+** charset: use unichar typedef
+** charset: limit number of combining marks to 20
+** clang: colorizing bug: static int (*qe__initcall_first)(void) qe__init_call 
= NULL;
+** clang: missed tag: static int (*qe__initcall_first)(void) qe__init_call = 
NULL;
 ** display: minibuffer and popup windows should be in a separate lists
 ** display: save display-width in binary and hex modes upon window change
 ** display: default display-width of 0 is automatic, other values are shared 
between binary and hex modes
@@ -14,13 +18,13 @@
 ** display: optimize display for very large display-width in binary and hex 
modes
 ** display: add screen dump command and format
 ** files: actually load file in find-file-noselect
-** xml: select on "<plist "
+** files: ignore .DS_Store in completion
+** files: fix SPC / TAB distinct behaviors on ~/comp/project/gnachman/
 ** shell: support ':' as alternate escape sequence argument separator
 ** shell: use target window for man and similar commands
-** charset: use unichar typedef
-** charset: limit number of combining marks to 20
-** clang: colorizing bug: static int (*qe__initcall_first)(void) qe__init_call 
= NULL;
-** clang: missed tag: static int (*qe__initcall_first)(void) qe__init_call = 
NULL;
+** tags: remove tags for modified line
+** undo: undo some cursor movements
+** xml: merge xml and htmlsrc modes, add submodes for plist and other config 
files
 
 * Priority 0
 

Index: display.h
===================================================================
RCS file: /sources/qemacs/qemacs/display.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- display.h   18 Apr 2017 09:14:55 -0000      1.21
+++ display.h   21 Apr 2017 14:44:14 -0000      1.22
@@ -171,12 +171,14 @@
 static inline QEFont *open_font(QEditScreen *s,
                                 int style, int size)
 {
+    if (s->dpy.dpy_open_font)
     return s->dpy.dpy_open_font(s, style, size);
+    return NULL;
 }
 
 static inline void close_font(QEditScreen *s, QEFont **fontp)
 {
-    if (*fontp && !(*fontp)->system_font)
+    if (*fontp && !(*fontp)->system_font && s->dpy.dpy_close_font)
         s->dpy.dpy_close_font(s, fontp);
 }
 

Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.255
retrieving revision 1.256
diff -u -b -r1.255 -r1.256
--- qe.h        18 Apr 2017 14:26:39 -0000      1.255
+++ qe.h        21 Apr 2017 14:44:14 -0000      1.256
@@ -1397,7 +1397,8 @@
 
     /* display area info */
     int width, height;
-    int ytop, xleft;
+    int xleft, ytop;
+    int cols, rows;
     /* full window size, including borders */
     int x1, y1, x2, y2;         /* window coordinates in device units */
     //int xx1, yy1, xx2, yy2;     /* window coordinates in 1/1000 */
@@ -1591,11 +1592,15 @@
     int buffer_cache_len;
 #endif
     EditBuffer *trace_buffer;
+    int trace_flags;
     int trace_buffer_state;
-#define EB_TRACE_TTY      1
-#define EB_TRACE_SHELL    2
-#define EB_TRACE_PTY      4
-#define EB_TRACE_COMMAND  8
+#define EB_TRACE_TTY      0x01
+#define EB_TRACE_SHELL    0x02
+#define EB_TRACE_PTY      0x04
+#define EB_TRACE_EMULATE  0x08
+#define EB_TRACE_COMMAND  0x10
+#define EB_TRACE_ALL      0x1F
+#define EB_TRACE_FLUSH    0x100
 
     /* global layout info : DO NOT modify these directly. do_refresh
        does it */
@@ -2093,7 +2098,7 @@
 /* misc */
 
 void do_set_emulation(EditState *s, const char *name);
-void do_set_trace(EditState *s);
+void do_set_trace(EditState *s, const char *options);
 void do_cd(EditState *s, const char *name);
 int qe_mode_set_key(ModeDef *m, const char *keystr, const char *cmd_name);
 void do_set_key(EditState *s, const char *keystr, const char *cmd_name,
@@ -2200,7 +2205,6 @@
                               const char *renamefile);
 void qe_save_open_files(EditState *s, EditBuffer *b);
 
-void do_doctor(EditState *s);
 void do_delete_other_windows(EditState *s, int all);
 void do_hide_window(EditState *s, int set);
 void do_delete_hidden_windows(EditState *s);
@@ -2298,9 +2302,9 @@
 #define SF_AUTO_CODING   0x08
 #define SF_AUTO_MODE     0x10
 #define SF_BUFED_MODE    0x20
-EditBuffer *new_shell_buffer(EditBuffer *b0, const char *bufname,
-                             const char *caption, const char *cmd,
-                             int shell_flags);
+EditBuffer *new_shell_buffer(EditBuffer *b0, EditState *e,
+                             const char *bufname, const char *caption,
+                             const char *cmd, int shell_flags);
 
 #define QASSERT(e)      do { if (!(e)) fprintf(stderr, "%s:%d: assertion 
failed: %s\n", __FILE__, __LINE__, #e); } while (0)
 

Index: shell.c
===================================================================
RCS file: /sources/qemacs/qemacs/shell.c,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -b -r1.127 -r1.128
--- shell.c     17 Apr 2017 18:14:15 -0000      1.127
+++ shell.c     21 Apr 2017 14:44:14 -0000      1.128
@@ -40,7 +40,7 @@
 
 static ModeDef shell_mode, pager_mode;
 
-#define MAX_ESC_PARAMS 6
+#define MAX_CSI_PARAMS  16
 
 enum QETermState {
     QE_TERM_STATE_NORM,
@@ -54,21 +54,23 @@
 typedef struct ShellState {
     QEModeData base;
     /* buffer state */
+    int cols, rows;
+    int scroll_top, scroll_bottom;  /* scroll region (top included, bottom 
excluded) */
     int pty_fd;
     int pid; /* -1 if not launched */
     unsigned int attr, fgcolor, bgcolor, reverse;
     int cur_offset; /* current offset at position x, y */
     int cur_prompt; /* offset of end of prompt on current line */
-    int nb_esc_params;
-    int esc_params[MAX_ESC_PARAMS];
-    int has_params[MAX_ESC_PARAMS];
+    int nb_params;
+    int params[MAX_CSI_PARAMS + 1];
     int state;
-    int esc1, esc2;
+    int esc1, esc2, lastc;
     int shifted;
     int cset, charset[2];
     int grab_keys;
-    unsigned char utf8_buf[8];
-    int utf8_len, utf8_pos;
+    unsigned char term_buf[256];
+    int term_len, term_pos;
+    int utf8_len;
     EditBuffer *b;
     EditBuffer *b_color; /* color buffer, one byte per char */
     struct QEmacsState *qe_state;
@@ -181,6 +183,8 @@
 {
     int pty_fd, pid, i, nb_fds;
     char tty_name[MAX_FILENAME_SIZE];
+    char lines_string[20];
+    char columns_string[20];
     struct winsize ws;
 
     pty_fd = get_pty(tty_name, sizeof(tty_name));
@@ -224,9 +228,6 @@
         for (i = 0; i < nb_fds; i++)
             close(i);
 
-        if (shell_flags & SF_INFINITE)
-            setenv("LINES", "10000", 1);
-
         /* open pseudo tty for standard I/O */
         if (shell_flags & SF_INTERACTIVE) {
             /* interactive shell: input from / output to pseudo terminal */
@@ -242,7 +243,15 @@
 #ifdef CONFIG_DARWIN
         setsid();
 #endif
-        setenv("TERM", "xterm", 1);
+        if (shell_flags & SF_INFINITE) {
+            rows += QE_TERM_YSIZE_INFINITE;
+        }
+        snprintf(lines_string, sizeof lines_string, "%d", rows);
+        snprintf(columns_string, sizeof columns_string, "%d", cols);
+
+        setenv("LINES", lines_string, 1);
+        setenv("COLUMNS", columns_string, 1);
+        setenv("TERM", "xterm-256color", 1);
         unsetenv("PAGER");
         //setenv("QELEVEL", "1", 1);
 
@@ -257,9 +266,13 @@
 
 /* VT100 emulation */
 
-#define TRACE_MSG(m)  /* do { if (qe_state.trace_buffer) \
-                               eb_trace_bytes(" <-- "m" ", -1, \
-                               EB_TRACE_SHELL); } while (0) */
+static void qe_trace_term(ShellState *s, const char *msg) {
+    eb_trace_bytes(msg, -1, EB_TRACE_FLUSH | EB_TRACE_EMULATE);
+    eb_trace_bytes(": ", -1, EB_TRACE_EMULATE);
+    eb_trace_bytes(s->term_buf, s->term_len, EB_TRACE_EMULATE);
+}
+
+#define TRACE_MSG(s, m)  qe_trace_term(s, m)
 
 static void qe_term_init(ShellState *s)
 {
@@ -273,6 +286,7 @@
     s->bgcolor = QE_TERM_DEF_BG;
     s->attr = 0;
     s->reverse = 0;
+    s->lastc = ' ';
 
     term = getenv("TERM");
     /* vt100 terminfo definitions */
@@ -438,7 +452,7 @@
     }
 }
 
-static inline void qe_term_set_setyle(ShellState *s) {
+static inline void qe_term_set_style(ShellState *s) {
     QETermStyle composite_color;
 
     if (s->reverse) {
@@ -449,6 +463,26 @@
     s->b->cur_style = QE_TERM_COMPOSITE | s->attr | composite_color;
 }
 
+static void qe_term_get_xy(ShellState *s, int *px, int *py, int offset)
+{
+    int total_lines, cur_line, line_num, col_num, offset1;
+
+    /* compute offset */
+    eb_get_pos(s->b, &total_lines, &col_num, s->b->total_size);
+    if (s->cur_offset == s->b->total_size
+    ||  eb_prevc(s->b, s->b->total_size, &offset1) != '\n')
+        total_lines++;
+
+    line_num = total_lines - s->rows;
+    if (line_num < 0)
+        line_num = 0;
+
+    eb_get_pos(s->b, &cur_line, &col_num, offset);
+
+    *px = col_num;
+    *py = clamp(cur_line - line_num, 0, s->rows - 1);
+}
+
 /* Compute offset of the char at column x and row y (0 based).
  * Can insert spaces or rows if needed.
  * x and y may each be relative to the current position.
@@ -464,7 +498,7 @@
     ||  eb_prevc(s->b, s->b->total_size, &offset1) != '\n')
         total_lines++;
 
-    line_num = total_lines - QE_TERM_YSIZE;
+    line_num = total_lines - s->rows;
     if (line_num < 0)
         line_num = 0;
 
@@ -481,8 +515,8 @@
     if (y < 0 || y >= QE_TERM_YSIZE_INFINITE - 1)
         y = 0;
     else
-    if (y >= QE_TERM_YSIZE)
-        y = QE_TERM_YSIZE - 1;
+    if (y >= s->rows)
+        y = s->rows - 1;
     if (x < 0)
         x = 0;
 
@@ -490,7 +524,7 @@
     /* add lines if necessary */
     while (line_num >= total_lines) {
         /* XXX: color may be wrong */
-        qe_term_set_setyle(s);
+        qe_term_set_style(s);
         eb_insert_uchar(s->b, s->b->total_size, '\n');
         total_lines++;
     }
@@ -508,121 +542,143 @@
     s->cur_offset = offset;
 }
 
-/* CG: XXX: tty_put_char purposely ignores charset when inserting chars */
-static int qe_term_put_char(ShellState *s, int c)
+static void qe_term_goto_tab(ShellState *s, int n)
 {
-    char buf[1];
-    int c1, cur_len, offset, offset1;
+    int col_num, cur_line;
+    eb_get_pos(s->b, &cur_line, &col_num, s->cur_offset);
+    /* assuming tab stops every 8 positions */
+    qe_term_goto_xy(s, max(0, col_num + n * 8) & ~7, 0, 2);
+}
+
+static int qe_term_overwrite(ShellState *s, int offset,
+                             const char *buf, int len)
+{
+    int offset1;
+    int c1;
 
-    offset = s->cur_offset;
-    buf[0] = c;
     c1 = eb_nextc(s->b, offset, &offset1);
-    qe_term_set_setyle(s);
+    qe_term_set_style(s);
     if (c1 == '\n') {
         /* insert */
-        eb_insert(s->b, offset, buf, 1);
+        eb_insert(s->b, offset, buf, len);
     } else {
-        /* check for (c1 != c) is not advisable optimisation because
-         * re-writing the same character may cause color changes.
+        /* check for buffer content change is not an advisable optimisation
+         * because re-writing the same character may cause color changes.
          */
-        cur_len = offset1 - offset;
-        if (cur_len == 1) {
-            eb_write(s->b, offset, buf, 1);
+        int cur_len = offset1 - offset;
+        if (cur_len == len) {
+            eb_write(s->b, offset, buf, len);
         } else {
             eb_delete(s->b, offset, cur_len);
-            eb_insert(s->b, offset, buf, 1);
+            eb_insert(s->b, offset, buf, len);
+        }
         }
+    return offset + len;
+}
+
+static int qe_term_put_char(ShellState *s, int offset, int c, int n)
+{
+    /* qe_term_put_char purposely ignores charset when writing chars */
+    char buf[1];
+    int i;
+
+    buf[0] = c;
+    for (i = 0; i < n; i++) {
+        offset = qe_term_overwrite(s, offset, buf, 1);
     }
-    return s->cur_offset = offset + 1;
+    return offset;
 }
 
-static void qe_term_csi_m(ShellState *s, int c, int has_param)
+static int qe_term_csi_m(ShellState *s, const int *params, int count)
 {
+    int c = *params;
+
     /* Comment from putty/terminal.c:
      *
-     * A VT100 without the AVO only had one
-     * attribute, either underline or
-     * reverse video depending on the
-     * cursor type, this was selected by
+     * A VT100 without the AVO only had one attribute, either underline or
+     * reverse video depending on the cursor type, this was selected by
      * CSI 7m.
      *
      * case 2:
-     *  This is sometimes DIM, eg on the
-     *  GIGI and Linux (aka FAINT in iTerm2)
+     *  This is sometimes DIM, eg on the GIGI and Linux (aka FAINT in iTerm2)
      * case 8:
      *  This is sometimes INVIS various ANSI.
      * case 21:
      *  This like 22 disables BOLD, DIM and INVIS
      *
-     * The ANSI colours appear on any
-     * terminal that has colour (obviously)
-     * but the interaction between sgr0 and
-     * the colours varies but is usually
-     * related to the background colour
-     * erase item. The interaction between
-     * colour attributes and the mono ones
-     * is also very implementation
+     * The ANSI colours appear on any terminal that has colour (obviously)
+     * but the interaction between sgr0 and the colours varies but is usually
+     * related to the background colour erase item. The interaction between
+     * colour attributes and the mono ones is also very implementation
      * dependent.
      *
-     * The 39 and 49 attributes are likely
-     * to be unimplemented.
+     * The 39 and 49 attributes are likely to be unimplemented.
      */
-
-    switch (has_param ? c : 0) {
-    case 0:     /* exit_attribute_mode */
+    switch (c) {
+    case -1:
+    case 0:     /* Normal (default). [exit_attribute_mode] */
         s->fgcolor = QE_TERM_DEF_FG;
         s->bgcolor = QE_TERM_DEF_BG;
         s->reverse = 0;
         s->attr = 0;
         break;
-    case 1:     /* enter_bold_mode */
+    case 1:     /* Bold. [enter_bold_mode] */
         s->attr |= QE_TERM_BOLD;
         break;
-    case 3:     /* enter_italic_mode */
+    case 2:     /* Faint, decreased intensity (ISO 6429). */
+        goto unhandled;
+    case 3:     /* Italicized (ISO 6429). [enter_italic_mode] */
         s->attr |= QE_TERM_ITALIC;
         break;
-    case 4:     /* enter_underline_mode */
+    case 4:     /* Underlined. [enter_underline_mode] */
         s->attr |= QE_TERM_UNDERLINE;
         break;
-    case 5:     /* enter_blink_mode */
+    case 5:     /* Blink (appears as Bold). [enter_blink_mode] */
         s->attr |= QE_TERM_BLINK;
         break;
-    case 7:     /* enter_reverse_mode, enter_standout_mode */
-                /* also Xenix combined reverse fg/bg: \027[7;FG;BGm */
+    case 6:     /* SCO light background */
+        goto unhandled;
+    case 7:     /* Inverse. [enter_reverse_mode, enter_standout_mode] */
         s->reverse = 1;
         break;
-    case 22:    /* exit_bold_mode */
+    case 8:     /* Invisible, i.e., hidden (VT300). enter_secure_mode */
+    case 9:     /* Crossed-out characters (ISO 6429). cygwin dim mode */
+    case 10:    /* SCO acs off */
+    case 11:    /* SCO acs on (CP437) */
+    case 12:    /* SCO acs on, |0x80 */
+        goto unhandled;
+    case 21:    /* Doubly-underlined (ISO 6429). */
+        goto unhandled;
+    case 22:    /* Normal (neither bold nor faint). [exit_bold_mode] */
         s->attr &= ~QE_TERM_BOLD;
         break;
-    case 23:    /* exit_italic_mode */
+    case 23:    /* Not italicized (ISO 6429). [exit_italic_mode] */
         s->attr &= ~QE_TERM_ITALIC;
         break;
-    case 24:    /* exit_underline_mode */
+    case 24:    /* Not underlined. [exit_underline_mode] */
         s->attr &= ~QE_TERM_UNDERLINE;
         break;
-    case 25:    /* exit_blink_mode */
+    case 25:    /* Steady (not blinking). [exit_blink_mode] */
         s->attr &= ~QE_TERM_BLINK;
         break;
-    case 27:    /* exit_reverse_mode, exit_standout_mode */
+    case 27:    /* Positive (not inverse). [exit_reverse_mode, 
exit_standout_mode] */
         s->reverse = 0;
         break;
-    case 2:     /* DIM or FAINT */
-    case 6:     /* SCO light background */
-    case 8:     /* enter_secure_mode */
-    case 9:     /* cygwin dim mode */
-    case 10:    /* SCO acs off */
-    case 11:    /* SCO acs on (CP437) */
-    case 12:    /* SCO acs on, |0x80 */
-    case 28:    /* exit_secure_mode */
-        TRACE_MSG("unhandled");
-        break;
-    case 39:    /* orig_pair(1) default-foreground */
-        s->fgcolor = QE_TERM_DEF_FG;
-        break;
-    case 49:    /* orig_pair(2) default-background */
-        s->bgcolor = QE_TERM_DEF_BG;
+    case 28:    /* Visible, i.e., not hidden (VT300). [exit_secure_mode] */
+    case 29:    /* Not crossed-out (ISO 6429). */
+        goto unhandled;
+    case 30: case 31: case 32: case 33:
+    case 34: case 35: case 36: case 37:
+        /* set foreground color */
+        /* 0:black 1:red 2:green 3:yellow 4:blue 5:magenta 6:cyan 7:white */
+        /* XXX: should distinguish system colors and palette colors */
+        s->fgcolor = c - 30;
+        if (QE_TERM_FG_COLORS < 256) {
+            s->fgcolor = qe_map_color(xterm_colors[c - 30], xterm_colors,
+                                      QE_TERM_FG_COLORS, NULL);
+        }
         break;
-    case 38:    /* set extended foreground color */
+    case 38:    /* set extended foreground color (ISO-8613-3) */
         // First subparam means:   # additional subparams:  Accepts optional 
params:
         // 1: transparent          0                        NO
         // 2: RGB                  3                        YES
@@ -647,76 +703,73 @@
         // where N is a value between 0 and 255. See the colors described in 
screen_char_t
         // in the comments for fgColorCode.
 
-        if (s->esc_params[1] == 5) {
+        if (count >= 3 && params[1] == 5) {
             /* set foreground color to third esc_param */
             /* complete syntax is \033[38;5;Nm where N is in range 0..255 */
-            int color = s->esc_params[2] & 255;
+            int color = clamp(params[2], 0, 255);
             QEColor rgb = xterm_colors[color];
 
             /* map color to qe-term palette */
             s->fgcolor = color;
             if (QE_TERM_FG_COLORS < 256)
                 s->fgcolor = qe_map_color(rgb, xterm_colors, 
QE_TERM_FG_COLORS, NULL);
-            s->nb_esc_params = 1;  /* XXX: should instead consume 2 arguments 
*/
-        } else
-        if (s->esc_params[1] == 2) {
+            return 3;
+        }
+        if (count >= 5 && params[1] == 2) {
             /* set foreground color to 24-bit color */
             /* complete syntax is \033[38;2;r;g;bm where r,g,b are in 0..255 */
-            QEColor rgb = QERGB25(s->esc_params[2] & 255,
-                                  s->esc_params[3] & 255,
-                                  s->esc_params[4] & 255);
+            QEColor rgb = QERGB25(clamp(params[2], 0, 255),
+                                  clamp(params[3], 0, 255),
+                                  clamp(params[4], 0, 255));
 
             /* map 24-bit colors to qe-term palette */
             s->fgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_FG_COLORS, 
NULL);
-            s->nb_esc_params = 1;  /* XXX: should instead consume 4 arguments 
*/
+            return 5;
         }
+        return 2;
+    case 39:    /* orig_pair(1) [default-foreground] */
+        s->fgcolor = QE_TERM_DEF_FG;
         break;
-    case 48:    /* set extended background color */
-        if (s->esc_params[1] == 5) {
+    case 40: case 41: case 42: case 43:
+    case 44: case 45: case 46: case 47:
+        /* set background color */
+        /* XXX: should distinguish system colors and palette colors */
+        s->bgcolor = c - 40;
+        if (QE_TERM_BG_COLORS < 256) {
+            s->bgcolor = qe_map_color(xterm_colors[c - 40], xterm_colors,
+                                      QE_TERM_BG_COLORS, NULL);
+        }
+        break;
+    case 48:    /* set extended background color (ISO-8613-3) */
+        if (count >= 3 && params[1] == 5) {
             /* set background color to third esc_param */
             /* complete syntax is \033[48;5;Nm where N is in range 0..255 */
-            int color = s->esc_params[2] & 255;
+            int color = clamp(params[2], 0, 255);
             QEColor rgb = xterm_colors[color];
 
             /* map color to qe-term palette */
             s->bgcolor = color;
             if (QE_TERM_BG_COLORS < 256)
                 s->bgcolor = qe_map_color(rgb, xterm_colors, 
QE_TERM_BG_COLORS, NULL);
-            s->nb_esc_params = 1;  /* XXX: should instead consume 2 arguments 
*/
-        } else
-        if (s->esc_params[1] == 2) {
+            return 3;
+        }
+        if (count >= 5 && params[1] == 2) {
             /* set background color to 24-bit color */
             /* complete syntax is \033[48;2;r;g;bm where r,g,b are in 0..255 */
-            QEColor rgb = QERGB25(s->esc_params[2] & 255,
-                                  s->esc_params[3] & 255,
-                                  s->esc_params[4] & 255);
+            QEColor rgb = QERGB25(clamp(params[2], 0, 255),
+                                  clamp(params[3], 0, 255),
+                                  clamp(params[4], 0, 255));
 
             /* map 24-bit colors to qe-term palette */
             s->bgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_BG_COLORS, 
NULL);
-            s->nb_esc_params = 1;  /* XXX: should instead consume 4 arguments 
*/
+            return 5;
         }
+        return 2;
+    case 49:    /* orig_pair(2) [default-background] */
+        s->bgcolor = QE_TERM_DEF_BG;
         break;
-    default:
-        /* 0:black 1:red 2:green 3:yellow 4:blue 5:magenta 6:cyan 7:white */
-        if (c >= 30 && c <= 37) {
-            /* set foreground color */
-            /* XXX: should distinguish system colors and palette colors */
-            s->fgcolor = c - 30;
-            if (QE_TERM_FG_COLORS < 256) {
-                s->fgcolor = qe_map_color(xterm_colors[c - 30], xterm_colors,
-                                          QE_TERM_FG_COLORS, NULL);
-            }
-        } else
-        if (c >= 40 && c <= 47) {
-            /* set background color */
-            /* XXX: should distinguish system colors and palette colors */
-            s->bgcolor = c - 40;
-            if (QE_TERM_BG_COLORS < 256) {
-                s->bgcolor = qe_map_color(xterm_colors[c - 40], xterm_colors,
-                                          QE_TERM_BG_COLORS, NULL);
-            }
-        } else
-        if (c >= 90 && c <= 97) {
+    case 90: case 91: case 92: case 93:
+    case 94: case 95: case 96: case 97:
             /* set bright foreground color */
             /* XXX: should distinguish system colors and palette colors */
             s->fgcolor = c - 90 + 8;
@@ -724,8 +777,9 @@
                 s->fgcolor = qe_map_color(xterm_colors[c - 90 + 8], 
xterm_colors,
                                           QE_TERM_FG_COLORS, NULL);
             }
-        } else
-        if (c >= 100 && c <= 107) {
+        break;
+    case 100: case 101: case 102: case 103:
+    case 104: case 105: case 106: case 107:
             /* set bright background color */
             /* XXX: should distinguish system colors and palette colors */
             s->bgcolor = c - 100 + 8;
@@ -733,11 +787,13 @@
                 s->bgcolor = qe_map_color(xterm_colors[c - 100 + 8], 
xterm_colors,
                                           QE_TERM_BG_COLORS, NULL);
             }
-        } else {
-            TRACE_MSG("unhandled");
-        }
+        break;
+    default:
+    unhandled:
+        TRACE_MSG(s, "unhandled SGR");
         break;
     }
+    return 1;
 }
 
 
@@ -858,12 +914,21 @@
 
 static void qe_term_emulate(ShellState *s, int c)
 {
-    int i, offset, offset1, offset2, n;
+    int i, n, param1, param2, len;
+    int offset, offset1, offset2;
     char buf1[10];
 
     offset = s->cur_offset;
 
-#define ESC2(c1,c2)  (((c1)<<8)|((unsigned char)c2))
+    if (s->state == QE_TERM_STATE_NORM) {
+        s->term_pos = 0;
+    }
+    if (s->term_pos < countof(s->term_buf)) {
+        s->term_buf[s->term_pos++] = c;
+        s->term_len = s->term_pos;
+    }
+
+#define ESC2(c1,c2)  (((c1) << 8) | (unsigned char)(c2))
     /* some bytes are state independent */
     switch (c) {
     case 0x18:
@@ -882,36 +947,41 @@
     switch (s->state) {
     case QE_TERM_STATE_NORM:
         switch (c) {
-            /* BEL            Bell (Ctrl-G) */
-            /* FF             Form Feed or New Page (NP) (Ctrl-L) same as LF */
-            /* VT             Vertical Tab (Ctrl-K) same as LF */
-
-        case 8:         /* ^H  BS = backspace */
+        case 5:     /* ENQ  Return Terminal Status (Ctrl-E).
+             * Default response is an empty string, but may be overridden
+             * by a resource <b>answerbackString</b>.
+             */
+            break;
+        case 7:     /* BEL  Bell (Ctrl-G). */
+            put_status(NULL, "Ding!");
+            break;
+        case 8:     /* BS   Backspace (Ctrl-H). */
             {
                 int c1;
                 c1 = eb_prevc(s->b, offset, &offset1);
                 if (c1 != '\n') {
                     s->cur_offset = offset1;
-                    /* back_color_erase */
-                    //qe_term_put_char(s, ' ');
                 }
             }
             break;
-        case 9:        /* ^I  HT = horizontal tab */
-            {
-                int col_num, cur_line;
-                eb_get_pos(s->b, &cur_line, &col_num, offset);
-                qe_term_goto_xy(s, (col_num + 8) & ~7, 0, 2);
+        case 9:     /* TAB  Horizontal Tab (HT) (Ctrl-I). */
+            qe_term_goto_tab(s, 1);
                 break;
-            }
-        case 10:        /* ^J  NL = line feed */
+        case 10:    /* Line Feed or New Line (NL).  (LF  is Ctrl-J). */
+        case 11:    /* VT   Vertical Tab (Ctrl-K).
+                     * This is treated the same as LF. */
+        case 12:    /* FF   Form Feed or New Page (NP) (Ctrl-L).
+                     * FF  is treated the same as LF. */
+            if (s->grab_keys) {
+                qe_term_goto_xy(s, 0, 1, 3);
+            } else {
             /* go to next line */
-            /* CG: should check if column should be kept */
+                /* CG: should check if column should be kept in cooked mode */
             for (;;) {
                 if (offset == s->b->total_size) {
                     /* add a new line */
                     /* CG: XXX: ignoring charset */
-                    qe_term_set_setyle(s);
+                        qe_term_set_style(s);
                     buf1[0] = '\n';
                     eb_insert(s->b, offset, buf1, 1);
                     offset = s->b->total_size;
@@ -921,22 +991,26 @@
                 if (c == '\n')
                     break;
             }
-            s->b->last_log = 0; /* close undo record */
             s->cur_offset = offset;
+            }
+            s->b->last_log = 0; /* close undo record */
             break;
-        case 13:        /* ^M  CR = carriage return */
+        case 13:    /* CR   Carriage Return (Ctrl-M). */
             /* move to bol */
             s->cur_offset = eb_goto_bol(s->b, offset);
             break;
-        case 14:        /* ^N  SO = shift out */
+        case 14:    /* SO   Shift Out (Ctrl-N) ->
+             * Switch to Alternate Character Set.  This
+             * invokes the G1 character set. */
             s->shifted = s->charset[s->cset = 1];
             break;
-        case 15:        /* ^O  SI = shift in */
+        case 15:    /* SI   Shift In (Ctrl-O) ->
+             * Switch to Standard Character Set.  This
+             * invokes the G0 character set (the default). */
             s->shifted = s->charset[s->cset = 0];
             break;
         default:
             if (c >= 32) {
-                int c1, cur_len, len;
                 /* CG: assuming ISO-8859-1 characters */
                 /* CG: horrible kludge for alternate charset support */
                 if (s->shifted && c >= 96 && c < 128) {
@@ -965,7 +1039,7 @@
                          * This hack is reversed in tty_term_flush().
                          */
                         c += 32;
-                        buf1[0] = c;
+                        buf1[0] = s->lastc = c;
                         len = 1;
                     }
                 } else {
@@ -982,72 +1056,30 @@
                     if (s->b->charset == &charset_utf8) {
                         s->utf8_len = utf8_length[c];
                         if (s->utf8_len > 1) {
-                            s->utf8_buf[0] = c;
-                            s->utf8_pos = 1;
                             s->state = QE_TERM_STATE_UTF8;
                             break;
                         }
                     }
                     //len = eb_encode_uchar(s->b, buf1, c);
-                    buf1[0] = c;
+                    buf1[0] = s->lastc = c;
                     len = 1;
                 }
-                c1 = eb_nextc(s->b, offset, &offset1);
-                qe_term_set_setyle(s);
-                /* Should simplify with qe_term_put_char */
-                if (c1 == '\n') {
-                    /* insert */
-                    eb_insert(s->b, offset, buf1, len);
-                } else {
-                    cur_len = offset1 - offset;
-                    if (cur_len == len) {
-                        eb_write(s->b, offset, buf1, len);
-                    } else {
-                        eb_delete(s->b, offset, cur_len);
-                        eb_insert(s->b, offset, buf1, len);
-                    }
-                }
-                s->cur_offset = offset + len;
+                s->cur_offset = qe_term_overwrite(s, offset, buf1, len);
            } else {
-                TRACE_MSG("control");
+                TRACE_MSG(s, "control");
            }
             break;
         }
         break;
     case QE_TERM_STATE_UTF8:
-        s->utf8_buf[s->utf8_pos++] = c;
-        if (s->utf8_pos >= s->utf8_len) {
-            int c1, cur_len, len;
-
-            len = s->utf8_len;
-            c1 = eb_nextc(s->b, offset, &offset1);
-            qe_term_set_setyle(s);
-            if (c1 == '\n') {
-                /* insert */
-                eb_insert(s->b, offset, s->utf8_buf, len);
-            } else {
-                cur_len = offset1 - offset;
-                if (cur_len == len) {
-                    eb_write(s->b, offset, s->utf8_buf, len);
-                } else {
-                    eb_delete(s->b, offset, cur_len);
-                    eb_insert(s->b, offset, s->utf8_buf, len);
-                }
-            }
-            s->cur_offset = offset + len;
+        /* XXX: should check that c is a utf-8 continuation byte */
+        if (s->term_pos >= s->utf8_len) {
+            s->cur_offset = qe_term_overwrite(s, offset,
+                                              cs8(s->term_buf), s->utf8_len);
             s->state = QE_TERM_STATE_NORM;
         }
         break;
     case QE_TERM_STATE_ESC:
-        if (c == '[') {
-            for (i = 0; i < MAX_ESC_PARAMS; i++) {
-                s->esc_params[i] = 1;
-                s->has_params[i] = 0;
-            }
-            s->nb_esc_params = 0;
-            s->esc1 = 0;
-            s->state = QE_TERM_STATE_CSI;
-        } else {
             /* CG: should deal with other sequences:
              * ansi: hts=\EH, s0ds=\E(B, s1ds=\E)B, s2ds=\E*B, s3ds=\E+B,
              * linux: hts=\EH, rc=\E8, ri=\EM, rs1=\Ec\E]R, sc=\E7,
@@ -1062,68 +1094,116 @@
              * tests: \E#8  fill screen with 'E's
              * tests: \Ec   reset
              */
+        s->esc1 = c;
             switch (c) {
+        case '[':   // Control Sequence Introducer (CSI  is 0x9b).
+            s->nb_params = 0;
+            s->params[0] = -1;
+            s->params[1] = -1;
+            s->esc1 = 0;
+            s->state = QE_TERM_STATE_CSI;
+            break;
+        case ' ':
+        case '#':
             case '%':
             case '(':
             case ')':
             case '*':
             case '+':
-            case ']':
-                s->esc1 = c;
+        case '-':
+        case '.':
+        case '/':
+        case ']':   // Operating System Command (OSC  is 0x9d).
                 s->state = QE_TERM_STATE_ESC2;
                 break;
-            case '7':   // sc   (save_cursor)
-            case '8':   // rc   (restore_cursor)
-            case '=':   // smkx (DECKPAM: Keypad application mode)
-            case '>':   // rmkx, is2, rs2  (DECKPNM: Keypad numeric mode)
-            case 'D':   // IND: exactly equivalent to LF
-            case 'E':   // NEL: exactly equivalent to CR-LF
-            case 'M':   // ri   (scroll_reverse, RI: reverse index - backwards 
LF)
-            case 'Z':   /* DECID: terminal type query */
-            case 'c':   // rs1  (reset_1string)
-                        /* RIS: restore power-on settings */
-            case 'H':   // hts  (set_tab)
-                // XXX: do these
+        case '^':   // Privacy Message (PM  is 0x9e).
+        case '_':   // Application Program Command (APC  is 0x9f).
+        case 'P':   // Device Control String (DCS  is 0x90).
+            s->state = QE_TERM_STATE_STRING;
+            break;
+        case '\\':  // String Terminator (ST  is 0x9c).
+            TRACE_MSG(s, "unhandled string");
+            s->state = QE_TERM_STATE_NORM;
+            break;
+        case '6':   // Back Index (DECBI), VT420 and up.
+        case '7':   // Save Cursor (DECSC). [sc]
+        case '8':   // Restore Cursor (DECRC). [rc]
+        case '9':   // Forward Index (DECFI), VT420 and up.
+        case '=':   // Application Keypad (DECKPAM). [smkx]
+        case '>':   // Normal Keypad (DECKPNM). [rmkx, is2, rs2]
+            s->state = QE_TERM_STATE_NORM;
+            break;
+        case 'D':   // Index (IND  is 0x84).
+        case 'E':   // Next Line (NEL  is 0x85).
+        case 'F':   // Cursor to lower left corner of screen.
+                    // This is enabled by the hpLowerleftBugCompat resource.
+        case 'H':   // Tab Set (HTS  is 0x88). [set_tab]
+        case 'M':   // Reverse Index (RI  is 0x8d). [ri]
+        case 'O':   // Single Shift Select of G3 Character Set (SS3  is 0x8f).
+                    // This affects next character only.
+        case 'V':   // Start of Guarded Area (SPA  is 0x96).
+        case 'W':   // End of Guarded Area (EPA  is 0x97).
+        case 'X':   // Start of String (SOS  is 0x98).
+        case 'Z':   // Return Terminal ID (DECID is 0x9a).
+                    // Obsolete form of CSI c  (DA).
+        case 'c':   // Full Reset (RIS). [rs1, reset_1string]
+        case 'l':   // Memory Lock (per HP terminals).  Locks memory above the 
cursor.
+        case 'm':   // Memory Unlock (per HP terminals).
+        case 'n':   // Invoke the G2 Character Set as GL (LS2).
+        case 'o':   // Invoke the G3 Character Set as GL (LS3).
+        case '|':   // Invoke the G3 Character Set as GR (LS3R).
+        case '}':   // Invoke the G2 Character Set as GR (LS2R).
+        case '~':   // Invoke the G1 Character Set as GR (LS1R).
             default:
-                TRACE_MSG("unhandled");
+            TRACE_MSG(s, "unhandled");
                 s->state = QE_TERM_STATE_NORM;
                 break;
             }
-        }
         break;
     case QE_TERM_STATE_ESC2:
         s->state = QE_TERM_STATE_NORM;
         s->esc2 = c;
         switch (ESC2(s->esc1, c)) {
-        case ESC2('%','G'):     /* set utf mode */
         case ESC2('%','8'):     /* set utf mode */
-        case ESC2('%','@'):     /* reset utf mode */
-            TRACE_MSG("utf mode");
+        case ESC2('%','G'):     /* Select UTF-8 character set (ISO 2022). */
+        case ESC2('%','@'):     /* Select default character set.
+                                   That is ISO 8859-1 (ISO 2022). */
+            TRACE_MSG(s, "utf mode");
+            break;
+            /* Designate G0 Character Set (ISO 2022, VT100). */
+        case ESC2('(','0'):     /* set charset0 CSET_LINEDRW */
+            s->charset[0] = 1;
             break;
         case ESC2('(','A'):     /* set charset0 CSET_GBCHR */
-        case ESC2('(','U'):     /* set charset0 CSET_SCOACS */
         case ESC2('(','B'):     /* set charset0 CSET_ASCII */
+        case ESC2('(','U'):     /* set charset0 CSET_SCOACS */
             s->charset[0] = 0;
             break;
-        case ESC2('(','0'):     /* set charset0 CSET_LINEDRW */
-            s->charset[0] = 1;
+            /* Designate G1 Character Set (ISO 2022, VT100). */
+        case ESC2(')','0'):     /* set charset1 CSET_LINEDRW */
+            s->charset[1] = 1;
             break;
         case ESC2(')','A'):     /* set charset1 CSET_GBCHR */
-        case ESC2(')','U'):     /* set charset1 CSET_SCOACS */
         case ESC2(')','B'):     /* set charset1 CSET_ASCII */
+        case ESC2(')','U'):     /* set charset1 CSET_SCOACS */
             s->charset[1] = 0;
             break;
-        case ESC2(')','0'):     /* set charset1 CSET_LINEDRW */
-            s->charset[1] = 1;
-            break;
+            /* Designate G2 Character Set (ISO 2022, VT220). */
         case ESC2('*','B'):
+            /* Designate G3 Character Set (ISO 2022, VT220). */
         case ESC2('+','B'):
-            /* XXX: Todo */
-            TRACE_MSG("unhandled");
-            break;
-        case ESC2(']','0'):     /* xterm's set-window-title and icon */
-        case ESC2(']','1'):     /* xterm's set-window-title */
-        case ESC2(']','2'):     /* xterm's set-window-title */
+            /* Designate G1 Character Set (VT300). */
+        case ESC2('-','B'):
+            /* Designate G2 Character Set (VT300). */
+        case ESC2('.','B'):
+            /* Designate G3 Character Set (VT300). */
+        case ESC2('/','B'):
+            TRACE_MSG(s, "set charset");
+            break;
+            /* XXX: OSC sequences should parse as OSC Ps;Pt ST */
+        case ESC2(']','0'):  /* Change Icon Name and Window Title to Pt. */
+        case ESC2(']','1'):  /* Change Icon Name to Pt. */
+        case ESC2(']','2'):  /* Change Window Title to Pt. */
         case ESC2(']','3'):     /* Set X property on top-level window */
             /* Pt should be in the form "prop=value", or just "prop" to delete 
the property */
         case ESC2(']','4'):     /* xterm's define-extended color 
"\033]4;c;name\007" */
@@ -1162,7 +1242,7 @@
         case ESC2(']','P'):     /* linux set palette */
         case ESC2(']','R'):     /* linux reset palette */
             /* XXX: Todo */
-            TRACE_MSG("linux palette");
+            TRACE_MSG(s, "linux palette");
             /* followed by 7 digit palette entry nrrggbb with
                n: letter 0-f for standard palette entries
                          g-m for extended attributes:
@@ -1170,7 +1250,7 @@
             */
             break;
        default:
-            TRACE_MSG("unhandled");
+            TRACE_MSG(s, "unhandled");
             break;
         }
         s->shifted = s->charset[s->cset];
@@ -1180,6 +1260,7 @@
         /* Stop string on CR or LF, for protection */
         if (c == '\012' || c == '\015') {
             s->state = QE_TERM_STATE_NORM;
+            TRACE_MSG(s, "broken string");
             break;
         }
         /* Stop string on \a (^G) or M-\ -- need better test for ESC \ */
@@ -1191,157 +1272,337 @@
             // iTerm2 reports the current rgb value with "<index>;?",
             //   e.g. "105;?" -> report as \033]4;P;rgb:00/cc/ff\007",
             s->state = QE_TERM_STATE_NORM;
+            TRACE_MSG(s, "unhandled string");
         }
         break;
     case QE_TERM_STATE_CSI:
-        if (c == '?' || c == '=') {
+        if (c == '?' || c == '=' || c == '"' || c == ' ' || c == '\'' || c == 
'&') {
             s->esc1 = c;
             break;
         }
         if (qe_isdigit(c)) {
-            if (s->nb_esc_params < MAX_ESC_PARAMS) {
-                if (!s->has_params[s->nb_esc_params]) {
-                    s->esc_params[s->nb_esc_params] = 0;
-                    s->has_params[s->nb_esc_params] = 1;
-                }
-                s->esc_params[s->nb_esc_params] =
-                    s->esc_params[s->nb_esc_params] * 10 + c - '0';
+            if (s->params[s->nb_params] < 0) {
+                s->params[s->nb_params] = 0;
             }
+            s->params[s->nb_params] *= 10;
+            s->params[s->nb_params] += c - '0';
             break;
-        } else {
-            s->nb_esc_params++;
-            if (c == ';')
+        }
+        if (s->nb_params == 0
+        ||  (s->nb_params < MAX_CSI_PARAMS && s->params[s->nb_params] >= 0)) {
+            s->nb_params++;
+            s->params[s->nb_params] = -1;
+        }
+        if (c == ';' || c == ':')
                 break;
             s->state = QE_TERM_STATE_NORM;
+        /* default param is 1 for most commands */
+        param1 = s->params[0] >= 0 ? s->params[0] : 1;
+        param2 = s->params[1] >= 0 ? s->params[1] : 1;
             switch (ESC2(s->esc1,c)) {
-               /* unhandled:
-                * \^[[4l
-                * \^[[?1h
-                * \^[[?7h
-                * \^[[?25l
-                * \^[[?1000h
-                */
-
-            case 'h':   /* SM: toggle modes to high */
-            case ESC2('?','h'): /* set terminal mode */
-                /* 1047: alternate screen
-                 * 1048: save / restore cursor
-                 * 1049: save / restore  cursor and alternate screen
-                 * should grab all keys while active!
-                 */
-                if (s->esc_params[0] == 1047 ||
-                    s->esc_params[0] == 1048 ||
-                    s->esc_params[0] == 1049) {
+        case '@':  /* ICH: Insert Ps (Blank) Character(s) (default = 1) */
+            buf1[0] = ' ';
+            offset1 = offset;
+            qe_term_set_style(s);
+            for (n = param1; n > 0; n--) {
+                /* XXX: incorrect for non 8 bit charsets */
+                eb_insert(s->b, offset1, buf1, 1);
+                offset1 += 1;
+            }
+            s->cur_offset = offset;
+            break;
+        case 'A':  /* CUU: Cursor Up Ps Times (default = 1) */
+            qe_term_goto_xy(s, 0, -param1, 3);
+            break;
+        case 'B':  /* CUD: Cursor Down Ps Times (default = 1) */
+        case 'e':  /* VPR: Line Position Relative [rows] (default = 1) */
+            qe_term_goto_xy(s, 0, param1, 3);
+            break;
+        case 'C':  /* CUF: Cursor Forward Ps Times (default = 1) */
+        case 'a':  /* HPR: Character Position Relative [columns] (default = 1) 
*/
+            qe_term_goto_xy(s, param1, 0, 3);
+            break;
+        case 'D':  /* CUB: Cursor Backward Ps Times (default = 1) */
+            qe_term_goto_xy(s, -param1, 0, 3);
+            break;
+        case 'E':  /* CNL: Cursor Next Line Ps Times (default = 1) and CR. */
+            qe_term_goto_xy(s, 0, param1, 2);
+            break;
+        case 'F':  /* CPL: Cursor Preceding Line Ps Times (default = 1) and 
CR. */
+            qe_term_goto_xy(s, 0, -param1, 2);
+            break;
+        case 'G':  /* CHA: Cursor Character Absolute [column]. */
+        case '`':  /* HPA: Character Position Absolute [column] (default = 1) 
*/
+            qe_term_goto_xy(s, param1 - 1, 0, 2);
+            break;
+        case 'H':  /* CUP: Cursor Position [row;column] (default = [1,1]). */
+        case 'f':  /* HVP: Horizontal and Vertical Position [row;column] 
(default = [1,1]) */
+            qe_term_goto_xy(s, param2 - 1, param1 - 1, 0);
+            break;
+        case 'I':  /* CHT: Cursor Forward Tabulation Ps tab stops (default = 
1). */
+            qe_term_goto_tab(s, param1);
+            break;
+        case 'J':  /* ED: Erase in Display. */
+        case ESC2('?','J'):  /* DECSED: Selective Erase in Display. */
+            /*     0: Below (default), 1: Above, 2: All, 3: Saved Lines 
(xterm) */
+            TRACE_MSG(s, "erase screen");
+            break;
+        case 'K':  /* EL: Erase in Line. */
+        case ESC2('?','K'):  /* DECSEL: Selective Erase in Line. */
+            {   /*     0: to Right (default), 1: to Left, 2: All */
+                /* XXX: should handle eol style */
+                int cur_line, col_num1, col_num2, n1, n2;
+
+                // default param is 0
+                n1 = n2 = 0;
+                eb_get_pos(s->b, &cur_line, &col_num1, offset);
+                offset1 = eb_goto_bol(s->b, offset);
+                offset2 = eb_goto_eol(s->b, offset);
+                eb_get_pos(s->b, &cur_line, &col_num2, offset2);
+                if (s->params[0] <= 0) {
+                    n2 = col_num2 - col_num1;
+                } else
+                if (s->params[0] == 1) {
+                    offset = offset1;
+                    n1 = col_num1;
+                } else
+                if (s->params[0] == 2) {
+                    offset = offset1;
+                    n1 = col_num1;
+                    n2 = col_num2 - col_num1;
+                }
+                /* update cursor as overwriting characters may change offsets 
*/
+                s->cur_offset = qe_term_put_char(s, offset, ' ', n1);
+                qe_term_put_char(s, s->cur_offset, ' ', n2);
+            }
+            break;
+        case 'L':  /* IL: Insert Ps Line(s) (default = 1). */
+            //TRACE_MSG(s, "insert lines");
+            {
+                int col, row, zone, keep;
+                s->cur_offset = offset = eb_goto_bol(s->b, offset);
+                qe_term_get_xy(s, &col, &row, offset);
+                zone = max(0, s->scroll_bottom - row);
+                param1 = min(param1, zone);
+                keep = zone - param1;
+                for (i = 0; i < param1; i++) {
+                    offset += eb_insert_uchar(s->b, offset, '\n');
+                }
+                for (i = 0; i < keep; i++) {
+                    offset = eb_next_line(s->b, offset);
+                }
+                for (i = 0; i < param1; i++) {
+                    eb_delete_range(s->b, offset, eb_next_line(s->b, offset));
+                }
+            }
+            break;
+        case 'M':  /* DL: Delete Ps Line(s) (default = 1). */
+            //TRACE_MSG(s, "delete lines");
+            {
+                int col, row, zone, keep;
+                s->cur_offset = offset = eb_goto_bol(s->b, offset);
+                qe_term_get_xy(s, &col, &row, offset);
+                zone = max(0, s->scroll_bottom - row);
+                param1 = min(param1, zone);
+                keep = zone - param1;
+                for (i = 0; i < param1; i++) {
+                    eb_delete_range(s->b, offset, eb_next_line(s->b, offset));
+                }
+                for (i = 0; i < keep; i++) {
+                    offset = eb_next_line(s->b, offset);
+                }
+                for (i = 0; i < param1; i++) {
+                    offset += eb_insert_uchar(s->b, offset, '\n');
+                }
+            }
+            break;
+        case 'P':  /* DCH: Delete Ps Character(s) (default = 1). */
+            offset1 = offset;
+            for (n = param1; n > 0; n--) {
+                c = eb_nextc(s->b, offset1, &offset2);
+                if (c == '\n')
+                    break;
+                offset1 = offset2;
+            }
+            eb_delete_range(s->b, offset, offset1);
+            break;
+        case 'S':  /* SU: Scroll up Ps lines (default = 1). */
+            /* scroll the whole page up */
+            TRACE_MSG(s, "scroll up");
+            break;
+        case 'T':  /* SD: Scroll down Ps lines (default = 1). */
+            /* scroll the whole page down */
+            TRACE_MSG(s, "scroll down");
+            break;
+        case 'X':  /* ECH: Erase Ps Character(s) (default = 1). */
+            qe_term_put_char(s, offset, ' ', param1);
+            break;
+        case 'Z':  /* CBT: Cursor Backward Tabulation Ps tab stops (default = 
1). */
+            qe_term_goto_tab(s, -param1);
+            break;
+        case 'b':  /* REP: Repeat the preceding graphic character Ps times. */
+            /* XXX: utf-8 issue for non ASCII characters */
+            s->cur_offset = qe_term_put_char(s, offset, s->lastc, param1);
+            break;
+        case 'c':  /* DA: Send Device Attributes (Primary DA) */
+            // default param is 0
+            if (s->params[0] <= 0) {
+                /* Report Advanced Video option (AVO) */
+                qe_term_write(s, "\033[?1;2c", -1);
+            }
+            break;
+        case ESC2('>','c'):  /* DA: Send Device Attributes (Secondary DA) */
+            // default param is 0
+            if (s->params[0] <= 0) {
+                /* Report Qemacs emulator version 0.5 */
+                qe_term_write(s, "\033[>42;0;5c", -1);
+            }
+            break;
+        case 'd':  /* VPA: Line Position Absolute [row] (default = 1). */
+            qe_term_goto_xy(s, 0, param1 - 1, 1);
+            break;
+        case 'g':  /* TBC: Tab Clear. */
+            // 0 (default) -> Clear Current Column, 3 -> Clear All */
+            TRACE_MSG(s, "clear tabs");
+            break;
+        case 'h':   /* SM: Set Mode. */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 2:   /* Keyboard Action Mode (AM). */
+                case 4:   /* Insert Mode (IRM). */
+                case 12:  /* Send/receive (SRM). */
+                case 20:  /* Automatic Newline (LNM). */
+                    break;
+                }
+            }
+            break;
+        case ESC2('?','h'): /* DEC Private Mode Set (DECSET) */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 1:     /* Application Cursor Keys (DECCKM). */
+                case 4:     /* Smooth (Slow) Scroll (DECSCLM). */
+                    break;
+                case 5:     /* Reverse Video (DECSCNM) */
+                    s->reverse = 1;
+                    break;
+                case 7:     /* Wraparound Mode (DECAWM). */
+                    break;
+                case 12:    /* Start Blinking Cursor (att610). */
+                    break;
+                case 25:    /* Show Cursor (DECTCEM). */
+                    break;
+                case 1000:  /* Send Mouse X & Y on button press and
+                                release. */
+                    break;
+                case 1034:  /* Interpret "meta" key, sets eighth bit.
+                     * (enables the eightBitInput resource).
+                     */
+                    break;
+                case 1047:  /* Use Alternate Screen Buffer. */
+                case 1048:  /* Save cursor as in DECSC. */
+                case 1049:  /* Save cursor as in DECSC and use Alternate
+                       Screen Buffer, clearing it first. */
                     if (s->shell_flags & SF_INTERACTIVE) {
                         /* only grab keys in interactive qe_term buffers */
                         s->grab_keys = 1;
                         qe_grab_keys(shell_key, s);
                         /* Should also clear screen */
                     }
-               } else {
-                    TRACE_MSG("set term mode");
-               }
                 break;
-            case 'i':   /* MC: Media copy */
-            case ESC2('?','i'):
-                TRACE_MSG("media copy");
+                default:
+                    TRACE_MSG(s, "mode set");
                 break;
-            case ESC2('?','l'): /* reset terminal mode */
-                if (s->esc_params[0] == 1047 ||
-                    s->esc_params[0] == 1048 ||
-                    s->esc_params[0] == 1049) {
-                    if (s->shell_flags & SF_INTERACTIVE) {
-                        qe_ungrab_keys();
-                        s->grab_keys = 0;
                     }
-               } else {
-                    TRACE_MSG("reset term mode");
                }
                 break;
-            case 'A':  /* CUU: move up N lines */
-                qe_term_goto_xy(s, 0, -s->esc_params[0], 3);
+        case 'i':   /* MC: Media Copy */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 0:   /* Print screen (default). */
+                case 4:   /* Turn off printer controller mode. */
+                case 5:   /* Turn on printer controller mode. */
+                case 10:  /* HTML screen dump. */
+                case 11:  /* SVG screen dump. */
                 break;
-            case 'e':  /* VPR: move down N lines */
-            case 'B':  /* CUD: Cursor down */
-                qe_term_goto_xy(s, 0, s->esc_params[0], 3);
+                }
+            }
+            TRACE_MSG(s, "media copy");
                 break;
-            case 'a':  /* HPR: move right N cols */
-            case 'C':  /* CUF: Cursor right */
-                qe_term_goto_xy(s, s->esc_params[0], 0, 3);
+        case ESC2('?','i'):  /* MC: Media Copy (MC, DEC-specific). */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 1:   /* Print line containing cursor. */
+                case 4:   /* Turn off autoprint mode. */
+                case 5:   /* Turn on autoprint mode. */
+                case 10:  /* Print composed display, ignores DECPEX. */
+                case 11:  /* Print all pages. */
                 break;
-            case 'D':  /* CUB: move left N cols */
-                qe_term_goto_xy(s, -s->esc_params[0], 0, 3);
+                }
+            }
+            TRACE_MSG(s, "media copy");
                 break;
-            case 'F':  /* CPL: move up N lines and CR */
-                qe_term_goto_xy(s, 0, -s->esc_params[0], 2);
+        case 'l':   /* RM: Reset Mode. */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 2:   /* Keyboard Action Mode (AM). */
+                case 4:   /* Insert Mode (IRM). */
+                case 12:  /* Send/receive (SRM). */
+                case 20:  /* Automatic Newline (LNM). */
                 break;
-            case 'G':  /* CHA: goto column_address */
-            case '`':  /* HPA: set horizontal posn */
-                qe_term_goto_xy(s, s->esc_params[0] - 1, 0, 2);
+                }
+            }
                 break;
-            case 'H':  /* CUP: goto xy */
-            case 'f':  /* HVP: set horz and vert posns at once */
-                qe_term_goto_xy(s, s->esc_params[1] - 1, s->esc_params[0] - 1, 
0);
+        case ESC2('?','l'): /* DEC Private Mode Reset (DECRST). */
+            for (i = 0; i < s->nb_params; i++) {
+                switch (s->params[i]) {
+                case 1:     /* Normal Cursor Keys (DECCKM). */
+                case 4:     /* Jump (Fast) Scroll (DECSCLM). */
                 break;
-            case 'd':
-                /* goto y */
-                qe_term_goto_xy(s, 0, s->esc_params[0] - 1, 1);
+                case 5:     /* Normal Video (DECSCNM). */
+                    s->reverse = 1;
                 break;
-            case 'J':  /* ED: erase screen or parts of it */
-                       /*     0: to end, 1: from begin, 2: all */
-               TRACE_MSG("erase screen");
-                //put_status(NULL, "erase screen %d", s->esc_params[0]);
+                case 7:     /* No Wraparound Mode (DECAWM). */
                 break;
-            case 'K':  /* EL: erase line or parts of it */
-                       /*     0: to end, 1: from begin, 2: all line */
-                offset1 = eb_goto_eol(s->b, offset);
-                eb_delete(s->b, offset, offset1 - offset);
+                case 12:    /* Stop Blinking Cursor (att610). */
                 break;
-            case 'L':  /* IL: insert lines */
-                /* TODO! scroll down */
-               TRACE_MSG("insert lines");
-                //put_status(NULL, "insert lines %d", s->esc_params[0]);
+                case 25:    /* Hide Cursor (DECTCEM). */
                 break;
-            case 'M':  /* delete lines */
-                /* TODO! scroll up */
-               TRACE_MSG("delete lines");
-                //put_status(NULL, "delete lines %d", s->esc_params[0]);
+                case 1000:  /* Don't send Mouse X & Y on button press and
+                                release. */
+                case 1034:  /* Don't interpret "meta" key.  (This disables
+                       the eightBitInput resource).
+                     */
                 break;
-            case '@':  /* ICH: insert chars (no cursor update) */
-                buf1[0] = ' ';
-                offset1 = offset;
-                qe_term_set_setyle(s);
-                for (n = s->esc_params[0]; n > 0; n--) {
-                    /* XXX: incorrect for non 8 bit charsets */
-                    eb_insert(s->b, offset1, buf1, 1);
-                    offset1 += 1;
+                case 1047:  /* Use Normal Screen Buffer, clearing screen
+                       first if in the Alternate Screen. */
+                case 1048:  /* Restore cursor as in DECRC. */
+                case 1049:  /* Use Normal Screen Buffer and restore cursor
+                       as in DECRC. */
+                    if (s->shell_flags & SF_INTERACTIVE) {
+                        qe_ungrab_keys();
+                        s->grab_keys = 0;
                 }
-                s->cur_offset = offset;
+                    qe_term_goto_xy(s, 0, s->rows, 0);
+                    eb_delete_range(s->b, s->cur_offset, s->b->total_size);
                 break;
-            case 'P':  /* DCH: delete chars */
-                offset1 = offset;
-                for (n = s->esc_params[0]; n > 0; n--) {
-                    c = eb_nextc(s->b, offset1, &offset2);
-                    if (c == '\n')
+                default:
+                    TRACE_MSG(s, "mode reset");
                         break;
-                    offset1 = offset2;
                 }
-                eb_delete(s->b, offset, offset1 - offset);
+            }
                 break;
-            case 'c':  /* DA: terminal type query */
-                if (s->esc_params[0] == 0) {
-                    /* Report Advanced Video option (AVO) */
-                    qe_term_write(s, "\033[?1;2c", -1);
+        case 'm':  /* SGR: Set Graphics Rendition (Character Attributes). */
+            for (i = 0; i < s->nb_params;) {
+                i += qe_term_csi_m(s, s->params + i, s->nb_params - i);
                 }
                 break;
-            case 'n':  /* DSR: cursor position query */
-                if (s->esc_params[0] == 5) {
-                    /* Status report: terminal is OK */
+        case 'n':  /* DSR: Device Status Report. */
+            if (param1 == 5) {
+                /* Status Report: terminal is OK */
                     qe_term_write(s, "\033[0n", -1);
                 } else
-                if (s->esc_params[0] == 6) {
-                    /* XXX: send cursor position, just to be able to
-                       launch qemacs in qemacs (in 8859-1) ! */
+            if (param1 == 6) {
+                /* Report Cursor Position (CPR) [row;column]. */
                     char buf2[20];
                     int col_num, cur_line;
                     eb_get_pos(s->b, &cur_line, &col_num, offset);
@@ -1351,66 +1612,78 @@
                     qe_term_write(s, buf2, -1);
                 }
                 break;
-            case 'g':  /* TBC: clear tabs */
-               TRACE_MSG("clear tabs");
-                break;
-            case 'r':  /* DECSTBM: set scroll margins */
-               TRACE_MSG("set scroll margins");
-                //put_status(NULL, "set scroll margins %d %d",
-                //           s->esc_params[0], s->esc_params[1]);
-                break;
-            case 'm':  /* SGR: set graphics rendition (style and colors) */
-                for (i = 0;;) {
-                    qe_term_csi_m(s, s->esc_params[i], s->has_params[i]);
-                    if (++i >= s->nb_esc_params)
-                        break;
-                }
-                break;
-            case 's':  /* save cursor */
-               TRACE_MSG("save cursor");
-               break;
-            case 'u':  /* restore cursor */
-               TRACE_MSG("restore cursor");
+        case 'p':  /* DECSCL: Set conformance level. */
+        case 'q':  /* DECLL: Load LEDs. */
+        case ESC2(' ','q'): /* Set cursor style (DECSCUSR, VT520). */
+            goto unhandled;
+        case 'r':  /* DECSTBM: Set Scrolling Region [top;bottom]
+                      (default = full size of window) */
+            /* XXX: the scrolling region should also affect LF operation */
+            s->scroll_top = clamp(s->params[0] - 1, 0, s->rows);
+            s->scroll_bottom = s->params[1] > 0 ? clamp(s->params[1], 1, 
s->rows) : s->rows;
+            break;
+        case ESC2('$','r'): /* DECCARA: Change Attributes in Rectangular
+                               Area, VT400 and up. */
+            goto unhandled;
+        case ESC2('?','r'):
+            /* Restore DEC Private Mode Values.  The value of Ps previously
+               saved is restored.  Ps values are the same as for DECSET. */
+            TRACE_MSG(s, "mode restore");
+            break;
+        case ESC2('?','s'):
+            /* Save DEC Private Mode Values.  <i>Ps</i> values are the same as 
for
+               DECSET.. */
+            TRACE_MSG(s, "mode save");
+            break;
+        case 's':  /* Save cursor (ANSI.SYS), available only when
+                      DECLRMM is disabled. */
+            /* DECSLRM: Set left and right margins, available only when
+               DECLRMM is enabled (VT420 and up). */
+            TRACE_MSG(s, "save cursor");
                break;
             case 't':  /* DECSLPP: set page size - ie window height */
                        /* also used for window changing and reports */
-               TRACE_MSG("set page size");
-                break;
-            case 'S':  /* SU: SCO scroll up (forward) n lines */
-               TRACE_MSG("scroll up");
-                //put_status(NULL, "scroll up %d", s->esc_params[0]);
+            TRACE_MSG(s, "set page size");
                 break;
-            case 'T':  /* SD: SCO scroll down (back) n lines */
-               TRACE_MSG("scroll down");
-                //put_status(NULL, "scroll down %d", s->esc_params[0]);
-                break;
-            case 'X':  /* ECH: erase n characters w/o moving cursor */
-                for (n = s->esc_params[0]; n > 0; n--) {
-                    qe_term_put_char(s, ' ');
-                }
-                /* restore cursor */
-                s->cur_offset = offset;
-                break;
-            case 'x':  /* DECREQTPARM: report terminal characteristics */
-            case 'Z':  /* CBT: move cursor back n tabs */
+        case ESC2('>','t'):  /* Set one or more features of the title modes. */
+            // Ps = 0  -> Set window/icon labels using hexadecimal.
+            // Ps = 1  -> Query window/icon labels using hexadecimal.
+            // Ps = 2  -> Set window/icon labels using UTF-8.
+            // Ps = 3  -> Query window/icon labels using UTF-8.  (See 
discussion of "Title Modes")
+            break;
+        case ESC2('$','t'):  /* DECRARA: Reverse Attributes in Rectangular 
Area,
+               VT400 and up. */
+            goto unhandled;
+        case 'u':  /* Restore cursor (ANSI.SYS). */
+            TRACE_MSG(s, "restore cursor");
+            break;
+        case ESC2('$','v'):  /* DECCRA: Copy Rectangular Area (VT400 and up). 
*/
+            goto unhandled;
+        case 'x':  /* DECREQTPARM: Request Terminal Parameters */
+        case ESC2('$','x'):  /* DECFRA: Fill Rectangular Area, VT420 and up. */
+        case ESC2('$','z'):  /* DECERA: Erase Rectangular Area, VT400 and up. 
*/
+        case ESC2('$','{'): /* DECSERA: Selective Erase Rectangular Area, 
VT400 and up. */
+        case ESC2('\'','{'): /* DECSLE: Select Locator Events. */
+        case ESC2('\'','|'): /* DECRQLP: Request Locator Position. */
+        case ESC2('\'','}'): /* DECIC: Insert Ps Column(s) (default = 1), 
VT420 and up. */
+        case ESC2('\'','~'): /* DECDC: Delete Ps Column(s) (default = 1), 
VT420 and up. */
             case ESC2('=','c'):   /* Hide or Show Cursor */
                         /* 0: hide, 1: restore, 2: block */
             case ESC2('=','C'):  /* set cursor shape */
             case ESC2('=','D'):  /* set blinking attr on/off */
             case ESC2('=','E'):  /* set blinking on/off */
-               TRACE_MSG("unhandled");
-                break;
+            goto unhandled;
             case ESC2('=','F'): /* select SCO foreground color */
-                s->fgcolor = sco_color[s->esc_params[0] & 15];
+            s->fgcolor = sco_color[param1 & 15];
                 break;
             case ESC2('=','G'): /* select SCO background color */
-                s->bgcolor = sco_color[s->esc_params[0] & 15];
+            s->bgcolor = sco_color[param1 & 15];
                 break;
             default:
-               TRACE_MSG("unhandled");
+        unhandled:
+            TRACE_MSG(s, "unhandled");
                 break;
             }
-        }
         break;
     }
 #undef ESC2
@@ -1579,15 +1852,15 @@
     dpy_flush(qs->screen);
 }
 
-EditBuffer *new_shell_buffer(EditBuffer *b0, const char *bufname,
-                             const char *caption, const char *cmd,
-                             int shell_flags)
+EditBuffer *new_shell_buffer(EditBuffer *b0, EditState *e,
+                             const char *bufname, const char *caption,
+                             const char *cmd, int shell_flags)
 {
     QEmacsState *qs = &qe_state;
     ShellState *s;
     EditBuffer *b;
     const char *lang;
-    int rows, cols;
+    int cols, rows;
 
     b = b0;
     if (!b) {
@@ -1631,10 +1904,15 @@
     qe_term_init(s);
 
     /* launch shell */
+    /* default values for cols, rows should come from the screen size */
     cols = QE_TERM_XSIZE;
     rows = QE_TERM_YSIZE;
-    if (shell_flags & SF_INFINITE)
-        rows = QE_TERM_YSIZE_INFINITE;
+    if (e) {
+        cols = e->cols - 1;
+        rows = e->rows;
+    }
+    s->cols = cols;
+    s->rows = rows;
 
     if (run_process(cmd, &s->pty_fd, &s->pid, cols, rows, shell_flags) < 0) {
         if (!b0)
@@ -1715,7 +1993,7 @@
     }
 
     /* create new buffer */
-    b = new_shell_buffer(b, "*shell*", "Shell process", NULL,
+    b = new_shell_buffer(b, s, "*shell*", "Shell process", NULL,
                          SF_COLOR | SF_INTERACTIVE);
     if (!b)
         return;
@@ -1740,7 +2018,7 @@
         return;
 
     /* create new buffer */
-    b = new_shell_buffer(NULL, bufname, NULL, cmd, SF_COLOR | SF_INFINITE);
+    b = new_shell_buffer(NULL, s, bufname, NULL, cmd, SF_COLOR | SF_INFINITE);
     if (!b)
         return;
 
@@ -1761,7 +2039,7 @@
     snprintf(bufname, sizeof(bufname), "*ssh-%s*", arg);
 
     /* create new buffer */
-    b = new_shell_buffer(NULL, bufname, "ssh", cmd,
+    b = new_shell_buffer(NULL, s, bufname, "ssh", cmd,
                          SF_COLOR | SF_INTERACTIVE);
     if (!b)
         return;
@@ -1941,7 +2219,7 @@
         int start_char, cur_char, end_char, size;
         if (start < s->cur_prompt) {
             /* delete part before the interactive input */
-            size = eb_delete(e->b, start, s->cur_prompt);
+            size = eb_delete_range(e->b, start, s->cur_prompt);
             end -= size;
             start = s->cur_prompt;
         }
@@ -2264,7 +2542,7 @@
     }
 
     /* create new buffer */
-    b = new_shell_buffer(NULL, "*shell command output*", NULL, cmd,
+    b = new_shell_buffer(NULL, e, "*shell command output*", NULL, cmd,
                          SF_COLOR | SF_INFINITE);
     if (!b)
         return;
@@ -2288,7 +2566,7 @@
         cmd = "make";
 
     /* create new buffer */
-    b = new_shell_buffer(NULL, "*compilation*", "Compilation", cmd,
+    b = new_shell_buffer(NULL, e, "*compilation*", "Compilation", cmd,
                          SF_COLOR | SF_INFINITE);
     if (!b)
         return;

Index: archive.c
===================================================================
RCS file: /sources/qemacs/qemacs/archive.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- archive.c   6 Mar 2017 12:54:49 -0000       1.27
+++ archive.c   21 Apr 2017 14:44:14 -0000      1.28
@@ -145,7 +145,7 @@
         eb_printf(b, "  Directory of %s archive %s\n",
                   atp->name, b->filename);
         qe_shell_subst(cmd, sizeof(cmd), atp->list_cmd, b->filename, NULL);
-        new_shell_buffer(b, get_basename(b->filename), NULL, cmd,
+        new_shell_buffer(b, NULL, get_basename(b->filename), NULL, cmd,
                          atp->sf_flags | SF_INFINITE | SF_BUFED_MODE);
 
         /* XXX: should check for archiver error */
@@ -289,7 +289,7 @@
         b->data_type_name = ctp->name;
         eb_clear(b);
         qe_shell_subst(cmd, sizeof(cmd), ctp->load_cmd, b->filename, NULL);
-        new_shell_buffer(b, get_basename(b->filename), NULL, cmd,
+        new_shell_buffer(b, NULL, get_basename(b->filename), NULL, cmd,
                          ctp->sf_flags | SF_INFINITE | SF_AUTO_CODING | 
SF_AUTO_MODE);
         /* XXX: should check for archiver error */
         /* XXX: should delay BF_SAVELOG until buffer is fully loaded */
@@ -378,7 +378,7 @@
 
     eb_clear(b);
     qe_shell_subst(cmd, sizeof(cmd), "wget -q -O - $1", b->filename, NULL);
-    new_shell_buffer(b, get_basename(b->filename), NULL, cmd,
+    new_shell_buffer(b, NULL, get_basename(b->filename), NULL, cmd,
                      SF_INFINITE | SF_AUTO_CODING | SF_AUTO_MODE);
     /* XXX: should refilter by content type */
     /* XXX: should have a way to keep http headers --save-headers */
@@ -469,7 +469,7 @@
 
     eb_clear(b);
     qe_shell_subst(cmd, sizeof(cmd), "man $1", b->filename, NULL);
-    new_shell_buffer(b, get_basename(b->filename), NULL, cmd,
+    new_shell_buffer(b, NULL, get_basename(b->filename), NULL, cmd,
                      SF_COLOR | SF_INFINITE);
     /* XXX: should check for man error */
     /* XXX: should delay BF_SAVELOG until buffer is fully loaded */

Index: latex-mode.c
===================================================================
RCS file: /sources/qemacs/qemacs/latex-mode.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -b -r1.56 -r1.57
--- latex-mode.c        17 Apr 2017 18:14:15 -0000      1.56
+++ latex-mode.c        21 Apr 2017 14:44:14 -0000      1.57
@@ -265,7 +265,7 @@
         }
 
         /* create new buffer */
-        b = new_shell_buffer(NULL, "*LaTeX output*", NULL, cmd,
+        b = new_shell_buffer(NULL, NULL, "*LaTeX output*", NULL, cmd,
                              SF_COLOR | SF_INFINITE);
         if (b) {
             /* XXX: try to split window if necessary */

Index: qeconfig.h
===================================================================
RCS file: /sources/qemacs/qemacs/qeconfig.h,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -b -r1.67 -r1.68
--- qeconfig.h  17 Apr 2017 18:14:15 -0000      1.67
+++ qeconfig.h  21 Apr 2017 14:44:14 -0000      1.68
@@ -285,8 +285,9 @@
 
     /*---------------- Help ----------------*/
 
-    CMD0( KEY_CTRLH('d'), KEY_NONE,
-          "doctor", do_doctor)
+    CMD2( KEY_CTRLH('t'), KEY_NONE,
+          "set-trace", do_set_trace, ESs,
+          "s{Trace options: }|trace|")
     CMD0( KEY_CTRLH('c'), KEY_CTRLH('k'),
           "describe-key-briefly", do_describe_key_briefly)
     CMD0( KEY_CTRLH(KEY_CTRL('h')), KEY_F1,
@@ -364,8 +365,6 @@
     CMD2( KEY_NONE, KEY_NONE,
           "set-emulation", do_set_emulation, ESs,
           "s{Emulation mode: }|emulation|")
-    CMD0( KEY_NONE, KEY_NONE,
-          "set-trace", do_set_trace)
     CMD2( KEY_NONE, KEY_NONE,
           "cd", do_cd, ESs,
           "s{Change default directory: }[file]|file|")

Index: tty.c
===================================================================
RCS file: /sources/qemacs/qemacs/tty.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -b -r1.81 -r1.82
--- tty.c       18 Apr 2017 09:14:55 -0000      1.81
+++ tty.c       21 Apr 2017 14:44:14 -0000      1.82
@@ -399,6 +399,7 @@
     TTYState *ts;
     struct winsize ws;
     int i, count, size;
+    const char *p;
     TTYChar tc;
 
     if (s == NULL)
@@ -406,18 +407,26 @@
 
     ts = s->priv_data;
 
-    s->width = 80;
-    s->height = 24;
+    /* get screen default values from environment */
+    s->width = (p = getenv("COLUMNS")) != NULL ? atoi(p) : 80;
+    s->height = (p = getenv("LINES")) != NULL ? atoi(p) : 25;
+
+    /* update screen dimensions from pseudo tty ioctl */
     if (ioctl(fileno(s->STDIN), TIOCGWINSZ, &ws) == 0) {
+        if (ws.ws_col >= 10 && ws.ws_row >= 4) {
         s->width = ws.ws_col;
         s->height = ws.ws_row;
-        if (s->width < 10)
-            s->width = 10;
+        }
+    }
+
         if (s->width > MAX_SCREEN_WIDTH)
             s->width = MAX_SCREEN_WIDTH;
+    if (s->height >= 10000)
+        s->height -= 10000;
+    if (s->height > MAX_SCREEN_LINES)
+        s->height = MAX_SCREEN_LINES;
         if (s->height < 3)
-            s->height = 3;
-    }
+        s->height = 25;
 
     count = s->width * s->height;
     size = count * sizeof(TTYChar);

Index: buffer.c
===================================================================
RCS file: /sources/qemacs/qemacs/buffer.c,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -b -r1.113 -r1.114
--- buffer.c    17 Apr 2017 09:16:24 -0000      1.113
+++ buffer.c    21 Apr 2017 14:44:14 -0000      1.114
@@ -733,9 +733,6 @@
     eb_add_callback(b, eb_offset_callback, &b->mark, 0);
     eb_add_callback(b, eb_offset_callback, &b->offset, 1);
 
-    if (strequal(name, "*trace*"))
-        qs->trace_buffer = b;
-
     if (flags & BF_STYLES)
         eb_create_style_buffer(b, flags);
 
@@ -878,7 +875,7 @@
     const u8 *p0, *endp, *p;
     int c, line, col, len, point;
 
-    if (!b)
+    if (!b || !(qs->trace_flags & state))
         return;
 
     point = b->total_size;
@@ -891,6 +888,7 @@
             eb_insert_uchar(b, b->total_size, '\n');
             col = 0;
         }
+        state &= ~EB_TRACE_FLUSH;
         qs->trace_buffer_state = state;
         switch (state) {
         case EB_TRACE_TTY:
@@ -902,6 +900,9 @@
         case EB_TRACE_SHELL:
             str = "  shell: ";
             break;
+        case EB_TRACE_EMULATE:
+            str = "emulate: ";
+            break;
         case EB_TRACE_COMMAND:
             eb_printf(b, "command: %s\n", cs8(buf));
             size = 0;
@@ -934,6 +935,8 @@
                 if ((c = 'n', *p == '\n')
                 ||  (c = 'r', *p == '\r')
                 ||  (c = 't', *p == '\t')
+                ||  (c = 'b', *p == '\010')
+                ||  (c = 'E', *p == '\033')
                 ||  (c = '\\', *p == '\\')) {
                     col += eb_printf(b, "\\%c", c);
                 } else

Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.274
retrieving revision 1.275
diff -u -b -r1.274 -r1.275
--- qe.c        19 Apr 2017 08:20:20 -0000      1.274
+++ qe.c        21 Apr 2017 14:44:14 -0000      1.275
@@ -447,11 +447,68 @@
     }
 }
 
-void do_set_trace(EditState *s)
+void do_set_trace(EditState *s, const char *options)
 {
+    char buf[80];
+    const char *p = options;
+    QEmacsState *qs = s->qe_state;
+    int last_flags = qs->trace_flags;
+
+    while (*p) {
+        p += strspn(p, " \t,");
+        if (strstart(p, "none", &p) || strstart(p, "off", &p))
+            qs->trace_flags = 0;
+        else
+        if (strstart(p, "all", &p) || strstart(p, "on", &p))
+            qs->trace_flags = EB_TRACE_ALL;
+        else
+        if (strstart(p, "tty", &p)) {
+            qs->trace_flags |= EB_TRACE_TTY;
+        } else
+        if (strstart(p, "shell", &p)) {
+            qs->trace_flags |= EB_TRACE_SHELL;
+        } else
+        if (strstart(p, "pty", &p)) {
+            qs->trace_flags |= EB_TRACE_PTY;
+        } else
+        if (strstart(p, "emulate", &p)) {
+            qs->trace_flags |= EB_TRACE_EMULATE;
+        } else
+        if (strstart(p, "command", &p)) {
+            qs->trace_flags |= EB_TRACE_COMMAND;
+        } else {
+            break;
+        }
+    }
+    if (qs->trace_flags) {
+        if (!qs->trace_buffer) {
+            qs->trace_buffer = eb_new("*trace*", BF_SYSTEM);
+        }
+        if (!last_flags) {
     do_split_window(s, 0);
     do_switch_to_buffer(s, "*trace*");
     do_previous_window(s);
+        }
+        *buf = '\0';
+        if (qs->trace_flags & EB_TRACE_TTY) {
+            strcat(buf, ", tty");
+        }
+        if (qs->trace_flags & EB_TRACE_SHELL) {
+            strcat(buf, ", shell");
+        }
+        if (qs->trace_flags & EB_TRACE_PTY) {
+            strcat(buf, ", pty");
+        }
+        if (qs->trace_flags & EB_TRACE_EMULATE) {
+            strcat(buf, ", emulate");
+        }
+        if (qs->trace_flags & EB_TRACE_COMMAND) {
+            strcat(buf, ", command");
+        }
+        put_status(s, "Tracing enabled for %s", buf + 2);
+    } else {
+        put_status(s, "Tracing disabled");
+    }
 }
 
 void do_cd(EditState *s, const char *path)
@@ -749,6 +806,7 @@
             /* insert space single space the word */
             if (offset == par_end
             ||  (col + 1 + word_size > s->b->fill_column)) {
+                /* XXX: should check if separator is a newline */
                 eb_delete_uchar(s->b, chunk_start);
                 chunk_start += eb_insert_uchar(s->b, chunk_start, '\n');
                 if (offset < par_end) {
@@ -761,6 +819,7 @@
                 }
                 col = word_size + indent_size;
             } else {
+                /* XXX: should check if separator is a space */
                 eb_delete_uchar(s->b, chunk_start);
                 chunk_start += eb_insert_uchar(s->b, chunk_start, ' ');
                 col += 1 + word_size;
@@ -1514,7 +1573,7 @@
 
     c = eb_prevc(s->b, s->offset, &offset0);
     if (c == accent) {
-        eb_delete(s->b, offset0, s->offset - offset0);
+        eb_delete_range(s->b, offset0, s->offset);
     } else
     if (((expand_ligature(g, c) && g[1] == (unsigned int)accent)
     ||   (c != '\n' && combine_accent(g, c, accent)))
@@ -5598,6 +5657,7 @@
 {
     QEmacsState *qs = s->qe_state;
     int x1, y1, x2, y2;
+    int line_height, cw;
 
     x1 = s->x1;
     y1 = s->y1;
@@ -5618,6 +5678,16 @@
     s->ytop = y1;
     s->width = x2 - x1;
     s->height = y2 - y1;
+
+    line_height = cw = 1;
+    if (s->screen && s->screen->dpy.dpy_probe) {
+        /* use window default style font except for dummy display */
+        line_height = get_line_height(s->screen, s, QE_STYLE_DEFAULT);
+        cw = get_glyph_width(s->screen, s, QE_STYLE_DEFAULT, '0');
+    }
+
+    s->rows = max(1, s->height / max(line_height, 1));
+    s->cols = max(1, s->width / max(cw, 1));
 }
 
 /* Create a new edit window, add it in the window list and sets it
@@ -7289,22 +7359,18 @@
 
 /*----------------*/
 
-void do_doctor(EditState *s)
-{
-    /* Should show keys? */
-    put_status(s, "Hello, how are you?");
-}
-
 int get_glyph_width(QEditScreen *screen, EditState *s, QETermStyle style, int 
c)
 {
     QEStyleDef styledef;
     QEFont *font;
-    int width;
+    int width = 1;
 
     get_style(s, &styledef, style);
     font = select_font(screen, styledef.font_style, styledef.font_size);
+    if (font) {
     width = glyph_width(screen, font, c);
     release_font(screen, font);
+    }
     return width;
 }
 
@@ -7312,12 +7378,14 @@
 {
     QEStyleDef styledef;
     QEFont *font;
-    int height;
+    int height = 1;
 
     get_style(s, &styledef, style);
     font = select_font(screen, styledef.font_style, styledef.font_size);
+    if (font) {
     height = font->ascent + font->descent;
     release_font(screen, font);
+    }
     return height;
 }
 

Index: search.c
===================================================================
RCS file: /sources/qemacs/qemacs/search.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- search.c    17 Apr 2017 18:14:15 -0000      1.14
+++ search.c    21 Apr 2017 14:44:15 -0000      1.15
@@ -676,7 +676,7 @@
 
     /* XXX: handle smart case replacement */
     is->nb_reps++;
-    eb_delete(s->b, is->found_offset, is->found_end - is->found_offset);
+    eb_delete_range(s->b, is->found_offset, is->found_end);
     is->found_offset += eb_insert_u32_buf(s->b, is->found_offset,
         is->replace_u32, is->replace_u32_len);
 }
@@ -882,8 +882,8 @@
             } else
             if (dir == 2) {
                 offset = eb_goto_bol(s->b, found_offset);
-                eb_delete(s->b, offset, 
-                          eb_next_line(s->b, found_offset) - offset);
+                eb_delete_range(s->b, offset,
+                                eb_next_line(s->b, found_offset));
                 continue;
             } else {
                 s->offset = (dir < 0) ? found_offset : found_end;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]