This is gui_athena.c in view mode; [Download] [Up]
/* vi:set ts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * GUI/Motif support by Robert Webb * Athena port by Bill Foster * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. */ #include <X11/StringDefs.h> #include <X11/Intrinsic.h> #include <X11/Xaw/Form.h> #include <X11/Xaw/SimpleMenu.h> #include <X11/Xaw/MenuButton.h> #include <X11/Xaw/SmeBSB.h> #include <X11/Xaw/Box.h> #include "vim.h" #include "globals.h" #include "proto.h" #include "option.h" #include "gui_at_sb.h" #define puller_width 19 #define puller_height 19 static char_u puller_bits[] = { 0x00,0x00,0xf8,0x00,0x00,0xf8,0xf8,0x7f,0xf8,0x04,0x80,0xf8,0x04,0x80,0xf9, 0x84,0x81,0xf9,0x84,0x83,0xf9,0x84,0x87,0xf9,0x84,0x8f,0xf9,0x84,0x8f,0xf9, 0x84,0x87,0xf9,0x84,0x83,0xf9,0x84,0x81,0xf9,0x04,0x80,0xf9,0x04,0x80,0xf9, 0xf8,0xff,0xf9,0xf0,0x7f,0xf8,0x00,0x00,0xf8,0x00,0x00,0xf8 }; extern Widget vimShell; static Widget vimForm = (Widget)NULL; static Widget textArea; static Widget menuBar; static void gui_athena_scroll_cb_jump __ARGS((Widget, XtPointer, XtPointer)); static void gui_athena_scroll_cb_scroll __ARGS((Widget, XtPointer, XtPointer)); static void gui_athena_reorder_menus __ARGS((void)); static void gui_athena_pullright_action __ARGS((Widget, XEvent *, String *, Cardinal *)); static void gui_athena_pullleft_action __ARGS((Widget, XEvent *, String *, Cardinal *)); static Widget get_popup_entry __ARGS((Widget w)); static XtActionsRec pullAction[2] = {{ "menu-pullright", (XtActionProc)gui_athena_pullright_action}, { "menu-pullleft", (XtActionProc)gui_athena_pullleft_action}}; static XtTranslations parentTrans, menuTrans, supermenuTrans; static Pixmap pullerBitmap; /* * Scrollbar callback (XtNjumpProc) for when the scrollbar is dragged with the * left or middle mouse button. */ static void gui_athena_scroll_cb_jump(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { GuiScrollbar *sb, *sb_info; long_u value; sb = gui_find_scrollbar((long)client_data); if (sb == NULL) return; else if (sb->wp != NULL) /* Left or right scrollbar */ { /* * Careful: need to get scrollbar info out of first (left) scrollbar * for window, but keep real scrollbar too because we must pass it to * gui_drag_scrollbar(). */ sb_info = &sb->wp->w_scrollbars[0]; } else /* Bottom scrollbar */ sb_info = sb; value = (long_u)(*((float *)call_data) * (float)(sb_info->max + 1) + 0.001); if (value > sb_info->max) value = sb_info->max; gui_drag_scrollbar(sb, value, TRUE); } /* * Scrollbar callback (XtNscrollProc) for paging up or down with the left or * right mouse buttons. */ static void gui_athena_scroll_cb_scroll(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { GuiScrollbar *sb, *sb_info; long value; int data = (int)call_data; int page; sb = gui_find_scrollbar((long)client_data); if (sb == NULL) return; else if (sb->wp != NULL) /* Left or right scrollbar */ { /* * Careful: need to get scrollbar info out of first (left) scrollbar * for window, but keep real scrollbar too because we must pass it to * gui_drag_scrollbar(). */ sb_info = &sb->wp->w_scrollbars[0]; if (sb_info->size > 5) page = sb_info->size - 2; /* use two lines of context */ else page = sb_info->size; switch (data) { case ONE_LINE_DATA: data = 1; break; case -ONE_LINE_DATA: data = -1; break; case ONE_PAGE_DATA: data = page; break; case -ONE_PAGE_DATA: data = -page; break; case END_PAGE_DATA: data = sb_info->max; break; case -END_PAGE_DATA: data = -sb_info->max; break; default: data = 0; break; } } else /* Bottom scrollbar */ { sb_info = sb; if (data < -1) data = -(Columns - 5); else if (data > 1) data = (Columns - 5); } value = sb_info->value + data; if (value > sb_info->max) value = sb_info->max; else if (value < 0) value = 0; gui_drag_scrollbar(sb, value, FALSE); } /* * Create all the Athena widgets necessary. */ void gui_x11_create_widgets() { /* * We don't have any borders handled internally by the textArea to worry * about so only skip over the configured border width. */ gui.border_offset = gui.border_width; XtInitializeWidgetClass(formWidgetClass); XtInitializeWidgetClass(boxWidgetClass); XtInitializeWidgetClass(coreWidgetClass); XtInitializeWidgetClass(menuButtonWidgetClass); XtInitializeWidgetClass(simpleMenuWidgetClass); XtInitializeWidgetClass(vim_scrollbarWidgetClass); /* The form containing all the other widgets */ vimForm = XtVaCreateManagedWidget("vimForm", formWidgetClass, vimShell, XtNborderWidth, 0, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, NULL); /* The top menu bar */ menuBar = XtVaCreateManagedWidget("menuBar", boxWidgetClass, vimForm, XtNresizable, True, XtNtop, XawChainTop, XtNbottom, XawChainTop, XtNleft, XawChainLeft, XtNright, XawChainRight, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, XtNborderColor, gui.menu_fg_pixel, NULL); /* The text area. */ textArea = XtVaCreateManagedWidget("textArea", coreWidgetClass, vimForm, XtNresizable, True, XtNtop, XawChainTop, XtNbottom, XawChainTop, XtNleft, XawChainLeft, XtNright, XawChainLeft, XtNbackground, gui.back_pixel, XtNborderWidth, 0, NULL); /* * Callbacks for textArea, vimForm, and vimShell. */ XtAddEventHandler(textArea, VisibilityChangeMask, FALSE, gui_x11_visibility_cb, (XtPointer)0); XtAddEventHandler(textArea, ExposureMask, FALSE, gui_x11_expose_cb, (XtPointer)0); XtAddEventHandler(vimForm, StructureNotifyMask, FALSE, gui_x11_resize_window_cb, (XtPointer)0); XtAddEventHandler(vimShell, FocusChangeMask, FALSE, gui_x11_focus_change_cb, (XtPointer)0); XtAddEventHandler(vimForm, KeyPressMask, FALSE, gui_x11_key_hit_cb, (XtPointer)0); XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, FALSE, gui_x11_mouse_cb, (XtPointer)0); parentTrans = XtParseTranslationTable("<EnterWindow>: highlight()\n<LeaveWindow>:\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight() menu-pullright()"); menuTrans = XtParseTranslationTable("<EnterWindow>: highlight()\n<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight() menu-pullright()"); supermenuTrans = XtParseTranslationTable("<EnterWindow>: highlight() menu-pullleft()\n<LeaveWindow>:\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>:"); XtAppAddActions(XtWidgetToApplicationContext(vimForm), pullAction, 2); pullerBitmap = XCreateBitmapFromData(gui.dpy, DefaultRootWindow(gui.dpy), (char *)puller_bits, puller_width, puller_height); } void gui_mch_set_text_area_pos(x, y, w, h) int x; int y; int w; int h; { XtUnmanageChild(textArea); XtVaSetValues(textArea, XtNhorizDistance, x, XtNvertDistance, y, XtNwidth, w, XtNheight, h, NULL); XtManageChild(textArea); } /* * Menu stuff. */ void gui_mch_enable_menu(flag) int flag; { if (flag) XtManageChild(menuBar); else XtUnmanageChild(menuBar); } void gui_mch_set_menu_pos(x, y, w, h) int x; int y; int w; int h; { Dimension border; XtUnmanageChild(menuBar); XtVaGetValues(menuBar, XtNborderWidth, &border, NULL); XtVaSetValues(menuBar, XtNhorizDistance, x, XtNvertDistance, y, XtNwidth, w - 2 * border, XtNheight, h - 2 * border, NULL); XtManageChild(menuBar); } void gui_mch_add_menu(menu, parent) GuiMenu *menu; GuiMenu *parent; { char_u *pullright_name; Dimension height, space, border; if (parent == NULL) { menu->id = XtVaCreateManagedWidget(menu->name, menuButtonWidgetClass, menuBar, XtNmenuName, menu->name, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, NULL); menu->submenu_id = XtVaCreatePopupShell(menu->name, simpleMenuWidgetClass, menu->id, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, NULL); /* * When we add a top-level item to the menu bar, we can figure out how * high the menu bar should be. */ XtVaGetValues(menuBar, XtNvSpace, &space, XtNborderWidth, &border, NULL); XtVaGetValues(menu->id, XtNheight, &height, NULL); gui.menu_height = height + 2 * (space + border); gui_athena_reorder_menus(); } else { menu->id = XtVaCreateManagedWidget(menu->name, smeBSBObjectClass, parent->submenu_id, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, XtNrightMargin, puller_width, XtNrightBitmap, pullerBitmap, NULL); XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb, (XtPointer)menu); pullright_name = vim_strnsave(menu->name, STRLEN(menu->name) + strlen("-pullright")); strcat((char *)pullright_name, "-pullright"); menu->submenu_id = XtVaCreatePopupShell(pullright_name, simpleMenuWidgetClass, parent->submenu_id, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, XtNtranslations, menuTrans, NULL); vim_free(pullright_name); XtOverrideTranslations(parent->submenu_id, parentTrans); } } void gui_mch_add_menu_item(menu, parent) GuiMenu *menu; GuiMenu *parent; { menu->submenu_id = (Widget)0; menu->id = XtVaCreateManagedWidget(menu->name, smeBSBObjectClass, parent->submenu_id, XtNforeground, gui.menu_fg_pixel, XtNbackground, gui.menu_bg_pixel, NULL); XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb, (XtPointer)menu); } /* * Destroy the machine specific menu widget. */ void gui_mch_destroy_menu(menu) GuiMenu *menu; { Widget parent; if (menu->submenu_id != (Widget)0) { XtDestroyWidget(menu->submenu_id); menu->submenu_id = (Widget)0; } if (menu->id != (Widget)0) { /* * This is a hack to stop the Athena simpleMenuWidget from getting a * BadValue error when a menu's last child is destroyed. We check to * see if this is the last child and if so, don't delete it. The parent * will be deleted soon anyway, and it will delete it's children like * all good widgets do. */ parent = XtParent(menu->id); if (parent != menuBar) { int num_children; XtVaGetValues(parent, XtNnumChildren, &num_children, NULL); if (num_children > 1) XtDestroyWidget(menu->id); } else XtDestroyWidget(menu->id); menu->id = (Widget)0; } } /* * Reorder the menus so "Help" is the rightmost item on the menu. */ static void gui_athena_reorder_menus() { Widget *children; Widget help_widget = (Widget)NULL; int num_children; int i; XtVaGetValues(menuBar, XtNchildren, &children, XtNnumChildren, &num_children, NULL); XtUnmanageChildren(children, num_children); for (i = 0; i < num_children - 1; i++) if (help_widget == (Widget)NULL) { if (strcmp((char *)XtName(children[i]), "Help") == 0) { help_widget = children[i]; children[i] = children[i + 1]; } } else children[i] = children[i + 1]; if (help_widget != (Widget)NULL) children[num_children - 1] = help_widget; XtManageChildren(children, num_children); } /* * Scrollbar stuff. */ void gui_mch_set_scrollbar_thumb(sb, val, size, max) GuiScrollbar *sb; int val; int size; int max; { float v, s; /* * Athena scrollbar must go from 0.0 to 1.0. */ if (max == 0) { /* So you can't scroll it at all (normally it scrolls past end) */ vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0); } else { v = (float)val / (float)(max + 1); s = (float)size / (float)(max + 1); vim_XawScrollbarSetThumb(sb->id, v, s, 1.0); } } void gui_mch_set_scrollbar_pos(sb, x, y, w, h) GuiScrollbar *sb; int x; int y; int w; int h; { XtUnmanageChild(sb->id); XtVaSetValues(sb->id, XtNhorizDistance, x, XtNvertDistance, y, XtNwidth, w, XtNheight, h, NULL); XtManageChild(sb->id); } void gui_mch_create_scrollbar(sb, orient) GuiScrollbar *sb; int orient; /* SBAR_VERT or SBAR_HORIZ */ { sb->id = XtVaCreateWidget("scrollBar", vim_scrollbarWidgetClass, vimForm, XtNresizable, True, XtNtop, XawChainTop, XtNbottom, XawChainTop, XtNleft, XawChainLeft, XtNright, XawChainLeft, XtNborderWidth, 0, XtNorientation, (orient == SBAR_VERT) ? XtorientVertical : XtorientHorizontal, XtNforeground, gui.scroll_fg_pixel, XtNbackground, gui.scroll_bg_pixel, NULL); XtAddCallback(sb->id, XtNjumpProc, gui_athena_scroll_cb_jump, (XtPointer)sb->ident); XtAddCallback(sb->id, XtNscrollProc, gui_athena_scroll_cb_scroll, (XtPointer)sb->ident); vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0); } void gui_mch_destroy_scrollbar(sb) GuiScrollbar *sb; { XtDestroyWidget(sb->id); } /* * Miscellaneous stuff: */ Window gui_x11_get_wid() { return( XtWindow(textArea) ); } static void gui_athena_pullright_action(w, event, args, nargs) Widget w; XEvent *event; String *args; Cardinal *nargs; { Dimension width, height; Widget popup; if (event->type != MotionNotify) return; XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL); if (event->xmotion.x >= (int)width || event->xmotion.y >= (int)height) return; /* We do the pull-off when the pointer is in the rightmost 1/4th */ if (event->xmotion.x < (int)(width * 3) / 4) return; popup = get_popup_entry(w); if (popup == (Widget)NULL) return; /* Don't Popdown the previous submenu now */ XtOverrideTranslations(w, supermenuTrans); XtVaSetValues(popup, XtNx, event->xmotion.x_root, XtNy, event->xmotion.y_root - 7, NULL); XtOverrideTranslations(popup, menuTrans); XtPopup(popup, XtGrabNonexclusive); } /* * Called when a submenu with another submenu gets focus again. */ static void gui_athena_pullleft_action(w, event, args, nargs) Widget w; XEvent *event; String *args; Cardinal *nargs; { Widget popup; Widget parent; if (event->type != EnterNotify) return; /* Do Popdown the submenu now */ popup = get_popup_entry(w); if (popup != (Widget)NULL) XtPopdown(popup); /* If this is the toplevel menu item, set parentTrans */ if ((parent = XtParent(w)) != (Widget)NULL && XtParent(parent) == menuBar) XtOverrideTranslations(w, parentTrans); else XtOverrideTranslations(w, menuTrans); } static Widget get_popup_entry(w) Widget w; { Widget menuw; char_u *pullright_name; Widget popup; /* Get the active entry for the current menu */ if ((menuw = XawSimpleMenuGetActiveEntry(w)) == (Widget)NULL) return NULL; pullright_name = vim_strnsave((char_u *)XtName(menuw), strlen(XtName(menuw)) + strlen("-pullright")); strcat((char *)pullright_name, "-pullright"); popup = XtNameToWidget(w, pullright_name); vim_free(pullright_name); return popup; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.