|
|
1.1 ! root 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.20 (Berkeley) 6/29/88"; ! 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: int (*scroll_func)(); ! 72: ! 73: /* ! 74: * See how many lines on the screen are affected. ! 75: * And calculate row1x, row2x, and left at the same time. ! 76: */ ! 77: for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++) ! 78: ; ! 79: if (i >= row2) /* can't do any fancy stuff */ ! 80: goto out; ! 81: row1x = i; ! 82: for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--) ! 83: ; ! 84: if (i <= row1x) ! 85: goto out; /* just one line is easy */ ! 86: row2x = i + 1; ! 87: ! 88: /* ! 89: * See how much of this window is visible. ! 90: */ ! 91: nvismax = wwncol * (row2x - row1x); ! 92: nvis = 0; ! 93: for (i = row1x; i < row2x; i++) ! 94: nvis += w->ww_nvis[i]; ! 95: ! 96: /* ! 97: * If it's a good idea to scroll and the terminal can, then do it. ! 98: * We handle retain (da and db) by putting the burden on scrolling up, ! 99: * which is the less common operation. It must ensure that ! 100: * text is not pushed below the screen, so scrolling down doesn't ! 101: * have to worry about it. ! 102: */ ! 103: if (nvis < nvismax / 2) ! 104: goto no_scroll; /* not worth it */ ! 105: /* ! 106: * Try scrolling region (or scrolling the whole screen) first. ! 107: * Can we assume "sr" doesn't push text below the screen ! 108: * so we don't have to worry about retain below? ! 109: * What about scrolling down with a newline? It probably does ! 110: * push text above (with da). Scrolling up would then have ! 111: * to take care of that. ! 112: * It's easy to be fool proof, but that slows things down. ! 113: * The current solution is to disallow tt_scroll_up if da or db is true ! 114: * but cs (scrolling region) is not. Again, we sacrifice scrolling ! 115: * up in favor of scrolling down. The idea is having scrolling regions ! 116: * probably means we can scroll (even the whole screen) with impunity. ! 117: * This lets us work efficiently on simple terminals (use newline ! 118: * on the bottom to scroll), on any terminal without retain, and ! 119: * on vt100 style scrolling regions (I think). ! 120: */ ! 121: if (scroll_func = dir > 0 ? tt.tt_scroll_down : tt.tt_scroll_up) { ! 122: if (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) ! 123: if (tt.tt_setscroll == 0) ! 124: scroll_func = 0; ! 125: else ! 126: (*tt.tt_setscroll)(row1x, row2x - 1); ! 127: if (scroll_func) { ! 128: (*scroll_func)(); ! 129: goto did_scroll; ! 130: } ! 131: } ! 132: /* ! 133: * Try insert/delete line. ! 134: * Don't worry about retain when scrolling down, ! 135: * but do worry when scrolling up, for hp2621. ! 136: */ ! 137: if (tt.tt_delline == 0 || tt.tt_insline == 0) ! 138: goto no_scroll; ! 139: if (dir > 0) { ! 140: (*tt.tt_move)(row1x, 0); ! 141: (*tt.tt_delline)(); ! 142: if (row2x < wwnrow) { ! 143: (*tt.tt_move)(row2x - 1, 0); ! 144: (*tt.tt_insline)(); ! 145: } ! 146: } else { ! 147: if (tt.tt_retain || row2x != wwnrow) { ! 148: (*tt.tt_move)(row2x - 1, 0); ! 149: (*tt.tt_delline)(); ! 150: } ! 151: (*tt.tt_move)(row1x, 0); ! 152: (*tt.tt_insline)(); ! 153: } ! 154: did_scroll: ! 155: scrolled = 1; ! 156: /* ! 157: * Fix up the old screen. ! 158: */ ! 159: { ! 160: register union ww_char *tmp; ! 161: register union ww_char **cpp, **cqq; ! 162: ! 163: if (dir > 0) { ! 164: cpp = &wwos[row1x]; ! 165: cqq = cpp + 1; ! 166: tmp = *cpp; ! 167: for (i = row2x - row1x; --i > 0;) ! 168: *cpp++ = *cqq++; ! 169: *cpp = tmp; ! 170: } else { ! 171: cpp = &wwos[row2x]; ! 172: cqq = cpp - 1; ! 173: tmp = *cqq; ! 174: for (i = row2x - row1x; --i > 0;) ! 175: *--cpp = *--cqq; ! 176: *cqq = tmp; ! 177: } ! 178: for (i = wwncol; --i >= 0;) ! 179: tmp++->c_w = ' '; ! 180: } ! 181: ! 182: no_scroll: ! 183: /* ! 184: * Fix the new screen. ! 185: */ ! 186: if (nvis == nvismax) { ! 187: /* ! 188: * Can shift whole lines. ! 189: */ ! 190: if (dir > 0) { ! 191: { ! 192: register union ww_char *tmp; ! 193: register union ww_char **cpp, **cqq; ! 194: ! 195: cpp = &wwns[row1x]; ! 196: cqq = cpp + 1; ! 197: tmp = *cpp; ! 198: for (i = row2x - row1x; --i > 0;) ! 199: *cpp++ = *cqq++; ! 200: *cpp = tmp; ! 201: } ! 202: if (scrolled) { ! 203: register char *p, *q; ! 204: ! 205: p = &wwtouched[row1x]; ! 206: q = p + 1; ! 207: for (i = row2x - row1x; --i > 0;) ! 208: *p++ = *q++; ! 209: *p |= WWU_TOUCHED; ! 210: } else { ! 211: register char *p; ! 212: ! 213: p = &wwtouched[row1x]; ! 214: for (i = row2x - row1x; --i >= 0;) ! 215: *p++ |= WWU_MAJOR|WWU_TOUCHED; ! 216: } ! 217: wwredrawwin1(w, row1, row1x, dir); ! 218: wwredrawwin1(w, row2x - 1, row2 - leaveit, dir); ! 219: } else { ! 220: { ! 221: register union ww_char *tmp; ! 222: register union ww_char **cpp, **cqq; ! 223: ! 224: cpp = &wwns[row2x]; ! 225: cqq = cpp - 1; ! 226: tmp = *cqq; ! 227: for (i = row2x - row1x; --i > 0;) ! 228: *--cpp = *--cqq; ! 229: *cqq = tmp; ! 230: } ! 231: if (scrolled) { ! 232: register char *p, *q; ! 233: ! 234: p = &wwtouched[row2x]; ! 235: q = p - 1; ! 236: for (i = row2x - row1x; --i > 0;) ! 237: *--p = *--q; ! 238: *q |= WWU_TOUCHED; ! 239: } else { ! 240: register char *p; ! 241: ! 242: p = &wwtouched[row1x]; ! 243: for (i = row2x - row1x; --i >= 0;) ! 244: *p++ |= WWU_MAJOR|WWU_TOUCHED; ! 245: } ! 246: wwredrawwin1(w, row1 + leaveit, row1x + 1, dir); ! 247: wwredrawwin1(w, row2x, row2, dir); ! 248: } ! 249: } else { ! 250: if (scrolled) { ! 251: register char *p; ! 252: ! 253: p = &wwtouched[row1x]; ! 254: for (i = row2x - row1x; --i >= 0;) ! 255: *p++ |= WWU_MAJOR|WWU_TOUCHED; ! 256: } ! 257: out: ! 258: if (dir > 0) ! 259: wwredrawwin1(w, row1, row2 - leaveit, dir); ! 260: else ! 261: wwredrawwin1(w, row1 + leaveit, row2, dir); ! 262: } ! 263: return scrolled; ! 264: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.