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[] = "@(#)wwscroll.c 3.22 (Berkeley) 05/11/89"; 20 #endif /* not lint */ 21 22 #include "ww.h" 23 #include "tt.h" 24 25 wwscroll(w, n) 26 register struct ww *w; 27 int n; 28 { 29 register dir; 30 register top; 31 32 if (n == 0) 33 return; 34 dir = n < 0 ? -1 : 1; 35 top = w->ww_b.t - n; 36 if (top > w->ww_w.t) 37 top = w->ww_w.t; 38 else if (top + w->ww_b.nr < w->ww_w.b) 39 top = w->ww_w.b - w->ww_b.nr; 40 n = abs(top - w->ww_b.t); 41 if (n < w->ww_i.nr) { 42 while (--n >= 0) { 43 (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0); 44 w->ww_buf += dir; 45 w->ww_b.t -= dir; 46 w->ww_b.b -= dir; 47 } 48 } else { 49 w->ww_buf -= top - w->ww_b.t; 50 w->ww_b.t = top; 51 w->ww_b.b = top + w->ww_b.nr; 52 wwredrawwin(w); 53 } 54 } 55 56 /* 57 * Scroll one line, between 'row1' and 'row2', in direction 'dir'. 58 * Don't adjust ww_scroll. 59 * And don't redraw 'leaveit' lines. 60 */ 61 wwscroll1(w, row1, row2, dir, leaveit) 62 register struct ww *w; 63 int row1, row2, dir; 64 int leaveit; 65 { 66 register i; 67 int row1x, row2x; 68 int nvis; 69 int nvismax; 70 int scrolled = 0; 71 72 /* 73 * See how many lines on the screen are affected. 74 * And calculate row1x, row2x, and left at the same time. 75 */ 76 for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++) 77 ; 78 if (i >= row2) /* can't do any fancy stuff */ 79 goto out; 80 row1x = i; 81 for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--) 82 ; 83 if (i <= row1x) 84 goto out; /* just one line is easy */ 85 row2x = i + 1; 86 87 /* 88 * See how much of this window is visible. 89 */ 90 nvismax = wwncol * (row2x - row1x); 91 nvis = 0; 92 for (i = row1x; i < row2x; i++) 93 nvis += w->ww_nvis[i]; 94 95 /* 96 * If it's a good idea to scroll and the terminal can, then do it. 97 */ 98 if (nvis < nvismax / 2) 99 goto no_scroll; /* not worth it */ 100 if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) || 101 (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) && 102 tt.tt_setscroll == 0) 103 if (tt.tt_delline == 0 || tt.tt_insline == 0) 104 goto no_scroll; 105 xxscroll(dir, row1x, row2x); 106 scrolled = 1; 107 /* 108 * Fix up the old screen. 109 */ 110 { 111 register union ww_char *tmp; 112 register union ww_char **cpp, **cqq; 113 114 if (dir > 0) { 115 cpp = &wwos[row1x]; 116 cqq = cpp + 1; 117 tmp = *cpp; 118 for (i = row2x - row1x; --i > 0;) 119 *cpp++ = *cqq++; 120 *cpp = tmp; 121 } else { 122 cpp = &wwos[row2x]; 123 cqq = cpp - 1; 124 tmp = *cqq; 125 for (i = row2x - row1x; --i > 0;) 126 *--cpp = *--cqq; 127 *cqq = tmp; 128 } 129 for (i = wwncol; --i >= 0;) 130 tmp++->c_w = ' '; 131 } 132 133 no_scroll: 134 /* 135 * Fix the new screen. 136 */ 137 if (nvis == nvismax) { 138 /* 139 * Can shift whole lines. 140 */ 141 if (dir > 0) { 142 { 143 register union ww_char *tmp; 144 register union ww_char **cpp, **cqq; 145 146 cpp = &wwns[row1x]; 147 cqq = cpp + 1; 148 tmp = *cpp; 149 for (i = row2x - row1x; --i > 0;) 150 *cpp++ = *cqq++; 151 *cpp = tmp; 152 } 153 if (scrolled) { 154 register char *p, *q; 155 156 p = &wwtouched[row1x]; 157 q = p + 1; 158 for (i = row2x - row1x; --i > 0;) 159 *p++ = *q++; 160 *p |= WWU_TOUCHED; 161 } else { 162 register char *p; 163 164 p = &wwtouched[row1x]; 165 for (i = row2x - row1x; --i >= 0;) 166 *p++ |= WWU_TOUCHED; 167 } 168 wwredrawwin1(w, row1, row1x, dir); 169 wwredrawwin1(w, row2x - 1, row2 - leaveit, dir); 170 } else { 171 { 172 register union ww_char *tmp; 173 register union ww_char **cpp, **cqq; 174 175 cpp = &wwns[row2x]; 176 cqq = cpp - 1; 177 tmp = *cqq; 178 for (i = row2x - row1x; --i > 0;) 179 *--cpp = *--cqq; 180 *cqq = tmp; 181 } 182 if (scrolled) { 183 register char *p, *q; 184 185 p = &wwtouched[row2x]; 186 q = p - 1; 187 for (i = row2x - row1x; --i > 0;) 188 *--p = *--q; 189 *q |= WWU_TOUCHED; 190 } else { 191 register char *p; 192 193 p = &wwtouched[row1x]; 194 for (i = row2x - row1x; --i >= 0;) 195 *p++ |= WWU_TOUCHED; 196 } 197 wwredrawwin1(w, row1 + leaveit, row1x + 1, dir); 198 wwredrawwin1(w, row2x, row2, dir); 199 } 200 } else { 201 if (scrolled) { 202 register char *p; 203 204 p = &wwtouched[row1x]; 205 for (i = row2x - row1x; --i >= 0;) 206 *p++ |= WWU_TOUCHED; 207 } 208 out: 209 if (dir > 0) 210 wwredrawwin1(w, row1, row2 - leaveit, dir); 211 else 212 wwredrawwin1(w, row1 + leaveit, row2, dir); 213 } 214 return scrolled; 215 } 216