1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)wwupdate.c 8.1 (Berkeley) 06/06/93"; 13 #endif /* not lint */ 14 15 #include "ww.h" 16 #include "tt.h" 17 18 wwupdate1(top, bot) 19 { 20 int i; 21 register j; 22 char *touched; 23 struct ww_update *upd; 24 char check_clreos = 0; 25 int scan_top, scan_bot; 26 27 wwnupdate++; 28 { 29 register char *t1 = wwtouched + top, *t2 = wwtouched + bot; 30 register n; 31 32 while (!*t1++) 33 if (t1 == t2) 34 return; 35 while (!*--t2) 36 ; 37 scan_top = top = t1 - wwtouched - 1; 38 scan_bot = bot = t2 - wwtouched + 1; 39 if (scan_bot - scan_top > 1 && 40 (tt.tt_clreos != 0 || tt.tt_clear != 0)) { 41 int st = tt.tt_clreos != 0 ? scan_top : 0; 42 43 /* 44 * t1 is one past the first touched row, 45 * t2 is on the last touched row. 46 */ 47 for (t1--, n = 1; t1 < t2;) 48 if (*t1++) 49 n++; 50 /* 51 * If we can't clreos then we try for clearing 52 * the whole screen. 53 */ 54 if (check_clreos = n * 10 > (wwnrow - st) * 9) { 55 scan_top = st; 56 scan_bot = wwnrow; 57 } 58 } 59 } 60 if (tt.tt_clreol == 0 && !check_clreos) 61 goto simple; 62 for (i = scan_top, touched = &wwtouched[i], upd = &wwupd[i]; 63 i < scan_bot; 64 i++, touched++, upd++) { 65 register gain = 0; 66 register best_gain = 0; 67 register best_col; 68 register union ww_char *ns, *os; 69 70 if (wwinterrupt()) 71 return; 72 if (!check_clreos && !*touched) 73 continue; 74 wwnupdscan++; 75 j = wwncol; 76 ns = &wwns[i][j]; 77 os = &wwos[i][j]; 78 while (--j >= 0) { 79 /* 80 * The cost of clearing is: 81 * ncol - nblank + X 82 * The cost of straight update is, more or less: 83 * ncol - nsame 84 * We clear if nblank - nsame > X 85 * X is the clreol overhead. 86 * So we make gain = nblank - nsame. 87 */ 88 if ((--ns)->c_w == (--os)->c_w) 89 gain--; 90 else 91 best_gain--; 92 if (ns->c_w == ' ') 93 gain++; 94 if (gain > best_gain) { 95 best_col = j; 96 best_gain = gain; 97 } 98 } 99 upd->best_gain = best_gain; 100 upd->best_col = best_col; 101 upd->gain = gain; 102 } 103 if (check_clreos) { 104 register struct ww_update *u; 105 register gain = 0; 106 register best_gain = 0; 107 int best_row; 108 register simple_gain = 0; 109 char didit = 0; 110 111 /* 112 * gain is the advantage of clearing all the lines. 113 * best_gain is the advantage of clearing to eos 114 * at best_row and u->best_col. 115 * simple_gain is the advantage of using only clreol. 116 * We use g > best_gain because u->best_col can be 117 * undefined when u->best_gain is 0 so we can't use it. 118 */ 119 for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) { 120 register g = gain + u->best_gain; 121 122 if (g > best_gain) { 123 best_gain = g; 124 best_row = j; 125 } 126 gain += u->gain; 127 if (tt.tt_clreol != 0 && u->best_gain > 4) 128 simple_gain += u->best_gain - 4; 129 } 130 if (tt.tt_clreos == 0) { 131 if (gain > simple_gain && gain > 4) { 132 xxclear(); 133 i = top = scan_top; 134 bot = scan_bot; 135 j = 0; 136 didit = 1; 137 } 138 } else 139 if (best_gain > simple_gain && best_gain > 4) { 140 i = best_row; 141 xxclreos(i, j = wwupd[i].best_col); 142 bot = scan_bot; 143 didit = 1; 144 } 145 if (didit) { 146 wwnupdclreos++; 147 wwnupdclreosline += wwnrow - i; 148 u = wwupd + i; 149 while (i < scan_bot) { 150 register union ww_char *os = &wwos[i][j]; 151 152 for (j = wwncol - j; --j >= 0;) 153 os++->c_w = ' '; 154 wwtouched[i++] |= WWU_TOUCHED; 155 u++->best_gain = 0; 156 j = 0; 157 } 158 } else 159 wwnupdclreosmiss++; 160 } 161 simple: 162 for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot; 163 i++, touched++, upd++) { 164 register union ww_char *os, *ns; 165 char didit; 166 167 if (!*touched) 168 continue; 169 *touched = 0; 170 wwnupdline++; 171 didit = 0; 172 if (tt.tt_clreol != 0 && upd->best_gain > 4) { 173 wwnupdclreol++; 174 xxclreol(i, j = upd->best_col); 175 for (os = &wwos[i][j], j = wwncol - j; --j >= 0;) 176 os++->c_w = ' '; 177 didit = 1; 178 } 179 ns = wwns[i]; 180 os = wwos[i]; 181 for (j = 0; j < wwncol;) { 182 register char *p, *q; 183 char m; 184 int c; 185 register n; 186 char buf[512]; /* > wwncol */ 187 union ww_char lastc; 188 189 for (; j++ < wwncol && ns++->c_w == os++->c_w;) 190 ; 191 if (j > wwncol) 192 break; 193 p = buf; 194 m = ns[-1].c_m; 195 c = j - 1; 196 os[-1] = ns[-1]; 197 *p++ = ns[-1].c_c; 198 n = 5; 199 q = p; 200 while (j < wwncol && ns->c_m == m) { 201 *p++ = ns->c_c; 202 if (ns->c_w == os->c_w) { 203 if (--n <= 0) 204 break; 205 os++; 206 ns++; 207 } else { 208 n = 5; 209 q = p; 210 lastc = *os; 211 *os++ = *ns++; 212 } 213 j++; 214 } 215 n = q - buf; 216 if (!wwwrap || i != wwnrow - 1 || c + n != wwncol) 217 xxwrite(i, c, buf, n, m); 218 else if (tt.tt_inschar || tt.tt_insspace) { 219 if (n > 1) { 220 q[-2] = q[-1]; 221 n--; 222 } else 223 c--; 224 xxwrite(i, c, buf, n, m); 225 c += n - 1; 226 if (tt.tt_inschar) 227 xxinschar(i, c, ns[-2].c_c, 228 ns[-2].c_m); 229 else { 230 xxinsspace(i, c); 231 xxwrite(i, c, &ns[-2].c_c, 1, 232 ns[-2].c_m); 233 } 234 } else { 235 if (--n) 236 xxwrite(i, c, buf, n, m); 237 os[-1] = lastc; 238 *touched = WWU_TOUCHED; 239 } 240 didit = 1; 241 } 242 if (!didit) 243 wwnupdmiss++; 244 } 245 } 246