ftp.nice.ch/pub/next/unix/editor/vim-5.0f.s.tar.gz#/vim-5.0f/src/gui_motif.c

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.