home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / window / wwscroll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  5.9 KB  |  235 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Edward Wang at The University of California, Berkeley.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)wwscroll.c    3.24 (Berkeley) 6/6/90";
  39. #endif /* not lint */
  40.  
  41. #include "ww.h"
  42. #include "tt.h"
  43.  
  44. wwscroll(w, n)
  45. register struct ww *w;
  46. int n;
  47. {
  48.     register dir;
  49.     register top;
  50.  
  51.     if (n == 0)
  52.         return;
  53.     dir = n < 0 ? -1 : 1;
  54.     top = w->ww_b.t - n;
  55.     if (top > w->ww_w.t)
  56.         top = w->ww_w.t;
  57.     else if (top + w->ww_b.nr < w->ww_w.b)
  58.         top = w->ww_w.b - w->ww_b.nr;
  59.     n = abs(top - w->ww_b.t);
  60.     if (n < w->ww_i.nr) {
  61.         while (--n >= 0) {
  62.             (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0);
  63.             w->ww_buf += dir;
  64.             w->ww_b.t -= dir;
  65.             w->ww_b.b -= dir;
  66.         }
  67.     } else {
  68.         w->ww_buf -= top - w->ww_b.t;
  69.         w->ww_b.t = top;
  70.         w->ww_b.b = top + w->ww_b.nr;
  71.         wwredrawwin(w);
  72.     }
  73. }
  74.  
  75. /*
  76.  * Scroll one line, between 'row1' and 'row2', in direction 'dir'.
  77.  * Don't adjust ww_scroll.
  78.  * And don't redraw 'leaveit' lines.
  79.  */
  80. wwscroll1(w, row1, row2, dir, leaveit)
  81. register struct ww *w;
  82. int row1, row2, dir;
  83. int leaveit;
  84. {
  85.     register i;
  86.     int row1x, row2x;
  87.     int nvis;
  88.     int nvismax;
  89.     int scrolled = 0;
  90.  
  91.     /*
  92.      * See how many lines on the screen are affected.
  93.      * And calculate row1x, row2x, and left at the same time.
  94.      */
  95.     for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++)
  96.         ;
  97.     if (i >= row2)            /* can't do any fancy stuff */
  98.         goto out;
  99.     row1x = i;
  100.     for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--)
  101.         ;
  102.     if (i <= row1x)
  103.         goto out;        /* just one line is easy */
  104.     row2x = i + 1;
  105.  
  106.     /*
  107.      * See how much of this window is visible.
  108.      */
  109.     nvismax = wwncol * (row2x - row1x);
  110.     nvis = 0;
  111.     for (i = row1x; i < row2x; i++)
  112.         nvis += w->ww_nvis[i];
  113.  
  114.     /*
  115.      * If it's a good idea to scroll and the terminal can, then do it.
  116.      */
  117.     if (nvis < nvismax / 2)
  118.         goto no_scroll;        /* not worth it */
  119.     if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) ||
  120.         (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) &&
  121.         tt.tt_setscroll == 0)
  122.         if (tt.tt_delline == 0 || tt.tt_insline == 0)
  123.             goto no_scroll;
  124.     xxscroll(dir, row1x, row2x);
  125.     scrolled = 1;
  126.     /*
  127.      * Fix up the old screen.
  128.      */
  129.     {
  130.         register union ww_char *tmp;
  131.         register union ww_char **cpp, **cqq;
  132.  
  133.         if (dir > 0) {
  134.             cpp = &wwos[row1x];
  135.             cqq = cpp + 1;
  136.             tmp = *cpp;
  137.             for (i = row2x - row1x; --i > 0;)
  138.                 *cpp++ = *cqq++;
  139.             *cpp = tmp;
  140.         } else {
  141.             cpp = &wwos[row2x];
  142.             cqq = cpp - 1;
  143.             tmp = *cqq;
  144.             for (i = row2x - row1x; --i > 0;)
  145.                 *--cpp = *--cqq;
  146.             *cqq = tmp;
  147.         }
  148.         for (i = wwncol; --i >= 0;)
  149.             tmp++->c_w = ' ';
  150.     }
  151.  
  152. no_scroll:
  153.     /*
  154.      * Fix the new screen.
  155.      */
  156.     if (nvis == nvismax) {
  157.         /*
  158.          * Can shift whole lines.
  159.          */
  160.         if (dir > 0) {
  161.             {
  162.                 register union ww_char *tmp;
  163.                 register union ww_char **cpp, **cqq;
  164.  
  165.                 cpp = &wwns[row1x];
  166.                 cqq = cpp + 1;
  167.                 tmp = *cpp;
  168.                 for (i = row2x - row1x; --i > 0;)
  169.                     *cpp++ = *cqq++;
  170.                 *cpp = tmp;
  171.             }
  172.             if (scrolled) {
  173.                 register char *p, *q;
  174.  
  175.                 p = &wwtouched[row1x];
  176.                 q = p + 1;
  177.                 for (i = row2x - row1x; --i > 0;)
  178.                     *p++ = *q++;
  179.                 *p |= WWU_TOUCHED;
  180.             } else {
  181.                 register char *p;
  182.  
  183.                 p = &wwtouched[row1x];
  184.                 for (i = row2x - row1x; --i >= 0;)
  185.                     *p++ |= WWU_TOUCHED;
  186.             }
  187.             wwredrawwin1(w, row1, row1x, dir);
  188.             wwredrawwin1(w, row2x - 1, row2 - leaveit, dir);
  189.         } else {
  190.             {
  191.                 register union ww_char *tmp;
  192.                 register union ww_char **cpp, **cqq;
  193.  
  194.                 cpp = &wwns[row2x];
  195.                 cqq = cpp - 1;
  196.                 tmp = *cqq;
  197.                 for (i = row2x - row1x; --i > 0;)
  198.                     *--cpp = *--cqq;
  199.                 *cqq = tmp;
  200.             }
  201.             if (scrolled) {
  202.                 register char *p, *q;
  203.  
  204.                 p = &wwtouched[row2x];
  205.                 q = p - 1;
  206.                 for (i = row2x - row1x; --i > 0;)
  207.                     *--p = *--q;
  208.                 *q |= WWU_TOUCHED;
  209.             } else {
  210.                 register char *p;
  211.  
  212.                 p = &wwtouched[row1x];
  213.                 for (i = row2x - row1x; --i >= 0;)
  214.                     *p++ |= WWU_TOUCHED;
  215.             }
  216.             wwredrawwin1(w, row1 + leaveit, row1x + 1, dir);
  217.             wwredrawwin1(w, row2x, row2, dir);
  218.         }
  219.     } else {
  220.         if (scrolled) {
  221.             register char *p;
  222.  
  223.             p = &wwtouched[row1x];
  224.             for (i = row2x - row1x; --i >= 0;)
  225.                 *p++ |= WWU_TOUCHED;
  226.         }
  227. out:
  228.         if (dir > 0)
  229.             wwredrawwin1(w, row1, row2 - leaveit, dir);
  230.         else
  231.             wwredrawwin1(w, row1 + leaveit, row2, dir);
  232.     }
  233.     return scrolled;
  234. }
  235.