insert mode bug fix and cleanup
[unix-history] / usr / src / usr.bin / window / wwwrite.c
index 3425d1d..90cf59b 100644 (file)
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)wwwrite.c   3.2 83/08/16";
-#endif
+static char sccsid[] = "@(#)wwwrite.c  3.30 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "ww.h"
 
 #include "ww.h"
+#include "tt.h"
+#include "char.h"
 
 
+#define UPDATE() \
+       if (!w->ww_noupdate && w->ww_cur.r >= 0 && w->ww_cur.r < wwnrow && \
+           wwtouched[w->ww_cur.r]) \
+               wwupdate1(w->ww_cur.r, w->ww_cur.r + 1)
+
+/*
+ * To support control character expansion, we save the old
+ * p and q values in r and s, and point p at the beginning
+ * of the expanded string, and q at some safe place beyond it
+ * (p + 10).  At strategic points in the loops, we check
+ * for (r && !*p) and restore the saved values back into
+ * p and q.  Essentially, we implement a stack of depth 2,
+ * to avoid recursion, which might be a better idea.
+ */
 wwwrite(w, p, n)
 register struct ww *w;
 register char *p;
 wwwrite(w, p, n)
 register struct ww *w;
 register char *p;
-register n;
+int n;
 {
 {
-       register char c;
-       int oldn = n;
+       char hascursor;
+       char *savep = p;
+       char *q = p + n;
+       char *r = 0;
+       char *s;
 
 
-       if (w == 0)
-               return -1;
-       wwnwrite++;
-       wwnwritec += n;
-       while (--n >= 0) {
-               c = *p++ & 0x7f;
-               switch (w->ww_wstate) {
-               case 0:
-                       asm("_wwwrite1:");
-                       if (c >= ' ' && c < 0x7f) {
-                               register i, j, cc;
+#ifdef lint
+       s = 0;                  /* define it before possible use */
+#endif
+       if (hascursor = w->ww_hascursor)
+               wwcursor(w, 0);
+       while (p < q && !w->ww_stopped && (!wwinterrupt() || w->ww_nointr)) {
+               if (r && !*p) {
+                       p = r;
+                       q = s;
+                       r = 0;
+                       continue;
+               }
+               if (w->ww_wstate == 0 &&
+                   (isprt(*p) || w->ww_unctrl && isunctrl(*p))) {
+                       register i;
+                       register union ww_char *bp;
+                       int col, col1;
 
 
-                               if (w->ww_insert)
-                                       wwinschar(w, w->ww_scroll + w->ww_cur.r,
-                                               w->ww_cur.c, c);
-                               else {
-                                       cc = w->ww_buf[w->ww_scroll
-                                               + w->ww_cur.r]
-                                               [w->ww_cur.c].c_w = c;
-                                       i = wwcurrow(w);
-                                       j = wwcurcol(w);
-                                       if (wwsmap[i][j] == w->ww_index) {
-                                               wwtouched[i] = 1;
-                                               cc = wwns[i][j].c_w = cc
-                                                       ^ w->ww_win[w->ww_cur.r]
-                                                       [w->ww_cur.c]
-                                                       << WWC_MSHIFT;
-                                       }
+                       if (w->ww_insert) {     /* this is very slow */
+                               if (*p == '\t') {
+                                       p++;
+                                       w->ww_cur.c += 8 -
+                                               (w->ww_cur.c - w->ww_w.l & 7);
+                                       goto chklf;
                                }
                                }
-               right:
-                               if (++w->ww_cur.c >= w->ww_w.nc) {
-                                       w->ww_cur.c = 0;
-                                       goto lf;
+                               if (!isprt(*p)) {
+                                       r = p + 1;
+                                       s = q;
+                                       p = unctrl(*p);
+                                       q = p + 10;
                                }
                                }
-                               break;
+                               wwinschar(w, w->ww_cur.r, w->ww_cur.c,
+                                       *p++, w->ww_modes);
+                               goto right;
                        }
                        }
-                       asm("_wwwrite2:");
-                       switch (c) {
+
+                       bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c];
+                       i = w->ww_cur.c;
+                       while (i < w->ww_w.r && p < q)
+                               if (!*p && r) {
+                                       p = r;
+                                       q = s;
+                                       r = 0;
+                               } else if (*p == '\t') {
+                                       register tmp = 8 - (i - w->ww_w.l & 7);
+                                       p++;
+                                       i += tmp;
+                                       bp += tmp;
+                               } else if (isprt(*p)) {
+                                       bp++->c_w = *p++
+                                               | w->ww_modes << WWC_MSHIFT;
+                                       i++;
+                               } else if (w->ww_unctrl && isunctrl(*p)) {
+                                       r = p + 1;
+                                       s = q;
+                                       p = unctrl(*p);
+                                       q = p + 10;
+                               } else
+                                       break;
+                       col = MAX(w->ww_cur.c, w->ww_i.l);
+                       col1 = MIN(i, w->ww_i.r);
+                       w->ww_cur.c = i;
+                       if (w->ww_cur.r >= w->ww_i.t
+                           && w->ww_cur.r < w->ww_i.b) {
+                               register union ww_char *ns = wwns[w->ww_cur.r];
+                               register char *smap = &wwsmap[w->ww_cur.r][col];
+                               register char *win = w->ww_win[w->ww_cur.r];
+                               int nchanged = 0;
+
+                               bp = w->ww_buf[w->ww_cur.r];
+                               for (i = col; i < col1; i++)
+                                       if (*smap++ == w->ww_index) {
+                                               nchanged++;
+                                               ns[i].c_w = bp[i].c_w
+                                                       ^ win[i] << WWC_MSHIFT;
+                                       }
+                               if (nchanged > 0)
+                                       wwtouched[w->ww_cur.r] |= WWU_TOUCHED;
+                       }
+               chklf:
+                       if (w->ww_cur.c >= w->ww_w.r)
+                               goto crlf;
+               } else switch (w->ww_wstate) {
+               case 0:
+                       switch (*p++) {
                        case '\n':
                                if (w->ww_mapnl)
                        case '\n':
                                if (w->ww_mapnl)
-                                       w->ww_cur.c = 0;
+               crlf:
+                                       w->ww_cur.c = w->ww_w.l;
                lf:
                lf:
-                               if (++w->ww_cur.r >= w->ww_w.nr) {
-                                       w->ww_cur.r = w->ww_w.nr - 1;
-                                       wwdelline(w, 0);
+                               UPDATE();
+                               if (++w->ww_cur.r >= w->ww_w.b) {
+                                       w->ww_cur.r = w->ww_w.b - 1;
+                                       if (w->ww_w.b < w->ww_b.b) {
+                                               (void) wwscroll1(w, w->ww_i.t,
+                                                       w->ww_i.b, 1, 0);
+                                               w->ww_buf++;
+                                               w->ww_b.t--;
+                                               w->ww_b.b--;
+                                       } else
+                                               wwdelline(w, w->ww_b.t);
                                }
                                break;
                                }
                                break;
-                       case '\t':
-                               w->ww_cur.c |= 7;
-                               goto right;
-                               break;
                        case '\b':
                        case '\b':
-                               if (--w->ww_cur.c < 0)
-                                       w->ww_cur.c = 0;
+                               if (--w->ww_cur.c < w->ww_w.l) {
+                                       w->ww_cur.c = w->ww_w.r - 1;
+                                       goto up;
+                               }
                                break;
                        case '\r':
                                break;
                        case '\r':
-                               w->ww_cur.c = 0;
+                               w->ww_cur.c = w->ww_w.l;
                                break;
                                break;
-                       case CTRL(g):
-                               wwbell();
+                       case ctrl('g'):
+                               ttputc(ctrl('g'));
                                break;
                                break;
-                       case CTRL([):
+                       case ctrl('['):
                                w->ww_wstate = 1;
                                break;
                        }
                        break;
                case 1:
                        w->ww_wstate = 0;
                                w->ww_wstate = 1;
                                break;
                        }
                        break;
                case 1:
                        w->ww_wstate = 0;
-                       switch (c) {
+                       switch (*p++) {
                        case '@':
                                w->ww_insert = 1;
                                break;
                        case 'A':
                        case '@':
                                w->ww_insert = 1;
                                break;
                        case 'A':
-                               if (--w->ww_cur.r < 0)
-                                       w->ww_cur.r = 0;
+               up:
+                               UPDATE();
+                               if (--w->ww_cur.r < w->ww_w.t) {
+                                       w->ww_cur.r = w->ww_w.t;
+                                       if (w->ww_w.t > w->ww_b.t) {
+                                               (void) wwscroll1(w, w->ww_i.t,
+                                                       w->ww_i.b, -1, 0);
+                                               w->ww_buf--;
+                                               w->ww_b.t++;
+                                               w->ww_b.b++;
+                                       } else
+                                               wwinsline(w, w->ww_b.t);
+                               }
                                break;
                        case 'B':
                                goto lf;
                        case 'C':
                                break;
                        case 'B':
                                goto lf;
                        case 'C':
-                               goto right;
+               right:
+                               w->ww_cur.c++;
+                               goto chklf;
                        case 'E':
                        case 'E':
-                               w->ww_scroll = 0;
-                               w->ww_cur.c = w->ww_cur.r = 0;
-                               wwclreos(w, 0, 0);
+                               w->ww_buf -= w->ww_w.t - w->ww_b.t;
+                               w->ww_b.t = w->ww_w.t;
+                               w->ww_b.b = w->ww_b.t + w->ww_b.nr;
+                               w->ww_cur.r = w->ww_w.t;
+                               w->ww_cur.c = w->ww_w.l;
+                               wwclreos(w, w->ww_w.t, w->ww_w.l);
                                break;
                        case 'H':
                                break;
                        case 'H':
-                               w->ww_cur.c = w->ww_cur.r = 0;
+                               UPDATE();
+                               w->ww_cur.r = w->ww_w.t;
+                               w->ww_cur.c = w->ww_w.l;
                                break;
                        case 'J':
                                break;
                        case 'J':
-                               wwclreos(w, w->ww_scroll + w->ww_cur.r,
-                                       w->ww_cur.c);
+                               wwclreos(w, w->ww_cur.r, w->ww_cur.c);
                                break;
                        case 'K':
                                break;
                        case 'K':
-                               wwclreol(w, w->ww_scroll + w->ww_cur.r,
-                                       w->ww_cur.c);
+                               wwclreol(w, w->ww_cur.r, w->ww_cur.c);
                                break;
                        case 'L':
                                break;
                        case 'L':
-                               wwinsline(w, w->ww_scroll + w->ww_cur.r);
+                               UPDATE();
+                               wwinsline(w, w->ww_cur.r);
                                break;
                        case 'M':
                                break;
                        case 'M':
-                               wwdelline(w, w->ww_scroll + w->ww_cur.r);
+                               wwdelline(w, w->ww_cur.r);
                                break;
                        case 'N':
                                break;
                        case 'N':
-                               wwdelchar(w, w->ww_scroll + w->ww_cur.r,
-                                       w->ww_cur.c);
+                               wwdelchar(w, w->ww_cur.r, w->ww_cur.c);
                                break;
                        case 'O':
                                w->ww_insert = 0;
                                break;
                                break;
                        case 'O':
                                w->ww_insert = 0;
                                break;
+                       case 'X':
+                               wwupdate();
+                               break;
                        case 'Y':
                        case 'Y':
+                               UPDATE();
                                w->ww_wstate = 2;
                                break;
                                w->ww_wstate = 2;
                                break;
+                       case 'Z':
+                               wwupdate();
+                               xxflush(0);
+                               break;
+                       case 's':
+                               w->ww_wstate = 4;
+                               break;
+                       case 'r':
+                               w->ww_wstate = 5;
+                               break;
                        }
                        break;
                case 2:
                        }
                        break;
                case 2:
-                       w->ww_cur.r = (c - ' ') % w->ww_w.nr;
-                       w->ww_wstate++;
+                       w->ww_cur.r = w->ww_w.t +
+                               (unsigned)(*p++ - ' ') % w->ww_w.nr;
+                       w->ww_wstate = 3;
                        break;
                case 3:
                        break;
                case 3:
-                       w->ww_cur.c = (c - ' ') % w->ww_w.nc;
+                       w->ww_cur.c = w->ww_w.l +
+                               (unsigned)(*p++ - ' ') % w->ww_w.nc;
+                       w->ww_wstate = 0;
+                       break;
+               case 4:
+                       w->ww_modes |= *p++ & wwavailmodes;
+                       w->ww_wstate = 0;
+                       break;
+               case 5:
+                       w->ww_modes &= ~*p++;
                        w->ww_wstate = 0;
                        break;
                }
        }
                        w->ww_wstate = 0;
                        break;
                }
        }
-       return oldn - n;
+       if (hascursor)
+               wwcursor(w, 1);
+       wwnwwr++;
+       wwnwwra += n;
+       n = p - savep;
+       wwnwwrc += n;
+       return n;
 }
 }