diff oldXMenu/Internal.c @ 25858:bbce331da1be

#
author Dave Love <fx@gnu.org>
date Sun, 03 Oct 1999 19:36:13 +0000
parents
children 23a1cea22d13
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oldXMenu/Internal.c	Sun Oct 03 19:36:13 1999 +0000
@@ -0,0 +1,1006 @@
+#include "copyright.h"
+
+/* $Header: /u/src/emacs/19.0/oldXMenu/RCS/Internal.c,v 1.1 1992/04/11 22:10:20 jimb Exp $ */
+/* Copyright    Massachusetts Institute of Technology    1985	*/
+
+/*
+ * XMenu:	MIT Project Athena, X Window system menu package
+ *
+ * 	XMenuInternal.c - XMenu internal (not user visible) routines.
+ *
+ *	Author:		Tony Della Fera, DEC
+ *			November, 1985
+ *
+ */
+
+#include <config.h>
+#include "XMenuInt.h"
+
+/*
+ * Toggle color macro.
+ */
+#define toggle_color(x) \
+	((x) == menu->bkgnd_color ? menu->s_frg_color : menu->bkgnd_color)
+
+/*
+ * Internal Window creation queue sizes.
+ */
+#define S_QUE_SIZE	300
+#define P_QUE_SIZE	20
+#define BUFFER_SIZE	(S_QUE_SIZE >= P_QUE_SIZE ? S_QUE_SIZE : P_QUE_SIZE)
+
+
+/*
+ * XMWinQue - Internal window creation queue datatype.
+ */
+typedef struct _xmwinquedef {
+    int sq_size;
+    XMSelect *sq[S_QUE_SIZE];
+    XMSelect **sq_ptr;
+    int pq_size;
+    XMPane *pq[P_QUE_SIZE];
+    XMPane **pq_ptr;
+} XMWinQue;
+
+/*
+ * _XMWinQue - Internal static window creation queue.
+ */
+static Bool _XMWinQueIsInit = False;
+static XMWinQue _XMWinQue;
+
+/*
+ * _XMErrorCode - Global XMenu error code.
+ */
+int _XMErrorCode = XME_NO_ERROR; 
+/*
+ * _XMErrorList - Global XMenu error code description strings.
+ */
+char *
+_XMErrorList[XME_CODE_COUNT] = {
+    "No error",				/* XME_NO_ERROR */
+    "Menu not initialized",		/* XME_NOT_INIT */
+    "Argument out of bounds",		/* XME_ARG_BOUNDS */
+    "Pane not found",			/* XME_P_NOT_FOUND */
+    "Selection not found",		/* XME_S_NOT_FOUND */
+    "Invalid menu style parameter",	/* XME_STYLE_PARAM */
+    "Unable to grab mouse",		/* XME_GRAB_MOUSE */
+    "Unable to interpret locator",	/* XME_INTERP_LOC */
+    "Unable to calloc memory",		/* XME_CALLOC */
+    "Unable to create XAssocTable",	/* XME_CREATE_ASSOC */
+    "Unable to store bitmap",		/* XME_STORE_BITMAP */
+    "Unable to make tile pixmaps",	/* XME_MAKE_TILES */
+    "Unable to make pixmap",		/* XME_MAKE_PIXMAP */
+    "Unable to create cursor",		/* XME_CREATE_CURSOR */
+    "Unable to open font",		/* XME_OPEN_FONT */
+    "Unable to create windows",		/* XME_CREATE_WINDOW */
+    "Unable to create transparencies",	/* XME_CREATE_TRANSP */
+};
+
+/*
+ * _XMEventHandler - Internal event handler variable.
+ */
+int (*_XMEventHandler)() = NULL;
+
+
+
+/*
+ * _XMWinQueInit - Internal routine to initialize the window
+ *		   queue.
+ */
+_XMWinQueInit()
+{
+    /*
+     * If the queue is not initialized initialize it.
+     */
+    if (!_XMWinQueIsInit) {
+	/*
+	 * Blank the queue structure.
+	 */
+	register int i;
+
+	for (i = 0; i < S_QUE_SIZE; i++)
+	  _XMWinQue.sq[i] = 0;
+
+	for (i = 0; i < P_QUE_SIZE; i++)
+	  _XMWinQue.pq[i] = 0;
+
+	_XMWinQue.sq_size = _XMWinQue.pq_size = 0;
+
+	/*
+	 * Initialize the next free location pointers.
+	 */
+	_XMWinQue.sq_ptr = _XMWinQue.sq;
+	_XMWinQue.pq_ptr = _XMWinQue.pq;
+    }
+}
+
+
+
+/*
+ * _XMWinQueAddPane - Internal routine to add a pane to the pane
+ *		      window queue.
+ */
+int
+_XMWinQueAddPane(display, menu, p_ptr)
+    register Display *display;
+    register XMenu *menu;	/* Menu being manipulated. */
+    register XMPane *p_ptr;	/* XMPane being queued. */
+{
+    /*
+     * If the queue is currently full then flush it.
+     */
+    if (_XMWinQue.pq_size == P_QUE_SIZE) {
+	if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
+    }
+
+    /*
+     * Insert the new XMPane pointer and increment the queue pointer
+     * and the queue size.
+     */
+    *_XMWinQue.pq_ptr = p_ptr;
+    _XMWinQue.pq_ptr++;
+    _XMWinQue.pq_size++;
+
+    /*
+     * All went well, return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMWinQueAddSelection - Internal routine to add a selection to
+ *			   the selection window queue.
+ */
+int
+_XMWinQueAddSelection(display, menu, s_ptr)
+    register Display *display;
+    register XMenu *menu;	/* Menu being manipulated. */
+    register XMSelect *s_ptr;	/* XMSelection being queued. */
+{
+    /*
+     * If this entry will overflow the queue then flush it.
+     */
+    if (_XMWinQue.sq_size == S_QUE_SIZE) {
+	if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
+    }
+
+    /*
+     * Insert the new XMSelect pointer and increment the queue pointer
+     * and the queue size.
+     */
+    *_XMWinQue.sq_ptr = s_ptr;
+    _XMWinQue.sq_ptr++;
+    _XMWinQue.sq_size++;
+
+    /*
+     * All went well, return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMWinQueFlush - Internal routine to flush the pane and
+ *		    selection window queues.
+ */
+int
+_XMWinQueFlush(display, menu, pane, select)
+    register Display *display;
+    register XMenu *menu;		/* Menu being manipulated. */
+    register XMPane *pane;		/* Current pane. */
+{
+    register int pq_index;		/* Pane queue index. */
+    register int sq_index;		/* Selection queue index. */
+    register XMPane *p_ptr;		/* XMPane pointer. */
+    register XMSelect *s_ptr;   	/* XMSelect pointer. */
+    unsigned long valuemask;    	/* Which attributes to set. */
+    XSetWindowAttributes *attributes; 	/* Attributes to be set. */
+
+    /*
+     * If the pane window queue is not empty...
+     */
+    
+    if (_XMWinQue.pq_size > 0) {
+	/*
+	 * set up attributes for pane window to be created.
+	 */
+	valuemask = (CWBackPixmap | CWBorderPixel | CWOverrideRedirect);
+	attributes = (XSetWindowAttributes *)malloc(sizeof(XSetWindowAttributes));
+	attributes->border_pixel = menu->p_bdr_color;
+	attributes->background_pixmap = menu->inact_pixmap;
+	attributes->override_redirect = True;
+	
+	/*
+	 * Create all the pending panes in order, so that the
+	 * current pane will be on top, with the others
+	 * stacked appropriately under it.
+	 */
+	for (pq_index = _XMWinQue.pq_size - 1;
+	     pq_index >= 0;
+	     pq_index--) 
+	  {
+	      p_ptr = _XMWinQue.pq[pq_index];  /* Retrieve next pane. */
+	      if (p_ptr == pane) break;
+	      p_ptr->window = XCreateWindow(display,
+					    menu->parent,
+					    p_ptr->window_x,
+					    p_ptr->window_y,
+					    p_ptr->window_w,
+					    p_ptr->window_h,
+					    menu->p_bdr_width,
+					    CopyFromParent,
+					    InputOutput,
+					    CopyFromParent,
+					    valuemask,
+					    attributes);
+	      XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
+	      XSelectInput(display, p_ptr->window, menu->p_events);
+	  }
+	for (pq_index = 0;
+	     pq_index < _XMWinQue.pq_size;
+	     pq_index++) 
+	  {
+	      p_ptr = _XMWinQue.pq[pq_index];	/* Retrieve next pane. */
+	      p_ptr->window = XCreateWindow(display,
+					    menu->parent,
+					    p_ptr->window_x,
+					    p_ptr->window_y,
+					    p_ptr->window_w,
+					    p_ptr->window_h,
+					    menu->p_bdr_width,
+					    CopyFromParent,
+					    InputOutput,
+					    CopyFromParent,
+					    valuemask,
+					    attributes);
+	      XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
+	      XSelectInput(display, p_ptr->window, menu->p_events);
+	      if (p_ptr == pane) break;
+	}
+
+	/*
+	 * Reset the pane queue pointer and size.
+	 */
+	_XMWinQue.pq_size = 0;
+	_XMWinQue.pq_ptr = _XMWinQue.pq;
+    }
+
+    /*
+     * If the selection window queue is not empty...
+     */
+    
+    if (_XMWinQue.sq_size > 0) {
+
+	for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) {
+	    /*
+	     * Retrieve the XMSelect pointer.
+	     */
+	    s_ptr = _XMWinQue.sq[sq_index];
+	    s_ptr->window = XCreateWindow(display,
+				   s_ptr->parent_p->window,
+				   s_ptr->window_x,
+				   s_ptr->window_y,
+				   s_ptr->window_w,
+				   s_ptr->window_h,
+				   0,                /* border width*/
+				   CopyFromParent,
+				   InputOnly,
+				   CopyFromParent,
+				   0,
+				   attributes);
+	    
+	    /*
+	     * Insert the new window id and its
+	     * associated XMSelect structure into the 
+	     * association table.
+	     */
+	    XMakeAssoc(display, menu->assoc_tab, s_ptr->window, s_ptr);
+	    XSelectInput(display, s_ptr->window, menu->s_events);
+	}
+
+	/*
+	 * Reset the selection queue pointer and size.
+	 */
+	_XMWinQue.sq_size = 0;
+	_XMWinQue.sq_ptr = _XMWinQue.sq;
+    }
+
+    /*
+     * Flush X's internal queues.
+     */
+    XFlush(display);
+
+    /*
+     * All went well, return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMGetPanePtr - 	Given a menu pointer and a pane index number, return
+ *			a pane pointer that points to the indexed pane.
+ */
+XMPane *
+_XMGetPanePtr(menu, p_num)
+    register XMenu *menu;	/* Menu to find the pane in. */
+    register int p_num;		/* Index number of pane to find. */
+{
+    register XMPane *p_ptr;	/* Pane pointer to be returned. */
+    register int i;		/* Loop counter. */
+
+    /*
+     * Is the pane number out of range?
+     */
+    if ((p_num < 0) || (p_num > (menu->p_count - 1))) {
+	_XMErrorCode = XME_P_NOT_FOUND;
+	return(NULL);
+    }
+
+    /*
+     * Find the right pane.
+     */
+    p_ptr = menu->p_list->next;
+    for (i = 0; i < p_num; i++) p_ptr = p_ptr->next;
+
+    /*
+     * Return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(p_ptr);
+}
+
+
+
+/*
+ * _XMGetSelectionPtr -	Given pane pointer and a selection index number,
+ *			return a selection pointer that points to the
+ *			indexed selection.
+ */
+XMSelect *
+_XMGetSelectionPtr(p_ptr, s_num)
+    register XMPane *p_ptr;	/* Pane to find the selection in. */
+    register int s_num;		/* Index number of the selection to find. */
+{
+    register XMSelect *s_ptr;	/* Selection pointer to be returned. */
+    register int i;		/* Loop counter. */
+    
+    /*
+     * Is the selection number out of range?
+     */
+    if ((s_num < 0) || (s_num > (p_ptr->s_count - 1))) {
+	_XMErrorCode = XME_S_NOT_FOUND;
+	return(NULL);
+    }
+
+    /*
+     * Find the right selection.
+     */
+    s_ptr = p_ptr->s_list->next;
+    for (i = 0; i < s_num; i++) s_ptr = s_ptr->next;
+
+    /*
+     * Return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(s_ptr);
+}
+
+
+
+/*
+ * _XMRecomputeGlobals - Internal subroutine to recompute menu wide
+ *			 global values.
+ */
+_XMRecomputeGlobals(display, menu)
+    register Display *display; /*X11 display variable. */	
+    register XMenu *menu;	/* Menu object to compute from. */
+{
+    register XMPane *p_ptr;	/* Pane pointer. */
+    register XMSelect *s_ptr;	/* Selection pointer. */
+
+    register int max_p_label = 0;	/* Maximum pane label width. */
+    register int max_s_label = 0;	/* Maximum selection label width. */
+    register int s_count = 0;		/* Maximum selection count. */
+
+    int p_s_pad;		/* Pane <-> selection padding. */
+    int p_s_diff;		/* Pane <-> selection separation. */
+
+    int p_height;		/* Pane window height. */
+    int p_width;		/* Pane window width. */
+    int s_width;		/* Selection window width. */
+
+    int screen;			/* DefaultScreen holder. */
+    
+    /*
+     * For each pane...
+     */
+    for (
+	p_ptr = menu->p_list->next;
+	p_ptr != menu->p_list;
+	p_ptr = p_ptr->next
+    ){
+	
+	/*
+	 * Recompute maximum pane label width.
+	 */
+	max_p_label = max(max_p_label, p_ptr->label_width);
+
+	/*
+	 * Recompute maximum selection count. 
+	 */
+	s_count = max(s_count, p_ptr->s_count);
+
+	/*
+	 * For each selection in the current pane...
+	 */
+	for (
+	    s_ptr = p_ptr->s_list->next;
+	    s_ptr != p_ptr->s_list;
+	    s_ptr = s_ptr->next
+	){
+
+	    /*
+	     * Recompute maximum selection label width.
+	     */
+	    max_s_label = max(max_s_label, s_ptr->label_width);
+	}
+    }
+
+    /*
+     * Recompute pane height.
+     */
+    p_height = (menu->flag_height << 1) + (menu->s_y_off * s_count);
+
+    /*
+     * Recompute horizontal padding between the pane window and the
+     * selection windows.
+     */
+    p_s_pad = menu->p_x_off << 1;
+
+    /*
+     * Recompute pane and selection window widths.
+     * This is done by first computing the window sizes from the maximum
+     * label widths.  If the spacing between the selection window and the
+     * containing pane window is less than the pane selection padding value
+     * (twice the pane X offset) then change the size of the pane to be
+     * the size of the selection window plus the padding.  If, however the
+     * spacing between the selection window and the containing pane window
+     * is more than the pane selection padding value increase the size of
+     * the selection to its maximum possible value (the pane width minus
+     * the pane selection padding value).
+     */
+    p_width = max_p_label + p_s_pad;
+    s_width = max_s_label + (menu->s_fnt_pad << 1) + (menu->s_bdr_width << 1);
+    p_s_diff = p_width - s_width;
+    if (p_s_diff < p_s_pad) {
+	p_width = s_width + p_s_pad;
+    }
+    else if (p_s_diff > p_s_pad) {
+	s_width = p_width - p_s_pad;
+    }
+
+    /*
+     * Reset menu wide global values.
+     */
+    menu->s_count = s_count;
+    menu->p_height = p_height;
+    menu->p_width = p_width;
+    menu->s_width = s_width;
+
+    /* 
+     * Ensure that the origin of the menu is placed so that
+     * None of the panes ore selections are off the screen.
+     */
+    screen = DefaultScreen(display);
+    if (menu->x_pos + menu->width > DisplayWidth(display, screen))
+	    menu->x_pos = DisplayWidth(display, screen) - menu->width;
+    else if (menu->x_pos < 0) menu->x_pos = 0;
+    if(menu->y_pos + menu->height > DisplayHeight(display, screen))
+	    menu->y_pos = DisplayHeight(display, screen) - menu->height;
+    else if (menu->y_pos < 0) menu->y_pos = 0;
+}
+
+
+/*
+ * _XMRecomputePane - Internal subroutine to recompute pane
+ *		      window dependencies.
+ */
+int
+_XMRecomputePane(display, menu, p_ptr, p_num)
+    register Display *display;	/* Standard X display variable. */
+    register XMenu *menu;	/* Menu object being recomputed. */
+    register XMPane *p_ptr;	/* Pane pointer. */
+    register int p_num;		/* Pane sequence number. */
+{
+    register int window_x;	/* Recomputed window X coordinate. */
+    register int window_y;	/* Recomputed window Y coordinate. */
+    
+    unsigned long change_mask;	/* Value mask to reconfigure window. */
+    XWindowChanges *changes;	/* Values to use in configure window. */
+    
+    register Bool config_p = False;	/* Reconfigure pane window? */
+
+    /*
+     * Update the pane serial number.
+     */
+    p_ptr->serial = p_num;
+
+    /*
+     * Recompute window X and Y coordinates.
+     */
+    switch (menu->menu_style) {
+	case LEFT:
+	    window_x = menu->p_x_off * ((menu->p_count - 1) - p_num);
+	    window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+	    break;
+	case RIGHT:
+	    window_x = menu->p_x_off * p_num;
+	    window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+	    break;
+	case CENTER:
+	    window_x = 0;
+	    window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
+	    break;
+	default:
+	    /* Error! Invalid style parameter. */
+	    _XMErrorCode = XME_STYLE_PARAM;
+	    return(_FAILURE);
+    }
+    window_x += menu->x_pos;
+    window_y += menu->y_pos;
+
+    /*
+     * If the newly compute pane coordinates differ from the 
+     * current coordinates, reset the current coordinates and
+     * reconfigure the pane.
+     */
+    if (
+	(window_x != p_ptr->window_x) ||
+	(window_y != p_ptr->window_y)
+    ){
+	/*
+	 * Reset the coordinates and schedule
+	 * the pane for reconfiguration.
+	 */
+	p_ptr->window_x = window_x;
+	p_ptr->window_y = window_y;
+	config_p = True;
+    }
+
+    /*
+     * If the local pane width and height differs from the
+     * menu pane width and height, reset the local values.
+     */
+    if (
+	(p_ptr->window_w != menu->p_width) ||
+	(p_ptr->window_h != menu->p_height)
+    ){
+	/*
+	 * Reset window width and height and schedule
+	 * the pane for reconfiguration.
+	 */
+	p_ptr->window_w = menu->p_width;
+	p_ptr->window_h = menu->p_height;
+	config_p = True;
+    }
+
+    /*
+     * If we need to reconfigure the pane window do it now.
+     */
+    if (config_p == True) {
+	/*
+	 * If the pane window has already been created then
+	 * reconfigure the existing window, otherwise queue
+	 * it for creation with the new configuration.
+	 */
+	if (p_ptr->window) {
+	    change_mask = (CWX | CWY | CWWidth | CWHeight);
+	    changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+	    changes->x = p_ptr->window_x;
+	    changes->y = p_ptr->window_y;
+	    changes->width = p_ptr->window_w;
+	    changes->height = p_ptr->window_h;
+	    
+	    XConfigureWindow(
+			     display,
+			     p_ptr->window,
+			     change_mask,
+			     changes
+			     );
+	    free(changes);
+	    
+	}
+	else {
+	    if (_XMWinQueAddPane(display, menu, p_ptr) == _FAILURE) {
+		return(_FAILURE);
+	    }
+	}
+    }
+ 
+    /*
+     * Recompute label X position.
+     */
+    switch (menu->p_style) {
+	case LEFT:
+	    p_ptr->label_x = menu->p_x_off + menu->p_fnt_pad;
+	    break;
+	case RIGHT:
+	    p_ptr->label_x = menu->p_width -
+		(p_ptr->label_width + menu->p_x_off + menu->p_fnt_pad);
+	    break;
+	case CENTER:
+	    p_ptr->label_x = (menu->p_width - p_ptr->label_width) >> 1;
+	    break;
+	default:
+	    /* Error! Invalid style parameter. */
+	    _XMErrorCode = XME_STYLE_PARAM;
+	    return(_FAILURE);
+    }
+    /*
+     * Recompute label Y positions.
+     */
+    p_ptr->label_uy = menu->p_fnt_pad + menu->p_fnt_info->max_bounds.ascent;
+    p_ptr->label_ly = (menu->p_height - menu->p_fnt_pad - menu->p_fnt_info->max_bounds.descent);
+
+    /*
+     * All went well, return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMRecomputeSelection - Internal subroutine to recompute
+ *			   selection window dependencies.
+ */
+int
+_XMRecomputeSelection(display, menu, s_ptr, s_num)
+    register Display *display;
+    register XMenu *menu;	/* Menu object being recomputed. */
+    register XMSelect *s_ptr;	/* Selection pointer. */
+    register int s_num;		/* Selection sequence number. */
+{
+    register Bool config_s = False;	/* Reconfigure selection window? */
+    XWindowChanges *changes;		/* Values to change in configure. */
+    unsigned long change_mask;		/* Value mask for XConfigureWindow. */
+    
+    /*
+     * If the selection serial numbers are out of order, begin
+     * resequencing selections.  Recompute selection window coordinates
+     * and serial number.
+     *
+     * When selections are created they are given a serial number of
+     * -1, this causes this routine to give a new selection
+     * its initial coordinates and serial number.
+     */
+    if (s_ptr->serial != s_num) {
+	/*
+	 * Fix the sequence number.
+	 */
+	s_ptr->serial = s_num;
+	/*
+	 * Recompute window X and Y coordinates.
+	 */
+	s_ptr->window_x = menu->s_x_off;
+	s_ptr->window_y = menu->flag_height + (menu->s_y_off * s_num);
+	/*
+	 * We must reconfigure the window.
+	 */
+	config_s = True;
+    }
+
+    /*
+     * If the local selection width and height differs from the
+     * menu selection width and height, reset the local values.
+     */
+    if (
+	(s_ptr->window_w != menu->s_width) ||
+	(s_ptr->window_h != menu->s_height)
+    ){
+	/*
+	 * We must reconfigure the window.
+	 */
+	config_s = True;
+	/*
+	 * Reset window width and height.
+	 */
+	s_ptr->window_w = menu->s_width;
+	s_ptr->window_h = menu->s_height;
+    }
+
+    /*
+     * If we need to reconfigure the selection window do it now.
+     */
+    if (config_s == True) {
+	/*
+	 * If the selection window has already been created then
+	 * reconfigure the existing window, otherwise queue it
+	 * for creation with the new configuration.
+	 */
+	if (s_ptr->window) {
+	    changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+	    change_mask = (CWX | CWY | CWWidth | CWHeight);
+	    changes = (XWindowChanges *)malloc(sizeof(XWindowChanges));
+	    changes->x = s_ptr->window_x;
+	    changes->y = s_ptr->window_y;
+	    changes->width = s_ptr->window_w;
+	    changes->height = s_ptr->window_h;
+	    
+	    XConfigureWindow(
+			     display,
+			     s_ptr->window,
+			     change_mask,
+			     changes
+			     );
+	    free(changes);
+	    
+	}
+	else {
+	    if (_XMWinQueAddSelection(display, menu, s_ptr) == _FAILURE) {
+		return(_FAILURE);
+	    }
+	}
+    }
+
+    /*
+     * Recompute label X position.
+     */
+    switch (menu->s_style) {
+	case LEFT:
+	    s_ptr->label_x = menu->s_bdr_width + menu->s_fnt_pad + s_ptr->window_x;
+	    break;
+	case RIGHT:
+	    s_ptr->label_x = s_ptr->window_x + menu->s_width -
+		(s_ptr->label_width + menu->s_bdr_width + menu->s_fnt_pad);
+	    break;
+	case CENTER:
+	    s_ptr->label_x = s_ptr->window_x + ((menu->s_width - s_ptr->label_width) >> 1);
+	    break;
+	default:
+	    /* Error! Invalid style parameter. */
+	    _XMErrorCode = XME_STYLE_PARAM;
+	    return(_FAILURE);
+    }
+    /*
+     * Recompute label Y position.
+     */
+    s_ptr->label_y = s_ptr->window_y + menu->s_fnt_info->max_bounds.ascent + menu->s_fnt_pad + menu->s_bdr_width;
+    
+    /*
+     * All went well, return successfully.
+     */
+    _XMErrorCode = XME_NO_ERROR;
+    return(_SUCCESS);
+}
+
+
+
+/*
+ * _XMTransToOrigin - Internal subroutine to translate the point at
+ *		      the center of the current pane and selection to the 
+ *		      the menu origin.
+ *
+ *	WARNING! ******	Be certain that all menu dependencies have been
+ *			recomputed before calling this routine or
+ *			unpredictable results will follow.
+ */
+_XMTransToOrigin(display, menu, p_ptr, s_ptr, x_pos, y_pos, orig_x, orig_y)
+    Display *display;		/* Not used. Included for consistency. */
+    register XMenu *menu;	/* Menu being computed against. */
+    register XMPane *p_ptr;	/* Current pane pointer. */
+    register XMSelect *s_ptr;	/* Current selection pointer. */
+    int x_pos;			/* X coordinate of point to translate. */
+    int y_pos;			/* Y coordinate of point to translate. */
+    int *orig_x;		/* Return value X coord. of the menu origin. */
+    int *orig_y;		/* Return value Y coord. of the menu origin. */
+{
+    register int l_orig_x;	/* Local X coordinate of the menu origin. */
+    register int l_orig_y;	/* Local Y coordinate of the menu origin. */
+    
+    /*
+     * Translate the menu origin such that the cursor hot point will be in the
+     * center of the desired current selection and pane.
+     * If the current selection pointer is NULL then assume that the hot point
+     * will be in the center of the current pane flag.
+     */
+
+    if (s_ptr == NULL) {
+	/*
+	 * Translate from the center of the pane flag to the upper left
+	 * of the current pane window.
+	 */
+	l_orig_x = x_pos - (menu->p_width >> 1) - menu->p_bdr_width;
+	l_orig_y = y_pos - (menu->flag_height >> 1) - menu->p_bdr_width;
+    }
+    else {
+	/*
+	 * First translate from the center of the current selection
+	 * to the upper left of the current selection window.
+	 */
+	l_orig_x = x_pos - (menu->s_width >> 1);
+	l_orig_y = y_pos - (menu->s_height >> 1);
+
+	/*
+	 * Then translate to the upper left of the current pane window.
+	 */
+	l_orig_x -= (s_ptr->window_x + menu->p_bdr_width);
+	l_orig_y -= (s_ptr->window_y + menu->p_bdr_width);
+    }
+
+    /*
+     * Finally translate to the upper left of the menu.
+     */
+    l_orig_x -= (p_ptr->window_x - menu->x_pos);
+    l_orig_y -= (p_ptr->window_y - menu->y_pos);
+
+    /*
+     * Set the return values.
+     */
+    *orig_x = l_orig_x;
+    *orig_y = l_orig_y;
+}
+
+/*
+ * _XMRefreshPane - Internal subroutine to completely refresh
+ *		    the contents of a pane.
+ */
+_XMRefreshPane(display, menu, pane)
+    register Display *display;
+    register XMenu *menu;
+    register XMPane *pane;
+{
+    register XMSelect *s_list = pane->s_list;
+    register XMSelect *s_ptr;
+
+    /*
+     * First clear the pane. 
+     */
+    XClearWindow(display, pane->window);
+    if (!pane->activated) {
+	XFillRectangle(display,
+		       pane->window,
+		       menu->inverse_select_GC,
+		       pane->label_x - menu->p_fnt_pad,
+		       pane->label_uy - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
+		       pane->label_width + (menu->p_fnt_pad << 1),
+		       menu->flag_height);
+
+	XFillRectangle(display,
+		       pane->window,
+		       menu->inverse_select_GC,
+		       pane->label_x - menu->p_fnt_pad,
+		       pane->label_ly - menu->p_fnt_info->max_bounds.ascent - menu->p_fnt_pad,
+		       pane->label_width + (menu->p_fnt_pad << 1),
+		       menu->flag_height);
+    }
+    if (!pane->active) {
+	XDrawString(display,
+		    pane->window,
+		    menu->inact_GC,
+		    pane->label_x, pane->label_uy,
+		    pane->label, pane->label_length);
+	XDrawString(display,
+		    pane->window,
+		    menu->inact_GC,
+		    pane->label_x, pane->label_ly,
+		    pane->label, pane->label_length);
+    }
+    else {
+	XDrawString(display,
+			 pane->window,
+			 menu->pane_GC,
+			 pane->label_x, pane->label_uy,
+			 pane->label, pane->label_length);
+	XDrawString(display,
+			 pane->window,
+			 menu->pane_GC,
+			 pane->label_x, pane->label_ly,
+			 pane->label, pane->label_length);
+
+	/*
+	 * Finally refresh each selection if the pane is activated.
+	 */
+	if (pane->activated) {
+	    for (s_ptr = s_list->next; s_ptr != s_list; s_ptr = s_ptr->next)
+		_XMRefreshSelection(display, menu, s_ptr);
+	}
+    }
+}
+    
+    
+
+
+/*
+ * _XMRefreshSelection - Internal subroutine that refreshes 
+ *			 a single selection window.
+ */
+_XMRefreshSelection(display, menu, select)
+    register Display *display;
+    register XMenu *menu;
+    register XMSelect *select;
+{
+    register int width = select->window_w;
+    register int height = select->window_h;
+    register int bdr_width = menu->s_bdr_width;
+    
+    if (select->type == SEPARATOR) {
+        XDrawLine(display,
+                  select->parent_p->window,
+                  menu->normal_select_GC,
+                  select->window_x,
+                  select->window_y + height / 2,
+                  select->window_x + width,
+                  select->window_y + height / 2);
+    }
+    else if (select->activated) {
+	if (menu->menu_mode == INVERT) {
+	    XFillRectangle(display, 
+			   select->parent_p->window,
+			   menu->normal_select_GC,
+			   select->window_x, select->window_y,
+			   width, height); 
+	    XDrawString(display,
+			select->parent_p->window,
+			menu->inverse_select_GC,
+			select->label_x,
+			select->label_y,
+			select->label, select->label_length);
+	}
+        else {
+            /*
+	     * Using BOX mode.
+             * Since most drawing routines with arbitrary width lines
+	     * are slow compared to raster-ops lets use a raster-op to
+	     * draw the boxes.
+             */
+	    
+	    XDrawRectangle(display,
+			   select->parent_p->window,
+			   menu->normal_select_GC,
+			   select->window_x + (bdr_width >> 1),
+			   select->window_y + (bdr_width >> 1 ),
+			   width - bdr_width,
+			   height - bdr_width);
+	    XDrawString(display,
+			select->parent_p->window,
+			menu->normal_select_GC,
+			select->label_x,
+			select->label_y,
+			select->label, select->label_length);
+        }
+    }
+    else {
+	XClearArea(display, 
+		   select->parent_p->window,
+		   select->window_x, select->window_y,
+		   width, height,
+		   False);
+	if (select->active) {
+	    XDrawString(display,
+			select->parent_p->window,
+			menu->normal_select_GC,
+			select->label_x,
+			select->label_y,
+			select->label, select->label_length);
+	}
+	else {
+	    XDrawString(display,
+			select->parent_p->window,
+			menu->inact_GC,
+			select->label_x,
+			select->label_y,
+			select->label, select->label_length);
+	}
+    }
+}
+