diff options
| author | Rodney W. Grimes <rgrimes@FreeBSD.org> | 1994-05-27 05:00:24 +0000 | 
|---|---|---|
| committer | Rodney W. Grimes <rgrimes@FreeBSD.org> | 1994-05-27 05:00:24 +0000 | 
| commit | 58f0484fa251c266ede97b591b499fe3dd4f578e (patch) | |
| tree | 41932a7161f4cd72005330a9c69747e7bab2ee5b /lib/libcurses/cr_put.c | |
| parent | fb49e767ba942f74b1cee8814e085e5f2615ac53 (diff) | |
Notes
Diffstat (limited to 'lib/libcurses/cr_put.c')
| -rw-r--r-- | lib/libcurses/cr_put.c | 431 | 
1 files changed, 431 insertions, 0 deletions
| diff --git a/lib/libcurses/cr_put.c b/lib/libcurses/cr_put.c new file mode 100644 index 000000000000..2f7a9e9d59ef --- /dev/null +++ b/lib/libcurses/cr_put.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1981, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cr_put.c	8.2 (Berkeley) 1/9/94"; +#endif	/* not lint */ + +#include <curses.h> +#include <string.h> + +#define	HARDTABS	8 + +/* + * Terminal driving and line formatting routines.  Basic motion optimizations + * are done here as well as formatting lines (printing of control characters, + * line numbering and the like). + */ + +/* Stub function for the users. */ +int +mvcur(ly, lx, y, x) +	int ly, lx, y, x; +{ +	return (__mvcur(ly, lx, y, x, 0)); +} + +static void	fgoto __P((int)); +static int	plod __P((int, int)); +static void	plodput __P((int)); +static int	tabcol __P((int, int)); + +static int outcol, outline, destcol, destline; + +/* + * Sync the position of the output cursor.  Most work here is rounding for + * terminal boundaries getting the column position implied by wraparound or + * the lack thereof and rolling up the screen to get destline on the screen. + */ +int +__mvcur(ly, lx, y, x, in_refresh) +	int ly, lx, y, x, in_refresh; +{ +#ifdef DEBUG +	__CTRACE("mvcur: moving cursor from (%d, %d) to (%d, %d)\n", +	    ly, lx, y, x); +#endif +	destcol = x; +	destline = y; +	outcol = lx; +	outline = ly; +	fgoto(in_refresh); +	return (OK); +}	 +         +static void +fgoto(in_refresh) +	int in_refresh; +{ +	register int c, l; +	register char *cgp; + +	if (destcol >= COLS) { +		destline += destcol / COLS; +		destcol %= COLS; +	} +	if (outcol >= COLS) { +		l = (outcol + 1) / COLS; +		outline += l; +		outcol %= COLS; +		if (AM == 0) { +			while (l > 0) { +				if (__pfast) +					if (CR) +						tputs(CR, 0, __cputchar); +					else +						putchar('\r'); +				if (NL) +					tputs(NL, 0, __cputchar); +				else +					putchar('\n'); +				l--; +			} +			outcol = 0; +		} +		if (outline > LINES - 1) { +			destline -= outline - (LINES - 1); +			outline = LINES - 1; +		} +	} +	if (destline >= LINES) { +		l = destline; +		destline = LINES - 1; +		if (outline < LINES - 1) { +			c = destcol; +			if (__pfast == 0 && !CA) +				destcol = 0; +			fgoto(in_refresh); +			destcol = c; +		} +		while (l >= LINES) { +			/* The following linefeed (or simulation thereof) is +			 * supposed to scroll up the screen, since we are on +			 * the bottom line.  We make the assumption that +			 * linefeed will scroll.  If ns is in the capability +			 * list this won't work.  We should probably have an +			 * sc capability but sf will generally take the place +			 * if it works. +			 *  +			 * Superbee glitch: in the middle of the screen have +			 * to use esc B (down) because linefeed screws up in +			 * "Efficient Paging" (what a joke) mode (which is +			 * essential in some SB's because CRLF mode puts +			 * garbage in at end of memory), but you must use +			 * linefeed to scroll since down arrow won't go past +			 * memory end. I turned this off after recieving Paul +			 * Eggert's Superbee description which wins better. +			 */ +			if (NL /* && !XB */ && __pfast) +				tputs(NL, 0, __cputchar); +			else +				putchar('\n'); +			l--; +			if (__pfast == 0) +				outcol = 0; +		} +	} +	if (destline < outline && !(CA || UP)) +		destline = outline; +	if (CA) { +		cgp = tgoto(CM, destcol, destline); + +		/* +		 * Need this condition due to inconsistent behavior +		 * of backspace on the last column. +		 */ +		if (outcol != COLS - 1 && plod(strlen(cgp), in_refresh) > 0) +			plod(0, in_refresh); +		else  +			tputs(cgp, 0, __cputchar); +	} else +		plod(0, in_refresh); +	outline = destline; +	outcol = destcol; +} +/* + * Move (slowly) to destination. + * Hard thing here is using home cursor on really deficient terminals. + * Otherwise just use cursor motions, hacking use of tabs and overtabbing + * and backspace. + */ + +static int plodcnt, plodflg; + +static void +plodput(c) +	int c; +{ +	if (plodflg) +		--plodcnt; +	else +		putchar(c); +} + +static int +plod(cnt, in_refresh) +	int cnt, in_refresh; +{ +	register int i, j, k, soutcol, soutline; + +	plodcnt = plodflg = cnt; +	soutcol = outcol; +	soutline = outline; +	/* +	 * Consider homing and moving down/right from there, vs. moving +	 * directly with local motions to the right spot. +	 */ +	if (HO) { +		/* +		 * i is the cost to home and tab/space to the right to get to +		 * the proper column.  This assumes ND space costs 1 char.  So +		 * i + destcol is cost of motion with home. +		 */ +		if (GT) +			i = (destcol / HARDTABS) + (destcol % HARDTABS); +		else +			i = destcol; + +		/* j is cost to move locally without homing. */ +		if (destcol >= outcol) {	/* if motion is to the right */ +			j = destcol / HARDTABS - outcol / HARDTABS; +			if (GT && j) +				j += destcol % HARDTABS; +			else +				j = destcol - outcol; +		} else +			/* leftward motion only works if we can backspace. */ +			if (outcol - destcol <= i && (BS || BC)) +				/* Cheaper to backspace. */ +				i = j = outcol - destcol; +			else +				/* Impossibly expensive. */ +				j = i + 1; + +		/* k is the absolute value of vertical distance. */ +		k = outline - destline; +		if (k < 0) +			k = -k; +		j += k; + +		/* Decision.  We may not have a choice if no UP. */ +		if (i + destline < j || (!UP && destline < outline)) { +			/* +			 * Cheaper to home.  Do it now and pretend it's a +			 * regular local motion. +			 */ +			tputs(HO, 0, plodput); +			outcol = outline = 0; +		} else if (LL) { +			/* +			 * Quickly consider homing down and moving from there. +			 * Assume cost of LL is 2. +			 */ +			k = (LINES - 1) - destline; +			if (i + k + 2 < j && (k <= 0 || UP)) { +				tputs(LL, 0, plodput); +				outcol = 0; +				outline = LINES - 1; +			} +		} +	} else +		/* No home and no up means it's impossible. */ +		if (!UP && destline < outline) +			return (-1); +	if (GT) +		i = destcol % HARDTABS + destcol / HARDTABS; +	else +		i = destcol; +#ifdef notdef +	if (BT && outcol > destcol && +	    (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) { +		j *= (k = strlen(BT)); +		if ((k += (destcol&7)) > 4) +			j += 8 - (destcol&7); +		else +			j += k; +	} +	else +#endif +		j = outcol - destcol; + +	/* +	 * If we will later need a \n which will turn into a \r\n by the +	 * system or the terminal, then don't bother to try to \r. +	 */ +	if ((NONL || !__pfast) && outline < destline) +		goto dontcr; + +	/* +	 * If the terminal will do a \r\n and there isn't room for it, then +	 * we can't afford a \r. +	 */ +	if (NC && outline >= destline) +		goto dontcr; + +	/* +	 * If it will be cheaper, or if we can't back up, then send a return +	 * preliminarily. +	 */ +	if (j > i + 1 || outcol > destcol && !BS && !BC) { +		/* +		 * BUG: this doesn't take the (possibly long) length of CR +		 * into account. +		 */ +		if (CR) +			tputs(CR, 0, plodput); +		else +			plodput('\r'); +		if (NC) { +			if (NL) +				tputs(NL, 0, plodput); +			else +				plodput('\n'); +			outline++; +		} +		outcol = 0; +	} + +dontcr:	while (outline < destline) { +		outline++; +		if (NL) +			tputs(NL, 0, plodput); +		else +			plodput('\n'); +		if (plodcnt < 0) +			goto out; +		if (NONL || __pfast == 0) +			outcol = 0; +	} +	if (BT) +		k = strlen(BT); +	while (outcol > destcol) { +		if (plodcnt < 0) +			goto out; +#ifdef notdef +		if (BT && outcol - destcol > k + 4) { +			tputs(BT, 0, plodput); +			outcol--; +			outcol &= ~7; +			continue; +		} +#endif +		outcol--; +		if (BC) +			tputs(BC, 0, plodput); +		else +			plodput('\b'); +	} +	while (outline > destline) { +		outline--; +		tputs(UP, 0, plodput); +		if (plodcnt < 0) +			goto out; +	} +	if (GT && destcol - outcol > 1) { +		for (;;) { +			i = tabcol(outcol, HARDTABS); +			if (i > destcol) +				break; +			if (TA) +				tputs(TA, 0, plodput); +			else +				plodput('\t'); +			outcol = i; +		} +		if (destcol - outcol > 4 && i < COLS && (BC || BS)) { +			if (TA) +				tputs(TA, 0, plodput); +			else +				plodput('\t'); +			outcol = i; +			while (outcol > destcol) { +				outcol--; +				if (BC) +					tputs(BC, 0, plodput); +				else +					plodput('\b'); +			} +		} +	} +	while (outcol < destcol) { +		/* +		 * Move one char to the right.  We don't use ND space because +		 * it's better to just print the char we are moving over. +		 */ +		if (in_refresh) +			if (plodflg)	/* Avoid a complex calculation. */ +				plodcnt--; +			else { +				i = curscr->lines[outline]->line[outcol].ch; +				if ((curscr->lines[outline]->line[outcol].attr +				     & __STANDOUT) == +				    (curscr->flags & __WSTANDOUT)) +					putchar(i); +				else +					goto nondes; +			} +		else +nondes:			if (ND) +				tputs(ND, 0, plodput); +			else +				plodput(' '); +		outcol++; +		if (plodcnt < 0) +			goto out; +	} + +out:	if (plodflg) { +		outcol = soutcol; +		outline = soutline; +	} +	return (plodcnt); +} + +/* + * Return the column number that results from being in column col and + * hitting a tab, where tabs are set every ts columns.  Work right for + * the case where col > COLS, even if ts does not divide COLS. + */ +static int +tabcol(col, ts) +	int col, ts; +{ +	int offset; + +	if (col >= COLS) { +		offset = COLS * (col / COLS); +		col -= offset; +	} else +		offset = 0; +	return (col + ts - (col % ts) + offset); +} | 
