Annotation of src/usr.bin/vim/gui_motif.c, Revision 1.2
1.2 ! downsj 1: /* $OpenBSD: gui_motif.c,v 1.1.1.1 1996/09/07 21:40:28 downsj Exp $ */
1.1 downsj 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:
1.2 ! downsj 333: /*
! 334: * Need to unmanage vimForm here for a moment, to avoid an error message
! 335: * when .gvimrc contains ":set guioptions=r".
! 336: */
! 337: XtUnmanageChild(vimForm);
1.1 downsj 338: XtVaSetValues(vimShell,
339: #ifdef XmNbaseWidth
340: XmNbaseWidth, base_width,
341: XmNbaseHeight, base_height,
342: #endif
343: XmNwidthInc, gui.char_width,
344: XmNheightInc, gui.char_height,
345: XmNminWidth, base_width + MIN_COLUMNS * gui.char_width,
346: XmNminHeight, base_height + MIN_ROWS * gui.char_height,
347: XmNwidth, base_width + Columns * gui.char_width,
348: XmNheight, base_height + Rows * gui.char_height,
349: NULL);
1.2 ! downsj 350: XtManageChild(vimForm);
1.1 downsj 351: }
352:
353: /*
354: * Menu stuff.
355: */
356:
357: void
358: gui_mch_add_menu(menu, parent)
359: GuiMenu *menu;
360: GuiMenu *parent;
361: {
362: #if (XmVersion >= 1002)
363: Widget widget;
364: XmString label = XmStringCreate((char *)menu->name,
365: XmFONTLIST_DEFAULT_TAG);
366: #else
367: XmString label = XmStringCreate((char *)menu->name,
368: XmSTRING_DEFAULT_CHARSET);
369: #endif
370: Widget shell;
371:
372: menu->id = XtVaCreateWidget("subMenu",
373: xmCascadeButtonWidgetClass,
374: (parent == NULL) ? menuBar : parent->submenu_id,
375: XmNlabelString, label,
376: XmNforeground, gui.menu_fg_pixel,
377: XmNbackground, gui.menu_bg_pixel,
378: NULL);
379: /* XtFree((char *)label); makes Lesstif crash */
380:
381: /* if 'guic' contains 'g', make menu's contain grey items */
382: if (vim_strchr(p_guioptions, GO_GREY) != NULL)
383: XtManageChild(menu->id);
384:
385: shell = XtVaCreateWidget("subMenuShell",
386: xmMenuShellWidgetClass, menu->id,
387: XmNwidth, 1,
388: XmNheight, 1,
389: XmNforeground, gui.menu_fg_pixel,
390: XmNbackground, gui.menu_bg_pixel,
391: NULL);
392: menu->submenu_id = XtVaCreateWidget("rowColumnMenu",
393: xmRowColumnWidgetClass, shell,
394: XmNrowColumnType, XmMENU_PULLDOWN,
395: #if (XmVersion >= 1002)
396: XmNtearOffModel, XmTEAR_OFF_ENABLED,
397: #endif
398: NULL);
399:
400: #if (XmVersion >= 1002)
401: /* Set the colors for the tear off widget */
402: if ((widget = XmGetTearOffControl(menu->submenu_id)) != (Widget)NULL)
403: XtVaSetValues(widget,
404: XmNforeground, gui.menu_fg_pixel,
405: XmNbackground, gui.menu_bg_pixel,
406: NULL);
407: #endif
408:
409: XtVaSetValues(menu->id,
410: XmNsubMenuId, menu->submenu_id,
411: NULL);
412:
413: /*
414: * The "Help" menu is a special case, and should be placed at the far right
415: * hand side of the menu-bar.
416: */
417: if (parent == NULL && STRCMP((char *)menu->name, "Help") == 0)
418: XtVaSetValues(menuBar,
419: XmNmenuHelpWidget, menu->id,
420: NULL);
421:
422: if (parent == NULL)
423: XtVaSetValues(XtParent(menu->id),
424: XmNforeground, gui.menu_fg_pixel,
425: XmNbackground, gui.menu_bg_pixel,
426: NULL);
427: }
428:
429: void
430: gui_mch_add_menu_item(menu, parent)
431: GuiMenu *menu;
432: GuiMenu *parent;
433: {
434: #if (XmVersion >= 1002)
435: XmString label = XmStringCreate((char *)menu->name,
436: XmFONTLIST_DEFAULT_TAG);
437: #else
438: XmString label = XmStringCreate((char *)menu->name,
439: XmSTRING_DEFAULT_CHARSET);
440: #endif
441:
442: menu->submenu_id = (Widget)0;
443: menu->id = XtVaCreateWidget("subMenu",
444: xmPushButtonWidgetClass, parent->submenu_id,
445: XmNlabelString, label,
446: XmNforeground, gui.menu_fg_pixel,
447: XmNbackground, gui.menu_bg_pixel,
448: NULL);
449: /* XtFree((char *)label); makes Lesstif crash */
450:
451: if (vim_strchr(p_guioptions, GO_GREY) != NULL)
452: XtManageChild(menu->id);
453:
454: XtAddCallback(menu->id, XmNactivateCallback, gui_x11_menu_cb,
455: (XtPointer)menu);
456: }
457:
458: /*
459: * Destroy the machine specific menu widget.
460: */
461: void
462: gui_mch_destroy_menu(menu)
463: GuiMenu *menu;
464: {
465: if (menu->id != (Widget)0)
466: XtDestroyWidget(menu->id);
467: if (menu->submenu_id != (Widget)0)
468: XtDestroyWidget(menu->submenu_id);
469: }
470:
471: /*
472: * Scrollbar stuff:
473: */
474:
475: void
476: gui_mch_create_which_components()
477: {
478: static int prev_which_scrollbars[3] = {FALSE, FALSE, FALSE};
479:
480: int i;
481: char *attach = NULL, *widget = NULL; /* NOT char_u */
482: WIN *wp;
483:
484: gui_x11_use_resize_callback(textArea, FALSE);
485:
486: for (i = 0; i < 3; i++)
487: {
488: switch (i)
489: {
490: case SB_LEFT: attach = XmNleftAttachment;
491: widget = XmNleftWidget; break;
492: case SB_RIGHT: attach = XmNrightAttachment;
493: widget = XmNrightWidget; break;
494: case SB_BOTTOM: attach = XmNbottomAttachment;
495: widget = XmNbottomWidget; break;
496: }
497: if (gui.which_scrollbars[i])
498: {
499: XtManageChild(scrollbarBox[i]);
500: XtVaSetValues(textArea,
501: attach, XmATTACH_WIDGET,
502: widget, scrollbarBox[i],
503: NULL);
504: if (i != SB_BOTTOM && gui.which_scrollbars[SB_BOTTOM])
505: XtVaSetValues(scrollbarBox[SB_BOTTOM],
506: attach, XmATTACH_WIDGET,
507: widget, scrollbarBox[i],
508: NULL);
509: }
510: else
511: {
512: XtUnmanageChild(scrollbarBox[i]);
513: XtVaSetValues(textArea,
514: attach, XmATTACH_FORM,
515: NULL);
516: if (i != SB_BOTTOM && gui.which_scrollbars[SB_BOTTOM])
517: XtVaSetValues(scrollbarBox[SB_BOTTOM],
518: attach, XmATTACH_FORM,
519: NULL);
520: }
521: if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
522: {
523: if (i == SB_LEFT || i == SB_RIGHT)
524: {
525: if (gui.which_scrollbars[i])
526: {
527: /* Scrollbar box has just appeared */
528: gui.new_sb[i] = TRUE;
529: }
530: else
531: {
532: /* Scrollbar box has just been deleted */
533: for (wp = firstwin; wp != NULL; wp = wp->w_next)
534: XtDestroyWidget(wp->w_scrollbar.id[i]);
535: }
536: }
537: prev_which_scrollbars[i] = gui.which_scrollbars[i];
538: }
539: }
540: if (gui.menu_is_active)
541: {
542: XtManageChild(menuBar);
543: XtVaSetValues(textArea, XmNtopAttachment, XmATTACH_WIDGET,
544: XmNtopWidget, menuBar, NULL);
545: if (gui.which_scrollbars[SB_LEFT])
546: {
547: XtVaSetValues(scrollbarBox[SB_LEFT],
548: XmNtopAttachment, XmATTACH_WIDGET,
549: XmNtopWidget, menuBar,
550: NULL);
551: }
552: if (gui.which_scrollbars[SB_RIGHT])
553: {
554: XtVaSetValues(scrollbarBox[SB_RIGHT],
555: XmNtopAttachment, XmATTACH_WIDGET,
556: XmNtopWidget, menuBar,
557: NULL);
558: }
559: }
560: else
561: {
562: XtUnmanageChild(menuBar);
563: XtVaSetValues(textArea, XmNtopAttachment, XmATTACH_FORM, NULL);
564: if (gui.which_scrollbars[SB_LEFT])
565: {
566: XtVaSetValues(scrollbarBox[SB_LEFT],
567: XmNtopAttachment, XmATTACH_FORM, NULL);
568: }
569: if (gui.which_scrollbars[SB_RIGHT])
570: {
571: XtVaSetValues(scrollbarBox[SB_RIGHT],
572: XmNtopAttachment, XmATTACH_FORM, NULL);
573: }
574: }
575: gui_x11_use_resize_callback(textArea, TRUE);
576: if (vimForm != (Widget)NULL)
577: gui_mch_set_winsize();
578: }
579:
580:
581: /*
582: * Vertical scrollbar stuff:
583: */
584:
585: void
586: gui_mch_update_scrollbars(worst_update, which_sb)
587: int worst_update;
588: int which_sb; /* SB_LEFT or SB_RIGHT */
589: {
590: WIN *wp;
591: GuiScrollbar *sb;
592: int idx;
593: Dimension h; /* Height of scrollbar (in pixels) */
594: Dimension y; /* Coord of top of scrollbar (in pixels) */
595: int tmp;
596: int val = 0, size = 0, max = 0;
597:
598: if (worst_update >= SB_UPDATE_HEIGHT)
599: {
600: gui_x11_use_resize_callback(textArea, FALSE);
601: XtUnmanageChild(scrollbarBox[which_sb]);
602: }
603:
604: for (wp = firstwin, idx = 0; wp; wp = wp->w_next, idx++)
605: {
606: sb = &wp->w_scrollbar;
607: if (sb->update[which_sb] >= SB_UPDATE_VALUE)
608: {
609: val = sb->value;
610: size = sb->size;
611: max = sb->max + 1; /* Motif has max one past the end */
612: }
613: if (sb->update[which_sb] == SB_UPDATE_CREATE)
614: {
615: sb->id[which_sb] = XtVaCreateManagedWidget("scrollBar",
616: xmScrollBarWidgetClass, scrollbarBox[which_sb],
617: XmNshadowThickness, 1,
618: #if (XmVersion >= 1002) /* What do we do otherwise? */
619: XmNpositionIndex, idx,
620: #endif
621: XmNminimum, 1,
622: XmNmaximum, max,
623: XmNbackground, gui.scroll_fg_pixel,
624: XmNtroughColor, gui.scroll_bg_pixel,
625: NULL);
626: XtAddCallback(sb->id[which_sb], XmNvalueChangedCallback,
627: scroll_cb, (XtPointer)wp);
628: XtAddCallback(sb->id[which_sb], XmNdragCallback,
629: scroll_cb, (XtPointer)wp);
630: }
631: if (sb->update[which_sb] >= SB_UPDATE_HEIGHT)
632: {
633: h = sb->height * gui.char_height
634: + sb->status_height * gui.char_height / 2;
635: y = wp->w_winpos * gui.char_height;
636:
637: if (wp == firstwin)
638: {
639: /* Height of top scrollbar includes width of top border */
640: h += gui.border_offset;
641: }
642: else
643: {
644: /*
645: * Height of other scrollbars includes half of status bar above
646: */
647: tmp = wp->w_prev->w_status_height * (gui.char_height + 1) / 2;
648: h += tmp;
649: y += gui.border_offset - tmp;
650: }
651:
652: XtVaSetValues(sb->id[which_sb],
653: XmNvalue, val,
654: XmNsliderSize, size,
655: XmNpageIncrement, (size > 2 ? size - 2 : 1),
656: XmNmaximum, max,
657: XmNheight, h,
658: XmNy, y,
659: NULL);
660: }
661: else if (sb->update[which_sb] == SB_UPDATE_VALUE)
662: {
663: XtVaSetValues(sb->id[which_sb],
664: XmNvalue, val,
665: XmNsliderSize, size,
666: XmNpageIncrement, (size > 2 ? size - 2 : 1),
667: XmNmaximum, max,
668: NULL);
669: }
670: sb->update[which_sb] = SB_UPDATE_NOTHING;
671: }
672:
673: /* Command line scrollbar */
674: sb = &gui.cmdline_sb;
675: max = sb->max + 1; /* Motif has max one past the end */
676: if (sb->update[which_sb] == SB_UPDATE_HEIGHT)
677: {
678: h = lastwin->w_status_height * (gui.char_height + 1) / 2;
679: y = (Rows - sb->height) * gui.char_height - h;
680: h += sb->height * gui.char_height;
681:
682: /* Height of cmdline scrollbar includes width of bottom border */
683: h += gui.border_offset;
684:
685: XtVaSetValues(sb->id[which_sb],
686: XmNvalue, sb->value,
687: XmNsliderSize, sb->size,
688: XmNmaximum, max,
689: XmNheight, h,
690: XmNy, y,
691: NULL);
692: }
693: else if (sb->update[which_sb] == SB_UPDATE_VALUE)
694: {
695: XtVaSetValues(sb->id[which_sb],
696: XmNvalue, sb->value,
697: XmNsliderSize, sb->size,
698: XmNmaximum, max,
699: NULL);
700: }
701: sb->update[which_sb] = SB_UPDATE_NOTHING;
702:
703: if (worst_update >= SB_UPDATE_HEIGHT)
704: {
705: if (worst_update >= SB_UPDATE_CREATE)
706: gui_mch_reorder_scrollbars(which_sb);
707: XtManageChild(scrollbarBox[which_sb]);
708: gui_x11_use_resize_callback(textArea, TRUE);
709: }
710: }
711:
712: void
713: gui_mch_reorder_scrollbars(which_sb)
714: int which_sb;
715: {
716: Widget *children;
717: int num_children;
718: Widget tmp;
719: WIN *wp, *wp2;
720: int i, j;
721:
722: XtVaGetValues(scrollbarBox[which_sb],
723: XmNchildren, &children,
724: XmNnumChildren, &num_children,
725: NULL);
726:
727: /* Should be in same order as in the window list */
728: wp = firstwin;
729: for (i = 0; i < num_children; i++, wp = wp->w_next)
730: {
731: if (wp == NULL)
732: break; /* Shouldn't happen */
733: if (wp->w_scrollbar.id[which_sb] != children[i])
734: {
735: /* It's in the wrong place, find what should go here */
736: wp2 = wp->w_next;
737: for (j = i + 1; j < num_children; j++, wp2 = wp2->w_next)
738: {
739: if (wp2 == NULL)
740: break; /* Shouldn't happen */
741: if (wp->w_scrollbar.id[which_sb] == children[j])
742: break; /* Found it */
743: }
744: if (j >= num_children || wp2 == NULL)
745: break; /* Shouldn't happen */
746: tmp = children[i];
747: children[i] = children[j];
748: children[j] = tmp;
749: }
750: }
751:
752: XtVaSetValues(scrollbarBox[which_sb],
753: XmNchildren, children,
754: NULL);
755: }
756:
757: void
758: gui_mch_destroy_scrollbar(wp)
759: WIN *wp;
760: {
761: if (gui.which_scrollbars[SB_LEFT])
762: XtDestroyWidget(wp->w_scrollbar.id[SB_LEFT]);
763: if (gui.which_scrollbars[SB_RIGHT])
764: XtDestroyWidget(wp->w_scrollbar.id[SB_RIGHT]);
765: gui.num_scrollbars--;
766: }
767:
768:
769: /*
770: * Horizontal scrollbar stuff:
771: */
772:
773: void
774: gui_mch_update_horiz_scrollbar(value, size, max)
775: int value;
776: int size;
777: int max;
778: {
779: static int prev_value = -1, prev_size = -1, prev_max = -1;
780:
781: if (value == prev_value && size == prev_size && max == prev_max)
782: return;
783:
784: prev_value = value;
785: prev_size = size;
786: prev_max = max;
787:
788: XtVaSetValues(scrollbarBox[SB_BOTTOM],
789: XmNvalue, value,
790: XmNsliderSize, size,
791: XmNpageIncrement, (size > 2 ? size - 2 : 1),
792: XmNmaximum, max,
793: NULL);
794: }
795:
796: Window
797: gui_mch_get_wid()
798: {
799: return( XtWindow(textArea) );
800: }