diff options
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 0000000..2f7a9e9 --- /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); +} |