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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)wwupdate.c 8.1 (Berkeley) 6/6/93 37 * $FreeBSD: src/usr.bin/window/wwupdate.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $ 38 * $DragonFly: src/usr.bin/window/wwupdate.c,v 1.2 2003/06/17 04:29:34 dillon Exp $ 39 */ 40 41 #include "ww.h" 42 #include "tt.h" 43 44 wwupdate1(top, bot) 45 { 46 int i; 47 register j; 48 char *touched; 49 struct ww_update *upd; 50 char check_clreos = 0; 51 int scan_top, scan_bot; 52 53 wwnupdate++; 54 { 55 register char *t1 = wwtouched + top, *t2 = wwtouched + bot; 56 register n; 57 58 while (!*t1++) 59 if (t1 == t2) 60 return; 61 while (!*--t2) 62 ; 63 scan_top = top = t1 - wwtouched - 1; 64 scan_bot = bot = t2 - wwtouched + 1; 65 if (scan_bot - scan_top > 1 && 66 (tt.tt_clreos != 0 || tt.tt_clear != 0)) { 67 int st = tt.tt_clreos != 0 ? scan_top : 0; 68 69 /* 70 * t1 is one past the first touched row, 71 * t2 is on the last touched row. 72 */ 73 for (t1--, n = 1; t1 < t2;) 74 if (*t1++) 75 n++; 76 /* 77 * If we can't clreos then we try for clearing 78 * the whole screen. 79 */ 80 if (check_clreos = n * 10 > (wwnrow - st) * 9) { 81 scan_top = st; 82 scan_bot = wwnrow; 83 } 84 } 85 } 86 if (tt.tt_clreol == 0 && !check_clreos) 87 goto simple; 88 for (i = scan_top, touched = &wwtouched[i], upd = &wwupd[i]; 89 i < scan_bot; 90 i++, touched++, upd++) { 91 register gain = 0; 92 register best_gain = 0; 93 register best_col; 94 register union ww_char *ns, *os; 95 96 if (wwinterrupt()) 97 return; 98 if (!check_clreos && !*touched) 99 continue; 100 wwnupdscan++; 101 j = wwncol; 102 ns = &wwns[i][j]; 103 os = &wwos[i][j]; 104 while (--j >= 0) { 105 /* 106 * The cost of clearing is: 107 * ncol - nblank + X 108 * The cost of straight update is, more or less: 109 * ncol - nsame 110 * We clear if nblank - nsame > X 111 * X is the clreol overhead. 112 * So we make gain = nblank - nsame. 113 */ 114 if ((--ns)->c_w == (--os)->c_w) 115 gain--; 116 else 117 best_gain--; 118 if (ns->c_w == ' ') 119 gain++; 120 if (gain > best_gain) { 121 best_col = j; 122 best_gain = gain; 123 } 124 } 125 upd->best_gain = best_gain; 126 upd->best_col = best_col; 127 upd->gain = gain; 128 } 129 if (check_clreos) { 130 register struct ww_update *u; 131 register gain = 0; 132 register best_gain = 0; 133 int best_row; 134 register simple_gain = 0; 135 char didit = 0; 136 137 /* 138 * gain is the advantage of clearing all the lines. 139 * best_gain is the advantage of clearing to eos 140 * at best_row and u->best_col. 141 * simple_gain is the advantage of using only clreol. 142 * We use g > best_gain because u->best_col can be 143 * undefined when u->best_gain is 0 so we can't use it. 144 */ 145 for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) { 146 register g = gain + u->best_gain; 147 148 if (g > best_gain) { 149 best_gain = g; 150 best_row = j; 151 } 152 gain += u->gain; 153 if (tt.tt_clreol != 0 && u->best_gain > 4) 154 simple_gain += u->best_gain - 4; 155 } 156 if (tt.tt_clreos == 0) { 157 if (gain > simple_gain && gain > 4) { 158 xxclear(); 159 i = top = scan_top; 160 bot = scan_bot; 161 j = 0; 162 didit = 1; 163 } 164 } else 165 if (best_gain > simple_gain && best_gain > 4) { 166 i = best_row; 167 xxclreos(i, j = wwupd[i].best_col); 168 bot = scan_bot; 169 didit = 1; 170 } 171 if (didit) { 172 wwnupdclreos++; 173 wwnupdclreosline += wwnrow - i; 174 u = wwupd + i; 175 while (i < scan_bot) { 176 register union ww_char *os = &wwos[i][j]; 177 178 for (j = wwncol - j; --j >= 0;) 179 os++->c_w = ' '; 180 wwtouched[i++] |= WWU_TOUCHED; 181 u++->best_gain = 0; 182 j = 0; 183 } 184 } else 185 wwnupdclreosmiss++; 186 } 187 simple: 188 for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot; 189 i++, touched++, upd++) { 190 register union ww_char *os, *ns; 191 char didit; 192 193 if (!*touched) 194 continue; 195 *touched = 0; 196 wwnupdline++; 197 didit = 0; 198 if (tt.tt_clreol != 0 && upd->best_gain > 4) { 199 wwnupdclreol++; 200 xxclreol(i, j = upd->best_col); 201 for (os = &wwos[i][j], j = wwncol - j; --j >= 0;) 202 os++->c_w = ' '; 203 didit = 1; 204 } 205 ns = wwns[i]; 206 os = wwos[i]; 207 for (j = 0; j < wwncol;) { 208 register char *p, *q; 209 char m; 210 int c; 211 register n; 212 char buf[512]; /* > wwncol */ 213 union ww_char lastc; 214 215 for (; j++ < wwncol && ns++->c_w == os++->c_w;) 216 ; 217 if (j > wwncol) 218 break; 219 p = buf; 220 m = ns[-1].c_m; 221 c = j - 1; 222 os[-1] = ns[-1]; 223 *p++ = ns[-1].c_c; 224 n = 5; 225 q = p; 226 while (j < wwncol && ns->c_m == m) { 227 *p++ = ns->c_c; 228 if (ns->c_w == os->c_w) { 229 if (--n <= 0) 230 break; 231 os++; 232 ns++; 233 } else { 234 n = 5; 235 q = p; 236 lastc = *os; 237 *os++ = *ns++; 238 } 239 j++; 240 } 241 n = q - buf; 242 if (!wwwrap || i != wwnrow - 1 || c + n != wwncol) 243 xxwrite(i, c, buf, n, m); 244 else if (tt.tt_inschar || tt.tt_insspace) { 245 if (n > 1) { 246 q[-2] = q[-1]; 247 n--; 248 } else 249 c--; 250 xxwrite(i, c, buf, n, m); 251 c += n - 1; 252 if (tt.tt_inschar) 253 xxinschar(i, c, ns[-2].c_c, 254 ns[-2].c_m); 255 else { 256 xxinsspace(i, c); 257 xxwrite(i, c, &ns[-2].c_c, 1, 258 ns[-2].c_m); 259 } 260 } else { 261 if (--n) 262 xxwrite(i, c, buf, n, m); 263 os[-1] = lastc; 264 *touched = WWU_TOUCHED; 265 } 266 didit = 1; 267 } 268 if (!didit) 269 wwnupdmiss++; 270 } 271 } 272