1 /* 2 * Copyright (c) 1989 Regents of the University of California. 3 * 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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)xxflush.c 3.6 (Berkeley) 06/06/90"; 13 #endif /* not lint */ 14 15 #include "ww.h" 16 #include "xx.h" 17 #include "tt.h" 18 19 xxflush(intr) 20 register intr; 21 { 22 register struct xx *xp, *xq; 23 24 for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) { 25 switch (xp->cmd) { 26 case xc_move: 27 if (xp->link == 0) 28 (*tt.tt_move)(xp->arg0, xp->arg1); 29 break; 30 case xc_scroll: 31 xxflush_scroll(xp); 32 break; 33 case xc_inschar: 34 (*tt.tt_move)(xp->arg0, xp->arg1); 35 tt.tt_nmodes = xp->arg3; 36 (*tt.tt_inschar)(xp->arg2); 37 break; 38 case xc_insspace: 39 (*tt.tt_move)(xp->arg0, xp->arg1); 40 (*tt.tt_insspace)(xp->arg2); 41 break; 42 case xc_delchar: 43 (*tt.tt_move)(xp->arg0, xp->arg1); 44 (*tt.tt_delchar)(xp->arg2); 45 break; 46 case xc_clear: 47 (*tt.tt_clear)(); 48 break; 49 case xc_clreos: 50 (*tt.tt_move)(xp->arg0, xp->arg1); 51 (*tt.tt_clreos)(); 52 break; 53 case xc_clreol: 54 (*tt.tt_move)(xp->arg0, xp->arg1); 55 (*tt.tt_clreol)(); 56 break; 57 case xc_write: 58 (*tt.tt_move)(xp->arg0, xp->arg1); 59 tt.tt_nmodes = xp->arg3; 60 (*tt.tt_write)(xp->buf, xp->arg2); 61 break; 62 } 63 xq = xp->link; 64 xxfree(xp); 65 } 66 if ((xx_head = xp) == 0) { 67 xx_tail = 0; 68 xxbufp = xxbuf; 69 } 70 (*tt.tt_flush)(); 71 } 72 73 xxflush_scroll(xp) 74 register struct xx *xp; 75 { 76 register struct xx *xq; 77 78 top: 79 if (xp->arg0 == 0) 80 return; 81 /* 82 * We handle retain (da and db) by putting the burden on scrolling up, 83 * which is the less common operation. It must ensure that 84 * text is not pushed below the screen, so scrolling down doesn't 85 * have to worry about it. 86 * 87 * Try scrolling region (or scrolling the whole screen) first. 88 * Can we assume "sr" doesn't push text below the screen 89 * so we don't have to worry about retain below? 90 * What about scrolling down with a newline? It probably does 91 * push text above (with da). Scrolling up would then have 92 * to take care of that. 93 * It's easy to be fool proof, but that slows things down. 94 * The current solution is to disallow tt_scroll_up if da or db is true 95 * but cs (scrolling region) is not. Again, we sacrifice scrolling 96 * up in favor of scrolling down. The idea is having scrolling regions 97 * probably means we can scroll (even the whole screen) with impunity. 98 * This lets us work efficiently on simple terminals (use newline 99 * on the bottom to scroll), on any terminal without retain, and 100 * on vt100 style scrolling regions (I think). 101 */ 102 if (xp->arg0 > 0) { 103 if ((xq = xp->link) != 0 && xq->cmd == xc_scroll && 104 xp->arg2 == xq->arg2 && xq->arg0 < 0) { 105 if (xp->arg1 < xq->arg1) { 106 if (xp->arg2 - xp->arg0 <= xq->arg1) { 107 xq->arg0 = xp->arg0; 108 xq->arg1 = xp->arg1; 109 xq->arg2 = xp->arg2; 110 return; 111 } 112 xp->arg2 = xq->arg1 + xp->arg0; 113 xq->arg0 += xp->arg0; 114 xq->arg1 = xp->arg2; 115 if (xq->arg0 > 0) 116 xq->arg1 -= xq->arg0; 117 goto top; 118 } else { 119 if (xp->arg1 - xq->arg0 >= xp->arg2) 120 return; 121 xq->arg2 = xp->arg1 - xq->arg0; 122 xp->arg0 += xq->arg0; 123 xp->arg1 = xq->arg2; 124 if (xp->arg0 < 0) 125 xp->arg1 += xp->arg0; 126 goto top; 127 } 128 } 129 if (xp->arg0 > xp->arg2 - xp->arg1) 130 xp->arg0 = xp->arg2 - xp->arg1; 131 if (tt.tt_scroll_down) { 132 if (tt.tt_scroll_top != xp->arg1 || 133 tt.tt_scroll_bot != xp->arg2 - 1) { 134 if (tt.tt_setscroll == 0) 135 goto down; 136 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 137 } 138 tt.tt_scroll_down(xp->arg0); 139 } else { 140 down: 141 (*tt.tt_move)(xp->arg1, 0); 142 (*tt.tt_delline)(xp->arg0); 143 if (xp->arg2 < tt.tt_nrow) { 144 (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 145 (*tt.tt_insline)(xp->arg0); 146 } 147 } 148 } else { 149 xp->arg0 = - xp->arg0; 150 if (xp->arg0 > xp->arg2 - xp->arg1) 151 xp->arg0 = xp->arg2 - xp->arg1; 152 if (tt.tt_scroll_up) { 153 if (tt.tt_scroll_top != xp->arg1 || 154 tt.tt_scroll_bot != xp->arg2 - 1) { 155 if (tt.tt_setscroll == 0) 156 goto up; 157 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 158 } 159 tt.tt_scroll_up(xp->arg0); 160 } else { 161 up: 162 if (tt.tt_retain || xp->arg2 != tt.tt_nrow) { 163 (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 164 (*tt.tt_delline)(xp->arg0); 165 } 166 (*tt.tt_move)(xp->arg1, 0); 167 (*tt.tt_insline)(xp->arg0); 168 } 169 } 170 } 171