1: #ifndef lint 2: static char sccsid[] = "@(#)wwscroll.c 3.13 4/24/85"; 3: #endif 4: 5: /* 6: * Copyright (c) 1983 Regents of the University of California, 7: * All rights reserved. Redistribution permitted subject to 8: * the terms of the Berkeley Software License Agreement. 9: */ 10: 11: #include "ww.h" 12: #include "tt.h" 13: 14: wwscroll(w, n) 15: register struct ww *w; 16: int n; 17: { 18: register dir; 19: register top; 20: 21: if (n == 0) 22: return; 23: dir = n < 0 ? -1 : 1; 24: top = w->ww_b.t - n; 25: if (top > w->ww_w.t) 26: top = w->ww_w.t; 27: else if (top + w->ww_b.nr < w->ww_w.b) 28: top = w->ww_w.b - w->ww_b.nr; 29: n = abs(top - w->ww_b.t); 30: if (n < w->ww_i.nr) { 31: while (--n >= 0) { 32: (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0); 33: w->ww_buf += dir; 34: w->ww_b.t -= dir; 35: w->ww_b.b -= dir; 36: } 37: } else { 38: w->ww_buf -= top - w->ww_b.t; 39: w->ww_b.t = top; 40: w->ww_b.b = top + w->ww_b.nr; 41: wwredrawwin(w); 42: } 43: } 44: 45: /* 46: * Scroll one line, between 'row1' and 'row2', in direction 'dir'. 47: * Don't adjust ww_scroll. 48: * And don't redraw 'leaveit' lines. 49: */ 50: wwscroll1(w, row1, row2, dir, leaveit) 51: register struct ww *w; 52: int row1, row2, dir; 53: int leaveit; 54: { 55: register i; 56: int row1x, row2x; 57: int nvis; 58: int nvismax; 59: int deleted = 0; 60: 61: /* 62: * See how many lines on the screen are affected. 63: * And calculate row1x, row2x, and left at the same time. 64: */ 65: for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++) 66: ; 67: if (i >= row2) /* can't do any fancy stuff */ 68: goto out; 69: row1x = i; 70: for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--) 71: ; 72: if (i <= row1x) 73: goto out; /* just one line is easy */ 74: row2x = i + 1; 75: 76: /* 77: * See how much of this window is visible. 78: */ 79: nvismax = wwncol * (row2x - row1x); 80: nvis = 0; 81: for (i = row1x; i < row2x; i++) 82: nvis += w->ww_nvis[i]; 83: 84: /* 85: * If it's a good idea to use delete and insert line 86: * and the terminal can, then do it. 87: */ 88: if (nvis > nvismax / 2 && tt.tt_delline && tt.tt_insline) { 89: register union ww_char *tmp; 90: register union ww_char **cpp, **cqq; 91: 92: /* 93: * Don't worry about retain when scrolling down. 94: * But do worry when scrolling up. For hp2621. 95: */ 96: if (dir > 0) { 97: (*tt.tt_move)(row1x, 0); 98: (*tt.tt_delline)(); 99: if (row2x < wwnrow) { 100: (*tt.tt_move)(row2x - 1, 0); 101: (*tt.tt_insline)(); 102: } 103: /* 104: * Fix up the old screen. 105: */ 106: cpp = &wwos[row1x]; 107: cqq = cpp + 1; 108: tmp = *cpp; 109: for (i = row2x - row1x; --i > 0;) 110: *cpp++ = *cqq++; 111: *cpp = tmp; 112: } else { 113: if (tt.tt_retain || row2x != wwnrow) { 114: (*tt.tt_move)(row2x - 1, 0); 115: (*tt.tt_delline)(); 116: } 117: (*tt.tt_move)(row1x, 0); 118: (*tt.tt_insline)(); 119: /* 120: * Fix up the old screen. 121: */ 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: deleted++; 132: } 133: 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 (deleted) { 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_MAJOR|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 (deleted) { 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_MAJOR|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: out: 202: if (dir > 0) 203: wwredrawwin1(w, row1, row2 - leaveit, dir); 204: else 205: wwredrawwin1(w, row1 + leaveit, row2, dir); 206: } 207: return deleted; 208: }