Annotation of src/usr.bin/vim/gui_motif.c, Revision 1.1.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: }