home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / curses / cr_put.c < prev    next >
C/C++ Source or Header  |  1996-02-25  |  10KB  |  433 lines

  1. /*
  2.  * Copyright (c) 1981, 1993, 1994
  3.  *    The Regents of the University of California.  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    8.3 (Berkeley) 5/4/94";
  36. #endif    /* not lint */
  37.  
  38. #include <string.h>
  39.  
  40. #include "curses.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. /* Stub function for the users. */
  51. int
  52. mvcur(ly, lx, y, x)
  53.     int ly, lx, y, x;
  54. {
  55.     return (__mvcur(ly, lx, y, x, 0));
  56. }
  57.  
  58. static void    fgoto();
  59. static int    plod();
  60. static void    plodput();
  61. static int    tabcol();
  62.  
  63. static int outcol, outline, destcol, destline;
  64.  
  65. /*
  66.  * Sync the position of the output cursor.  Most work here is rounding for
  67.  * terminal boundaries getting the column position implied by wraparound or
  68.  * the lack thereof and rolling up the screen to get destline on the screen.
  69.  */
  70. int
  71. __mvcur(ly, lx, y, x, in_refresh)
  72.     int ly, lx, y, x, in_refresh;
  73. {
  74. #ifdef CURSES_DEBUG
  75.     __CTRACE("mvcur: moving cursor from (%d, %d) to (%d, %d)\n",
  76.         ly, lx, y, x);
  77. #endif
  78.     destcol = x;
  79.     destline = y;
  80.     outcol = lx;
  81.     outline = ly;
  82.     fgoto(in_refresh);
  83.     return (OK);
  84. }    
  85.         
  86. static void
  87. fgoto(in_refresh)
  88.     int in_refresh;
  89. {
  90.     register int c, l;
  91.     register char *cgp;
  92.  
  93.     if (destcol >= COLS) {
  94.         destline += destcol / COLS;
  95.         destcol %= COLS;
  96.     }
  97.     if (outcol >= COLS) {
  98.         l = (outcol + 1) / COLS;
  99.         outline += l;
  100.         outcol %= COLS;
  101.         if (AM == 0) {
  102.             while (l > 0) {
  103.                 if (__pfast)
  104.                     if (CR)
  105.                         tputs(CR, 0, __cputchar);
  106.                     else
  107.                         putchar('\r');
  108.                 if (NL)
  109.                     tputs(NL, 0, __cputchar);
  110.                 else
  111.                     putchar('\n');
  112.                 l--;
  113.             }
  114.             outcol = 0;
  115.         }
  116.         if (outline > LINES - 1) {
  117.             destline -= outline - (LINES - 1);
  118.             outline = LINES - 1;
  119.         }
  120.     }
  121.     if (destline >= LINES) {
  122.         l = destline;
  123.         destline = LINES - 1;
  124.         if (outline < LINES - 1) {
  125.             c = destcol;
  126.             if (__pfast == 0 && !CA)
  127.                 destcol = 0;
  128.             fgoto(in_refresh);
  129.             destcol = c;
  130.         }
  131.         while (l >= LINES) {
  132.             /* The following linefeed (or simulation thereof) is
  133.              * supposed to scroll up the screen, since we are on
  134.              * the bottom line.  We make the assumption that
  135.              * linefeed will scroll.  If ns is in the capability
  136.              * list this won't work.  We should probably have an
  137.              * sc capability but sf will generally take the place
  138.              * if it works.
  139.              * 
  140.              * Superbee glitch: in the middle of the screen have
  141.              * to use esc B (down) because linefeed screws up in
  142.              * "Efficient Paging" (what a joke) mode (which is
  143.              * essential in some SB's because CRLF mode puts
  144.              * garbage in at end of memory), but you must use
  145.              * linefeed to scroll since down arrow won't go past
  146.              * memory end. I turned this off after recieving Paul
  147.              * Eggert's Superbee description which wins better.
  148.              */
  149.             if (NL /* && !XB */ && __pfast)
  150.                 tputs(NL, 0, __cputchar);
  151.             else
  152.                 putchar('\n');
  153.             l--;
  154.             if (__pfast == 0)
  155.                 outcol = 0;
  156.         }
  157.     }
  158.     if (destline < outline && !(CA || UP))
  159.         destline = outline;
  160.     if (CA) {
  161.         cgp = tgoto(CM, destcol, destline);
  162.  
  163.         /*
  164.          * Need this condition due to inconsistent behavior
  165.          * of backspace on the last column.
  166.          */
  167.         if (outcol != COLS - 1 && plod(strlen(cgp), in_refresh) > 0)
  168.             plod(0, in_refresh);
  169.         else 
  170.             tputs(cgp, 0, __cputchar);
  171.     } else
  172.         plod(0, in_refresh);
  173.     outline = destline;
  174.     outcol = destcol;
  175. }
  176. /*
  177.  * Move (slowly) to destination.
  178.  * Hard thing here is using home cursor on really deficient terminals.
  179.  * Otherwise just use cursor motions, hacking use of tabs and overtabbing
  180.  * and backspace.
  181.  */
  182.  
  183. static int plodcnt, plodflg;
  184.  
  185. static void
  186. plodput(c)
  187.     int c;
  188. {
  189.     if (plodflg)
  190.         --plodcnt;
  191.     else
  192.         putchar(c);
  193. }
  194.  
  195. static int
  196. plod(cnt, in_refresh)
  197.     int cnt, in_refresh;
  198. {
  199.     register int i, j, k, soutcol, soutline;
  200.  
  201.     plodcnt = plodflg = cnt;
  202.     soutcol = outcol;
  203.     soutline = outline;
  204.     /*
  205.      * Consider homing and moving down/right from there, vs. moving
  206.      * directly with local motions to the right spot.
  207.      */
  208.     if (HO) {
  209.         /*
  210.          * i is the cost to home and tab/space to the right to get to
  211.          * the proper column.  This assumes ND space costs 1 char.  So
  212.          * i + destcol is cost of motion with home.
  213.          */
  214.         if (GT)
  215.             i = (destcol / HARDTABS) + (destcol % HARDTABS);
  216.         else
  217.             i = destcol;
  218.  
  219.         /* j is cost to move locally without homing. */
  220.         if (destcol >= outcol) {    /* if motion is to the right */
  221.             j = destcol / HARDTABS - outcol / HARDTABS;
  222.             if (GT && j)
  223.                 j += destcol % HARDTABS;
  224.             else
  225.                 j = destcol - outcol;
  226.         } else
  227.             /* leftward motion only works if we can backspace. */
  228.             if (outcol - destcol <= i && (BS || BC))
  229.                 /* Cheaper to backspace. */
  230.                 i = j = outcol - destcol;
  231.             else
  232.                 /* Impossibly expensive. */
  233.                 j = i + 1;
  234.  
  235.         /* k is the absolute value of vertical distance. */
  236.         k = outline - destline;
  237.         if (k < 0)
  238.             k = -k;
  239.         j += k;
  240.  
  241.         /* Decision.  We may not have a choice if no UP. */
  242.         if (i + destline < j || (!UP && destline < outline)) {
  243.             /*
  244.              * Cheaper to home.  Do it now and pretend it's a
  245.              * regular local motion.
  246.              */
  247.             tputs(HO, 0, plodput);
  248.             outcol = outline = 0;
  249.         } else if (LL) {
  250.             /*
  251.              * Quickly consider homing down and moving from there.
  252.              * Assume cost of LL is 2.
  253.              */
  254.             k = (LINES - 1) - destline;
  255.             if (i + k + 2 < j && (k <= 0 || UP)) {
  256.                 tputs(LL, 0, plodput);
  257.                 outcol = 0;
  258.                 outline = LINES - 1;
  259.             }
  260.         }
  261.     } else
  262.         /* No home and no up means it's impossible. */
  263.         if (!UP && destline < outline)
  264.             return (-1);
  265.     if (GT)
  266.         i = destcol % HARDTABS + destcol / HARDTABS;
  267.     else
  268.         i = destcol;
  269. #ifdef notdef
  270.     if (BT && outcol > destcol &&
  271.         (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
  272.         j *= (k = strlen(BT));
  273.         if ((k += (destcol&7)) > 4)
  274.             j += 8 - (destcol&7);
  275.         else
  276.             j += k;
  277.     }
  278.     else
  279. #endif
  280.         j = outcol - destcol;
  281.  
  282.     /*
  283.      * If we will later need a \n which will turn into a \r\n by the
  284.      * system or the terminal, then don't bother to try to \r.
  285.      */
  286.     if ((NONL || !__pfast) && outline < destline)
  287.         goto dontcr;
  288.  
  289.     /*
  290.      * If the terminal will do a \r\n and there isn't room for it, then
  291.      * we can't afford a \r.
  292.      */
  293.     if (NC && outline >= destline)
  294.         goto dontcr;
  295.  
  296.     /*
  297.      * If it will be cheaper, or if we can't back up, then send a return
  298.      * preliminarily.
  299.      */
  300.     if (j > i + 1 || outcol > destcol && !BS && !BC) {
  301.         /*
  302.          * BUG: this doesn't take the (possibly long) length of CR
  303.          * into account.
  304.          */
  305.         if (CR)
  306.             tputs(CR, 0, plodput);
  307.         else
  308.             plodput('\r');
  309.         if (NC) {
  310.             if (NL)
  311.                 tputs(NL, 0, plodput);
  312.             else
  313.                 plodput('\n');
  314.             outline++;
  315.         }
  316.         outcol = 0;
  317.     }
  318.  
  319. dontcr:    while (outline < destline) {
  320.         outline++;
  321.         if (NL)
  322.             tputs(NL, 0, plodput);
  323.         else
  324.             plodput('\n');
  325.         if (plodcnt < 0)
  326.             goto out;
  327.         if (NONL || __pfast == 0)
  328.             outcol = 0;
  329.     }
  330.     if (BT)
  331.         k = strlen(BT);
  332.     while (outcol > destcol) {
  333.         if (plodcnt < 0)
  334.             goto out;
  335. #ifdef notdef
  336.         if (BT && outcol - destcol > k + 4) {
  337.             tputs(BT, 0, plodput);
  338.             outcol--;
  339.             outcol &= ~7;
  340.             continue;
  341.         }
  342. #endif
  343.         outcol--;
  344.         if (BC)
  345.             tputs(BC, 0, plodput);
  346.         else
  347.             plodput('\b');
  348.     }
  349.     while (outline > destline) {
  350.         outline--;
  351.         tputs(UP, 0, plodput);
  352.         if (plodcnt < 0)
  353.             goto out;
  354.     }
  355.     if (GT && destcol - outcol > 1) {
  356.         for (;;) {
  357.             i = tabcol(outcol, HARDTABS);
  358.             if (i > destcol)
  359.                 break;
  360.             if (TA)
  361.                 tputs(TA, 0, plodput);
  362.             else
  363.                 plodput('\t');
  364.             outcol = i;
  365.         }
  366.         if (destcol - outcol > 4 && i < COLS && (BC || BS)) {
  367.             if (TA)
  368.                 tputs(TA, 0, plodput);
  369.             else
  370.                 plodput('\t');
  371.             outcol = i;
  372.             while (outcol > destcol) {
  373.                 outcol--;
  374.                 if (BC)
  375.                     tputs(BC, 0, plodput);
  376.                 else
  377.                     plodput('\b');
  378.             }
  379.         }
  380.     }
  381.     while (outcol < destcol) {
  382.         /*
  383.          * Move one char to the right.  We don't use ND space because
  384.          * it's better to just print the char we are moving over.
  385.          */
  386.         if (in_refresh)
  387.             if (plodflg)    /* Avoid a complex calculation. */
  388.                 plodcnt--;
  389.             else {
  390.                 i = curscr->lines[outline]->line[outcol].ch;
  391.                 if ((curscr->lines[outline]->line[outcol].attr
  392.                      & __STANDOUT) ==
  393.                     (curscr->flags & __WSTANDOUT))
  394.                     putchar(i);
  395.                 else
  396.                     goto nondes;
  397.             }
  398.         else
  399. nondes:            if (ND)
  400.                 tputs(ND, 0, plodput);
  401.             else
  402.                 plodput(' ');
  403.         outcol++;
  404.         if (plodcnt < 0)
  405.             goto out;
  406.     }
  407.  
  408. out:    if (plodflg) {
  409.         outcol = soutcol;
  410.         outline = soutline;
  411.     }
  412.     return (plodcnt);
  413. }
  414.  
  415. /*
  416.  * Return the column number that results from being in column col and
  417.  * hitting a tab, where tabs are set every ts columns.  Work right for
  418.  * the case where col > COLS, even if ts does not divide COLS.
  419.  */
  420. static int
  421. tabcol(col, ts)
  422.     int col, ts;
  423. {
  424.     int offset;
  425.  
  426.     if (col >= COLS) {
  427.         offset = COLS * (col / COLS);
  428.         col -= offset;
  429.     } else
  430.         offset = 0;
  431.     return (col + ts - (col % ts) + offset);
  432. }
  433.