home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / libcurses / cr_put.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-31  |  9.9 KB  |  421 lines

  1. /*
  2.  * Copyright (c) 1981 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)cr_put.c    5.8 (Berkeley) 8/31/92";
  36. #endif    /* not lint */
  37.  
  38. #include <curses.h>
  39. #include <string.h>
  40. #include <termios.h>
  41.  
  42. #define    HARDTABS    8
  43.  
  44. /*
  45.  * Terminal driving and line formatting routines.  Basic motion optimizations
  46.  * are done here as well as formatting lines (printing of control characters,
  47.  * line numbering and the like).
  48.  */
  49.  
  50. static void    fgoto __P((void));
  51. static int    plod __P((int));
  52. static void    plodput __P((int));
  53. static int    tabcol __P((int, int));
  54.  
  55. /*
  56.  * Sync the position of the output cursor.  Most work here is rounding for
  57.  * terminal boundaries getting the column position implied by wraparound or
  58.  * the lack thereof and rolling up the screen to get destline on the screen.
  59.  */
  60.  
  61. static int outcol, outline, destcol, destline;
  62.  
  63. WINDOW *_win;
  64.  
  65. int
  66. mvcur(ly, lx, y, x)
  67.     int ly, lx, y, x;
  68. {
  69. #ifdef DEBUG
  70.     __TRACE("mvcur: moving cursor from (%d, %d) to (%d, %d)\n",
  71.         ly, lx, y, x);
  72. #endif
  73.     destcol = x;
  74.     destline = y;
  75.     outcol = lx;
  76.     outline = ly;
  77.     fgoto();
  78.     return (OK);
  79. }
  80.  
  81. static void
  82. fgoto()
  83. {
  84.     register int c, l;
  85.     register char *cgp;
  86.  
  87.     if (destcol >= COLS) {
  88.         destline += destcol / COLS;
  89.         destcol %= COLS;
  90.     }
  91.     if (outcol >= COLS) {
  92.         l = (outcol + 1) / COLS;
  93.         outline += l;
  94.         outcol %= COLS;
  95.         if (AM == 0) {
  96.             while (l > 0) {
  97.                 if (__pfast)
  98.                     if (CR)
  99.                         tputs(CR, 0, __cputchar);
  100.                     else
  101.                         putchar('\r');
  102.                 if (NL)
  103.                     tputs(NL, 0, __cputchar);
  104.                 else
  105.                     putchar('\n');
  106.                 l--;
  107.             }
  108.             outcol = 0;
  109.         }
  110.         if (outline > LINES - 1) {
  111.             destline -= outline - (LINES - 1);
  112.             outline = LINES - 1;
  113.         }
  114.     }
  115.     if (destline >= LINES) {
  116.         l = destline;
  117.         destline = LINES - 1;
  118.         if (outline < LINES - 1) {
  119.             c = destcol;
  120.             if (__pfast == 0 && !CA)
  121.                 destcol = 0;
  122.             fgoto();
  123.             destcol = c;
  124.         }
  125.         while (l >= LINES) {
  126.             /* The following linefeed (or simulation thereof) is
  127.              * supposed to scroll up the screen, since we are on
  128.              * the bottom line.  We make the assumption that
  129.              * linefeed will scroll.  If ns is in the capability
  130.              * list this won't work.  We should probably have an
  131.              * sc capability but sf will generally take the place
  132.              * if it works.
  133.              * 
  134.              * Superbee glitch: in the middle of the screen have
  135.              * to use esc B (down) because linefeed screws up in
  136.              * "Efficient Paging" (what a joke) mode (which is
  137.              * essential in some SB's because CRLF mode puts
  138.              * garbage in at end of memory), but you must use
  139.              * linefeed to scroll since down arrow won't go past
  140.              * memory end. I turned this off after recieving Paul
  141.              * Eggert's Superbee description which wins better.
  142.              */
  143.             if (NL /* && !XB */ && __pfast)
  144.                 tputs(NL, 0, __cputchar);
  145.             else
  146.                 putchar('\n');
  147.             l--;
  148.             if (__pfast == 0)
  149.                 outcol = 0;
  150.         }
  151.     }
  152.     if (destline < outline && !(CA || UP))
  153.         destline = outline;
  154.     if (CA) {
  155.         cgp = tgoto(CM, destcol, destline);
  156.         if (plod(strlen(cgp)) > 0)
  157.             plod(0);
  158.         else
  159.             tputs(cgp, 0, __cputchar);
  160.     } else
  161.         plod(0);
  162.     outline = destline;
  163.     outcol = destcol;
  164. }
  165. /*
  166.  * Move (slowly) to destination.
  167.  * Hard thing here is using home cursor on really deficient terminals.
  168.  * Otherwise just use cursor motions, hacking use of tabs and overtabbing
  169.  * and backspace.
  170.  */
  171.  
  172. static int plodcnt, plodflg;
  173.  
  174. static void
  175. plodput(c)
  176.     int c;
  177. {
  178.     if (plodflg)
  179.         --plodcnt;
  180.     else
  181.         putchar(c);
  182. }
  183.  
  184. static int
  185. plod(cnt)
  186.     int cnt;
  187. {
  188.     register int i, j, k, soutcol, soutline;
  189.  
  190.     plodcnt = plodflg = cnt;
  191.     soutcol = outcol;
  192.     soutline = outline;
  193.     /*
  194.      * Consider homing and moving down/right from there, vs. moving
  195.      * directly with local motions to the right spot.
  196.      */
  197.     if (HO) {
  198.         /*
  199.          * i is the cost to home and tab/space to the right to get to
  200.          * the proper column.  This assumes ND space costs 1 char.  So
  201.          * i + destcol is cost of motion with home.
  202.          */
  203.         if (GT)
  204.             i = (destcol / HARDTABS) + (destcol % HARDTABS);
  205.         else
  206.             i = destcol;
  207.  
  208.         /* j is cost to move locally without homing. */
  209.         if (destcol >= outcol) {    /* if motion is to the right */
  210.             j = destcol / HARDTABS - outcol / HARDTABS;
  211.             if (GT && j)
  212.                 j += destcol % HARDTABS;
  213.             else
  214.                 j = destcol - outcol;
  215.         } else
  216.             /* leftward motion only works if we can backspace. */
  217.             if (outcol - destcol <= i && (BS || BC))
  218.                 /* Cheaper to backspace. */
  219.                 i = j = outcol - destcol;
  220.             else
  221.                 /* Impossibly expensive. */
  222.                 j = i + 1;
  223.  
  224.         /* k is the absolute value of vertical distance. */
  225.         k = outline - destline;
  226.         if (k < 0)
  227.             k = -k;
  228.         j += k;
  229.  
  230.         /* Decision.  We may not have a choice if no UP. */
  231.         if (i + destline < j || (!UP && destline < outline)) {
  232.             /*
  233.              * Cheaper to home.  Do it now and pretend it's a
  234.              * regular local motion.
  235.              */
  236.             tputs(HO, 0, plodput);
  237.             outcol = outline = 0;
  238.         } else if (LL) {
  239.             /*
  240.              * Quickly consider homing down and moving from there.
  241.              * Assume cost of LL is 2.
  242.              */
  243.             k = (LINES - 1) - destline;
  244.             if (i + k + 2 < j && (k <= 0 || UP)) {
  245.                 tputs(LL, 0, plodput);
  246.                 outcol = 0;
  247.                 outline = LINES - 1;
  248.             }
  249.         }
  250.     } else
  251.         /* No home and no up means it's impossible. */
  252.         if (!UP && destline < outline)
  253.             return (-1);
  254.     if (GT)
  255.         i = destcol % HARDTABS + destcol / HARDTABS;
  256.     else
  257.         i = destcol;
  258. #ifdef notdef
  259.     if (BT && outcol > destcol &&
  260.         (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
  261.         j *= (k = strlen(BT));
  262.         if ((k += (destcol&7)) > 4)
  263.             j += 8 - (destcol&7);
  264.         else
  265.             j += k;
  266.     }
  267.     else
  268. #endif
  269.         j = outcol - destcol;
  270.  
  271.     /*
  272.      * If we will later need a \n which will turn into a \r\n by the
  273.      * system or the terminal, then don't bother to try to \r.
  274.      */
  275.     if ((!(origtermio.c_oflag & ONLCR) || !__pfast) && outline < destline)
  276.         goto dontcr;
  277.  
  278.     /*
  279.      * If the terminal will do a \r\n and there isn't room for it, then
  280.      * we can't afford a \r.
  281.      */
  282.     if (NC && outline >= destline)
  283.         goto dontcr;
  284.  
  285.     /*
  286.      * If it will be cheaper, or if we can't back up, then send a return
  287.      * preliminarily.
  288.      */
  289.     if (j > i + 1 || outcol > destcol && !BS && !BC) {
  290.         /*
  291.          * BUG: this doesn't take the (possibly long) length of CR
  292.          * into account.
  293.          */
  294.         if (CR)
  295.             tputs(CR, 0, plodput);
  296.         else
  297.             plodput('\r');
  298.         if (NC) {
  299.             if (NL)
  300.                 tputs(NL, 0, plodput);
  301.             else
  302.                 plodput('\n');
  303.             outline++;
  304.         }
  305.         outcol = 0;
  306.     }
  307.  
  308. dontcr:    while (outline < destline) {
  309.         outline++;
  310.         if (NL)
  311.             tputs(NL, 0, plodput);
  312.         else
  313.             plodput('\n');
  314.         if (plodcnt < 0)
  315.             goto out;
  316.         if (!(origtermio.c_oflag & ONLCR) || __pfast == 0)
  317.             outcol = 0;
  318.     }
  319.     if (BT)
  320.         k = strlen(BT);
  321.     while (outcol > destcol) {
  322.         if (plodcnt < 0)
  323.             goto out;
  324. #ifdef notdef
  325.         if (BT && outcol - destcol > k + 4) {
  326.             tputs(BT, 0, plodput);
  327.             outcol--;
  328.             outcol &= ~7;
  329.             continue;
  330.         }
  331. #endif
  332.         outcol--;
  333.         if (BC)
  334.             tputs(BC, 0, plodput);
  335.         else
  336.             plodput('\b');
  337.     }
  338.     while (outline > destline) {
  339.         outline--;
  340.         tputs(UP, 0, plodput);
  341.         if (plodcnt < 0)
  342.             goto out;
  343.     }
  344.     if (GT && destcol - outcol > 1) {
  345.         for (;;) {
  346.             i = tabcol(outcol, HARDTABS);
  347.             if (i > destcol)
  348.                 break;
  349.             if (TA)
  350.                 tputs(TA, 0, plodput);
  351.             else
  352.                 plodput('\t');
  353.             outcol = i;
  354.         }
  355.         if (destcol - outcol > 4 && i < COLS && (BC || BS)) {
  356.             if (TA)
  357.                 tputs(TA, 0, plodput);
  358.             else
  359.                 plodput('\t');
  360.             outcol = i;
  361.             while (outcol > destcol) {
  362.                 outcol--;
  363.                 if (BC)
  364.                     tputs(BC, 0, plodput);
  365.                 else
  366.                     plodput('\b');
  367.             }
  368.         }
  369.     }
  370.     while (outcol < destcol) {
  371.         /*
  372.          * Move one char to the right.  We don't use ND space because
  373.          * it's better to just print the char we are moving over.
  374.          */
  375.         if (_win != NULL)
  376.             if (plodflg)    /* Avoid a complex calculation. */
  377.                 plodcnt--;
  378.             else {
  379.                 i = curscr->_y[outline][outcol];
  380.                 if ((i & _STANDOUT) ==
  381.                     (curscr->_flags & _STANDOUT))
  382.                     putchar(i & 0177);
  383.                 else
  384.                     goto nondes;
  385.             }
  386.         else
  387. nondes:            if (ND)
  388.                 tputs(ND, 0, plodput);
  389.             else
  390.                 plodput(' ');
  391.         outcol++;
  392.         if (plodcnt < 0)
  393.             goto out;
  394.     }
  395.  
  396. out:    if (plodflg) {
  397.         outcol = soutcol;
  398.         outline = soutline;
  399.     }
  400.     return (plodcnt);
  401. }
  402.  
  403. /*
  404.  * Return the column number that results from being in column col and
  405.  * hitting a tab, where tabs are set every ts columns.  Work right for
  406.  * the case where col > COLS, even if ts does not divide COLS.
  407.  */
  408. static int
  409. tabcol(col, ts)
  410.     int col, ts;
  411. {
  412.     int offset;
  413.  
  414.     if (col >= COLS) {
  415.         offset = COLS * (col / COLS);
  416.         col -= offset;
  417.     } else
  418.         offset = 0;
  419.     return (col + ts - (col % ts) + offset);
  420. }
  421.