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