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.22 (Berkeley) 08/08/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 for (n = 1; t1 < t2;) 52 if (*t1++) 53 n++; 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 for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) { 112 register g = gain + u->best_gain; 113 114 if (g >= best_gain) { 115 best_gain = g; 116 best_row = j; 117 } 118 gain += u->gain; 119 if (tt.tt_clreol != 0 && u->best_gain > 4) 120 simple_gain += u->best_gain - 4; 121 } 122 if (tt.tt_clreos == 0) { 123 if (gain > simple_gain && gain > 4) { 124 (*tt.tt_clear)(); 125 i = top = scan_top; 126 bot = scan_bot; 127 j = 0; 128 didit = 1; 129 } 130 } else 131 if (best_gain > simple_gain && best_gain > 4) { 132 i = best_row; 133 (*tt.tt_move)(i, j = wwupd[i].best_col); 134 (*tt.tt_clreos)(); 135 bot = scan_bot; 136 didit = 1; 137 } 138 if (didit) { 139 wwnupdclreos++; 140 wwnupdclreosline += wwnrow - i; 141 u = wwupd + i; 142 while (i < scan_bot) { 143 register union ww_char *os = &wwos[i][j]; 144 145 for (j = wwncol - j; --j >= 0;) 146 os++->c_w = ' '; 147 wwtouched[i++] |= WWU_TOUCHED; 148 u++->best_gain = 0; 149 j = 0; 150 } 151 } else 152 wwnupdclreosmiss++; 153 } 154 simple: 155 for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot; 156 i++, touched++, upd++) { 157 register union ww_char *os, *ns; 158 char didit; 159 160 if (!*touched) 161 continue; 162 *touched = 0; 163 wwnupdline++; 164 didit = 0; 165 if (tt.tt_clreol != 0 && upd->best_gain > 4) { 166 wwnupdclreol++; 167 (*tt.tt_move)(i, j = upd->best_col); 168 (*tt.tt_clreol)(); 169 for (os = &wwos[i][j], j = wwncol - j; --j >= 0;) 170 os++->c_w = ' '; 171 didit = 1; 172 } 173 ns = wwns[i]; 174 os = wwos[i]; 175 for (j = 0; j < wwncol;) { 176 register char *p, *q; 177 char m; 178 int c; 179 register n; 180 char buf[512]; /* > wwncol */ 181 union ww_char lastc; 182 183 for (; j++ < wwncol && ns++->c_w == os++->c_w;) 184 ; 185 if (j > wwncol) 186 break; 187 p = buf; 188 m = ns[-1].c_m; 189 c = j - 1; 190 os[-1] = ns[-1]; 191 *p++ = ns[-1].c_c; 192 n = 5; 193 q = p; 194 while (j < wwncol && ns->c_m == m) { 195 *p++ = ns->c_c; 196 if (ns->c_w == os->c_w) { 197 if (--n <= 0) 198 break; 199 os++; 200 ns++; 201 } else { 202 n = 5; 203 q = p; 204 lastc = *os; 205 *os++ = *ns++; 206 } 207 j++; 208 } 209 tt.tt_nmodes = m; 210 if (wwwrap 211 && i == wwnrow - 1 && q - buf + c == wwncol) { 212 if (tt.tt_hasinsert) { 213 if (q - buf != 1) { 214 (*tt.tt_move)(i, c); 215 (*tt.tt_write)(buf + 1, 216 q - buf - 1); 217 (*tt.tt_move)(i, c); 218 tt.tt_ninsert = 1; 219 (*tt.tt_write)(buf, 1); 220 tt.tt_ninsert = 0; 221 } else { 222 (*tt.tt_move)(i, c - 1); 223 (*tt.tt_write)(buf, 1); 224 tt.tt_nmodes = ns[-2].c_m; 225 (*tt.tt_move)(i, c - 1); 226 tt.tt_ninsert = 1; 227 (*tt.tt_write)(&ns[-2].c_c, 1); 228 tt.tt_ninsert = 0; 229 } 230 } else { 231 if (q - buf > 1) { 232 (*tt.tt_move)(i, c); 233 (*tt.tt_write)(buf, q-buf-1); 234 } 235 os[-1] = lastc; 236 *touched = WWU_TOUCHED; 237 } 238 } else { 239 (*tt.tt_move)(i, c); 240 (*tt.tt_write)(buf, q - buf); 241 } 242 didit = 1; 243 } 244 if (!didit) 245 wwnupdmiss++; 246 } 247 } 248