document distributed with 4.3BSD
[unix-history] / usr / src / lib / libcurses / cr_put.c
index f832c67..11be3a0 100644 (file)
@@ -1,5 +1,14 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cr_put.c   5.1 (Berkeley) %G%";
+#endif not lint
+
 # include      "curses.ext"
 # include      "curses.ext"
-# include      "cr_ex.h"
 
 # define       HARDTABS        8
 
 
 # define       HARDTABS        8
 
@@ -11,8 +20,6 @@ int           plodput();
  * Basic motion optimizations are done here as well
  * as formatting of lines (printing of control characters,
  * line numbering and the like).
  * Basic motion optimizations are done here as well
  * as formatting of lines (printing of control characters,
  * line numbering and the like).
- *
- * %G% (Berkeley) @(#)cr_put.c 1.1
  */
 
 /*
  */
 
 /*
@@ -22,7 +29,7 @@ int           plodput();
  * rolling up the screen to get destline on the screen.
  */
 
  * rolling up the screen to get destline on the screen.
  */
 
-static int     outcol, outline, destcol, destline, plodcnt;
+static int     outcol, outline, destcol, destline;
 
 WINDOW         *_win;
 
 
 WINDOW         *_win;
 
@@ -39,24 +46,30 @@ int ly, lx, y, x; {
        fgoto();
 }
 
        fgoto();
 }
 
-fgoto() {
-
+fgoto()
+{
        reg char        *cgp;
        reg int         l, c;
 
        reg char        *cgp;
        reg int         l, c;
 
-       if (destcol > COLS - 1) {
+       if (destcol >= COLS) {
                destline += destcol / COLS;
                destcol %= COLS;
        }
                destline += destcol / COLS;
                destcol %= COLS;
        }
-       if (outcol > COLS - 1) {
+       if (outcol >= COLS) {
                l = (outcol + 1) / COLS;
                outline += l;
                outcol %= COLS;
                if (AM == 0) {
                        while (l > 0) {
                l = (outcol + 1) / COLS;
                outline += l;
                outcol %= COLS;
                if (AM == 0) {
                        while (l > 0) {
-                               putchar('\n');
                                if (_pfast)
                                if (_pfast)
-                                       putchar('\r');
+                                       if (CR)
+                                               _puts(CR);
+                                       else
+                                               _putchar('\r');
+                               if (NL)
+                                       _puts(NL);
+                               else
+                                       _putchar('\n');
                                l--;
                        }
                        outcol = 0;
                                l--;
                        }
                        outcol = 0;
@@ -66,7 +79,7 @@ fgoto() {
                        outline = LINES - 1;
                }
        }
                        outline = LINES - 1;
                }
        }
-       if (destline > LINES - 1) {
+       if (destline >= LINES) {
                l = destline;
                destline = LINES - 1;
                if (outline < LINES - 1) {
                l = destline;
                destline = LINES - 1;
                if (outline < LINES - 1) {
@@ -76,84 +89,143 @@ fgoto() {
                        fgoto();
                        destcol = c;
                }
                        fgoto();
                        destcol = c;
                }
-               while (l > LINES - 1) {
-                       putchar('\n');
+               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 we
+                        * 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)
+                               _puts(NL);
+                       else
+                               _putchar('\n');
                        l--;
                        if (_pfast == 0)
                                outcol = 0;
                }
        }
                        l--;
                        if (_pfast == 0)
                                outcol = 0;
                }
        }
-       if (destline < outline && !(CA || UP != NULL))
+       if (destline < outline && !(CA || UP))
                destline = outline;
                destline = outline;
-       cgp = tgoto(CM, destcol, destline);
-       if (CA)
+       if (CA) {
+               cgp = tgoto(CM, destcol, destline);
                if (plod(strlen(cgp)) > 0)
                        plod(0);
                else
                        tputs(cgp, 0, _putchar);
                if (plod(strlen(cgp)) > 0)
                        plod(0);
                else
                        tputs(cgp, 0, _putchar);
+       }
        else
                plod(0);
        outline = destline;
        outcol = destcol;
 }
 
        else
                plod(0);
        outline = destline;
        outcol = destcol;
 }
 
-char
-_putchar(c)
-reg char       c; {
+/*
+ * 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.
+ */
 
 
-       putchar(c);
-#ifdef DEBUG
-       fprintf(outf, "_PUTCHAR(%s)\n", unctrl(c));
-#endif
-}
+static int plodcnt, plodflg;
 
 
-extern bool    plodflg;
-extern int     plodcnt;
+plodput(c)
+{
+       if (plodflg)
+               plodcnt--;
+       else
+               _putchar(c);
+}
 
 plod(cnt)
 
 plod(cnt)
