home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / amiga / vim46src.lha / vim-4.6 / src / gui_motif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-16  |  19.5 KB  |  804 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved            by Bram Moolenaar
  4.  *                                GUI/Motif support by Robert Webb
  5.  *
  6.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  7.  * Do ":help credits" in Vim to see a list of people who contributed.
  8.  */
  9.  
  10. #include <Xm/Form.h>
  11. #include <Xm/RowColumn.h>
  12. #include <Xm/PushB.h>
  13. #include <Xm/PanedW.h>
  14. #include <Xm/CascadeB.h>
  15. #include <Xm/ScrollBar.h>
  16. #include <Xm/RowColumn.h>
  17. #include <Xm/MenuShell.h>
  18. #if (XmVersion >= 1002)
  19. # include <Xm/RepType.h>
  20. #endif
  21.  
  22. #include <X11/keysym.h>
  23. #include <X11/Xatom.h>
  24. #include <X11/StringDefs.h>
  25.  
  26. #include "vim.h"
  27. #include "globals.h"
  28. #include "proto.h"
  29. #include "option.h"
  30. #include "ops.h"
  31.  
  32. extern Widget vimShell;
  33.  
  34. static Widget vimForm;
  35. static Widget textArea;
  36. static Widget scrollbarBox[3];        /* Left, right & bottom scrollbar boxes */
  37. static Widget menuBar;
  38.  
  39. /*
  40.  * Call-back routines.
  41.  */
  42.  
  43.     static void
  44. scroll_cb(w, client_data, call_data)
  45.     Widget        w;
  46.     XtPointer    client_data, call_data;
  47. {
  48.     char_u        bytes[4 + sizeof(long_u)];
  49.     WIN            *wp;
  50.     GuiScrollbar *sb;
  51.     int            sb_num;
  52.  
  53.     if (((XmScrollBarCallbackStruct *)call_data)->reason == XmCR_DRAG)
  54.         gui.dragged_sb = (XtParent(w) == scrollbarBox[SB_LEFT]) ? SB_LEFT
  55.                                                                 : SB_RIGHT;
  56.     else
  57.         gui.dragged_sb = SB_NONE;
  58.     gui.dragged_wp = (WIN *)client_data;
  59.     sb_num = 0;
  60.     for (wp = firstwin; wp != gui.dragged_wp && wp != NULL; wp = wp->w_next)
  61.         sb_num++;
  62.     
  63.     bytes[0] = CSI;
  64.     bytes[1] = KS_SCROLLBAR;
  65.     bytes[2] = K_FILLER;
  66.     bytes[3] = (char_u)sb_num;
  67.     if (gui.dragged_wp == NULL)
  68.         sb = &gui.cmdline_sb;
  69.     else
  70.         sb = &wp->w_scrollbar;
  71.     sb->value = ((XmScrollBarCallbackStruct *)call_data)->value;
  72.     add_long_to_buf((long_u)sb->value, bytes + 4);
  73.     add_to_input_buf(bytes, 4 + sizeof(long_u));
  74. }
  75.  
  76.     static void
  77. horiz_scroll_cb(w, client_data, call_data)
  78.     Widget        w;
  79.     XtPointer    client_data, call_data;
  80. {
  81.     char_u        bytes[3 + sizeof(long_u)];
  82.  
  83.     if (((XmScrollBarCallbackStruct *)call_data)->reason == XmCR_DRAG)
  84.         gui.dragged_sb = SB_BOTTOM;
  85.     else
  86.         gui.dragged_sb = SB_NONE;
  87.     
  88.     bytes[0] = CSI;
  89.     bytes[1] = KS_HORIZ_SCROLLBAR;
  90.     bytes[2] = K_FILLER;
  91.     add_long_to_buf((long_u)((XmScrollBarCallbackStruct *)call_data)->value,
  92.                     bytes + 3);
  93.     add_to_input_buf(bytes, 3 + sizeof(long_u));
  94. }
  95.  
  96. /*
  97.  * End of call-back routines
  98.  */
  99.  
  100. /*
  101.  * Create all the motif widgets necessary.
  102.  */
  103.     void
  104. gui_mch_create_widgets()
  105. {
  106.     int            i;
  107.     Dimension    n;
  108.  
  109.     /*
  110.      * Start out by adding the configured border width into the border offset
  111.      */
  112.     gui.border_offset = gui.border_width;
  113.  
  114.     /*
  115.      * Install the tearOffModel resource converter.
  116.      */
  117. #if (XmVersion >= 1002)
  118.     XmRepTypeInstallTearOffModelConverter();
  119. #endif
  120.  
  121.     XtInitializeWidgetClass(xmFormWidgetClass);
  122.     XtInitializeWidgetClass(xmRowColumnWidgetClass);
  123.     XtInitializeWidgetClass(xmRowColumnWidgetClass);
  124.     XtInitializeWidgetClass(xmPrimitiveWidgetClass);
  125.  
  126.     vimForm = XtVaCreateManagedWidget("vimForm",
  127.         xmFormWidgetClass, vimShell,
  128.         XmNresizePolicy, XmRESIZE_GROW,
  129.         XmNforeground, gui.menu_fg_pixel,
  130.         XmNbackground, gui.menu_bg_pixel,
  131.         NULL);
  132.  
  133.     menuBar = XtVaCreateManagedWidget("menuBar",
  134.         xmRowColumnWidgetClass, vimForm,
  135.         XmNresizeHeight, False,
  136. #if (XmVersion >= 1002)
  137.         XmNtearOffModel, XmTEAR_OFF_ENABLED,
  138. #endif
  139.         XmNtopAttachment, XmATTACH_FORM,
  140.         XmNleftAttachment, XmATTACH_FORM,
  141.         XmNrightAttachment, XmATTACH_FORM,
  142.         XmNrowColumnType, XmMENU_BAR,
  143.         XmNheight, gui.menu_height,
  144.         XmNforeground, gui.menu_fg_pixel,
  145.         XmNbackground, gui.menu_bg_pixel,
  146.         NULL);
  147.  
  148.     scrollbarBox[SB_LEFT] = XtVaCreateWidget("leftScrollBarBox",
  149.         xmRowColumnWidgetClass, vimForm,
  150.         XmNresizeWidth, False,
  151.         XmNtopAttachment, XmATTACH_WIDGET,
  152.         XmNtopWidget, menuBar,
  153.         XmNbottomAttachment, XmATTACH_FORM,
  154.         XmNleftAttachment, XmATTACH_FORM,
  155.         XmNmarginWidth, 0,
  156.         XmNmarginHeight, 0,
  157.         XmNspacing, 0,
  158.         XmNwidth, gui.scrollbar_width,
  159.         XmNforeground, gui.scroll_fg_pixel,
  160.         XmNbackground, gui.scroll_fg_pixel,
  161.         NULL);
  162.  
  163.     scrollbarBox[SB_RIGHT] = XtVaCreateWidget("rightScrollBarBox",
  164.         xmRowColumnWidgetClass, vimForm,
  165.         XmNresizeWidth, False,
  166.         XmNtopAttachment, XmATTACH_WIDGET,
  167.         XmNtopWidget, menuBar,
  168.         XmNbottomAttachment, XmATTACH_FORM,
  169.         XmNrightAttachment, XmATTACH_FORM,
  170.         XmNmarginWidth, 0,
  171.         XmNmarginHeight, 0,
  172.         XmNspacing, 0,
  173.         XmNwidth, gui.scrollbar_width,
  174.         XmNforeground, gui.scroll_fg_pixel,
  175.         XmNbackground, gui.scroll_fg_pixel,
  176.         NULL);
  177.  
  178.     scrollbarBox[SB_BOTTOM] = XtVaCreateWidget("bottomScrollBarBox",
  179.         xmScrollBarWidgetClass, vimForm,
  180.         XmNorientation, XmHORIZONTAL,
  181.         XmNminimum, 0,
  182.         XmNvalue, 0,
  183.         XmNsliderSize, Columns,
  184.         XmNmaximum, Columns,        /* Motif want one more than actual max */
  185.         XmNresizeHeight, False,
  186.         XmNbottomAttachment, XmATTACH_FORM,
  187.         XmNheight, gui.scrollbar_width,
  188.         XmNshadowThickness, 1,
  189.         XmNbackground, gui.scroll_fg_pixel,
  190.         XmNtroughColor, gui.scroll_bg_pixel,
  191.         NULL);
  192.     XtAddCallback(scrollbarBox[SB_BOTTOM], XmNvalueChangedCallback,
  193.         horiz_scroll_cb, (XtPointer)NULL);
  194.     XtAddCallback(scrollbarBox[SB_BOTTOM], XmNdragCallback,
  195.         horiz_scroll_cb, (XtPointer)NULL);
  196.  
  197.     textArea = XtVaCreateManagedWidget("textArea",
  198.         xmPrimitiveWidgetClass, vimForm,
  199.         XmNtopAttachment, XmATTACH_WIDGET,
  200.         XmNtopWidget, menuBar,
  201.         XmNbackground, gui.back_pixel,
  202.  
  203.         /* These take some control away from the user, but avoids making them
  204.          * add resources to get a decent looking setup. */
  205.         XmNborderWidth, 0,
  206.         XmNhighlightThickness, 0,
  207.         XmNshadowThickness, 0,
  208.         NULL);
  209.  
  210.     /*
  211.      * If there are highlight or shadow borders, add their widths to our
  212.      * border offset so we don't draw over them.
  213.      */
  214.     XtVaGetValues(textArea, XmNhighlightThickness, &n, NULL);
  215.     gui.border_offset += n;
  216.     XtVaGetValues(textArea, XmNshadowThickness, &n, NULL);
  217.     gui.border_offset += n;
  218.  
  219.     /* Create the command line scroll bars */
  220.     for (i = 0; i < 2; i++)
  221.     {
  222.         gui.cmdline_sb.id[i] = XtVaCreateManagedWidget("cmdlineScrollBar",
  223.             xmScrollBarWidgetClass, scrollbarBox[i],
  224.             XmNshadowThickness, 1,
  225.             XmNshowArrows, False,
  226.             XmNbackground, gui.scroll_fg_pixel,
  227.             XmNtroughColor, gui.scroll_fg_pixel,
  228.             NULL);
  229.         XtAddCallback(gui.cmdline_sb.id[i], XmNvalueChangedCallback,
  230.             scroll_cb, (XtPointer)NULL);
  231.         XtAddCallback(gui.cmdline_sb.id[i], XmNdragCallback,
  232.             scroll_cb, (XtPointer)NULL);
  233.     }
  234.     gui.num_scrollbars = 1;
  235.  
  236.     /*
  237.      * Text area callbacks
  238.      */
  239.     XtAddEventHandler(textArea, VisibilityChangeMask, FALSE,
  240.         gui_x11_visibility_cb, (XtPointer)0);
  241.  
  242.     XtAddEventHandler(textArea, ExposureMask, FALSE, gui_x11_expose_cb,
  243.         (XtPointer)0);
  244.  
  245.     XtAddEventHandler(textArea, StructureNotifyMask, FALSE,
  246.         gui_x11_resize_window_cb, (XtPointer)0);
  247.  
  248.     XtAddEventHandler(textArea, FocusChangeMask, FALSE, gui_x11_focus_change_cb,
  249.         (XtPointer)0);
  250.  
  251.     XtAddEventHandler(textArea, KeyPressMask, FALSE, gui_x11_key_hit_cb,
  252.         (XtPointer)0);
  253.  
  254.     XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask |
  255.         ButtonMotionMask, FALSE, gui_x11_mouse_cb, (XtPointer)0);
  256. }
  257.  
  258.     int
  259. gui_mch_get_winsize()
  260. {
  261.     Dimension    n;
  262.     Dimension    base_width = 0, base_height = 0;
  263.  
  264.     if (gui.which_scrollbars[SB_LEFT])
  265.     {
  266.         XtVaGetValues(scrollbarBox[SB_LEFT], XmNwidth, &n, NULL);
  267.         base_width += n;
  268.     }
  269.     if (gui.which_scrollbars[SB_RIGHT])
  270.     {
  271.         XtVaGetValues(scrollbarBox[SB_RIGHT], XmNwidth, &n, NULL);
  272.         base_width += n;
  273.     }
  274.     if (gui.which_scrollbars[SB_BOTTOM])
  275.     {
  276.         XtVaGetValues(scrollbarBox[SB_BOTTOM], XmNheight, &n, NULL);
  277.         base_height += n;
  278.     }
  279.  
  280.     base_height += 2 * gui.border_offset;
  281.     base_width  += 2 * gui.border_offset;
  282.  
  283.     if (gui.menu_is_active)
  284.     {
  285.         XtVaGetValues(menuBar, XmNheight, &n, NULL);
  286.         base_height += n;
  287.     }
  288.  
  289.     XtVaGetValues(vimShell, XmNheight, &n, NULL);
  290.     gui.num_rows = (int)(n - base_height) / (int)gui.char_height;
  291.  
  292.     XtVaGetValues(vimShell, XmNwidth, &n, NULL);
  293.     gui.num_cols = (int)(n - base_width) / (int)gui.char_width;
  294.  
  295.     Rows = gui.num_rows;
  296.     Columns = gui.num_cols;
  297.     gui_reset_scroll_region();
  298.  
  299.     return OK;
  300. }
  301.  
  302.     void
  303. gui_mch_set_winsize()
  304. {
  305.     Dimension    left_width, right_width, bottom_height, menu_height;
  306.     Dimension    base_width = 0, base_height = 0;
  307.  
  308.     base_width  += 2 * gui.border_offset;
  309.     base_height += 2 * gui.border_offset;
  310.  
  311.     if (gui.which_scrollbars[SB_LEFT])
  312.     {
  313.         XtVaGetValues(scrollbarBox[SB_LEFT], XmNwidth, &left_width, NULL);
  314.         base_width += left_width;
  315.     }
  316.     if (gui.which_scrollbars[SB_RIGHT])
  317.     {
  318.         XtVaGetValues(scrollbarBox[SB_RIGHT], XmNwidth, &right_width, NULL);
  319.         base_width += right_width;
  320.     }
  321.     if (gui.which_scrollbars[SB_BOTTOM])
  322.     {
  323.         XtVaGetValues(scrollbarBox[SB_BOTTOM], XmNheight, &bottom_height, NULL);
  324.         base_height += bottom_height;
  325.     }
  326.     if (gui.menu_is_active)
  327.     {
  328.         XtVaGetValues(menuBar, XmNheight, &menu_height, NULL);
  329.         base_height += menu_height;
  330.     }
  331.  
  332.     /*
  333.      * Need to unmanage vimForm here for a moment, to avoid an error message
  334.      * when .gvimrc contains ":set guioptions=r".
  335.      * Only do this when sourcing, otherwise the screen won't get updated with
  336.      * some versions of Motif.
  337.      */
  338.     if (sourcing_name != NULL)
  339.         XtUnmanageChild(vimForm);
  340.     XtVaSetValues(vimShell,
  341. #ifdef XmNbaseWidth
  342.         XmNbaseWidth, base_width,
  343.         XmNbaseHeight, base_height,
  344. #endif
  345.         XmNwidthInc,  gui.char_width,
  346.         XmNheightInc, gui.char_height,
  347.         XmNminWidth,  base_width  + MIN_COLUMNS * gui.char_width,
  348.         XmNminHeight, base_height + MIN_ROWS * gui.char_height,
  349.         XmNwidth,      base_width  + Columns * gui.char_width,
  350.         XmNheight,      base_height + Rows * gui.char_height,
  351.         NULL);
  352.     if (sourcing_name != NULL)
  353.         XtManageChild(vimForm);
  354. }
  355.  
  356. /*
  357.  * Menu stuff.
  358.  */
  359.  
  360.     void
  361. gui_mch_add_menu(menu, parent)
  362.     GuiMenu    *menu;
  363.     GuiMenu    *parent;
  364. {
  365. #if (XmVersion >= 1002)
  366.     Widget        widget;
  367.     XmString label = XmStringCreate((char *)menu->name,
  368.                                                       XmFONTLIST_DEFAULT_TAG);
  369. #else
  370.     XmString label = XmStringCreate((char *)menu->name,
  371.                                                     XmSTRING_DEFAULT_CHARSET);
  372. #endif
  373.     Widget shell;
  374.  
  375.     menu->id = XtVaCreateWidget("subMenu",
  376.         xmCascadeButtonWidgetClass,
  377.         (parent == NULL) ? menuBar : parent->submenu_id,
  378.         XmNlabelString, label,
  379.         XmNforeground, gui.menu_fg_pixel,
  380.         XmNbackground, gui.menu_bg_pixel,
  381.         NULL);
  382.     /* XtFree((char *)label); makes Lesstif crash */
  383.  
  384.     /* if 'guic' contains 'g', make menu's contain grey items */
  385.     if (vim_strchr(p_guioptions, GO_GREY) != NULL)
  386.         XtManageChild(menu->id);
  387.  
  388.     shell = XtVaCreateWidget("subMenuShell",
  389.         xmMenuShellWidgetClass, menu->id,
  390.         XmNwidth, 1,
  391.         XmNheight, 1,
  392.         XmNforeground, gui.menu_fg_pixel,
  393.         XmNbackground, gui.menu_bg_pixel,
  394.         NULL);
  395.     menu->submenu_id = XtVaCreateWidget("rowColumnMenu",
  396.         xmRowColumnWidgetClass, shell,
  397.         XmNrowColumnType, XmMENU_PULLDOWN,
  398. #if (XmVersion >= 1002)
  399.         XmNtearOffModel, XmTEAR_OFF_ENABLED,
  400. #endif
  401.         NULL);
  402.  
  403. #if (XmVersion >= 1002)
  404.     /* Set the colors for the tear off widget */
  405.     if ((widget = XmGetTearOffControl(menu->submenu_id)) != (Widget)NULL)
  406.         XtVaSetValues(widget,
  407.             XmNforeground, gui.menu_fg_pixel,
  408.             XmNbackground, gui.menu_bg_pixel,
  409.             NULL);
  410. #endif
  411.     
  412.     XtVaSetValues(menu->id,
  413.         XmNsubMenuId, menu->submenu_id,
  414.         NULL);
  415.  
  416.     /*
  417.      * The "Help" menu is a special case, and should be placed at the far right
  418.      * hand side of the menu-bar.
  419.      */
  420.     if (parent == NULL && STRCMP((char *)menu->name, "Help") == 0)
  421.         XtVaSetValues(menuBar,
  422.             XmNmenuHelpWidget, menu->id,
  423.             NULL);
  424.  
  425.     if (parent == NULL)
  426.         XtVaSetValues(XtParent(menu->id),
  427.             XmNforeground, gui.menu_fg_pixel,
  428.             XmNbackground, gui.menu_bg_pixel,
  429.             NULL);
  430. }
  431.  
  432.     void
  433. gui_mch_add_menu_item(menu, parent)
  434.     GuiMenu    *menu;
  435.     GuiMenu    *parent;
  436. {
  437. #if (XmVersion >= 1002)
  438.     XmString label = XmStringCreate((char *)menu->name,
  439.                                                       XmFONTLIST_DEFAULT_TAG);
  440. #else
  441.     XmString label = XmStringCreate((char *)menu->name,
  442.                                                     XmSTRING_DEFAULT_CHARSET);
  443. #endif
  444.  
  445.     menu->submenu_id = (Widget)0;
  446.     menu->id = XtVaCreateWidget("subMenu",
  447.         xmPushButtonWidgetClass, parent->submenu_id,
  448.         XmNlabelString, label,
  449.         XmNforeground, gui.menu_fg_pixel,
  450.         XmNbackground, gui.menu_bg_pixel,
  451.         NULL);
  452.     /* XtFree((char *)label); makes Lesstif crash */
  453.  
  454.     if (vim_strchr(p_guioptions, GO_GREY) != NULL)
  455.         XtManageChild(menu->id);
  456.  
  457.     XtAddCallback(menu->id, XmNactivateCallback, gui_x11_menu_cb,
  458.         (XtPointer)menu);
  459. }
  460.  
  461. /*
  462.  * Destroy the machine specific menu widget.
  463.  */
  464.     void
  465. gui_mch_destroy_menu(menu)
  466.     GuiMenu    *menu;
  467. {
  468.     if (menu->id != (Widget)0)
  469.         XtDestroyWidget(menu->id);
  470.     if (menu->submenu_id != (Widget)0)
  471.         XtDestroyWidget(menu->submenu_id);
  472. }
  473.  
  474. /*
  475.  * Scrollbar stuff:
  476.  */
  477.  
  478.     void
  479. gui_mch_create_which_components()
  480. {
  481.     static int prev_which_scrollbars[3] = {FALSE, FALSE, FALSE};
  482.  
  483.     int        i;
  484.     char    *attach = NULL, *widget = NULL;        /* NOT char_u */
  485.     WIN        *wp;
  486.  
  487.     gui_x11_use_resize_callback(textArea, FALSE);
  488.  
  489.     for (i = 0; i < 3; i++)
  490.     {
  491.         switch (i)
  492.         {
  493.             case SB_LEFT:    attach = XmNleftAttachment;
  494.                             widget = XmNleftWidget;            break;
  495.             case SB_RIGHT:    attach = XmNrightAttachment;
  496.                             widget = XmNrightWidget;        break;
  497.             case SB_BOTTOM:    attach = XmNbottomAttachment;
  498.                             widget = XmNbottomWidget;        break;
  499.         }
  500.         if (gui.which_scrollbars[i])
  501.         {
  502.             XtManageChild(scrollbarBox[i]);
  503.             XtVaSetValues(textArea,
  504.                 attach, XmATTACH_WIDGET,
  505.                 widget, scrollbarBox[i],
  506.                 NULL);
  507.             if (i != SB_BOTTOM && gui.which_scrollbars[SB_BOTTOM])
  508.                 XtVaSetValues(scrollbarBox[SB_BOTTOM],
  509.                     attach, XmATTACH_WIDGET,
  510.                     widget, scrollbarBox[i],
  511.                     NULL);
  512.         }
  513.         else
  514.         {
  515.             XtUnmanageChild(scrollbarBox[i]);
  516.             XtVaSetValues(textArea,
  517.                 attach, XmATTACH_FORM,
  518.                 NULL);
  519.             if (i != SB_BOTTOM && gui.which_scrollbars[SB_BOTTOM])
  520.                 XtVaSetValues(scrollbarBox[SB_BOTTOM],
  521.                     attach, XmATTACH_FORM,
  522.                     NULL);
  523.         }
  524.         if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
  525.         {
  526.             if (i == SB_LEFT || i == SB_RIGHT)
  527.             {
  528.                 if (gui.which_scrollbars[i])
  529.                 {
  530.                     /* Scrollbar box has just appeared */
  531.                     gui.new_sb[i] = TRUE;
  532.                 }
  533.                 else
  534.                 {
  535.                     /* Scrollbar box has just been deleted */
  536.                     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  537.                         XtDestroyWidget(wp->w_scrollbar.id[i]);
  538.                 }
  539.             }
  540.             prev_which_scrollbars[i] = gui.which_scrollbars[i];
  541.         }
  542.     }
  543.     if (gui.menu_is_active)
  544.     {
  545.         XtManageChild(menuBar);
  546.         XtVaSetValues(textArea, XmNtopAttachment, XmATTACH_WIDGET,
  547.                         XmNtopWidget, menuBar, NULL);
  548.         if (gui.which_scrollbars[SB_LEFT])
  549.         {
  550.             XtVaSetValues(scrollbarBox[SB_LEFT],
  551.                 XmNtopAttachment, XmATTACH_WIDGET,
  552.                 XmNtopWidget, menuBar,
  553.                 NULL);
  554.         }
  555.         if (gui.which_scrollbars[SB_RIGHT])
  556.         {
  557.             XtVaSetValues(scrollbarBox[SB_RIGHT],
  558.                 XmNtopAttachment, XmATTACH_WIDGET,
  559.                 XmNtopWidget, menuBar,
  560.                 NULL);
  561.         }
  562.     }
  563.     else
  564.     {
  565.         XtUnmanageChild(menuBar);
  566.         XtVaSetValues(textArea, XmNtopAttachment, XmATTACH_FORM, NULL);
  567.         if (gui.which_scrollbars[SB_LEFT])
  568.         {
  569.             XtVaSetValues(scrollbarBox[SB_LEFT],
  570.                 XmNtopAttachment, XmATTACH_FORM, NULL);
  571.         }
  572.         if (gui.which_scrollbars[SB_RIGHT])
  573.         {
  574.             XtVaSetValues(scrollbarBox[SB_RIGHT],
  575.                 XmNtopAttachment, XmATTACH_FORM, NULL);
  576.           }
  577.       }
  578.     gui_x11_use_resize_callback(textArea, TRUE);
  579.     if (vimForm != (Widget)NULL)
  580.         gui_mch_set_winsize();
  581. }
  582.  
  583.  
  584. /*
  585.  * Vertical scrollbar stuff:
  586.  */
  587.  
  588.     void
  589. gui_mch_update_scrollbars(worst_update, which_sb)
  590.     int        worst_update;
  591.     int        which_sb;        /* SB_LEFT or SB_RIGHT */
  592. {
  593.     WIN                *wp;
  594.     GuiScrollbar    *sb;
  595.     int                idx;
  596.     Dimension        h;        /* Height of scrollbar (in pixels) */
  597.     Dimension        y;        /* Coord of top of scrollbar (in pixels) */
  598.     int                tmp;
  599.     int                val = 0, size = 0, max = 0;
  600.  
  601.     if (worst_update >= SB_UPDATE_HEIGHT)
  602.     {
  603.         gui_x11_use_resize_callback(textArea, FALSE);
  604.         XtUnmanageChild(scrollbarBox[which_sb]);
  605.     }
  606.  
  607.     for (wp = firstwin, idx = 0; wp; wp = wp->w_next, idx++)
  608.     {
  609.         sb = &wp->w_scrollbar;
  610.         if (sb->update[which_sb] >= SB_UPDATE_VALUE)
  611.         {
  612.             val = sb->value;
  613.             size = sb->size;
  614.             max = sb->max + 1;        /* Motif has max one past the end */
  615.         }
  616.         if (sb->update[which_sb] == SB_UPDATE_CREATE)
  617.         {
  618.             sb->id[which_sb] = XtVaCreateManagedWidget("scrollBar",
  619.                 xmScrollBarWidgetClass, scrollbarBox[which_sb],
  620.                 XmNshadowThickness, 1,
  621. #if (XmVersion >= 1002)        /* What do we do otherwise? */
  622.                 XmNpositionIndex, idx,
  623. #endif
  624.                 XmNminimum, 1,
  625.                 XmNmaximum, max,
  626.                 XmNbackground, gui.scroll_fg_pixel,
  627.                 XmNtroughColor, gui.scroll_bg_pixel,
  628.                 NULL);
  629.             XtAddCallback(sb->id[which_sb], XmNvalueChangedCallback,
  630.                 scroll_cb, (XtPointer)wp);
  631.             XtAddCallback(sb->id[which_sb], XmNdragCallback,
  632.                 scroll_cb, (XtPointer)wp);
  633.         }
  634.         if (sb->update[which_sb] >= SB_UPDATE_HEIGHT)
  635.         {
  636.             h = sb->height * gui.char_height
  637.                     + sb->status_height * gui.char_height / 2;
  638.             y = wp->w_winpos * gui.char_height;
  639.  
  640.             if (wp == firstwin)
  641.             {
  642.                 /* Height of top scrollbar includes width of top border */
  643.                 h += gui.border_offset;
  644.             }
  645.             else
  646.             {
  647.                 /*
  648.                  * Height of other scrollbars includes half of status bar above
  649.                  */
  650.                 tmp = wp->w_prev->w_status_height * (gui.char_height + 1) / 2;
  651.                 h += tmp;
  652.                 y += gui.border_offset - tmp;
  653.             }
  654.  
  655.             XtVaSetValues(sb->id[which_sb],
  656.                 XmNvalue, val,
  657.                 XmNsliderSize, size,
  658.                 XmNpageIncrement, (size > 2 ? size - 2 : 1),
  659.                 XmNmaximum, max,
  660.                 XmNheight, h,
  661.                 XmNy, y,
  662.                 NULL);
  663.         }
  664.         else if (sb->update[which_sb] == SB_UPDATE_VALUE)
  665.         {
  666.             XtVaSetValues(sb->id[which_sb],
  667.                 XmNvalue, val,
  668.                 XmNsliderSize, size,
  669.                 XmNpageIncrement, (size > 2 ? size - 2 : 1),
  670.                 XmNmaximum, max,
  671.                 NULL);
  672.         }
  673.         sb->update[which_sb] = SB_UPDATE_NOTHING;
  674.     }
  675.  
  676.     /* Command line scrollbar */
  677.     sb = &gui.cmdline_sb;
  678.     max = sb->max + 1;            /* Motif has max one past the end */
  679.     if (sb->update[which_sb] == SB_UPDATE_HEIGHT)
  680.     {
  681.         h = lastwin->w_status_height * (gui.char_height + 1) / 2;
  682.         y = (Rows - sb->height) * gui.char_height - h;
  683.         h += sb->height * gui.char_height;
  684.  
  685.         /* Height of cmdline scrollbar includes width of bottom border */
  686.         h += gui.border_offset;
  687.  
  688.         XtVaSetValues(sb->id[which_sb],
  689.             XmNvalue, sb->value,
  690.             XmNsliderSize, sb->size,
  691.             XmNmaximum, max,
  692.             XmNheight, h,
  693.             XmNy, y,
  694.             NULL);
  695.     }
  696.     else if (sb->update[which_sb] == SB_UPDATE_VALUE)
  697.     {
  698.         XtVaSetValues(sb->id[which_sb],
  699.             XmNvalue, sb->value,
  700.             XmNsliderSize, sb->size,
  701.             XmNmaximum, max,
  702.             NULL);
  703.     }
  704.     sb->update[which_sb] = SB_UPDATE_NOTHING;
  705.  
  706.     if (worst_update >= SB_UPDATE_HEIGHT)
  707.     {
  708.         if (worst_update >= SB_UPDATE_CREATE)
  709.             gui_mch_reorder_scrollbars(which_sb);
  710.         XtManageChild(scrollbarBox[which_sb]);
  711.         gui_x11_use_resize_callback(textArea, TRUE);
  712.     }
  713. }
  714.  
  715.     void
  716. gui_mch_reorder_scrollbars(which_sb)
  717.     int        which_sb;
  718. {
  719.     Widget *children;
  720.     int        num_children;
  721.     Widget    tmp;
  722.     WIN        *wp, *wp2;
  723.     int        i, j;
  724.  
  725.     XtVaGetValues(scrollbarBox[which_sb],
  726.         XmNchildren, &children,
  727.         XmNnumChildren, &num_children,
  728.         NULL);
  729.     
  730.     /* Should be in same order as in the window list */
  731.     wp = firstwin;
  732.     for (i = 0; i < num_children; i++, wp = wp->w_next)
  733.     {
  734.         if (wp == NULL)
  735.             break;        /* Shouldn't happen */
  736.         if (wp->w_scrollbar.id[which_sb] != children[i])
  737.         {
  738.             /* It's in the wrong place, find what should go here */
  739.             wp2 = wp->w_next;
  740.             for (j = i + 1; j < num_children; j++, wp2 = wp2->w_next)
  741.             {
  742.                 if (wp2 == NULL)
  743.                     break;        /* Shouldn't happen */
  744.                 if (wp->w_scrollbar.id[which_sb] == children[j])
  745.                     break;        /* Found it */
  746.             }
  747.             if (j >= num_children || wp2 == NULL)
  748.                 break;            /* Shouldn't happen */
  749.             tmp = children[i];
  750.             children[i] = children[j];
  751.             children[j] = tmp;
  752.         }
  753.     }
  754.  
  755.     XtVaSetValues(scrollbarBox[which_sb],
  756.         XmNchildren, children,
  757.         NULL);
  758. }
  759.  
  760.     void
  761. gui_mch_destroy_scrollbar(wp)
  762.     WIN        *wp;
  763. {
  764.     if (gui.which_scrollbars[SB_LEFT])
  765.         XtDestroyWidget(wp->w_scrollbar.id[SB_LEFT]);
  766.     if (gui.which_scrollbars[SB_RIGHT])
  767.         XtDestroyWidget(wp->w_scrollbar.id[SB_RIGHT]);
  768.     gui.num_scrollbars--;
  769. }
  770.  
  771.  
  772. /*
  773.  * Horizontal scrollbar stuff:
  774.  */
  775.  
  776.     void
  777. gui_mch_update_horiz_scrollbar(value, size, max)
  778.     int        value;
  779.     int        size;
  780.     int        max;
  781. {
  782.     static int prev_value = -1, prev_size = -1, prev_max = -1;
  783.  
  784.     if (value == prev_value && size == prev_size && max == prev_max)
  785.         return;
  786.  
  787.     prev_value = value;
  788.     prev_size = size;
  789.     prev_max = max;
  790.  
  791.     XtVaSetValues(scrollbarBox[SB_BOTTOM],
  792.         XmNvalue, value,
  793.         XmNsliderSize, size,
  794.         XmNpageIncrement, (size > 2 ? size - 2 : 1),
  795.         XmNmaximum, max,
  796.         NULL);
  797. }
  798.  
  799.     Window
  800. gui_mch_get_wid()
  801. {
  802.     return( XtWindow(textArea) );
  803. }
  804.