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