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