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