insert mode bug fix and cleanup
[unix-history] / usr / src / usr.bin / window / wwupdate.c
index 2025b08..5fda014 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 = "@(#)wwupdate.c  3.9 83/12/02";
-#endif
+static char sccsid[] = "@(#)wwupdate.c 3.26 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "ww.h"
 #include "tt.h"
 
 
 #include "ww.h"
 #include "tt.h"
 
-wwupdate()
+wwupdate1(top, bot)
 {
        int i;
        register j;
 {
        int i;
        register j;
-       int c, x;
-       register union ww_char *ns, *os;
-       register char *p, *q;
-       char m;
        char *touched;
        char *touched;
-       register didit;
-       char buf[512];                  /* > wwncol */
-       union ww_char lastc;
+       struct ww_update *upd;
+       char check_clreos = 0;
+       int scan_top, scan_bot;
 
        wwnupdate++;
 
        wwnupdate++;
-       for (i = 0, touched = wwtouched; i < wwnrow; i++, touched++) {
-               if (!*touched)
+       {
+               register char *t1 = wwtouched + top, *t2 = wwtouched + bot;
+               register n;
+
+               while (!*t1++)
+                       if (t1 == t2)
+                               return;
+               while (!*--t2)
+                       ;
+               scan_top = top = t1 - wwtouched - 1;
+               scan_bot = bot = t2 - wwtouched + 1;
+               if (scan_bot - scan_top > 1 &&
+                   (tt.tt_clreos != 0 || tt.tt_clear != 0)) {
+                       int st = tt.tt_clreos != 0 ? scan_top : 0;
+
+                       /*
+                        * t1 is one past the first touched row,
+                        * t2 is on the last touched row.
+                        */
+                       for (t1--, n = 1; t1 < t2;)
+                               if (*t1++)
+                                       n++;
+                       /*
+                        * If we can't clreos then we try for clearing
+                        * the whole screen.
+                        */
+                       if (check_clreos = n * 10 > (wwnrow - st) * 9) {
+                               scan_top = st;
+                               scan_bot = wwnrow;
+                       }
+               }
+       }
+       if (tt.tt_clreol == 0 && !check_clreos)
+               goto simple;
+       for (i = scan_top, touched = &wwtouched[i], upd = &wwupd[i];
+            i < scan_bot;
+            i++, touched++, upd++) {
+               register gain = 0;
+               register best_gain = 0;
+               register best_col;
+               register union ww_char *ns, *os;
+
+               if (wwinterrupt())
+                       return;
+               if (!check_clreos && !*touched)
                        continue;
                        continue;
-               if (*touched & WWU_MAJOR) {
-                       int ncleared = 0;
-                       int nsame = 0;
+               wwnupdscan++;
+               j = wwncol;
+               ns = &wwns[i][j];
+               os = &wwos[i][j];
+               while (--j >= 0) {
+                       /*
+                        * The cost of clearing is:
+                        *      ncol - nblank + X
+                        * The cost of straight update is, more or less:
+                        *      ncol - nsame
+                        * We clear if  nblank - nsame > X
+                        * X is the clreol overhead.
+                        * So we make gain = nblank - nsame.
+                        */
+                       if ((--ns)->c_w == (--os)->c_w)
+                               gain--;
+                       else
+                               best_gain--;
+                       if (ns->c_w == ' ')
+                               gain++;
+                       if (gain > best_gain) {
+                               best_col = j;
+                               best_gain = gain;
+                       }
+               }
+               upd->best_gain = best_gain;
+               upd->best_col = best_col;
+               upd->gain = gain;
+       }
+       if (check_clreos) {
+               register struct ww_update *u;
+               register gain = 0;
+               register best_gain = 0;
+               int best_row;
+               register simple_gain = 0;
+               char didit = 0;
 
 
-                       wwnmajline++;
-                       j = wwncol;
-                       ns = wwns[i];
-                       os = wwos[i];
-                       while (--j >= 0) {
-                               if (ns->c_w == ' ') {
-                                       if (ns->c_w != os->c_w)
-                                               ncleared++;
-                               } else
-                                       if (ns->c_w == os->c_w)
-                                               nsame++;
-                               ns++;
-                               os++;
+               /*
+                * gain is the advantage of clearing all the lines.
+                * best_gain is the advantage of clearing to eos
+                * at best_row and u->best_col.
+                * simple_gain is the advantage of using only clreol.
+                * We use g > best_gain because u->best_col can be
+                * undefined when u->best_gain is 0 so we can't use it.
+                */
+               for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) {
+                       register g = gain + u->best_gain;
+
+                       if (g > best_gain) {
+                               best_gain = g;
+                               best_row = j;
                        }
                        }
-                       if (tt.tt_clreol != 0 && ncleared > nsame + 4) {
-                               (*tt.tt_move)(i, 0);
-                               (*tt.tt_clreol)();
-                               for (j = wwncol, os = wwos[i]; --j >= 0;)
-                                       os++->c_w = ' ';
-                       } else
-                               wwnmajmiss++;
+                       gain += u->gain;
+                       if (tt.tt_clreol != 0 && u->best_gain > 4)
+                               simple_gain += u->best_gain - 4;
                }
                }
+               if (tt.tt_clreos == 0) {
+                       if (gain > simple_gain && gain > 4) {
+                               xxclear();
+                               i = top = scan_top;
+                               bot = scan_bot;
+                               j = 0;
+                               didit = 1;
+                       }
+               } else
+                       if (best_gain > simple_gain && best_gain > 4) {
+                               i = best_row;
+                               xxclreos(i, j = wwupd[i].best_col);
+                               bot = scan_bot;
+                               didit = 1;
+                       }
+               if (didit) {
+                       wwnupdclreos++;
+                       wwnupdclreosline += wwnrow - i;
+                       u = wwupd + i;
+                       while (i < scan_bot) {
+                               register union ww_char *os = &wwos[i][j];
+
+                               for (j = wwncol - j; --j >= 0;)
+                                       os++->c_w = ' ';
+                               wwtouched[i++] |= WWU_TOUCHED;
+                               u++->best_gain = 0;
+                               j = 0;
+                       }
+               } else
+                       wwnupdclreosmiss++;
+       }
+simple:
+       for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot;
+            i++, touched++, upd++) {
+               register union ww_char *os, *ns;
+               char didit;
+
+               if (!*touched)
+                       continue;
+               *touched = 0;
                wwnupdline++;
                didit = 0;
                wwnupdline++;
                didit = 0;
+               if (tt.tt_clreol != 0 && upd->best_gain > 4) {
+                       wwnupdclreol++;
+                       xxclreol(i, j = upd->best_col);
+                       for (os = &wwos[i][j], j = wwncol - j; --j >= 0;)
+                               os++->c_w = ' ';
+                       didit = 1;
+               }
                ns = wwns[i];
                os = wwos[i];
                for (j = 0; j < wwncol;) {
                ns = wwns[i];
                os = wwos[i];
                for (j = 0; j < wwncol;) {
+                       register char *p, *q;
+                       char m;
+                       int c;
+                       register n;
+                       char buf[512];                  /* > wwncol */
+                       union ww_char lastc;
+
                        for (; j++ < wwncol && ns++->c_w == os++->c_w;)
                                ;
                        if (j > wwncol)
                                break;
                        p = buf;
                        for (; j++ < wwncol && ns++->c_w == os++->c_w;)
                                ;
                        if (j > wwncol)
                                break;
                        p = buf;
-                       m = ns[-1].c_m & tt.tt_availmodes;
+                       m = ns[-1].c_m;
                        c = j - 1;
                        os[-1] = ns[-1];
                        *p++ = ns[-1].c_c;
                        c = j - 1;
                        os[-1] = ns[-1];
                        *p++ = ns[-1].c_c;
-                       x = 5;
+                       n = 5;
                        q = p;
                        q = p;
-                       while (j < wwncol && (ns->c_m&tt.tt_availmodes) == m) {
+                       while (j < wwncol && ns->c_m == m) {
                                *p++ = ns->c_c;
                                if (ns->c_w == os->c_w) {
                                *p++ = ns->c_c;
                                if (ns->c_w == os->c_w) {
-                                       if (--x <= 0)
+                                       if (--n <= 0)
                                                break;
                                        os++;
                                        ns++;
                                } else {
                                                break;
                                        os++;
                                        ns++;
                                } else {
-                                       x = 5;
+                                       n = 5;
                                        q = p;
                                        lastc = *os;
                                        *os++ = *ns++;
                                }
                                j++;
                        }
                                        q = p;
                                        lastc = *os;
                                        *os++ = *ns++;
                                }
                                j++;
                        }
-                       tt.tt_nmodes = m;
-                       (*tt.tt_move)(i, c);
                        if (wwwrap
                            && i == wwnrow - 1 && q - buf + c == wwncol) {
                        if (wwwrap
                            && i == wwnrow - 1 && q - buf + c == wwncol) {
-                               if (tt.tt_hasinsert) {
-                                       (*tt.tt_write)(buf + 1, q - buf - 1);
-                                       (*tt.tt_move)(i, c);
-                                       tt.tt_ninsert = 1;
-                                       (*tt.tt_write)(buf, 1);
-                                       tt.tt_ninsert = 0;
+                               if (tt.tt_inschar) {
+                                       if (q - buf != 1) {
+                                               xxwrite(i, c, buf + 1,
+                                                       q - buf - 1, m);
+                                               xxinschar(i, c, *buf, m);
+                                       } else {
+                                               xxwrite(i, c - 1, buf, 1, m);
+                                               xxinschar(i, c - 1,
+                                                       ns[-2].c_c, ns[-2].c_m);
+                                       }
+                               } else if (tt.tt_insspace) {
+                                       if (q - buf != 1) {
+                                               xxwrite(i, c, buf + 1,
+                                                       q - buf - 1, m);
+                                               xxinsspace(i, c);
+                                               xxwrite(i, c, buf, 1, m);
+                                       } else {
+                                               xxwrite(i, c - 1, buf, 1, m);
+                                               xxinsspace(i, c - 1);
+                                               xxwrite(i, c - 1, &ns[-2].c_c,
+                                                       1, ns[-2].c_m);
+                                       }
                                } else {
                                } else {
+                                       if (q - buf > 1)
+                                               xxwrite(i, c, buf,
+                                                       q - buf - 1, m);
                                        os[-1] = lastc;
                                        os[-1] = lastc;
-                                       (*tt.tt_write)(buf, q - buf - 1);
+                                       *touched = WWU_TOUCHED;
                                }
                        } else
                                }
                        } else
-                               (*tt.tt_write)(buf, q - buf);
-                       didit++;
+                               xxwrite(i, c, buf, q - buf, m);
+                       didit = 1;
                }
                if (!didit)
                        wwnupdmiss++;
                }
                if (!didit)
                        wwnupdmiss++;
-               *touched = 0;
        }
 }
        }
 }