Annotation of src/usr.bin/vim/gui_athena.c, Revision 1.3
1.3 ! downsj 1: /* $OpenBSD: gui_athena.c,v 1.2 1996/09/21 06:23:03 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: * Athena port by Bill Foster
7: *
8: * Do ":help uganda" in Vim to read copying and usage conditions.
9: * Do ":help credits" in Vim to see a list of people who contributed.
10: */
11:
12: #include <X11/StringDefs.h>
13: #include <X11/Intrinsic.h>
14: #include <X11/Xaw/Paned.h>
15: #include <X11/Xaw/Form.h>
16: #include <X11/Xaw/SimpleMenu.h>
17: #include <X11/Xaw/MenuButton.h>
18: #include <X11/Xaw/SmeBSB.h>
19: #include <X11/Xaw/Box.h>
20:
21: #include "vim.h"
22: #include "globals.h"
23: #include "proto.h"
24: #include "option.h"
25: #include "ops.h"
26: #include "gui_at_sb.h"
27:
28: #define puller_width 19
29: #define puller_height 19
30:
1.2 downsj 31: static char_u puller_bits[] =
1.1 downsj 32: {
33: 0x00,0x00,0xf8,0x00,0x00,0xf8,0xf8,0x7f,0xf8,0x04,0x80,0xf8,0x04,0x80,0xf9,
34: 0x84,0x81,0xf9,0x84,0x83,0xf9,0x84,0x87,0xf9,0x84,0x8f,0xf9,0x84,0x8f,0xf9,
35: 0x84,0x87,0xf9,0x84,0x83,0xf9,0x84,0x81,0xf9,0x04,0x80,0xf9,0x04,0x80,0xf9,
36: 0xf8,0xff,0xf9,0xf0,0x7f,0xf8,0x00,0x00,0xf8,0x00,0x00,0xf8
37: };
38:
39: extern Widget vimShell;
40:
41: static Widget vimPanes;
42: static Widget vimForm = (Widget)NULL;
43: static Widget textArea;
44: static Widget scrollbarBox[3]; /* Left, right & bottom scrollbar boxes */
45: static Widget bottomScrollbar; /* Bottom scrollbar */
46: static Widget leftBottomScrollFiller; /* Left filler for bottom scrollbar */
47: static Widget rightBottomScrollFiller; /* Right filler for bottom scrollbar */
48: static Widget leftScrollbarFiller; /* Filler for left scrollbar */
49: static Widget rightScrollbarFiller; /* Filler for right scrollbar */
50: static Widget menuBar;
51:
52: static void gui_athena_scroll_cb_jump __ARGS((Widget, XtPointer, XtPointer));
53: static void gui_athena_scroll_cb_scroll __ARGS((Widget, XtPointer, XtPointer));
54: static void gui_athena_reorder_menus __ARGS((void));
55: static void gui_athena_pullright_action __ARGS((Widget, XEvent *, String *,
56: Cardinal *));
57:
58: static XtActionsRec pullAction = { "menu-pullright",
59: (XtActionProc)gui_athena_pullright_action };
60: static XtTranslations parentTrans, menuTrans;
61: static Pixmap pullerBitmap;
62:
63: /*
64: * Scrollbar callback (XtNjumpProc) for when the scrollbar is dragged with the
65: * left or middle mouse button.
66: */
67: static void
68: gui_athena_scroll_cb_jump(w, client_data, call_data)
69: Widget w;
70: XtPointer client_data, call_data;
71: {
72: char_u bytes[4 + sizeof(long_u)];
73: WIN *wp;
74: GuiScrollbar *sb;
75: int sb_num;
76: int i;
77: int byte_count;
78: long_u value;
79:
80: gui.dragged_sb = SB_NONE;
81: for (i = 0; i <= SB_BOTTOM; i++)
82: if (XtParent(w) == scrollbarBox[i])
83: {
84: gui.dragged_sb = i;
85: break;
86: }
87:
88: switch (gui.dragged_sb)
89: {
90: case SB_LEFT:
91: case SB_RIGHT:
92: gui.dragged_wp = (WIN *)client_data;
93: sb_num = 0;
94: wp = firstwin;
95: for ( ; wp != gui.dragged_wp && wp != NULL; wp = wp->w_next)
96: sb_num++;
97:
98: if (gui.dragged_wp == NULL)
99: return;
100:
101: sb = &wp->w_scrollbar;
102:
1.2 downsj 103: value = *((float *)call_data) * (float)(sb->max - 1) + 0.5;
1.1 downsj 104: ++value; /* range is 1 to line_count */
105: sb->value = value;
106:
107: bytes[0] = CSI;
108: bytes[1] = KS_SCROLLBAR;
109: bytes[2] = K_FILLER;
110: bytes[3] = (char_u)sb_num;
111: byte_count = 4;
112: break;
113:
114: case SB_BOTTOM:
115: /* why not use sb->max? */
116: value = *((float *)call_data) *
117: (float)(gui_get_max_horiz_scroll()) + 0.5;
118: bytes[0] = CSI;
119: bytes[1] = KS_HORIZ_SCROLLBAR;
120: bytes[2] = K_FILLER;
121: byte_count = 3;
122: break;
123:
124: case SB_NONE:
125: default:
126: return;
127: }
128:
129: add_long_to_buf(value, bytes + byte_count);
130: add_to_input_buf(bytes, byte_count + sizeof(long_u));
131: }
132:
133: /*
134: * Scrollbar callback (XtNscrollProc) for paging up or down with the left or
135: * right mouse buttons.
136: */
137: static void
138: gui_athena_scroll_cb_scroll(w, client_data, call_data)
139: Widget w;
140: XtPointer client_data, call_data;
141: {
142: char_u bytes[4 + sizeof(long_u)];
143: WIN *wp;
144: GuiScrollbar *sb;
145: int sb_num;
146: int i;
147: int byte_count;
148: long value;
149: int data = (int)call_data;
150:
151: for (i = 0; i <= SB_BOTTOM; i++)
152: if (XtParent(w) == scrollbarBox[i])
153: {
154: gui.dragged_sb = i;
155: break;
156: }
157:
158: switch (gui.dragged_sb)
159: {
160: case SB_LEFT:
161: case SB_RIGHT:
162: gui.dragged_wp = (WIN *)client_data;
163: sb_num = 0;
164: wp = firstwin;
165: for ( ; wp != gui.dragged_wp && wp != NULL; wp = wp->w_next)
166: sb_num++;
167:
168: if (gui.dragged_wp == NULL)
169: return;
170:
171: sb = &wp->w_scrollbar;
172:
173: if (sb->size > 5)
174: i = sb->size - 2; /* use two lines of context */
175: else
176: i = sb->size;
177: switch (data)
178: {
179: case ONE_LINE_DATA: data = 1; break;
180: case -ONE_LINE_DATA: data = -1; break;
181: case ONE_PAGE_DATA: data = i; break;
182: case -ONE_PAGE_DATA: data = -i; break;
183: case END_PAGE_DATA: data = sb->max; break;
184: case -END_PAGE_DATA: data = -sb->max; break;
185: default: data = 0; break;
186: }
187: value = sb->value + data;
188: if (value > sb->max)
189: value = sb->max;
190: else if (value < 1) /* range is 1 to line_count */
191: value = 1;
192:
193: bytes[0] = CSI;
194: bytes[1] = KS_SCROLLBAR;
195: bytes[2] = K_FILLER;
196: bytes[3] = (char_u)sb_num;
197: byte_count = 4;
198: break;
199:
200: case SB_BOTTOM:
201: if (data < -1)
202: data = -(Columns - 5);
203: else if (data > 1)
204: data = (Columns - 5);
205: value = curwin->w_leftcol + data;
206: if (value < 0) /* range is 0 to max_col */
207: value = 0;
208: else
209: {
210: int max;
211: /* why not use sb->max here? */
212: max = gui_get_max_horiz_scroll();
213: if (value >= max)
214: value = max;
215: }
216:
217: bytes[0] = CSI;
218: bytes[1] = KS_HORIZ_SCROLLBAR;
219: bytes[2] = K_FILLER;
220: byte_count = 3;
221: break;
222:
223: case SB_NONE:
224: default:
225: return;
226: }
227:
228: /*
229: * This type of scrolling doesn't move the thumb automatically so we need
230: * make sure the scrollbar still gets updated.
231: */
232: gui.dragged_sb = SB_NONE;
233:
234: add_long_to_buf((long_u)value, bytes + byte_count);
235: add_to_input_buf(bytes, byte_count + sizeof(long_u));
236: }
237:
238: /*
239: * Create all the Athena widgets necessary.
240: */
241: void
242: gui_mch_create_widgets()
243: {
244: Dimension base_width, base_height;
245:
246: /*
247: * We don't have any borders handled internally by the textArea to worry
248: * about so only skip over the configured border width.
249: */
250: gui.border_offset = gui.border_width;
251:
252: base_width = 2 * gui.border_offset;
253: base_height = 2 * gui.border_offset;
254:
255: XtInitializeWidgetClass(panedWidgetClass);
256: XtInitializeWidgetClass(simpleMenuWidgetClass);
257: XtInitializeWidgetClass(vim_scrollbarWidgetClass);
258: XtInitializeWidgetClass(labelWidgetClass);
259:
260: /* Panes for menu bar, middle stuff, and bottom scrollbar box */
261: vimPanes = XtVaCreateManagedWidget("vimPanes",
262: panedWidgetClass, vimShell,
263: XtNorientation, XtorientVertical,
264: NULL);
265:
266: /* The top menu bar */
267: menuBar = XtVaCreateManagedWidget("menuBar",
268: boxWidgetClass, vimPanes,
269: XtNmin, gui.menu_height,
270: XtNborderWidth, 1,
271: XtNallowResize, True,
272: XtNresizeToPreferred, True,
273: XtNskipAdjust, True,
274: XtNshowGrip, False,
275: XtNforeground, gui.menu_fg_pixel,
276: XtNbackground, gui.menu_bg_pixel,
277: XtNborderColor, gui.menu_fg_pixel,
278: NULL);
279:
280: /*
281: * Panes for the middle stuff (left scrollbar box, text area, and right
282: * scrollbar box.
283: */
284: vimForm = XtVaCreateManagedWidget("vimForm",
285: panedWidgetClass, vimPanes,
286: XtNallowResize, True,
287: XtNorientation, XtorientHorizontal,
288: XtNborderWidth, 0,
289: XtNdefaultDistance, 0,
290: XtNshowGrip, False,
291: NULL);
292:
293: /* Panes for the left window scrollbars. */
294: scrollbarBox[SB_LEFT] = XtVaCreateWidget("scrollBarBox",
295: panedWidgetClass, vimForm,
296: XtNpreferredPaneSize, gui.scrollbar_width,
297: XtNallowResize, True,
298: XtNskipAdjust, True,
299: XtNborderWidth, 1,
300: XtNshowGrip, False,
301: XtNforeground, gui.scroll_fg_pixel,
302: XtNbackground, gui.scroll_fg_pixel,
303: XtNborderColor, gui.scroll_fg_pixel,
304: NULL);
305:
306: /* The text area. */
307: textArea = XtVaCreateManagedWidget("textArea",
308: coreWidgetClass, vimForm,
309: XtNallowResize, True,
310: XtNshowGrip, False,
311: XtNbackground, gui.back_pixel,
312: XtNborderWidth, 0,
313: XtNheight, Rows * gui.char_height + base_height,
314: XtNwidth, Columns * gui.char_width + base_width,
315: NULL);
316:
317: /* Panes for the right window scrollbars. */
318: scrollbarBox[SB_RIGHT] = XtVaCreateWidget("scrollBarBox",
319: panedWidgetClass, vimForm,
320: XtNpreferredPaneSize, gui.scrollbar_width,
321: XtNallowResize, True,
322: XtNskipAdjust, True,
323: XtNborderWidth, 1,
324: XtNresizeToPreferred, True,
325: XtNshowGrip, False,
326: XtNforeground, gui.scroll_fg_pixel,
327: XtNbackground, gui.scroll_fg_pixel,
328: XtNborderColor, gui.scroll_fg_pixel,
329: NULL);
330:
331: /* Panes for the bottom scrollbar and fillers on each side. */
332: scrollbarBox[SB_BOTTOM] = XtVaCreateWidget("scrollBarBox",
333: panedWidgetClass, vimPanes,
334: XtNpreferredPaneSize, gui.scrollbar_width,
335: XtNallowResize, True,
336: XtNskipAdjust, True,
337: XtNborderWidth, 1,
338: XtNresizeToPreferred, True,
339: XtNshowGrip, False,
340: XtNforeground, gui.scroll_fg_pixel,
341: XtNbackground, gui.scroll_fg_pixel,
342: XtNborderColor, gui.scroll_fg_pixel,
343: XtNorientation, XtorientHorizontal,
344: NULL);
345:
346: /* A filler for the gap on the left side of the bottom scrollbar. */
347: leftBottomScrollFiller = XtVaCreateManagedWidget("",
348: labelWidgetClass, scrollbarBox[SB_BOTTOM],
349: XtNshowGrip, False,
350: XtNresize, False,
351: XtNborderWidth, 4,
352: XtNmin, gui.scrollbar_width + 1,
353: XtNmax, gui.scrollbar_width + 1,
354: XtNforeground, gui.scroll_fg_pixel,
355: XtNbackground, gui.scroll_fg_pixel,
356: XtNborderColor, gui.scroll_fg_pixel,
357: NULL);
358:
359: /* The bottom scrollbar. */
360: bottomScrollbar = XtVaCreateManagedWidget("bottomScrollBar",
361: vim_scrollbarWidgetClass, scrollbarBox[SB_BOTTOM],
362: XtNresizeToPreferred, True,
363: XtNallowResize, True,
364: XtNskipAdjust, True,
365: XtNshowGrip, False,
366: XtNorientation, XtorientHorizontal,
367: XtNforeground, gui.scroll_fg_pixel,
368: XtNbackground, gui.scroll_bg_pixel,
369: NULL);
370:
371: XtAddCallback(bottomScrollbar, XtNjumpProc,
372: gui_athena_scroll_cb_jump, (XtPointer)NULL);
373: XtAddCallback(bottomScrollbar, XtNscrollProc,
374: gui_athena_scroll_cb_scroll, (XtPointer)NULL);
375:
376: vim_XawScrollbarSetThumb(bottomScrollbar, 0., 1., 0.);
377:
378: /* A filler for the gap on the right side of the bottom scrollbar. */
379: rightBottomScrollFiller = XtVaCreateManagedWidget("",
380: labelWidgetClass, scrollbarBox[SB_BOTTOM],
381: XtNshowGrip, False,
382: XtNresize, False,
383: XtNborderWidth, 4,
384: XtNmin, gui.scrollbar_width + 1,
385: XtNmax, gui.scrollbar_width + 1,
386: XtNforeground, gui.scroll_fg_pixel,
387: XtNbackground, gui.scroll_fg_pixel,
388: NULL);
389:
390: /* A filler for the gap on the bottom of the left scrollbar. */
391: leftScrollbarFiller = XtVaCreateManagedWidget("",
392: labelWidgetClass, scrollbarBox[SB_LEFT],
393: XtNshowGrip, False,
394: XtNresize, False,
395: XtNborderWidth, 4,
396: XtNmin, gui.scrollbar_width + 1,
397: XtNmax, gui.scrollbar_width + 1,
398: XtNforeground, gui.scroll_fg_pixel,
399: XtNbackground, gui.scroll_fg_pixel,
400: NULL);
401:
402: /* A filler for the gap on the bottom of the right scrollbar. */
403: rightScrollbarFiller = XtVaCreateManagedWidget("",
404: labelWidgetClass, scrollbarBox[SB_RIGHT],
405: XtNshowGrip, False,
406: XtNresize, False,
407: XtNborderWidth, 4,
408: XtNmin, gui.scrollbar_width + 1,
409: XtNmax, gui.scrollbar_width + 1,
410: XtNforeground, gui.scroll_fg_pixel,
411: XtNbackground, gui.scroll_fg_pixel,
412: NULL);
413:
414: gui.num_scrollbars = 0;
415:
416: /*
417: * Text area callbacks
418: */
419: XtAddEventHandler(textArea, VisibilityChangeMask, FALSE,
420: gui_x11_visibility_cb, (XtPointer)0);
421:
422: XtAddEventHandler(textArea, ExposureMask, FALSE, gui_x11_expose_cb,
423: (XtPointer)0);
424:
425: XtAddEventHandler(textArea, StructureNotifyMask, FALSE,
426: gui_x11_resize_window_cb, (XtPointer)0);
427:
428: XtAddEventHandler(vimShell, FocusChangeMask, FALSE, gui_x11_focus_change_cb,
429: (XtPointer)0);
430:
431: XtAddEventHandler(vimPanes, KeyPressMask, FALSE, gui_x11_key_hit_cb,
432: (XtPointer)0);
433:
434: XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask |
435: ButtonMotionMask, FALSE, gui_x11_mouse_cb, (XtPointer)0);
436:
437: parentTrans = XtParseTranslationTable("<BtnMotion>: highlight() menu-pullright()");
438: menuTrans = XtParseTranslationTable("<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight()");
439:
440: XtAppAddActions(XtWidgetToApplicationContext(vimForm), &pullAction, 1);
441:
442: pullerBitmap = XCreateBitmapFromData(gui.dpy, DefaultRootWindow(gui.dpy),
443: (char *)puller_bits, puller_width, puller_height);
444: }
445:
446: int
447: gui_mch_get_winsize()
448: {
449: Dimension base_width, base_height;
450: Dimension total_width, total_height;
451: Dimension left_width = 0, right_width = 0;
452: Dimension bottom_height = 0, menu_height = 0;
453:
454: base_height = 2 * gui.border_offset;
455: base_width = 2 * gui.border_offset;
456:
457: if (gui.which_scrollbars[SB_LEFT])
458: XtVaGetValues(scrollbarBox[SB_LEFT], XtNwidth, &left_width, NULL);
459:
460: if (gui.which_scrollbars[SB_RIGHT])
461: XtVaGetValues(scrollbarBox[SB_RIGHT], XtNwidth, &right_width, NULL);
462:
463: if (gui.which_scrollbars[SB_BOTTOM])
464: XtVaGetValues(scrollbarBox[SB_BOTTOM], XtNheight, &bottom_height, NULL);
465:
466: if (XtIsManaged(menuBar))
467: XtVaGetValues(menuBar, XtNheight, &menu_height, NULL);
468:
469: base_width += left_width + right_width;
470: base_height += menu_height + bottom_height;
471:
472: XtVaGetValues(vimShell,
473: XtNheight, &total_height,
474: XtNwidth, &total_width,
475: NULL);
476:
1.3 ! downsj 477: gui.num_rows = (int)(total_height - base_height) / gui.char_height;
! 478: gui.num_cols = (int)(total_width - base_width) / gui.char_width;
1.1 downsj 479:
480: Rows = gui.num_rows;
481: Columns = gui.num_cols;
482: gui_reset_scroll_region();
483:
484: return OK;
485: }
486:
487: void
488: gui_mch_set_winsize()
489: {
490: Dimension left_width = 0, right_width = 0;
491: Dimension bottom_height = 0, menu_height = 0;
492: Dimension base_width, base_height;
493:
494: base_width = 2 * gui.border_offset;
495: base_height = 2 * gui.border_offset;
496:
497: if (gui.which_scrollbars[SB_LEFT])
498: XtVaGetValues(scrollbarBox[SB_LEFT], XtNwidth, &left_width, NULL);
499:
500: if (gui.which_scrollbars[SB_RIGHT])
501: XtVaGetValues(scrollbarBox[SB_RIGHT], XtNwidth, &right_width, NULL);
502:
503: if (gui.which_scrollbars[SB_BOTTOM])
504: XtVaGetValues(scrollbarBox[SB_BOTTOM], XtNheight, &bottom_height, NULL);
505:
506: if (XtIsManaged(menuBar))
507: XtVaGetValues(menuBar, XtNheight, &menu_height, NULL);
508:
509: base_width += left_width + right_width;
510: base_height += menu_height + bottom_height;
511:
512: XtVaSetValues(vimShell,
513: XtNwidthInc, gui.char_width,
514: XtNheightInc, gui.char_height,
515: XtNbaseWidth, base_width,
516: XtNbaseHeight, base_height,
517: XtNminWidth, base_width + MIN_COLUMNS * gui.char_width,
518: XtNminHeight, base_height + MIN_ROWS * gui.char_height,
519: XtNwidth, base_width + Columns * gui.char_width,
520: XtNheight, base_height + Rows * gui.char_height,
521: NULL);
522: }
523:
524: /*
525: * Menu stuff.
526: */
527:
528: void
529: gui_mch_add_menu(menu, parent)
530: GuiMenu *menu;
531: GuiMenu *parent;
532: {
533: char_u *pullright_name;
534:
535: if (parent == NULL)
536: {
537: menu->id = XtVaCreateManagedWidget(menu->name,
538: menuButtonWidgetClass, menuBar,
539: XtNmenuName, menu->name,
540: XtNforeground, gui.menu_fg_pixel,
541: XtNbackground, gui.menu_bg_pixel,
542: NULL);
543:
544: menu->submenu_id = XtVaCreatePopupShell(menu->name,
545: simpleMenuWidgetClass, menu->id,
546: XtNforeground, gui.menu_fg_pixel,
547: XtNbackground, gui.menu_bg_pixel,
548: NULL);
549:
550: gui_athena_reorder_menus();
551: }
552: else
553: {
554: menu->id = XtVaCreateManagedWidget(menu->name,
555: smeBSBObjectClass, parent->submenu_id,
556: XtNforeground, gui.menu_fg_pixel,
557: XtNbackground, gui.menu_bg_pixel,
558: XtNrightMargin, puller_width,
559: XtNrightBitmap, pullerBitmap,
560:
561: NULL);
562: XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
563: (XtPointer)menu);
564:
1.2 downsj 565: pullright_name = strnsave(menu->name,
566: STRLEN(menu->name) + strlen("-pullright"));
567: strcat((char *)pullright_name, "-pullright");
1.1 downsj 568: menu->submenu_id = XtVaCreatePopupShell(pullright_name,
569: simpleMenuWidgetClass, parent->submenu_id,
570: XtNforeground, gui.menu_fg_pixel,
571: XtNbackground, gui.menu_bg_pixel,
572: XtNtranslations, menuTrans,
573: NULL);
574: vim_free(pullright_name);
575:
576: XtOverrideTranslations(parent->submenu_id, parentTrans);
577: }
578: }
579:
580: void
581: gui_mch_add_menu_item(menu, parent)
582: GuiMenu *menu;
583: GuiMenu *parent;
584: {
585: menu->submenu_id = (Widget)0;
586: menu->id = XtVaCreateManagedWidget(menu->name,
587: smeBSBObjectClass, parent->submenu_id,
588: XtNforeground, gui.menu_fg_pixel,
589: XtNbackground, gui.menu_bg_pixel,
590: NULL);
591: XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
592: (XtPointer)menu);
593: }
594:
595: /*
596: * Destroy the machine specific menu widget.
597: */
598: void
599: gui_mch_destroy_menu(menu)
600: GuiMenu *menu;
601: {
602: if (menu->id != (Widget)NULL)
603: {
604: /*
605: * This is a hack for the Athena simpleMenuWidget to keep it from
606: * getting a BadValue error when it's last child is destroyed. We
607: * check to see if this is the last child and if so, go ahead and
608: * delete the parent ahead of time. The parent will delete it's
609: * children like all good widgets do.
610: */
611: if (XtParent(menu->id) != menuBar)
612: {
613: int num_children;
614:
615: XtVaGetValues(XtParent(menu->id),
616: XtNnumChildren, &num_children, NULL);
617: if (num_children <= 1)
618: XtDestroyWidget(XtParent(menu->id));
619: else
620: XtDestroyWidget(menu->id);
621: }
622: else
623: XtDestroyWidget(menu->id);
624: menu->id = (Widget)NULL;
625: }
626: }
627:
628: /*
629: * Reorder the menus so "Help" is the rightmost item on the menu.
630: */
631: static void
632: gui_athena_reorder_menus()
633: {
634: Widget *children;
635: Widget help_widget = (Widget)NULL;
636: int num_children;
637: int i;
638:
639: XtVaGetValues(menuBar,
640: XtNchildren, &children,
641: XtNnumChildren, &num_children,
642: NULL);
643:
644: XtUnmanageChildren(children, num_children);
645:
646: for (i = 0; i < num_children - 1; i++)
647: if (help_widget == (Widget)NULL)
648: {
649: if (strcmp((char *)XtName(children[i]), "Help") == 0)
650: {
651: help_widget = children[i];
652: children[i] = children[i + 1];
653: }
654: }
655: else
656: children[i] = children[i + 1];
657:
658: if (help_widget != (Widget)NULL)
659: children[num_children - 1] = help_widget;
660:
661: XtManageChildren(children, num_children);
662: }
663:
664:
665: /*
666: * Scrollbar stuff:
667: */
668:
669: void
670: gui_mch_create_which_components()
671: {
672: static int prev_which_scrollbars[3] = {-1, -1, -1};
673: static int prev_menu_is_active = -1;
674:
675: int i;
676: WIN *wp;
677:
678: /*
679: * When removing the left/right scrollbar and creating the right/left
680: * scrollbar, we have to force a redraw (the size of the text area doesn't
681: * change).
682: */
683: if (prev_which_scrollbars[SB_LEFT] != gui.which_scrollbars[SB_LEFT] &&
684: prev_which_scrollbars[SB_RIGHT] != gui.which_scrollbars[SB_RIGHT])
685: must_redraw = CLEAR;
686:
687: gui_x11_use_resize_callback(textArea, FALSE);
688:
689: for (i = 0; i < 3; i++)
690: {
691: if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
692: {
693: if (gui.which_scrollbars[i])
694: {
695: switch (i)
696: {
697: /* When adding the left one, we need to reorder them all */
698: case SB_LEFT:
699: XtUnmanageChild(textArea);
700: if (gui.which_scrollbars[SB_RIGHT])
701: XtUnmanageChild(scrollbarBox[SB_RIGHT]);
702: XtManageChild(scrollbarBox[SB_LEFT]);
703: XtManageChild(textArea);
704: if (gui.which_scrollbars[SB_RIGHT])
705: XtManageChild(scrollbarBox[SB_RIGHT]);
706:
707: /*
708: * When adding at the left and we have a bottom
709: * scrollbar, we need to reorder these too.
710: */
711: if (gui.which_scrollbars[SB_BOTTOM])
712: {
713: XtUnmanageChild(bottomScrollbar);
714: if (gui.which_scrollbars[SB_RIGHT])
715: XtUnmanageChild(rightBottomScrollFiller);
716:
717: XtManageChild(leftBottomScrollFiller);
718: XtManageChild(bottomScrollbar);
719: if (gui.which_scrollbars[SB_RIGHT])
720: XtManageChild(rightBottomScrollFiller);
721: }
722: break;
723:
724: case SB_RIGHT:
725: XtManageChild(rightBottomScrollFiller);
726: XtManageChild(scrollbarBox[i]);
727: break;
728:
729: case SB_BOTTOM:
730: /* Unmanage the bottom scrollbar and fillers */
731: XtUnmanageChild(leftBottomScrollFiller);
732: XtUnmanageChild(bottomScrollbar);
733: XtUnmanageChild(rightBottomScrollFiller);
734:
735: /*
736: * Now manage the bottom scrollbar and fillers that
737: * are supposed to be there.
738: */
739: if (gui.which_scrollbars[SB_LEFT])
740: XtManageChild(leftBottomScrollFiller);
741: XtManageChild(bottomScrollbar);
742: if (gui.which_scrollbars[SB_RIGHT])
743: XtManageChild(rightBottomScrollFiller);
744:
745: XtManageChild(scrollbarBox[i]);
746: break;
747: }
748: }
749: else
750: {
751: switch (i)
752: {
753: case SB_LEFT:
754: XtUnmanageChild(leftBottomScrollFiller);
755: break;
756:
757: case SB_RIGHT:
758: XtUnmanageChild(rightBottomScrollFiller);
759: break;
760: }
761: XtUnmanageChild(scrollbarBox[i]);
762: }
763: }
764: if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
765: {
766: if (i == SB_LEFT || i == SB_RIGHT)
767: {
768: if (gui.which_scrollbars[i])
769: {
770: /* Scrollbar box has just appeared */
771: gui.new_sb[i] = TRUE;
772: }
773: else if (prev_which_scrollbars[i] == TRUE)
774: {
775: /* Scrollbar box has just been deleted */
776: for (wp = firstwin; wp != NULL; wp = wp->w_next)
777: XtDestroyWidget(wp->w_scrollbar.id[i]);
778: }
779: }
780: }
781: prev_which_scrollbars[i] = gui.which_scrollbars[i];
782: }
783:
784: if (gui.menu_is_active != prev_menu_is_active)
785: {
786: if (gui.menu_is_active)
787: {
788: XtUnmanageChild(menuBar);
789: XtUnmanageChild(vimForm);
790: if (gui.which_scrollbars[SB_BOTTOM])
791: XtUnmanageChild(scrollbarBox[SB_BOTTOM]);
792:
793: XtManageChild(menuBar);
794: XtManageChild(vimForm);
795: if (gui.which_scrollbars[SB_BOTTOM])
796: XtManageChild(scrollbarBox[SB_BOTTOM]);
797: }
798: else
799: XtUnmanageChild(menuBar);
800: prev_menu_is_active = gui.menu_is_active;
801: }
802:
803: gui_x11_use_resize_callback(textArea, TRUE);
804: if (vimForm != (Widget)NULL && XtIsRealized(vimForm))
805: gui_mch_set_winsize();
806: }
807:
808:
809: /*
810: * Vertical scrollbar stuff:
811: */
812: void
813: gui_mch_update_scrollbars(worst_update, which_sb)
814: int worst_update;
815: int which_sb; /* SB_LEFT or SB_RIGHT */
816: {
817: WIN *wp;
818: GuiScrollbar *sb;
819: int idx;
820: Dimension h; /* Height of scrollbar (in pixels) */
821: Dimension y; /* Coord of top of scrollbar (in pixels) */
822: int tmp;
823: float val = 0., size = 0.;
824:
825: if (worst_update >= SB_UPDATE_HEIGHT)
826: {
827: XawPanedSetRefigureMode(scrollbarBox[which_sb], False);
828: gui_x11_use_resize_callback(textArea, FALSE);
829: }
830:
831: /*
832: * This has to get cleared manually since Athena doesn't tell us when the
833: * draggin' stops.
834: */
835: gui.dragged_sb = SB_NONE;
836:
837: for (wp = firstwin, idx = 0; wp; wp = wp->w_next, idx++)
838: {
839: sb = &wp->w_scrollbar;
840: if (sb->update[which_sb] >= SB_UPDATE_VALUE)
841: {
842: val = (float)(sb->value - 1) / (float)sb->max;
843: size = (float)sb->size / (float)sb->max;
844: }
845: if (sb->update[which_sb] == SB_UPDATE_CREATE)
846: {
847: sb->id[which_sb] = XtVaCreateManagedWidget("scrollBar",
848: vim_scrollbarWidgetClass, scrollbarBox[which_sb],
849: XtNborderWidth, 1,
850: XtNdefaultDistance, 0,
851: XtNallowResize, True,
852: XtNpreferredPaneSize, True,
853: XtNresizeToPreferred, True,
854: XtNskipAdjust, True,
855: XtNorientation, XtorientVertical,
856: XtNshowGrip, False,
857: XtNforeground, gui.scroll_fg_pixel,
858: XtNbackground, gui.scroll_bg_pixel,
859: NULL);
860: XtAddCallback(sb->id[which_sb], XtNjumpProc,
861: gui_athena_scroll_cb_jump, (XtPointer)wp);
862: XtAddCallback(sb->id[which_sb], XtNscrollProc,
863: gui_athena_scroll_cb_scroll, (XtPointer)wp);
864: }
865: if (sb->update[which_sb] >= SB_UPDATE_HEIGHT)
866: {
867: h = sb->height * gui.char_height
868: + sb->status_height * gui.char_height / 2;
869: y = wp->w_winpos * gui.char_height + gui.border_offset;
870:
871: if (wp == firstwin)
872: {
873: /* Height of top scrollbar includes width of top border */
874: h += gui.border_offset;
875: }
876: else
877: {
878: /*
879: * Height of other scrollbars includes half of status bar above
880: */
881: tmp = wp->w_prev->w_status_height * (gui.char_height + 1) / 2;
882: h += tmp;
883: y -= tmp;
884: }
885:
886: XtVaSetValues(sb->id[which_sb],
887: XtNheight, h,
888: XtNmin, h,
889: XtNmax, h,
890: XtNy, y,
891: NULL);
892: vim_XawScrollbarSetThumb(sb->id[which_sb], val, size, 1.0);
893: }
894: else if (sb->update[which_sb] == SB_UPDATE_VALUE)
895: {
896: vim_XawScrollbarSetThumb(sb->id[which_sb], val, size, 1.0);
897: }
898: sb->update[which_sb] = SB_UPDATE_NOTHING;
899: }
900:
901: if (worst_update >= SB_UPDATE_HEIGHT)
902: {
903: if (worst_update >= SB_UPDATE_CREATE)
904: gui_mch_reorder_scrollbars(which_sb);
905: XawPanedSetRefigureMode(scrollbarBox[which_sb], True);
906: gui_x11_use_resize_callback(textArea, TRUE);
907: }
908: }
909:
910: void
911: gui_mch_reorder_scrollbars(which_sb)
912: int which_sb;
913: {
914: WIN *wp;
915:
916: if (which_sb == SB_LEFT)
917: XtUnmanageChild(leftScrollbarFiller);
918: else
919: XtUnmanageChild(rightScrollbarFiller);
920:
921: for (wp = firstwin; wp != NULL; wp = wp->w_next)
922: if (wp->w_scrollbar.id[which_sb] != NULL)
923: XtUnmanageChild(wp->w_scrollbar.id[which_sb]);
924:
925: for (wp = firstwin; wp != NULL; wp = wp->w_next)
926: if (wp->w_scrollbar.id[which_sb] != NULL)
927: XtManageChild(wp->w_scrollbar.id[which_sb]);
928:
929: if (which_sb == SB_LEFT)
930: XtManageChild(leftScrollbarFiller);
931: else
932: XtManageChild(rightScrollbarFiller);
933:
934: }
935:
936: void
937: gui_mch_destroy_scrollbar(wp)
938: WIN *wp;
939: {
940: if (gui.which_scrollbars[SB_LEFT])
941: XtDestroyWidget(wp->w_scrollbar.id[SB_LEFT]);
942: if (gui.which_scrollbars[SB_RIGHT])
943: XtDestroyWidget(wp->w_scrollbar.id[SB_RIGHT]);
944: gui.num_scrollbars--;
945: }
946:
947:
948: /*
949: * Horizontal scrollbar stuff:
950: */
951: void
952: gui_mch_update_horiz_scrollbar(value, size, max)
953: int value;
954: int size;
955: int max;
956: {
957: static int prev_value = -1, prev_size = -1, prev_max = -1;
958: float val, shown, maxval;
959:
960: if (value == prev_value && size == prev_size && max == prev_max)
961: return;
962:
963: prev_value = value;
964: prev_size = size;
965: prev_max = max;
966:
967: if (max == 1) /* maximum is one more than maximal value */
968: {
969: val = 0.0;
970: shown = 1.0;
971: maxval = 0.0;
972: }
973: else
974: {
975: val = (float)value / (float)max;
976: shown = (float)size / (float)max;
977: maxval = 1.0;
978: }
979: vim_XawScrollbarSetThumb(bottomScrollbar, val, shown, maxval);
980: }
981:
982: Window
983: gui_mch_get_wid()
984: {
985: return( XtWindow(textArea) );
986: }
987:
988: static void
989: gui_athena_pullright_action(w, event, args, nargs)
990: Widget w;
991: XEvent *event;
992: String *args;
993: Cardinal *nargs;
994: {
995: Widget menuw;
996: Dimension width, height;
997: char_u *pullright_name;
998: Widget popup;
999:
1000: if (event->type != MotionNotify)
1001: return;
1002:
1003: /* Get the active entry for the current menu */
1004: if ((menuw = XawSimpleMenuGetActiveEntry(w)) == (Widget)NULL)
1005: return;
1006:
1007: XtVaGetValues(w,
1008: XtNwidth, &width,
1009: XtNheight, &height,
1010: NULL);
1011:
1.3 ! downsj 1012: if (event->xmotion.x >= (int)width || event->xmotion.y >= (int)height)
1.1 downsj 1013: return;
1014:
1015: /* We do the pull-off when the pointer is in the rightmost 1/4th */
1.3 ! downsj 1016: if (event->xmotion.x < (int)(width * 3) / 4)
1.1 downsj 1017: return;
1018:
1.2 downsj 1019: pullright_name = strnsave((char_u *)XtName(menuw),
1020: strlen(XtName(menuw)) + strlen("-pullright"));
1021: strcat((char *)pullright_name, "-pullright");
1.1 downsj 1022: popup = XtNameToWidget(w, pullright_name);
1023: vim_free(pullright_name);
1024:
1025: if (popup == (Widget)NULL)
1026: return;
1027:
1028: XtVaSetValues(popup,
1029: XtNx, event->xmotion.x_root,
1030: XtNy, event->xmotion.y_root - 7,
1031: NULL);
1032:
1033: XtPopup(popup, XtGrabExclusive);
1034: }