138745Sedward /* 238745Sedward * Copyright (c) 1989 Regents of the University of California. 338745Sedward * All rights reserved. 438745Sedward * 538745Sedward * Redistribution and use in source and binary forms are permitted 638745Sedward * provided that the above copyright notice and this paragraph are 738745Sedward * duplicated in all such forms and that any documentation, 838745Sedward * advertising materials, and other materials related to such 938745Sedward * distribution and use acknowledge that the software was developed 1038745Sedward * by the University of California, Berkeley. The name of the 1138745Sedward * University may not be used to endorse or promote products derived 1238745Sedward * from this software without specific prior written permission. 1338745Sedward * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1438745Sedward * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538745Sedward * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1638745Sedward */ 1738745Sedward 1838745Sedward #ifndef lint 19*39159Sedward static char sccsid[] = "@(#)xxflush.c 3.4 (Berkeley) 09/15/89"; 2038745Sedward #endif /* not lint */ 2138745Sedward 2238745Sedward #include "ww.h" 2338745Sedward #include "xx.h" 2438745Sedward #include "tt.h" 2538745Sedward 2638745Sedward xxflush(intr) 2738745Sedward register intr; 2838745Sedward { 2938745Sedward register struct xx *xp, *xq; 3038745Sedward 3138745Sedward for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) { 3238745Sedward switch (xp->cmd) { 3338745Sedward case xc_move: 3438745Sedward if (xp->link == 0) 3538745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 3638745Sedward break; 3738745Sedward case xc_scroll: 3838745Sedward xxflush_scroll(xp); 3938745Sedward break; 4038745Sedward case xc_inschar: 4138745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 4238747Sedward tt.tt_nmodes = xp->arg3; 4338747Sedward (*tt.tt_inschar)(xp->arg2); 4438745Sedward break; 4538747Sedward case xc_insspace: 4638747Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 4738747Sedward (*tt.tt_insspace)(xp->arg2); 4838747Sedward break; 4938745Sedward case xc_delchar: 5038745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 5138745Sedward (*tt.tt_delchar)(xp->arg2); 5238745Sedward break; 5338745Sedward case xc_clear: 5438745Sedward (*tt.tt_clear)(); 5538745Sedward break; 5638745Sedward case xc_clreos: 5738745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 5838745Sedward (*tt.tt_clreos)(); 5938745Sedward break; 6038745Sedward case xc_clreol: 6138745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 6238745Sedward (*tt.tt_clreol)(); 6338745Sedward break; 6438745Sedward case xc_write: 6538745Sedward (*tt.tt_move)(xp->arg0, xp->arg1); 6638745Sedward tt.tt_nmodes = xp->arg3; 67*39159Sedward (*tt.tt_write)(xp->buf, xp->arg2); 6838745Sedward break; 6938745Sedward } 7038745Sedward xq = xp->link; 7138745Sedward xxfree(xp); 7238745Sedward } 7338745Sedward if ((xx_head = xp) == 0) { 7438745Sedward xx_tail = 0; 7538745Sedward xxbufp = xxbuf; 7638745Sedward } 77*39159Sedward (*tt.tt_flush)(); 7838745Sedward } 7938745Sedward 8038745Sedward xxflush_scroll(xp) 8138745Sedward register struct xx *xp; 8238745Sedward { 8338745Sedward register struct xx *xq; 8438745Sedward 8538745Sedward top: 8638745Sedward if (xp->arg0 == 0) 8738745Sedward return; 8838745Sedward /* 8938745Sedward * We handle retain (da and db) by putting the burden on scrolling up, 9038745Sedward * which is the less common operation. It must ensure that 9138745Sedward * text is not pushed below the screen, so scrolling down doesn't 9238745Sedward * have to worry about it. 9338745Sedward * 9438745Sedward * Try scrolling region (or scrolling the whole screen) first. 9538745Sedward * Can we assume "sr" doesn't push text below the screen 9638745Sedward * so we don't have to worry about retain below? 9738745Sedward * What about scrolling down with a newline? It probably does 9838745Sedward * push text above (with da). Scrolling up would then have 9938745Sedward * to take care of that. 10038745Sedward * It's easy to be fool proof, but that slows things down. 10138745Sedward * The current solution is to disallow tt_scroll_up if da or db is true 10238745Sedward * but cs (scrolling region) is not. Again, we sacrifice scrolling 10338745Sedward * up in favor of scrolling down. The idea is having scrolling regions 10438745Sedward * probably means we can scroll (even the whole screen) with impunity. 10538745Sedward * This lets us work efficiently on simple terminals (use newline 10638745Sedward * on the bottom to scroll), on any terminal without retain, and 10738745Sedward * on vt100 style scrolling regions (I think). 10838745Sedward */ 10938745Sedward if (xp->arg0 > 0) { 11038745Sedward if ((xq = xp->link) != 0 && xq->cmd == xc_scroll && 11138745Sedward xp->arg2 == xq->arg2 && xq->arg0 < 0) { 11238745Sedward if (xp->arg1 < xq->arg1) { 11338745Sedward if (xp->arg2 - xp->arg0 <= xq->arg1) { 11438745Sedward xq->arg0 = xp->arg0; 11538745Sedward xq->arg1 = xp->arg1; 11638745Sedward xq->arg2 = xp->arg2; 11738745Sedward return; 11838745Sedward } 11938745Sedward xp->arg2 = xq->arg1 + xp->arg0; 12038745Sedward xq->arg0 += xp->arg0; 12138745Sedward xq->arg1 = xp->arg2; 12238745Sedward if (xq->arg0 > 0) 12338745Sedward xq->arg1 -= xq->arg0; 12438745Sedward goto top; 12538745Sedward } else { 12638745Sedward if (xp->arg1 - xq->arg0 >= xp->arg2) 12738745Sedward return; 12838745Sedward xq->arg2 = xp->arg1 - xq->arg0; 12938745Sedward xp->arg0 += xq->arg0; 13038745Sedward xp->arg1 = xq->arg2; 13138745Sedward if (xp->arg0 < 0) 13238745Sedward xp->arg1 += xp->arg0; 13338745Sedward goto top; 13438745Sedward } 13538745Sedward } 13638745Sedward if (xp->arg0 > xp->arg2 - xp->arg1) 13738745Sedward xp->arg0 = xp->arg2 - xp->arg1; 13838745Sedward if (tt.tt_scroll_down) { 13938745Sedward if (tt.tt_scroll_top != xp->arg1 || 14038745Sedward tt.tt_scroll_bot != xp->arg2 - 1) { 14138745Sedward if (tt.tt_setscroll == 0) 14238745Sedward goto down; 14338745Sedward (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 14438745Sedward } 14538745Sedward tt.tt_scroll_down(xp->arg0); 14638745Sedward } else { 14738745Sedward down: 14838745Sedward (*tt.tt_move)(xp->arg1, 0); 14938745Sedward (*tt.tt_delline)(xp->arg0); 15038745Sedward if (xp->arg2 < tt.tt_nrow) { 15138745Sedward (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 15238745Sedward (*tt.tt_insline)(xp->arg0); 15338745Sedward } 15438745Sedward } 15538745Sedward } else { 15638745Sedward xp->arg0 = - xp->arg0; 15738745Sedward if (xp->arg0 > xp->arg2 - xp->arg1) 15838745Sedward xp->arg0 = xp->arg2 - xp->arg1; 15938745Sedward if (tt.tt_scroll_up) { 16038745Sedward if (tt.tt_scroll_top != xp->arg1 || 16138745Sedward tt.tt_scroll_bot != xp->arg2 - 1) { 16238745Sedward if (tt.tt_setscroll == 0) 16338745Sedward goto up; 16438745Sedward (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); 16538745Sedward } 16638745Sedward tt.tt_scroll_up(xp->arg0); 16738745Sedward } else { 16838745Sedward up: 16938745Sedward if (tt.tt_retain || xp->arg2 != tt.tt_nrow) { 17038745Sedward (*tt.tt_move)(xp->arg2 - xp->arg0, 0); 17138745Sedward (*tt.tt_delline)(xp->arg0); 17238745Sedward } 17338745Sedward (*tt.tt_move)(xp->arg1, 0); 17438745Sedward (*tt.tt_insline)(xp->arg0); 17538745Sedward } 17638745Sedward } 17738745Sedward } 178