home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / linux / old-src / xterm / scrollbar.c < prev    next >
C/C++ Source or Header  |  1991-05-21  |  14KB  |  520 lines

  1. /*
  2.  *    $XConsortium: scrollbar.c,v 1.41 91/05/22 15:20:07 gildea Exp $
  3.  */
  4.  
  5. /*
  6.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  7.  *
  8.  *                         All Rights Reserved
  9.  *
  10.  * Permission to use, copy, modify, and distribute this software and its
  11.  * documentation for any purpose and without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and that
  13.  * both that copyright notice and this permission notice appear in
  14.  * supporting documentation, and that the name of Digital Equipment
  15.  * Corporation not be used in advertising or publicity pertaining to
  16.  * distribution of the software without specific, written prior permission.
  17.  *
  18.  *
  19.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  20.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  21.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  22.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  23.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  24.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  25.  * SOFTWARE.
  26.  */
  27.  
  28. #include "ptyx.h"        /* gets Xt headers, too */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <X11/Xatom.h>
  33.  
  34. #include <X11/StringDefs.h>
  35. #include <X11/Shell.h>
  36.  
  37. #include <X11/Xaw/Scrollbar.h>
  38.  
  39. #include "data.h"
  40. #include "error.h"
  41. #include "menu.h"
  42.  
  43. /* Event handlers */
  44.  
  45. static void ScrollTextTo();
  46. static void ScrollTextUpDownBy();
  47.  
  48.  
  49. /* resize the text window for a terminal screen, modifying the
  50.  * appropriate WM_SIZE_HINTS and taking advantage of bit gravity.
  51.  */
  52.  
  53. static void ResizeScreen(xw, min_width, min_height )
  54.     register XtermWidget xw;
  55.     int min_width, min_height;
  56. {
  57.     register TScreen *screen = &xw->screen;
  58. #ifndef nothack
  59.     XSizeHints sizehints;
  60.     long supp;
  61. #endif
  62.     XtGeometryResult geomreqresult;
  63.     Dimension reqWidth, reqHeight, repWidth, repHeight;
  64.  
  65.     /*
  66.      * I'm going to try to explain, as I understand it, why we
  67.      * have to do XGetWMNormalHints and XSetWMNormalHints here,
  68.      * although I can't guarantee that I've got it right.
  69.      *
  70.      * In a correctly written toolkit program, the Shell widget
  71.      * parses the user supplied geometry argument.  However,
  72.      * because of the way xterm does things, the VT100 widget does
  73.      * the parsing of the geometry option, not the Shell widget.
  74.      * The result of this is that the Shell widget doesn't set the
  75.      * correct window manager hints, and doesn't know that the
  76.      * user has specified a geometry.
  77.      *
  78.      * The XtVaSetValues call below tells the Shell widget to
  79.      * change its hints.  However, since it's confused about the
  80.      * hints to begin with, it doesn't get them all right when it
  81.      * does the SetValues -- it undoes some of what the VT100
  82.      * widget did when it originally set the hints.
  83.      *
  84.      * To fix this, we do the following:
  85.      *
  86.      * 1. Get the sizehints directly from the window, going around
  87.      *    the (confused) shell widget.
  88.      * 2. Call XtVaSetValues to let the shell widget know which
  89.      *    hints have changed.  Note that this may not even be
  90.      *    necessary, since we're going to right ahead after that
  91.      *    and set the hints ourselves, but it's good to put it
  92.      *    here anyway, so that when we finally do fix the code so
  93.      *    that the Shell does the right thing with hints, we
  94.      *    already have the XtVaSetValues in place.
  95.      * 3. We set the sizehints directly, this fixing up whatever
  96.      *    damage was done by the Shell widget during the
  97.      *    XtVaSetValues.
  98.      *
  99.      * Gross, huh?
  100.      *
  101.      * The correct fix is to redo VTRealize, VTInitialize and
  102.      * VTSetValues so that font processing happens early enough to
  103.      * give back responsibility for the size hints to the Shell.
  104.      *
  105.      * Someday, we hope to have time to do this.  Someday, we hope
  106.      * to have time to completely rewrite xterm.
  107.      */
  108.  
  109. #ifndef nothack
  110.     /*
  111.      * NOTE: If you change the way any of the hints are calculated
  112.      * below, make sure you change the calculation both in the
  113.      * sizehints assignments and in the XtVaSetValues.
  114.      */
  115.  
  116.     if (! XGetWMNormalHints(screen->display, XtWindow(XtParent(xw)),
  117.                 &sizehints, &supp))
  118.          sizehints.flags = 0;
  119.     sizehints.base_width = min_width;
  120.     sizehints.base_height = min_height;
  121.     sizehints.width_inc = FontWidth(screen);
  122.     sizehints.height_inc = FontHeight(screen);
  123.     sizehints.min_width = sizehints.base_width + sizehints.width_inc;
  124.     sizehints.min_height = sizehints.base_height + sizehints.height_inc;
  125.     sizehints.flags |= (PBaseSize|PMinSize|PResizeInc);
  126.     /* These are obsolete, but old clients may use them */
  127.     sizehints.width = (screen->max_col + 1) * FontWidth(screen)
  128.          + min_width;
  129.     sizehints.height = (screen->max_row + 1) * FontHeight(screen)
  130.          + min_height;
  131. #endif
  132.     
  133.     /*
  134.      * Note: width and height are not set here because they are 
  135.      * obsolete.                         
  136.      */
  137.     XtVaSetValues(XtParent(xw),
  138.               XtNbaseWidth, min_width,
  139.               XtNbaseHeight, min_height,
  140.               XtNwidthInc, FontWidth(screen),
  141.               XtNheightInc, FontHeight(screen),
  142.               XtNminWidth, min_width + FontWidth(screen),
  143.               XtNminHeight, min_height + FontHeight(screen),
  144.               NULL);
  145.  
  146.     reqWidth = (screen->max_col + 1) * FontWidth(screen) + min_width;
  147.     reqHeight = FontHeight(screen) * (screen->max_row + 1) + min_height;
  148.     geomreqresult = XtMakeResizeRequest ((Widget)xw, reqWidth, reqHeight,
  149.                          &repWidth, &repHeight);
  150.  
  151.     if (geomreqresult == XtGeometryAlmost) {
  152.          geomreqresult = XtMakeResizeRequest ((Widget)xw, repWidth,
  153.                           repHeight, NULL, NULL);
  154.     }
  155.  
  156. #ifndef nothack
  157.     XSetWMNormalHints(screen->display, XtWindow(XtParent(xw)), &sizehints);
  158. #endif
  159. }
  160.  
  161. void DoResizeScreen (xw)
  162.     register XtermWidget xw;
  163. {
  164.     int border = 2 * xw->screen.border;
  165.     ResizeScreen (xw, border + xw->screen.scrollbar, border);
  166. }
  167.  
  168.  
  169. static Widget CreateScrollBar(xw, x, y, height)
  170.     XtermWidget xw;
  171.     int x, y, height;
  172. {
  173.     Widget scrollWidget;
  174.  
  175.     static Arg argList[] = {
  176.        {XtNx,        (XtArgVal) 0},
  177.        {XtNy,        (XtArgVal) 0},
  178.        {XtNheight,        (XtArgVal) 0},
  179.        {XtNreverseVideo,    (XtArgVal) 0},
  180.        {XtNorientation,    (XtArgVal) XtorientVertical},
  181.        {XtNborderWidth,    (XtArgVal) 1},
  182.     };   
  183.  
  184.     argList[0].value = (XtArgVal) x;
  185.     argList[1].value = (XtArgVal) y;
  186.     argList[2].value = (XtArgVal) height;
  187.     argList[3].value = (XtArgVal) xw->misc.re_verse;
  188.  
  189.     scrollWidget = XtCreateWidget("scrollbar", scrollbarWidgetClass, 
  190.       (Widget)xw, argList, XtNumber(argList));
  191.         XtAddCallback (scrollWidget, XtNscrollProc, ScrollTextUpDownBy, 0);
  192.         XtAddCallback (scrollWidget, XtNjumpProc, ScrollTextTo, 0);
  193.     return (scrollWidget);
  194. }
  195.  
  196. static void RealizeScrollBar (sbw, screen)
  197.     Widget sbw;
  198.     TScreen *screen;
  199. {
  200.     XtRealizeWidget (sbw);
  201. }
  202.  
  203.  
  204. ScrollBarReverseVideo(scrollWidget)
  205.     register Widget scrollWidget;
  206. {
  207.     Arg args[4];
  208.     int nargs = XtNumber(args);
  209.     unsigned long bg, fg, bdr;
  210.     Pixmap bdpix;
  211.  
  212.     XtSetArg(args[0], XtNbackground, &bg);
  213.     XtSetArg(args[1], XtNforeground, &fg);
  214.     XtSetArg(args[2], XtNborderColor, &bdr);
  215.     XtSetArg(args[3], XtNborderPixmap, &bdpix);
  216.     XtGetValues (scrollWidget, args, nargs);
  217.     args[0].value = (XtArgVal) fg;
  218.     args[1].value = (XtArgVal) bg;
  219.     nargs--;                /* don't set border_pixmap */
  220.     if (bdpix == XtUnspecifiedPixmap) {    /* if not pixmap then pixel */
  221.         args[2].value = args[1].value;    /* set border to new fg */
  222.     } else {                /* ignore since pixmap */
  223.         nargs--;                /* don't set border pixel */
  224.     }
  225.     XtSetValues (scrollWidget, args, nargs);
  226. }
  227.  
  228.  
  229.  
  230. ScrollBarDrawThumb(scrollWidget)
  231.     register Widget scrollWidget;
  232. {
  233.     register TScreen *screen = &term->screen;
  234.     register int thumbTop, thumbHeight, totalHeight;
  235.     
  236.     thumbTop    = screen->topline + screen->savedlines;
  237.     thumbHeight = screen->max_row + 1;
  238.     totalHeight = thumbHeight + screen->savedlines;
  239.  
  240.     XawScrollbarSetThumb(scrollWidget,
  241.      ((float)thumbTop) / totalHeight,
  242.      ((float)thumbHeight) / totalHeight);
  243.     
  244. }
  245.  
  246. ResizeScrollBar(scrollWidget, x, y, height)
  247.     register Widget scrollWidget;
  248.     int x, y;
  249.     unsigned height;
  250. {
  251.     XtConfigureWidget(scrollWidget, x, y, scrollWidget->core.width,
  252.         height, scrollWidget->core.border_width);
  253.     ScrollBarDrawThumb(scrollWidget);
  254. }
  255.  
  256. WindowScroll(screen, top)
  257.     register TScreen *screen;
  258.     int top;
  259. {
  260.     register int i, lines;
  261.     register int scrolltop, scrollheight, refreshtop;
  262.     register int x = 0;
  263.  
  264.     if (top < -screen->savedlines)
  265.         top = -screen->savedlines;
  266.     else if (top > 0)
  267.         top = 0;
  268.     if((i = screen->topline - top) == 0) {
  269.         ScrollBarDrawThumb(screen->scrollWidget);
  270.         return;
  271.     }
  272.  
  273.     ScrollSelection(screen, i);
  274.  
  275.     if(screen->cursor_state)
  276.         HideCursor();
  277.     lines = i > 0 ? i : -i;
  278.     if(lines > screen->max_row + 1)
  279.         lines = screen->max_row + 1;
  280.     scrollheight = screen->max_row - lines + 1;
  281.     if(i > 0)
  282.         refreshtop = scrolltop = 0;
  283.     else {
  284.         scrolltop = lines;
  285.         refreshtop = scrollheight;
  286.     }
  287.     x = screen->scrollbar +    screen->border;
  288.     scrolling_copy_area(screen, scrolltop, scrollheight, -i);
  289.     screen->topline = top;
  290.     XClearArea(
  291.         screen->display,
  292.         TextWindow(screen), 
  293.         (int) x,
  294.         (int) refreshtop * FontHeight(screen) + screen->border, 
  295.         (unsigned) Width(screen),
  296.         (unsigned) lines * FontHeight(screen),
  297.         FALSE);
  298.     ScrnRefresh(screen, refreshtop, 0, lines, screen->max_col + 1, False);
  299.  
  300.     ScrollBarDrawThumb(screen->scrollWidget);
  301. }
  302.  
  303.  
  304. ScrollBarOn (xw, init, doalloc)
  305.     XtermWidget xw;
  306.     int init, doalloc;
  307. {
  308.     register TScreen *screen = &xw->screen;
  309.     register int border = 2 * screen->border;
  310.     register int i;
  311.     Char *realloc(), *calloc();
  312.  
  313.     if(screen->scrollbar)
  314.         return;
  315.  
  316.     if (init) {            /* then create it only */
  317.         if (screen->scrollWidget) return;
  318.  
  319.         /* make it a dummy size and resize later */
  320.         if ((screen->scrollWidget = CreateScrollBar (xw, -1, - 1, 5))
  321.         == NULL) {
  322.         Bell();
  323.         return;
  324.         }
  325.  
  326.         return;
  327.  
  328.     }
  329.  
  330.     if (!screen->scrollWidget) {
  331.         Bell ();
  332.         Bell ();
  333.         return;
  334.     }
  335.  
  336.     if (doalloc && screen->allbuf) {
  337.         if((screen->allbuf =
  338.         (ScrnBuf) realloc((char *) screen->buf,
  339.                   (unsigned) 2*(screen->max_row + 2 +
  340.                         screen->savelines) *
  341.                   sizeof(char *)))
  342.            == NULL)
  343.           Error (ERROR_SBRALLOC);
  344.         screen->buf = &screen->allbuf[2 * screen->savelines];
  345.         bcopy ((char *)screen->allbuf, (char *)screen->buf,
  346.            2 * (screen->max_row + 2) * sizeof (char *));
  347.         for(i = 2 * screen->savelines - 1 ; i >= 0 ; i--)
  348.           if((screen->allbuf[i] =
  349.           calloc((unsigned) screen->max_col + 1, sizeof(char))) ==
  350.          NULL)
  351.         Error (ERROR_SBRALLOC2);
  352.     }
  353.  
  354.     ResizeScrollBar (screen->scrollWidget, -1, -1, 
  355.              Height (screen) + border);
  356.     RealizeScrollBar (screen->scrollWidget, screen);
  357.     screen->scrollbar = screen->scrollWidget->core.width +
  358.          screen->scrollWidget->core.border_width;
  359.  
  360.     ScrollBarDrawThumb(screen->scrollWidget);
  361.     DoResizeScreen (xw);
  362.     XtMapWidget(screen->scrollWidget);
  363.     update_scrollbar ();
  364.     if (screen->buf) {
  365.         XClearWindow (screen->display, XtWindow (term));
  366.         Redraw ();
  367.     }
  368. }
  369.  
  370. ScrollBarOff(screen)
  371.     register TScreen *screen;
  372. {
  373.     if(!screen->scrollbar)
  374.         return;
  375.     XtUnmapWidget(screen->scrollWidget);
  376.     screen->scrollbar = 0;
  377.     DoResizeScreen (term);
  378.     update_scrollbar ();
  379.     if (screen->buf) {
  380.         XClearWindow (screen->display, XtWindow (term));
  381.         Redraw ();
  382.     }
  383. }
  384.  
  385. /*ARGSUSED*/
  386. static void ScrollTextTo(scrollbarWidget, closure, topPercent)
  387.     Widget scrollbarWidget;
  388.     caddr_t closure;
  389.     float *topPercent;
  390. {
  391.     register TScreen *screen = &term->screen;
  392.     int thumbTop;    /* relative to first saved line */
  393.     int newTopLine;
  394.  
  395. /*
  396.    screen->savedlines : Number of offscreen text lines,
  397.    screen->maxrow + 1 : Number of onscreen  text lines,
  398.    screen->topline    : -Number of lines above the last screen->max_row+1 lines
  399. */
  400.  
  401.     thumbTop = *topPercent * (screen->savedlines + screen->max_row+1);
  402.     newTopLine = thumbTop - screen->savedlines;
  403.     WindowScroll(screen, newTopLine);
  404. }
  405.  
  406. /*ARGSUSED*/
  407. static void ScrollTextUpDownBy(scrollbarWidget, closure, pixels)
  408.     Widget scrollbarWidget;
  409.     Opaque closure;
  410.     int pixels;
  411. {
  412.     register TScreen *screen = &term->screen;
  413.     register int rowOnScreen, newTopLine;
  414.  
  415.     rowOnScreen = pixels / FontHeight(screen);
  416.     if (rowOnScreen == 0) {
  417.         if (pixels < 0)
  418.             rowOnScreen = -1;
  419.         else if (pixels > 0)
  420.             rowOnScreen = 1;
  421.     }
  422.     newTopLine = screen->topline + rowOnScreen;
  423.     WindowScroll(screen, newTopLine);
  424. }
  425.  
  426.  
  427. /*
  428.  * assume that b is lower case and allow plural
  429.  */
  430. static int specialcmplowerwiths (a, b)
  431.     char *a, *b;
  432. {
  433.     register char ca, cb;
  434.  
  435.     if (!a || !b) return 0;
  436.  
  437.     while (1) {
  438.     ca = *a;
  439.     cb = *b;
  440.     if (isascii(ca) && isupper(ca)) {        /* lowercasify */
  441. #ifdef _tolower
  442.         ca = _tolower (ca);
  443. #else
  444.         ca = tolower (ca);
  445. #endif
  446.     }
  447.     if (ca != cb || ca == '\0') break;  /* if not eq else both nul */
  448.     a++, b++;
  449.     }
  450.     if (cb == '\0' && (ca == '\0' || (ca == 's' && a[1] == '\0')))
  451.       return 1;
  452.  
  453.     return 0;
  454. }
  455.  
  456. static int params_to_pixels (screen, params, n)
  457.     TScreen *screen;
  458.     String *params;
  459.     int n;
  460. {
  461.     register mult = 1;
  462.     register char *s;
  463.  
  464.     switch (n > 2 ? 2 : n) {
  465.       case 2:
  466.     s = params[1];
  467.     if (specialcmplowerwiths (s, "page")) {
  468.         mult = (screen->max_row + 1) * FontHeight(screen);
  469.     } else if (specialcmplowerwiths (s, "halfpage")) {
  470.         mult = ((screen->max_row + 1) * FontHeight(screen)) >> 1;
  471.     } else if (specialcmplowerwiths (s, "pixel")) {
  472.         mult = 1;
  473.     } /* else assume that it is Line */
  474.     mult *= atoi (params[0]);
  475.     break;
  476.       case 1:
  477.     mult = atoi (params[0]) * FontHeight(screen);    /* lines */
  478.     break;
  479.       default:
  480.     mult = screen->scrolllines * FontHeight(screen);
  481.     break;
  482.     }
  483.  
  484.     return mult;
  485. }
  486.  
  487.  
  488. /*ARGSUSED*/
  489. void HandleScrollForward (gw, event, params, nparams)
  490.     Widget gw;
  491.     XEvent *event;
  492.     String *params;
  493.     Cardinal *nparams;
  494. {
  495.     XtermWidget w = (XtermWidget) gw;
  496.     register TScreen *screen = &w->screen;
  497.  
  498.     ScrollTextUpDownBy (gw, (Opaque) NULL,
  499.             params_to_pixels (screen, params, (int) *nparams));
  500.     return;
  501. }
  502.  
  503.  
  504. /*ARGSUSED*/
  505. void HandleScrollBack (gw, event, params, nparams)
  506.     Widget gw;
  507.     XEvent *event;
  508.     String *params;
  509.     Cardinal *nparams;
  510. {
  511.     XtermWidget w = (XtermWidget) gw;
  512.     register TScreen *screen = &w->screen;
  513.  
  514.     ScrollTextUpDownBy (gw, (Opaque) NULL,
  515.             -params_to_pixels (screen, params, (int) *nparams));
  516.     return;
  517. }
  518.  
  519.  
  520.