home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / mxterm.zip / mxterm / scrollbar.c < prev    next >
C/C++ Source or Header  |  1992-10-18  |  16KB  |  600 lines

  1. /*
  2.  *    $XConsortium: scrollbar.c,v 1.32 89/12/15 11:45:51 kit Exp $
  3.  */
  4.  
  5. #include <X11/copyright.h>
  6.  
  7. /*
  8.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  9.  *
  10.  *                         All Rights Reserved
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose and without fee is hereby granted,
  14.  * provided that the above copyright notice appear in all copies and that
  15.  * both that copyright notice and this permission notice appear in
  16.  * supporting documentation, and that the name of Digital Equipment
  17.  * Corporation not be used in advertising or publicity pertaining to
  18.  * distribution of the software without specific, written prior permission.
  19.  *
  20.  *
  21.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  22.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  23.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  24.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  25.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  26.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  27.  * SOFTWARE.
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <setjmp.h>
  33. #include <X11/Xatom.h>
  34.  
  35. #include "ptyx.h"        /* X headers included here. */
  36.  
  37. #include <X11/StringDefs.h>
  38. #include <X11/Shell.h>
  39.  
  40. #ifdef MOTIF
  41. #include <X11/cursorfont.h>
  42. #include <Xm/ScrollBar.h>
  43. #else
  44. #include <X11/Xaw/Scrollbar.h>
  45. #endif /* MOTIF */
  46.  
  47. #include "data.h"
  48. #include "error.h"
  49. #include "menu.h"
  50.  
  51. extern void bcopy();
  52.  
  53. #ifndef lint
  54. static char rcs_id[] = "$XConsortium: scrollbar.c,v 1.32 89/12/15 11:45:51 kit Exp $";
  55. #endif    /* lint */
  56.  
  57. /* Event handlers */
  58.  
  59. static void ScrollTextTo();
  60. static void ScrollTextUpDownBy();
  61.  
  62. static Bool IsEventType( display, event, type )
  63.     Display *display;
  64.     XEvent *event;
  65.     int type;
  66. {
  67.     return (event->type == type);
  68. }
  69.  
  70.  
  71. /* resize the text window for a terminal screen, modifying the
  72.  * appropriate WM_SIZE_HINTS and taking advantage of bit gravity.
  73.  */
  74.  
  75. static void ResizeScreen(xw, min_width, min_height )
  76.     register XtermWidget xw;
  77.     int min_width, min_height;
  78. {
  79.     register TScreen *screen = &xw->screen;
  80.     XSizeHints sizehints;
  81.     XSetWindowAttributes newAttributes;
  82.     XWindowAttributes oldAttributes;
  83.     XEvent event;
  84.     XtGeometryResult geomreqresult;
  85.     Dimension oldWidth, oldHeight;
  86.     Dimension reqWidth, reqHeight, repWidth, repHeight;
  87.     static Arg argList[] = {
  88.         {XtNminWidth,    0},
  89.         {XtNminHeight,    0},
  90.         /* %%% the next two should move to VTInitialize, VTSetValues */
  91.         {XtNwidthInc,    0},
  92.         {XtNheightInc,    0}
  93.     };
  94.  
  95. #ifndef nothack
  96.     long supp;
  97.  
  98.     /* %%% gross hack caused by our late processing of geometry
  99.        (in VTRealize) and setting of size hints there, leaving
  100.        Shell with insufficient information to do the job properly here.
  101.        Instead of doing it properly, we save and restore the
  102.        size hints around Shell.SetValues and Shell.GeometryManager
  103.      */
  104.     if (!XGetWMNormalHints (screen->display, XtWindow(XtParent(xw)),
  105.                 &sizehints, &supp))
  106.         sizehints.flags = 0;
  107.     sizehints.base_width = min_width;
  108.     sizehints.base_height = min_height;
  109.     sizehints.width_inc = FontWidth(screen);
  110.     sizehints.height_inc = FontHeight(screen);
  111.     sizehints.min_width = sizehints.base_width + sizehints.width_inc;
  112.     sizehints.min_height = sizehints.base_height + sizehints.height_inc;
  113.     sizehints.width =  (screen->max_col + 1) * FontWidth(screen)
  114.                 + min_width;
  115.     sizehints.height = FontHeight(screen) * (screen->max_row + 1)
  116.                 + min_height;
  117.     sizehints.flags |= (PBaseSize|PMinSize|PResizeInc);
  118. #endif
  119.  
  120.     argList[0].value = (XtArgVal)min_width;
  121.     argList[1].value = (XtArgVal)min_height;
  122.     argList[2].value = (XtArgVal)FontWidth(screen);
  123.     argList[3].value = (XtArgVal)FontHeight(screen);
  124.     XtSetValues( XtParent(xw), argList, XtNumber(argList) );
  125.  
  126.     XGetWindowAttributes( screen->display, TextWindow(screen),
  127.                   &oldAttributes );
  128.  
  129.     newAttributes.event_mask =
  130.         oldAttributes.your_event_mask | StructureNotifyMask;
  131.     newAttributes.bit_gravity = EastGravity;
  132.  
  133.         /* The following statement assumes scrollbar is on Left! 
  134.            If we ever have scrollbars on the right, then the
  135.            bit-gravity should be left alone, NOT changed to EastGravity. */
  136.     XChangeWindowAttributes( screen->display, TextWindow(screen),
  137.          CWEventMask|CWBitGravity, &newAttributes );
  138.  
  139.     oldWidth = xw->core.width;
  140.     oldHeight = xw->core.height;
  141.     reqWidth = (screen->max_col + 1) * FontWidth(screen) + min_width;
  142.     reqHeight = FontHeight(screen) * (screen->max_row + 1) + min_height;
  143.     geomreqresult = XtMakeResizeRequest ((Widget)xw, reqWidth, reqHeight,
  144.                          &repWidth, &repHeight);
  145.  
  146. #ifndef nothack
  147.     XSetWMNormalHints(screen->display, XtWindow(XtParent(xw)), &sizehints);
  148. #endif
  149.  
  150.     if (oldWidth != reqWidth || oldHeight != reqHeight) {
  151.         /* wait for a window manager to actually do it */
  152.         XIfEvent (screen->display, &event, IsEventType, (char *)ConfigureNotify);
  153.     }
  154.  
  155.     newAttributes.event_mask = oldAttributes.your_event_mask;
  156.     newAttributes.bit_gravity = NorthWestGravity;
  157.     XChangeWindowAttributes( screen->display, TextWindow(screen),
  158.                  CWEventMask|CWBitGravity,
  159.                  &newAttributes );
  160.  
  161. /*
  162. ** Cwikla -- nobrainer hack to make the screen update correctly.
  163. */
  164.   XClearArea(screen->display, TextWindow(screen), 0, 0, reqWidth, reqHeight, TRUE);
  165. }
  166.  
  167. void DoResizeScreen (xw)
  168.     register XtermWidget xw;
  169. {
  170.     int border = 2 * xw->screen.border;
  171.     int sb = (xw->screen.scrollbar ? xw->screen.scrollWidget->core.width 
  172.       + 2 * xw->screen.scrollWidget->core.border_width : 0);
  173.  
  174.     ResizeScreen (xw, border + sb, border);
  175. }
  176.  
  177.  
  178. static Widget CreateScrollBar(xw, x, y, height)
  179.     XtermWidget xw;
  180.     int x, y, height;
  181. {
  182.     Widget scrollWidget;
  183. #ifdef MOTIF
  184.     static Arg argList[] = {
  185.        {XmNx,        (XtArgVal) 0},
  186.        {XmNy,        (XtArgVal) 0},
  187.        {XmNheight,        (XtArgVal) 0},
  188.        /* motif widget doesn't have reverse video garbage */
  189.        {XmNorientation,    (XtArgVal) XmVERTICAL},
  190.        {XmNborderWidth,    (XtArgVal) 1},
  191.     };   
  192.  
  193.     argList[0].value = (XtArgVal) x;
  194.     argList[1].value = (XtArgVal) y;
  195.     argList[2].value = (XtArgVal) height;
  196.  
  197.     scrollWidget = XtCreateWidget("scrollbar", xmScrollBarWidgetClass, 
  198.       (Widget) xw, argList, XtNumber(argList));
  199.         XtAddCallback (scrollWidget, XmNvalueChangedCallback, ScrollTextTo, 0);
  200.         XtAddCallback (scrollWidget, XmNdragCallback, ScrollTextTo, 0);
  201. #else
  202.     static Arg argList[] = {
  203.        {XtNx,        (XtArgVal) 0},
  204.        {XtNy,        (XtArgVal) 0},
  205.        {XtNheight,        (XtArgVal) 0},
  206.        {XtNreverseVideo,    (XtArgVal) 0},
  207.        {XtNorientation,    (XtArgVal) XtorientVertical},
  208.        {XtNborderWidth,    (XtArgVal) 1},
  209.     };   
  210.  
  211.     argList[0].value = (XtArgVal) x;
  212.     argList[1].value = (XtArgVal) y;
  213.     argList[2].value = (XtArgVal) height;
  214.     argList[3].value = (XtArgVal) xw->misc.re_verse;
  215.  
  216.     scrollWidget = XtCreateWidget("scrollbar", scrollbarWidgetClass, 
  217.       xw, argList, XtNumber(argList));
  218.         XtAddCallback (scrollWidget, XtNscrollProc, ScrollTextUpDownBy, 0);
  219.         XtAddCallback (scrollWidget, XtNjumpProc, ScrollTextTo, 0);
  220. #endif /* MOTIF */
  221.     
  222.     return (scrollWidget);
  223. }
  224.  
  225. static void RealizeScrollBar (sbw, screen)
  226.     Widget sbw;
  227.     TScreen *screen;
  228. {
  229. #ifdef MOTIF
  230.     Cursor arrowCursor;
  231.  
  232.         XtRealizeWidget (sbw);
  233.  
  234.     /* define pointer cursor for it */
  235.     arrowCursor = XCreateFontCursor(XtDisplay(sbw), XC_left_ptr);
  236.     XDefineCursor(XtDisplay(sbw), XtWindow(sbw), arrowCursor);
  237.     XFreeCursor(XtDisplay(sbw), arrowCursor);
  238. #else
  239.         XtRealizeWidget (sbw);
  240. #endif /* MOTIF */
  241. }
  242.  
  243.  
  244. ScrollBarReverseVideo(scrollWidget)
  245.     register Widget scrollWidget;
  246. {
  247. #ifndef MOTIF    
  248.     Arg args[4];
  249.     int nargs = XtNumber(args);
  250.     unsigned long bg, fg, bdr;
  251.     Pixmap bdpix;
  252.  
  253.     XtSetArg(args[0], XtNbackground, &bg);
  254.     XtSetArg(args[1], XtNforeground, &fg);
  255.     XtSetArg(args[2], XtNborderColor, &bdr);
  256.     XtSetArg(args[3], XtNborderPixmap, &bdpix);
  257.     XtGetValues (scrollWidget, args, nargs);
  258.     args[0].value = (XtArgVal) fg;
  259.     args[1].value = (XtArgVal) bg;
  260.     nargs--;                /* don't set border_pixmap */
  261.     if (bdpix == XtUnspecifiedPixmap) {    /* if not pixmap then pixel */
  262.         args[2].value = args[1].value;    /* set border to new fg */
  263.     } else {                /* ignore since pixmap */
  264.         nargs--;                /* don't set border pixel */
  265.     }
  266.     XtSetValues (scrollWidget, args, nargs);
  267. #endif /* MOTIF */    
  268. }
  269.  
  270.  
  271.  
  272. ScrollBarDrawThumb(scrollWidget)
  273.     register Widget scrollWidget;
  274. {
  275.     register TScreen *screen = &term->screen;
  276.     register int thumbTop, thumbHeight, totalHeight;
  277.     
  278.     thumbTop    = screen->topline + screen->savedlines;
  279.     thumbHeight = screen->max_row + 1;
  280.     totalHeight = thumbHeight + screen->savedlines;
  281. #ifdef MOTIF
  282.     {
  283.         register Arg wargs[4];
  284.         register int n = 0;
  285.         XtSetArg(wargs[n], XmNmaximum, totalHeight); n++; 
  286.         XtSetArg(wargs[n], XmNsliderSize, thumbHeight); n++;
  287.         XtSetArg(wargs[n], XmNvalue, thumbTop); n++;
  288.         XtSetArg(wargs[n], XmNpageIncrement, thumbHeight); n++;
  289.         XtSetValues(scrollWidget, wargs, n);
  290.     }
  291. #else
  292.     XawScrollbarSetThumb(scrollWidget,
  293.      ((float)thumbTop) / totalHeight,
  294.      ((float)thumbHeight) / totalHeight);
  295. #endif /* MOTIF */    
  296. }
  297.  
  298. ResizeScrollBar(scrollWidget, x, y, height)
  299.     register Widget scrollWidget;
  300.     int x, y;
  301.     unsigned height;
  302. {
  303.     XtConfigureWidget(scrollWidget, x, y, scrollWidget->core.width,
  304.         height, scrollWidget->core.border_width);
  305.     ScrollBarDrawThumb(scrollWidget);
  306. }
  307.  
  308. WindowScroll(screen, top)
  309.     register TScreen *screen;
  310.     int top;
  311. {
  312.     register int i, lines;
  313.     register int scrolltop, scrollheight, refreshtop;
  314.     register int x = 0;
  315.  
  316.     if (top < -screen->savedlines)
  317.         top = -screen->savedlines;
  318.     else if (top > 0)
  319.         top = 0;
  320.     if((i = screen->topline - top) == 0) {
  321.         ScrollBarDrawThumb(screen->scrollWidget);
  322.         return;
  323.     }
  324.  
  325.     ScrollSelection(screen, i);
  326.  
  327.     if(screen->cursor_state)
  328.         HideCursor();
  329.     lines = i > 0 ? i : -i;
  330.     if(lines > screen->max_row + 1)
  331.         lines = screen->max_row + 1;
  332.     scrollheight = screen->max_row - lines + 1;
  333.     if(i > 0)
  334.         refreshtop = scrolltop = 0;
  335.     else {
  336.         scrolltop = lines;
  337.         refreshtop = scrollheight;
  338.     }
  339.     x = screen->scrollbar +    screen->border;
  340.     if(scrollheight > 0) {
  341.         if (screen->multiscroll && scrollheight == 1 &&
  342.          screen->topline == 0 && screen->top_marg == 0 &&
  343.          screen->bot_marg == screen->max_row) {
  344.             if (screen->incopy < 0 && screen->scrolls == 0)
  345.                 CopyWait (screen);
  346.             screen->scrolls++;
  347.         } else {
  348.             if (screen->incopy)
  349.                 CopyWait (screen);
  350.             screen->incopy = -1;
  351.         }
  352.         XCopyArea(
  353.             screen->display, 
  354.             TextWindow(screen), TextWindow(screen),
  355.             screen->normalGC,
  356.             (int) x,
  357.             (int) scrolltop * FontHeight(screen) + screen->border, 
  358.             (unsigned) Width(screen),
  359.             (unsigned) scrollheight * FontHeight(screen),
  360.             (int) x,
  361.             (int) (scrolltop + i) * FontHeight(screen)
  362.             + screen->border);
  363.     }
  364.     screen->topline = top;
  365.     XClearArea(
  366.         screen->display,
  367.         TextWindow(screen), 
  368.         (int) x,
  369.         (int) refreshtop * FontHeight(screen) + screen->border, 
  370.         (unsigned) Width(screen),
  371.         (unsigned) lines * FontHeight(screen),
  372.         FALSE);
  373.     ScrnRefresh(screen, refreshtop, 0, lines, screen->max_col + 1, False);
  374.  
  375.     ScrollBarDrawThumb(screen->scrollWidget);
  376. }
  377.  
  378.  
  379. ScrollBarOn (xw, init, doalloc)
  380.     XtermWidget xw;
  381.     int init, doalloc;
  382. {
  383.     register TScreen *screen = &xw->screen;
  384.     register int border = 2 * screen->border;
  385.     register int i;
  386.     Char *realloc(), *calloc();
  387.  
  388.     if(screen->scrollbar)
  389.         return;
  390.  
  391.     if (init) {            /* then create it only */
  392.         if (screen->scrollWidget) return;
  393.  
  394.         /* make it a dummy size and resize later */
  395.         if ((screen->scrollWidget = CreateScrollBar (xw, -1, - 1, 5))
  396.         == NULL) {
  397.         Bell();
  398.         return;
  399.         }
  400.  
  401.         return;
  402.  
  403.     }
  404.  
  405.     if (!screen->scrollWidget) {
  406.         Bell ();
  407.         Bell ();
  408.         return;
  409.     }
  410.  
  411.     if (doalloc && screen->allbuf) {
  412.         if((screen->allbuf =
  413.         (ScrnBuf) realloc((char *) screen->buf,
  414.                   (unsigned) 2*(screen->max_row + 2 +
  415.                         screen->savelines) *
  416.                   sizeof(char *)))
  417.            == NULL)
  418.           Error (ERROR_SBRALLOC);
  419.         screen->buf = &screen->allbuf[2 * screen->savelines];
  420.         bcopy ((char *)screen->allbuf, (char *)screen->buf,
  421.            2 * (screen->max_row + 2) * sizeof (char *));
  422.         for(i = 2 * screen->savelines - 1 ; i >= 0 ; i--)
  423.           if((screen->allbuf[i] =
  424.           calloc((unsigned) screen->max_col + 1, sizeof(char))) ==
  425.          NULL)
  426.         Error (ERROR_SBRALLOC2);
  427.     }
  428.  
  429.     ResizeScrollBar (screen->scrollWidget, -1, -1, 
  430.              Height (screen) + border);
  431.     RealizeScrollBar (screen->scrollWidget, screen);
  432.     screen->scrollbar = screen->scrollWidget->core.width + 2 * screen->scrollWidget->core.border_width;
  433.  
  434.     ScrollBarDrawThumb(screen->scrollWidget);
  435.     /* map afterwards so BitGravity can be used profitably */
  436.     XMapWindow(screen->display, XtWindow(screen->scrollWidget));
  437.     update_scrollbar ();
  438.  
  439.   DoResizeScreen(xw);
  440. }
  441.  
  442. ScrollBarOff(screen)
  443.     register TScreen *screen;
  444. {
  445.     if(!screen->scrollbar)
  446.         return;
  447.     screen->scrollbar = 0;
  448.     XUnmapWindow(screen->display, XtWindow(screen->scrollWidget));
  449.     DoResizeScreen (term);
  450.     update_scrollbar ();
  451. }
  452.  
  453. #ifdef MOTIF
  454. /*ARGSUSED*/
  455. static void ScrollTextTo(scrollbarWidget, closure, call_data)
  456.     Widget scrollbarWidget;
  457.     caddr_t closure;
  458.     XmScrollBarCallbackStruct *call_data;
  459. #else
  460. /*ARGSUSED*/
  461. static void ScrollTextTo(scrollbarWidget, closure, topPercent)
  462.     Widget scrollbarWidget;
  463.     caddr_t closure;
  464.     float *topPercent;
  465. #endif /* MOTIF */
  466. {
  467.     register TScreen *screen = &term->screen;
  468.     int thumbTop;    /* relative to first saved line */
  469.     int newTopLine;
  470.  
  471. /*
  472.    screen->savedlines : Number of offscreen text lines,
  473.    screen->maxrow + 1 : Number of onscreen  text lines,
  474.    screen->topline    : -Number of lines above the last screen->max_row+1 lines
  475. */
  476.  
  477. #ifdef MOTIF
  478.     thumbTop = call_data->value;
  479. #else    
  480.     thumbTop = *topPercent * (screen->savedlines + screen->max_row+1);
  481. #endif /* MOTIF */    
  482.     newTopLine = thumbTop - screen->savedlines;
  483.     WindowScroll(screen, newTopLine);
  484. }
  485.  
  486. /*ARGSUSED*/
  487. static void ScrollTextUpDownBy(scrollbarWidget, closure, pixels)
  488.     Widget scrollbarWidget;
  489.     Opaque closure;
  490.     int pixels;
  491. {
  492.     register TScreen *screen = &term->screen;
  493.     register int rowOnScreen, newTopLine;
  494.  
  495.     rowOnScreen = pixels / FontHeight(screen);
  496.     if (rowOnScreen == 0) {
  497.         if (pixels < 0)
  498.             rowOnScreen = -1;
  499.         else if (pixels > 0)
  500.             rowOnScreen = 1;
  501.     }
  502.     newTopLine = screen->topline + rowOnScreen;
  503.     WindowScroll(screen, newTopLine);
  504. }
  505.  
  506.  
  507. /*
  508.  * assume that b is lower case and allow plural
  509.  */
  510. static int specialcmplowerwiths (a, b)
  511.     char *a, *b;
  512. {
  513.     register char ca, cb;
  514.  
  515.     if (!a || !b) return 0;
  516.  
  517.     while (1) {
  518.     ca = *a;
  519.     cb = *b;
  520.     if (isascii(ca) && isupper(ca)) {        /* lowercasify */
  521. #ifdef _tolower
  522.         ca = _tolower (ca);
  523. #else
  524.         ca = tolower (ca);
  525. #endif
  526.     }
  527.     if (ca != cb || ca == '\0') break;  /* if not eq else both nul */
  528.     a++, b++;
  529.     }
  530.     if (cb == '\0' && (ca == '\0' || (ca == 's' && a[1] == '\0')))
  531.       return 1;
  532.  
  533.     return 0;
  534. }
  535.  
  536. static int params_to_pixels (screen, params, n)
  537.     TScreen *screen;
  538.     String *params;
  539.     int n;
  540. {
  541.     register mult = 1;
  542.     register char *s;
  543.  
  544.     switch (n > 2 ? 2 : n) {
  545.       case 2:
  546.     s = params[1];
  547.     if (specialcmplowerwiths (s, "page")) {
  548.         mult = (screen->max_row + 1) * FontHeight(screen);
  549.     } else if (specialcmplowerwiths (s, "halfpage")) {
  550.         mult = ((screen->max_row + 1) * FontHeight(screen)) >> 1;
  551.     } else if (specialcmplowerwiths (s, "pixel")) {
  552.         mult = 1;
  553.     } /* else assume that it is Line */
  554.     mult *= atoi (params[0]);
  555.     break;
  556.       case 1:
  557.     mult = atoi (params[0]) * FontHeight(screen);    /* lines */
  558.     break;
  559.       default:
  560.     mult = screen->scrolllines * FontHeight(screen);
  561.     break;
  562.     }
  563.  
  564.     return mult;
  565. }
  566.  
  567.  
  568. /*ARGSUSED*/
  569. void HandleScrollForward (gw, event, params, nparams)
  570.     Widget gw;
  571.     XEvent *event;
  572.     String *params;
  573.     Cardinal *nparams;
  574. {
  575.     XtermWidget w = (XtermWidget) gw;
  576.     register TScreen *screen = &w->screen;
  577.  
  578.     ScrollTextUpDownBy (gw, (Opaque) NULL,
  579.             params_to_pixels (screen, params, (int) *nparams));
  580.     return;
  581. }
  582.  
  583.  
  584. /*ARGSUSED*/
  585. void HandleScrollBack (gw, event, params, nparams)
  586.     Widget gw;
  587.     XEvent *event;
  588.     String *params;
  589.     Cardinal *nparams;
  590. {
  591.     XtermWidget w = (XtermWidget) gw;
  592.     register TScreen *screen = &w->screen;
  593.  
  594.     ScrollTextUpDownBy (gw, (Opaque) NULL,
  595.             -params_to_pixels (screen, params, (int) *nparams));
  596.     return;
  597. }
  598.  
  599.  
  600.