This is gui_motif.c in view mode; [Download] [Up]
/* vi:set ts=4 sw=4:
*
* VIM - Vi IMproved by Bram Moolenaar
* GUI/Motif support by Robert Webb
*
* 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 <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/CascadeB.h>
#include <Xm/ScrollBar.h>
#include <Xm/MenuShell.h>
#if (XmVersion >= 1002)
# include <Xm/RepType.h>
#endif
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/StringDefs.h>
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "option.h"
extern Widget vimShell;
static Widget vimForm;
static Widget textArea;
static Widget menuBar;
/*
* Call-back routines.
*/
static void
scroll_cb(w, client_data, call_data)
Widget w;
XtPointer client_data, call_data;
{
GuiScrollbar *sb;
int value, dragging;
sb = gui_find_scrollbar((long)client_data);
value = ((XmScrollBarCallbackStruct *)call_data)->value;
dragging = (((XmScrollBarCallbackStruct *)call_data)->reason == XmCR_DRAG);
gui_drag_scrollbar(sb, value, dragging);
}
/*
* End of call-back routines
*/
/*
* Create all the motif widgets necessary.
*/
void
gui_x11_create_widgets()
{
#if 0
Dimension n;
#endif
/*
* Start out by adding the configured border width into the border offset
*/
gui.border_offset = gui.border_width;
/*
* Install the tearOffModel resource converter.
*/
#if (XmVersion >= 1002)
XmRepTypeInstallTearOffModelConverter();
#endif
XtInitializeWidgetClass(xmFormWidgetClass);
XtInitializeWidgetClass(xmRowColumnWidgetClass);
XtInitializeWidgetClass(xmPrimitiveWidgetClass);
XtInitializeWidgetClass(xmCascadeButtonWidgetClass);
XtInitializeWidgetClass(xmMenuShellWidgetClass);
XtInitializeWidgetClass(xmPushButtonWidgetClass);
XtInitializeWidgetClass(xmScrollBarWidgetClass);
vimForm = XtVaCreateManagedWidget("vimForm",
xmFormWidgetClass, vimShell,
XmNborderWidth, 0,
XmNhighlightThickness, 0,
XmNshadowThickness, 0,
XmNmarginWidth, 0,
XmNmarginHeight, 0,
XmNresizePolicy, XmRESIZE_ANY,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
NULL);
textArea = XtVaCreateManagedWidget("textArea",
xmPrimitiveWidgetClass, vimForm,
XmNbackground, gui.back_pixel,
XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_OPPOSITE_FORM,
XmNbottomAttachment, XmATTACH_OPPOSITE_FORM,
/*
* These take some control away from the user, but avoids making them
* add resources to get a decent looking setup.
*/
XmNborderWidth, 0,
XmNhighlightThickness, 0,
XmNshadowThickness, 0,
NULL);
#if 0 /* nobody knows why these are here, since XmNhighlightThickness and
XmNshadowThickness are set to 0 above. Keep them around, in
case somebody complains */
/*
* If there are highlight or shadow borders, add their widths to our
* border offset so we don't draw over them.
*/
XtVaGetValues(textArea, XmNhighlightThickness, &n, NULL);
gui.border_offset += n;
XtVaGetValues(textArea, XmNshadowThickness, &n, NULL);
gui.border_offset += n;
#endif
menuBar = XtVaCreateManagedWidget("menuBar",
xmRowColumnWidgetClass, vimForm,
#if (XmVersion >= 1002)
XmNtearOffModel, XmTEAR_OFF_ENABLED,
#endif
XmNrowColumnType, XmMENU_BAR,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_OPPOSITE_FORM,
XmNrightOffset, 0, /* Always stick to rigth hand side */
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(textArea, KeyPressMask, FALSE, gui_x11_key_hit_cb,
(XtPointer)0);
XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask, FALSE, gui_x11_mouse_cb, (XtPointer)0);
}
void
gui_mch_set_text_area_pos(x, y, w, h)
int x;
int y;
int w;
int h;
{
XtVaSetValues(textArea,
XmNleftOffset, x,
XmNtopOffset, y,
XmNrightOffset, -x - w,
XmNbottomOffset, -y - h,
NULL);
}
/*
* 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;
{
XtVaSetValues(menuBar,
XmNleftOffset, x,
XmNtopOffset, y,
XmNbottomOffset, -y - h,
NULL);
}
void
gui_mch_add_menu(menu, parent)
GuiMenu *menu;
GuiMenu *parent;
{
Dimension height, margin;
#if (XmVersion >= 1002)
Widget widget;
XmString label = XmStringCreate((char *)menu->name,
XmFONTLIST_DEFAULT_TAG);
#else
XmString label = XmStringCreate((char *)menu->name,
XmSTRING_DEFAULT_CHARSET);
#endif
Widget shell;
menu->id = XtVaCreateWidget("subMenu",
xmCascadeButtonWidgetClass,
(parent == NULL) ? menuBar : parent->submenu_id,
XmNlabelString, label,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
NULL);
/* XtFree((char *)label); makes Lesstif crash */
shell = XtVaCreateWidget("subMenuShell",
xmMenuShellWidgetClass, menu->id,
XmNwidth, 1,
XmNheight, 1,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
NULL);
menu->submenu_id = XtVaCreateWidget("rowColumnMenu",
xmRowColumnWidgetClass, shell,
XmNrowColumnType, XmMENU_PULLDOWN,
#if (XmVersion >= 1002)
XmNtearOffModel, XmTEAR_OFF_ENABLED,
#endif
NULL);
#if (XmVersion >= 1002)
/* Set the colors for the tear off widget */
if ((widget = XmGetTearOffControl(menu->submenu_id)) != (Widget)NULL)
XtVaSetValues(widget,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
NULL);
#endif
XtVaSetValues(menu->id,
XmNsubMenuId, menu->submenu_id,
NULL);
/*
* The "Help" menu is a special case, and should be placed at the far right
* hand side of the menu-bar.
*/
if (parent == NULL && STRCMP((char *)menu->name, "Help") == 0)
XtVaSetValues(menuBar,
XmNmenuHelpWidget, menu->id,
NULL);
if (parent == 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,
XmNmarginHeight, &margin,
NULL);
XtVaGetValues(menu->id,
XmNheight, &height,
NULL);
gui.menu_height = height + 2 * margin;
}
}
void
gui_mch_add_menu_item(menu, parent)
GuiMenu *menu;
GuiMenu *parent;
{
#if (XmVersion >= 1002)
XmString label = XmStringCreate((char *)menu->name,
XmFONTLIST_DEFAULT_TAG);
#else
XmString label = XmStringCreate((char *)menu->name,
XmSTRING_DEFAULT_CHARSET);
#endif
menu->submenu_id = (Widget)0;
menu->id = XtVaCreateWidget("subMenu",
xmPushButtonWidgetClass, parent->submenu_id,
XmNlabelString, label,
XmNforeground, gui.menu_fg_pixel,
XmNbackground, gui.menu_bg_pixel,
NULL);
/* XtFree((char *)label); makes Lesstif crash */
XtAddCallback(menu->id, XmNactivateCallback, 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 LessTif from crashing 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;
}
}
/*
* Scrollbar stuff.
*/
void
gui_mch_set_scrollbar_thumb(sb, val, size, max)
GuiScrollbar *sb;
int val;
int size;
int max;
{
XtVaSetValues(sb->id,
XmNvalue, val,
XmNsliderSize, size,
XmNpageIncrement, (size > 2 ? size - 2 : 1),
XmNmaximum, max + 1, /* Motif has max one past the end */
NULL);
}
void
gui_mch_set_scrollbar_pos(sb, x, y, w, h)
GuiScrollbar *sb;
int x;
int y;
int w;
int h;
{
XtVaSetValues(sb->id,
XmNleftOffset, x,
XmNtopOffset, y,
XmNrightOffset, -x - w,
XmNbottomOffset, -y - h,
NULL);
}
void
gui_mch_create_scrollbar(sb, orient)
GuiScrollbar *sb;
int orient; /* SBAR_VERT or SBAR_HORIZ */
{
sb->id = XtVaCreateManagedWidget("scrollBar",
xmScrollBarWidgetClass, vimForm,
XmNshadowThickness, 1,
XmNminimum, 0,
XmNorientation, (orient == SBAR_VERT) ? XmVERTICAL
: XmHORIZONTAL,
XmNforeground, gui.scroll_fg_pixel,
XmNbackground, gui.scroll_fg_pixel,
XmNtroughColor, gui.scroll_bg_pixel,
XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_OPPOSITE_FORM,
XmNbottomAttachment, XmATTACH_OPPOSITE_FORM,
NULL);
XtAddCallback(sb->id, XmNvalueChangedCallback,
scroll_cb, (XtPointer)sb->ident);
XtAddCallback(sb->id, XmNdragCallback,
scroll_cb, (XtPointer)sb->ident);
}
void
gui_mch_destroy_scrollbar(sb)
GuiScrollbar *sb;
{
XtDestroyWidget(sb->id);
}
/*
* Miscellaneous stuff:
*/
Window
gui_x11_get_wid()
{
return(XtWindow(textArea));
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.