1 /* $NetBSD: xxflush.c,v 1.6 2003/08/07 11:17:47 agc Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Edward Wang at The University of California, Berkeley. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)xxflush.c 8.1 (Berkeley) 6/6/93"; 39 #else 40 __RCSID("$NetBSD: xxflush.c,v 1.6 2003/08/07 11:17:47 agc Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include "ww.h" 45 #include "xx.h" 46 #include "tt.h" 47 48 void 49 xxflush(int intr) 50 { 51 struct xx *xp, *xq; 52 53 for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) { 54 switch (xp->cmd) { 55 case xc_move: 56 if (xp->link == 0) 57 (*tt.tt_move)(xp->arg0, xp->arg1); 58 break; 59 case xc_scroll: 60 xxflush_scroll(xp); 61 break; 62 case xc_inschar: 63 (*tt.tt_move)(xp->arg0, xp->arg1); 64 tt.tt_nmodes = xp->arg3; 65 (*tt.tt_inschar)(xp->arg2); 66 break; 67 case xc_insspace: 68 (*tt.tt_move)(xp->arg0, xp->arg1); 69 (*tt.tt_insspace)(xp->arg2); 70 break; 71 case xc_delchar: 72 (*tt.tt_move)(xp->arg0, xp->arg1); 73 (*tt.tt_delchar)(xp->arg2); 74 break; 75 case xc_clear: 76 (*tt.tt_clear)(); 77 break; 78 case xc_clreos: 79 (*tt.tt_move)(xp->arg0, xp->arg1); 80 (*tt.tt_clreos)(); 81 break; 82 case xc_clreol: 83 (*tt.tt_move)(xp->arg0, xp->arg1); 84 (*tt.tt_clreol)(); 85 break; 86 case xc_write: 87 (*tt.tt_move)(xp->arg0, xp->arg1); 88 tt.tt_nmodes = xp->arg3; 89 (*tt.tt_write)(xp->buf, xp->arg2); 90 break; 91 } 92 xq = xp->link; 93 xxfree(xp); 94 } 95 if ((xx_head = xp) == 0) { 96 xx_tail = 0; 97 xxbufp = xxbuf; 98 } 99 ttflush(); 100 } 101 102 void 103 xxflush_scroll(struct xx *xp) 104 { 105 struct xx *xq; 106 107 top: 108 if (xp->arg0 == 0) 109 return; 110 /* 111 * We handle retain (da and db) by putting the burden on scrolling up, 112 * which is the less common operation. It must ensure that 113 * text is not pushed below the screen, so scrolling down doesn't 114 * have to worry about it. 115 * 116 * Try scrolling region (or scrolling the whole screen) first. 117 * Can we assume "sr" doesn't push text below the screen 118 * so we don't have to worry about retain below? 119 * What about scrolling down with a newline? It probably does 120 * push text above (with da). Scrolling up would then have 121 * to take care of that. 122 * It's easy to be fool proof, but that slows things down. 123 * The current solution is to disallow tt_scroll_up if da or db is true 124 * but cs (scrolling region) is not. Again, we sacrifice scrolling 125 * up in favor of scrolling down. The idea is having scrolling regions 126 * probably means we can scroll (even the whole screen) with impunity. 127 * This lets us work efficiently on simple terminals (use newline 128 * on the bottom to scroll), on any terminal without retain, and 129 * on vt100 style scrolling regions (I think). 130 */ 131 if (xp->arg0 > 0) { 132 if ((xq = xp->link) != 0 && xq->cmd == xc_scroll && 133 xp->arg2 == xq->arg2 && xq->arg0 < 0) { 134 if (xp->arg1 < xq->arg1) { 135 if (xp->arg2 - xp->arg0 <= xq->arg1) { 136 xq->arg0 = xp->arg0; 137 xq->arg1 = xp->arg1; 138 xq->arg2 = xp->arg2; 139 return; 140 } 141 xp->arg2 = xq->arg1 + xp->arg0; 142 xq->arg0 += xp->arg0; 143 xq->arg1 = xp->arg2; 144 if (xq->arg0 > 0) 145 xq->arg1 -= xq->arg0; 146 goto top; 147 } else { 148 if (xp->arg1 - xq->arg0 >= xp->arg2) 149 return; 150 xq->arg2 = xp->arg1 - xq->arg0; 151 xp->arg0 += xq->arg0; 152 xp->arg1 = xq->arg2; 153 if (xp->arg0 < 0) 154 xp->arg1 += xp->arg0; 155 goto top; 156 } 157 } 158 if (xp->arg0 > xp->arg2 - xp->arg1) 159 xp->arg0 = xp->arg2 - xp->arg1; 160 if (tt.tt_scroll_down) { 161 if (tt.tt_scroll_top != xp->arg1 || 162 tt.tt_scroll_bot != xp->arg2 - 1) { 163 if (tt.tt_setscroll == 0) 164 goto down; 165 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 166 } 167 tt.tt_scroll_down(xp->arg0); 168 } else { 169 down: 170 (*tt.tt_move)(xp->arg1, 0); 171 (*tt.tt_delline)(xp->arg0); 172 if (xp->arg2 < tt.tt_nrow) { 173 (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 174 (*tt.tt_insline)(xp->arg0); 175 } 176 } 177 } else { 178 xp->arg0 = - xp->arg0; 179 if (xp->arg0 > xp->arg2 - xp->arg1) 180 xp->arg0 = xp->arg2 - xp->arg1; 181 if (tt.tt_scroll_up) { 182 if (tt.tt_scroll_top != xp->arg1 || 183 tt.tt_scroll_bot != xp->arg2 - 1) { 184 if (tt.tt_setscroll == 0) 185 goto up; 186 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 187 } 188 tt.tt_scroll_up(xp->arg0); 189 } else { 190 up: 191 if (tt.tt_retain || xp->arg2 != tt.tt_nrow) { 192 (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 193 (*tt.tt_delline)(xp->arg0); 194 } 195 (*tt.tt_move)(xp->arg1, 0); 196 (*tt.tt_insline)(xp->arg0); 197 } 198 } 199 } 200