-int    cnt; {
-
-       reg int         i, j, k;
-       reg int         soutcol, soutline;
-       reg char        c;
+{
+       register int i, j, k;
+       register int soutcol, soutline;
 
        plodcnt = plodflg = cnt;
        soutcol = outcol;
        soutline = outline;
 
        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) {
        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;
                if (GT)
                        i = (destcol / HARDTABS) + (destcol % HARDTABS);
                else
                        i = destcol;
-        if (destcol >= outcol) {
-                j = destcol / HARDTABS - outcol / HARDTABS;
-                if (GT && j)
-                        j += destcol % HARDTABS;
+               /*
+                * 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
                else
-                       j = destcol - outcol;
-        } else
+                       /* leftward motion only works if we can backspace. */
                        if (outcol - destcol <= i && (BS || BC))
                        if (outcol - destcol <= i && (BS || BC))
-                               i = j = outcol - destcol;
+                               i = j = outcol - destcol; /* cheaper to backspace */
                        else
                        else
-                               j = i + 1;
+                               j = i + 1; /* impossibly expensive */
+
+               /* k is the absolute value of vertical distance */
                k = outline - destline;
                if (k < 0)
                        k = -k;
                j += k;
                k = outline - destline;
                if (k < 0)
                        k = -k;
                j += k;
-               if (i + destline < j) {
+
+               /*
+                * 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;
                        tputs(HO, 0, plodput);
                        outcol = outline = 0;
-               } else if (LL) {
+               }
+               else if (LL) {
+                       /*
+                        * Quickly consider homing down and moving from there.
+                        * Assume cost of LL is 2.
+                        */
                        k = (LINES - 1) - destline;
                        k = (LINES - 1) - destline;
-                       if (i + k + 2 < j) {
+                       if (i + k + 2 < j && (k<=0 || UP)) {
                                tputs(LL, 0, plodput);
                                outcol = 0;
                                outline = LINES - 1;
                        }
                }
        }
                                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)
        if (GT)
-        i = destcol % HARDTABS + destcol / HARDTABS;
+               i = destcol % HARDTABS + destcol / HARDTABS;
        else
                i = destcol;
 /*
        else
                i = destcol;
 /*
@@ -163,7 +235,8 @@ int cnt; {
                        j += 8 - (destcol&7);
                else
                        j += k;
                        j += 8 - (destcol&7);
                else
                        j += k;
-       } else
+       }
+       else
 */
                j = outcol - destcol;
        /*
 */
                j = outcol - destcol;
        /*
@@ -183,9 +256,19 @@ int        cnt; {
         * a return preliminarily.
         */
        if (j > i + 1 || outcol > destcol && !BS && !BC) {
         * a return preliminarily.
         */
        if (j > i + 1 || outcol > destcol && !BS && !BC) {
-               plodput('\r');
+               /*
+                * 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 (NC) {
-                       plodput('\n');
+                       if (NL)
+                               tputs(NL, 0, plodput);
+                       else
+                               plodput('\n');
                        outline++;
                }
                outcol = 0;
                        outline++;
                }
                outcol = 0;
@@ -193,7 +276,10 @@ int        cnt; {
 dontcr:
        while (outline < destline) {
                outline++;
 dontcr:
        while (outline < destline) {
                outline++;
-               plodput('\n');
+               if (NL)
+                       tputs(NL, 0, plodput);
+               else
+                       plodput('\n');
                if (plodcnt < 0)
                        goto out;
                if (NONL || _pfast == 0)
                if (plodcnt < 0)
                        goto out;
                if (NONL || _pfast == 0)
@@ -205,7 +291,7 @@ dontcr:
                if (plodcnt < 0)
                        goto out;
 /*
                if (plodcnt < 0)
                        goto out;
 /*
-               if (BT && outcol - destcol > 4+k) {
+               if (BT && outcol - destcol > k + 4) {
                        tputs(BT, 0, plodput);
                        outcol--;
                        outcol &= ~7;
                        tputs(BT, 0, plodput);
                        outcol--;
                        outcol &= ~7;
@@ -225,10 +311,10 @@ dontcr:
                        goto out;
        }
        if (GT && destcol - outcol > 1) {
                        goto out;
        }
        if (GT && destcol - outcol > 1) {
-        for (;;) {
-                i = (outcol / HARDTABS + 1) * HARDTABS;
-                if (i > destcol)
-                        break;
+               for (;;) {
+                       i = tabcol(outcol, HARDTABS);
+                       if (i > destcol)
+                               break;
                        if (TA)
                                tputs(TA, 0, plodput);
                        else
                        if (TA)
                                tputs(TA, 0, plodput);
                        else
@@ -251,13 +337,18 @@ dontcr:
                }
        }
        while (outcol < destcol) {
                }
        }
        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 (_win != NULL)
                        if (plodflg)    /* avoid a complex calculation */
                                plodcnt--;
                        else {
                if (_win != NULL)
                        if (plodflg)    /* avoid a complex calculation */
                                plodcnt--;
                        else {
-                               c = _win->_y[outline-_win->_begy][outcol-_win->_begx];
-                               if ((c&_STANDOUT) == (curscr->_flags&_STANDOUT))
-                                       putchar(c);
+                               i = curscr->_y[outline][outcol];
+                               if ((i&_STANDOUT) == (curscr->_flags&_STANDOUT))
+                                       _putchar(i);
                                else
                                        goto nondes;
                        }
                                else
                                        goto nondes;
                        }
@@ -280,36 +371,20 @@ out:
 }
 
 /*
 }
 
 /*
- * 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.
+ * 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.
  */
  */
+tabcol(col, ts)
+int col, ts;
+{
+       int offset, result;
 
 
-static bool    plodflg;
-
-plodput(c)
-reg char       c; {
-
-       if (plodflg)
-               plodcnt--;
-       else {
-               putchar(c);
-#ifdef DEBUG
-               fprintf(outf, "PLODPUT(%s)\n", unctrl(c));
-#endif
+       if (col >= COLS) {
+               offset = COLS * (col / COLS);
+               col -= offset;
        }
        }
-}
-
-/*
- * Put with padding
- */
-putpad(cp)
-reg char       *cp; {
-
-       fflush(stdout);
-#ifdef DEBUG
-       fprintf(outf, "PUTPAD: _puts(\"%s\")\n", cp);
-#endif
-       _puts(cp);
+       else
+               offset = 0;
+       return col + ts - (col % ts) + offset;
 }
 }