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