Beispiel #1
0
int
XMenuSetPane(register XMenu *menu, register int p_num, register int active)
                         	/* Menu object to be modified. */
                       		/* Pane number to be modified. */
                        	/* Make selection active? */
{
    register XMPane *p_ptr;	/* XMPane pointer. */

    /*
     * Find the right pane.
     */
    p_ptr = _XMGetPanePtr(menu, p_num);
    if (p_ptr == NULL) return(XM_FAILURE);

    /*
     * Set its active switch.
     */
    p_ptr->active = active;
    if (p_ptr->active == False) p_ptr->activated = False;

    /*
     * Return the pane number just set.
     */
    _XMErrorCode = XME_NO_ERROR;
    return(p_num);
}
Beispiel #2
0
int
XMenuFindSelection(register XMenu *menu, int p_num, register char *label)
{
    register XMPane *p_ptr;
    register XMSelect *s_ptr;
    register int i = 0;

    /*
     * Check for NULL pointers!
     */
    if (label == NULL) {
	_XMErrorCode = XME_ARG_BOUNDS;
	return(XM_FAILURE);
    }

    /*
     * Find the right pane.
     */
    p_ptr = _XMGetPanePtr(menu, p_num);
    if (p_ptr == NULL) return(XM_FAILURE);

    /*
     * Find the right selection.
     */
    for (
	s_ptr = p_ptr->s_list->next;
	s_ptr != p_ptr->s_list;
	s_ptr = s_ptr->next
    ){
	if (s_ptr->label_length == 0) {
	    if (*label == '\0') {
		_XMErrorCode = XME_NO_ERROR;
		return (i);
	    }
	}
	else {
	    if (strncmp (label, s_ptr->label, s_ptr->label_length) == 0) {
		_XMErrorCode = XME_NO_ERROR;
		return (i);
	    }
	}
	i++;
    }

    /*
     * If we get here then we have not found
     * a match.
     */
    _XMErrorCode = XME_S_NOT_FOUND;
    return (XM_FAILURE);
}
Beispiel #3
0
int
XMenuChangePane(register XMenu *menu, register int p_num, char *label)
                         	/* Menu object to be modified. */
                       		/* Pane number to be modified. */
                		/* Selection label. */
{
    register XMPane *p_ptr;	/* XMPane pointer. */

    int label_length;		/* Label length in characters. */
    int label_width;		/* Label width in pixels. */

    /*
     * Check for NULL pointers!
     */
    if (label == NULL) {
	_XMErrorCode = XME_ARG_BOUNDS;
	return(XM_FAILURE);
    }

    /*
     * Find the right pane.
     */
    p_ptr = _XMGetPanePtr(menu, p_num);
    if (p_ptr == NULL) return(XM_FAILURE);

    /*
     * Determine label size.
     */
    label_length = strlen(label);
    label_width = XTextWidth(menu->p_fnt_info, label, label_length);

    /*
     * Change the pane data.
     */
    p_ptr->label = label;
    p_ptr->label_width = label_width;
    p_ptr->label_length = label_length;

    /*
     * Schedule a recompute.
     */
    menu->recompute = 1;

    /*
     * Return the pane number just changed.
     */
    _XMErrorCode = XME_NO_ERROR;
    return(p_num);
}
Beispiel #4
0
int
XMenuActivate(
    register Display *display,		/* Display to put menu on. */
    register XMenu *menu,		/* Menu to activate. */
    int *p_num,				/* Pane number selected. */
    int *s_num,				/* Selection number selected. */
    int x_pos,				/* X coordinate of menu position. */
    int y_pos,				/* Y coordinate of menu position. */
    unsigned int event_mask,		/* Mouse button event mask. */
    char **data,			/* Pointer to return data value. */
    void (*help_callback) (char const *, int, int)) /* Help callback.  */
{
    int status;				/* X routine call status. */
    int orig_x;				/* Upper left menu origin X coord. */
    int orig_y;				/* Upper left menu origin Y coord. */
    int ret_val;			/* Return value. */

    register XMPane *p_ptr;		/* Current XMPane. */
    register XMPane *event_xmp;		/* Event XMPane pointer. */
    register XMPane *cur_p;		/* Current pane. */
    register XMSelect *cur_s;		/* Current selection. */
    XMWindow *event_xmw;		/* Event XMWindow pointer. */
    XEvent event;			/* X input event. */
    XEvent peek_event;			/* X input peek ahead event. */

    Bool selection = False;		/* Selection has been made. */
    Bool forward = True;		/* Moving forward in the pane list. */

    Window root, child;
    int root_x, root_y, win_x, win_y;
    unsigned int mask;
    KeySym keysym;

    /*
     * Define and allocate a foreign event queue to hold events
     * that don't belong to XMenu.  These events are later restored
     * to the X event queue.
     */
    typedef struct _xmeventque {
	XEvent event;
	struct _xmeventque *next;
    } XMEventQue;

    XMEventQue *feq = NULL;    		/* Foreign event queue. */
    XMEventQue *feq_tmp;		/* Foreign event queue temporary. */

    /*
     * If there are no panes in the menu then return failure
     * because the menu is not initialized.
     */
    if (menu->p_count == 0) {
	_XMErrorCode = XME_NOT_INIT;
	return(XM_FAILURE);
    }

    /*
     * Find the desired current pane.
     */
    cur_p = _XMGetPanePtr(menu, *p_num);
    if (cur_p == NULL) {
	return(XM_FAILURE);
    }
    cur_p->activated = cur_p->active;

    /*
     * Find the desired current selection.
     * If the current selection index is out of range a null current selection
     * will be assumed and the cursor will be placed in the current pane
     * header.
     */
    cur_s = _XMGetSelectionPtr(cur_p, *s_num);

    /*
     * Compute origin of menu so that cursor is in
     * Correct pane and selection.
     */
    _XMTransToOrigin(display,
		     menu,
		     cur_p, cur_s,
		     x_pos, y_pos,
		     &orig_x, &orig_y);
    menu->x_pos = orig_x;	/* Store X and Y coords of menu. */
    menu->y_pos = orig_y;

    if (XMenuRecompute(display, menu) == XM_FAILURE) {
	return(XM_FAILURE);
    }

    /*
     * Flush the window creation queue.
     * This batches all window creates since lazy evaluation
     * is more efficient than individual evaluation.
     * This routine also does an XFlush().
     */
    if (_XMWinQueFlush(display, menu, cur_p, cur_s) == _FAILURE) {
	return(XM_FAILURE);
    }

    /*
     * Make sure windows are in correct order (in case we were passed
     * an already created menu in incorrect order.)
     */
    for(p_ptr = menu->p_list->next; p_ptr != cur_p; p_ptr = p_ptr->next)
	XRaiseWindow(display, p_ptr->window);
    for(p_ptr = menu->p_list->prev; p_ptr != cur_p->prev; p_ptr = p_ptr->prev)
	XRaiseWindow(display, p_ptr->window);

    /*
     * Make sure all selection windows are mapped.
     */
    for (
	p_ptr = menu->p_list->next;
	p_ptr != menu->p_list;
	p_ptr = p_ptr->next
    ){
	XMapSubwindows(display, p_ptr->window);
    }

    /*
     * Synchronize the X buffers and the event queue.
     * From here on, all events in the queue that don't belong to
     * XMenu are sent back to the application via an application
     * provided event handler or discarded if the application has
     * not provided an event handler.
     */
    XSync(display, 0);

    /*
     * Grab the mouse for menu input.
     */

    status = XGrabPointer(
			  display,
			  menu->parent,
			  True,
			  event_mask,
			  GrabModeAsync,
			  GrabModeAsync,
			  None,
			  menu->mouse_cursor,
			  CurrentTime
			  );
    if (status == Success && x_menu_grab_keyboard)
      {
        status = XGrabKeyboard (display,
                                menu->parent,
                                False,
                                GrabModeAsync,
                                GrabModeAsync,
                                CurrentTime);
        if (status != Success)
          XUngrabPointer(display, CurrentTime);
      }

    if (status == _X_FAILURE) {
	_XMErrorCode = XME_GRAB_MOUSE;
	return(XM_FAILURE);
    }

    /*
     * Map the menu panes.
     */
    XMapWindow(display, cur_p->window);
    for (p_ptr = menu->p_list->next;
	 p_ptr != cur_p;
	 p_ptr = p_ptr->next)
      XMapWindow(display, p_ptr->window);
    for (p_ptr = cur_p->next;
	 p_ptr != menu->p_list;
	 p_ptr = p_ptr->next)
      XMapWindow(display, p_ptr->window);

    XRaiseWindow(display, cur_p->window);	/* Make sure current */
						/* pane is on top. */

    cur_s = NULL;			/* Clear current selection. */

    /*
     * Begin event processing loop.
     */
    while (1) {
        if (wait_func) (*wait_func) (wait_data);
	XNextEvent(display, &event);	/* Get next event. */
	switch (event.type) {		/* Dispatch on the event type. */
    case Expose:
	    event_xmp = (XMPane *)XLookUpAssoc(display,
					       menu->assoc_tab,
					       event.xexpose.window);
	    if (event_xmp == NULL) {
		/*
		 * If AEQ mode is enabled then queue the event.
		 */
		if (menu->aeq) {
		    feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
		    if (feq_tmp == NULL) {
			_XMErrorCode = XME_CALLOC;
			return(XM_FAILURE);
		    }
		    feq_tmp->event = event;
		    feq_tmp->next = feq;
		    feq = feq_tmp;
		}
		else if (_XMEventHandler) (*_XMEventHandler)(&event);
		break;
	    }
	    if (event_xmp->activated) {
		XSetWindowBackground(display,
				     event_xmp->window,
				     menu->bkgnd_color);
	    }
	    else {
		XSetWindowBackgroundPixmap(display,
					   event_xmp->window,
					   menu->inact_pixmap);
	    }
	    _XMRefreshPane(display, menu, event_xmp);
	    break;
    case EnterNotify:
	    /*
	     * First wait a small period of time, and see
	     * if another EnterNotify event follows hard on the
	     * heels of this one. i.e., the user is simply
	     * "passing through". If so, ignore this one.
	     */

	    event_xmw = (XMWindow *)XLookUpAssoc(display,
						 menu->assoc_tab,
						 event.xcrossing.window);
	    if (event_xmw == NULL) break;
	    if (event_xmw->type == SELECTION) {
		/*
		 * We have entered a selection.
		 */
		/* if (XPending(display) == 0) usleep(150000); */
		if (XPending(display) != 0) {
		    XPeekEvent(display, &peek_event);
		    if(peek_event.type == LeaveNotify) {
			break;
		    }
		}
		cur_s = (XMSelect *)event_xmw;
		help_callback (cur_s->help_string,
			       cur_p->serial, cur_s->serial);

		/*
		 * If the pane we are in is active and the
		 * selection entered is active then activate
		 * the selection.
		 */
		if (cur_p->active && cur_s->active > 0) {
		    cur_s->activated = 1;
		    _XMRefreshSelection(display, menu, cur_s);
		}
	    }
	    else {
		/*
		 * We have entered a pane.
		 */
		/* if (XPending(display) == 0) usleep(150000); */
		if (XPending(display) != 0) {
		    XPeekEvent(display, &peek_event);
		    if (peek_event.type == EnterNotify) break;
		}
		XQueryPointer(display,
			      menu->parent,
			      &root, &child,
			      &root_x, &root_y,
			      &win_x, &win_y,
			      &mask);
		event_xmp = (XMPane *)XLookUpAssoc(display,
						   menu->assoc_tab,
						   child);
		if (event_xmp == NULL) break;
		if (event_xmp == cur_p) break;
		if (event_xmp->serial > cur_p->serial) forward = True;
		else forward = False;
		p_ptr = cur_p;
		while (p_ptr != event_xmp) {
		    if (forward) p_ptr = p_ptr->next;
		    else p_ptr = p_ptr->prev;
		    XRaiseWindow(display, p_ptr->window);
		}
		if (cur_p->activated) {
		    cur_p->activated = False;
		    XSetWindowBackgroundPixmap(display,
					       cur_p->window,
					       menu->inact_pixmap);
		    _XMRefreshPane(display, menu, cur_p);
		}
		if (event_xmp->active) event_xmp->activated = True;
#if 1
		/*
		 * i suspect the we don't get an EXPOSE event when backing
		 * store is enabled; the menu windows content is probably
		 * not drawn in when it should be in that case.
		 * in that case, this is probably an ugly fix!
		 * i hope someone more familiar with this code would
		 * take it from here.  -- [email protected].
		 */
		XSetWindowBackground(display,
				     event_xmp->window,
				     menu->bkgnd_color);
		_XMRefreshPane(display, menu, event_xmp);
#endif
		cur_p = event_xmp;
	    }
	    break;
    case LeaveNotify:
	    event_xmw = (XMWindow *)XLookUpAssoc(
						 display,
						 menu->assoc_tab,
						 event.xcrossing.window
						 );
	    if (event_xmw == NULL) break;
	    if(cur_s == NULL) break;

	    /*
	     * If the current selection was activated then
	     * deactivate it.
	     */
	    if (cur_s->activated) {
		cur_s->activated = False;
		_XMRefreshSelection(display, menu, cur_s);
	    }
	    cur_s = NULL;
	    break;

    case ButtonPress:
    case ButtonRelease:
		*p_num = cur_p->serial;
		/*
		 * Check to see if there is a current selection.
		 */
		if (cur_s != NULL) {
		    /*
		     * Set the selection number to the current selection.
		     */
		    *s_num = cur_s->serial;
		    /*
		     * If the current selection was activated then
		     * we have a valid selection otherwise we have
		     * an inactive selection.
		     */
		    if (cur_s->activated) {
			*data = cur_s->data;
			ret_val = XM_SUCCESS;
		    }
		    else {
			ret_val = XM_IA_SELECT;
		    }
		}
		else {
		    /*
		     * No selection was current.
		     */
		    ret_val = XM_NO_SELECT;
		}
		selection = True;
		break;
        case KeyPress:
        case KeyRelease:
                keysym = XLookupKeysym (&event.xkey, 0);

                /* Pop down on C-g and Escape.  */
                if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
                    || keysym == XK_Escape) /* Any escape, ignore modifiers.  */
                  {
                    ret_val = XM_NO_SELECT;
                    selection = True;
                  }
               break;
	    default:
		/*
		 * If AEQ mode is enabled then queue the event.
		 */
		if (menu->aeq) {
		    feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
		    if (feq_tmp == NULL) {
			_XMErrorCode = XME_CALLOC;
			return(XM_FAILURE);
		    }
		    feq_tmp->event = event;
		    feq_tmp->next = feq;
		    feq = feq_tmp;
		}
		else if (_XMEventHandler) (*_XMEventHandler)(&event);
	}
	/*
	 * If a selection has been made, break out of the event loop.
	 */
	if (selection == True) break;
    }

    /*
     * Unmap the menu.
     */
    for ( p_ptr = menu->p_list->next;
	 p_ptr != menu->p_list;
	 p_ptr = p_ptr->next)
      {
	  XUnmapWindow(display, p_ptr->window);
      }

    /*
     * Ungrab the mouse.
     */
    XUngrabPointer(display, CurrentTime);
    XUngrabKeyboard(display, CurrentTime);

    /*
     * Restore bits under where the menu was if we managed
     * to save them and free the pixmap.
     */

    /*
     * If there is a current selection deactivate it.
     */
    if (cur_s != NULL) cur_s->activated = 0;

    /*
     * Deactivate the current pane.
     */
    cur_p->activated = 0;
    XSetWindowBackgroundPixmap(display, cur_p->window, menu->inact_pixmap);

    /*
     * Synchronize the X buffers and the X event queue.
     */
    XSync(display, 0);

    /*
     * Dispatch any events remaining on the queue.
     */
    while (QLength(display)) {
	/*
	 * Fetch the next event.
	 */
	XNextEvent(display, &event);

	/*
	 * Discard any events left on the queue that belong to XMenu.
	 * All others are held and then returned to the event queue.
	 */
	switch (event.type) {
	    case Expose:
	    case EnterNotify:
	    case LeaveNotify:
	    case ButtonPress:
	    case ButtonRelease:
		/*
		 * Does this event belong to one of XMenu's windows?
		 * If so, discard it and process the next event.
		 * If not fall through and treat it as a foreign event.
		 */
		event_xmp = (XMPane *)XLookUpAssoc(
						   display,
						   menu->assoc_tab,
						   event.xbutton.window
						   );
		if (event_xmp != NULL) continue;
	    default:
		/*
		 * This is a foreign event.
		 * Queue it for later return to the X event queue.
		 */
		feq_tmp = (XMEventQue *)malloc(sizeof(XMEventQue));
		if (feq_tmp == NULL) {
		    _XMErrorCode = XME_CALLOC;
		    return(XM_FAILURE);
		}
		feq_tmp->event = event;
		feq_tmp->next = feq;
		feq = feq_tmp;
	    }
    }
    /*
     * Return any foreign events that were queued to the X event queue.
     */
    while (feq != NULL) {
	feq_tmp = feq;
	XPutBackEvent(display, &feq_tmp->event);
	feq = feq_tmp->next;
	free((char *)feq_tmp);
    }

    wait_func = 0;

    /*
     * Return successfully.
     */
    _XMErrorCode = XME_NO_ERROR;
    return(ret_val);

}
Beispiel #5
0
int
XMenuAddSelection(Display *display, register XMenu *menu, register int p_num, char *data, char *label, int active, char *help)
                     
                         	/* Menu object to be modified. */
                       		/* Pane number to be modified. */
               			/* Data value. */
                		/* Selection label. */
               			/* Make selection active? */
               			/* Help string */
{
    register XMPane *pane;	/* Pane containing the new selection. */
    register XMSelect *select;	/* Newly created selection. */


    int label_length;		/* Label lenght in characters. */
    int label_width;		/* Label width in pixels. */

    /*
     * Check for NULL pointers!
     */
    if (label == NULL) {
	_XMErrorCode = XME_ARG_BOUNDS;
	return(XM_FAILURE);
    }
    /*
     * Find the right pane.
     */
    pane = _XMGetPanePtr(menu, p_num);
    if (pane == NULL) return(XM_FAILURE);

    /*
     * Calloc the XMSelect structure.
     */
    select = (XMSelect *)calloc(1, sizeof(XMSelect));
    if (select == NULL) {
	_XMErrorCode = XME_CALLOC;
	return(XM_FAILURE);
    }
    /*
     * Determine label size.
     */
    label_length = strlen(label);
    label_width = XTextWidth(menu->s_fnt_info, label, label_length);

    /*
     * Fill the XMSelect structure.
     */
    if (!strcmp (label, "--") || !strcmp (label, "---"))
      {
	select->type = SEPARATOR;
	select->active = 0;
      }
    else
      {
	select->type = SELECTION;
	select->active = active;
      }

    select->serial = -1;
    select->label = label;
    select->label_width = label_width;
    select->label_length = label_length;
    select->data = data;
    select->parent_p = pane;
    select->help_string = help;

    /*
     * Insert the selection at the end of the selection list.
     */
    emacs_insque(select, pane->s_list->prev);

    /*
     * Update the selection count.
     */
    pane->s_count++;

    /*
     * Schedule a recompute.
     */
    menu->recompute = 1;

    /*
     * Return the selection number just added.
     */
    _XMErrorCode = XME_NO_ERROR;
    return((pane->s_count - 1));
}
Beispiel #6
0
int
XMenuInsertPane(register XMenu *menu, register int p_num, char *label, int active)
                         	/* Menu object to be modified. */
                       		/* Pane number of new pane. */
                		/* Selection label. */
               			/* Make selection active? */
{
    register XMPane *p_ptr;	/* XMPane pointer. */
    register XMPane *pane;	/* Newly created pane. */
    register XMSelect *sel;	/* Initial selection for the new pane. */

    int label_length;		/* Label length in characters. */
    int label_width;		/* Label width in pixels. */

    /*
     * Check for NULL pointers!
     */
    if (label == NULL) {
	_XMErrorCode = XME_ARG_BOUNDS;
	return(XM_FAILURE);
    }

    /*
     * Find the pane number one less than the one specified since that
     * is the pane after which the insertion will occur.
     */
    p_ptr = _XMGetPanePtr(menu, (p_num - 1));
    if (p_ptr == NULL) return(XM_FAILURE);

    /*
     * Calloc the XMPane structure and the initial XMSelect.
     */
    pane = (XMPane *)calloc(1, sizeof(XMPane));
    if (pane == NULL) {
	_XMErrorCode = XME_CALLOC;
	return(XM_FAILURE);
    }
    sel = (XMSelect *)calloc(1, sizeof(XMSelect));
    if (sel == NULL) {
	_XMErrorCode = XME_CALLOC;
	return(XM_FAILURE);
    }

    /*
     * Determine label size.
     */
    label_length = strlen(label);
    label_width = XTextWidth(menu->p_fnt_info, label, label_length);

    /*
     * Set up the initial selection.
     * Values not explicitly set are zeroed by calloc.
     */
    sel->next = sel;
    sel->prev = sel;
    sel->type = SL_HEADER;
    sel->serial = -1;
    sel->parent_p = pane;

    /*
     * Fill the XMPane structure.
     */
    pane->type = PANE;
    pane->active = active;
    pane->serial = -1;
    pane->label = label;
    pane->label_width = label_width;
    pane->label_length = label_length;
    pane->s_list = sel;

    /*
     * Insert the pane after the pane with the pane
     * number one less than the desired number for the
     * new pane.
     */
    emacs_insque(pane, p_ptr);

    /*
     * Update the pane count.
     */
    menu->p_count++;

    /*
     * Schedule a recompute.
     */
    menu->recompute = 1;

    /*
     * Return the number of the pane just added.
     */
    _XMErrorCode = XME_NO_ERROR;
    return(p_num);
}
Beispiel #7
0
int
XMenuInsertSelection(register XMenu *menu, register int p_num, register int s_num, char *data, char *label, int active)
                         	/* Menu object to be modified. */
                       		/* Pane number to be modified. */
                       		/* Selection number of new selection. */
               			/* Data value. */
                		/* Selection label. */
               			/* Make selection active? */
{
    register XMPane *p_ptr;	/* XMPane pointer. */
    register XMSelect *s_ptr;	/* XMSelect pointer. */

    XMSelect *select;		/* Newly created selection. */

    int label_length;		/* Label length in characters. */
    int label_width;		/* Label width in pixels. */

    /*
     * Check for NULL pointers!
     */
    if (label == NULL) {
	_XMErrorCode = XME_ARG_BOUNDS;
	return(XM_FAILURE);
    }

    /*
     * Find the right pane.
     */
    p_ptr = _XMGetPanePtr(menu, p_num);
    if (p_ptr == NULL) return(XM_FAILURE);

    /*
     * Find the selection number one less than the one specified since that
     * is the selection after which the insertion will occur.
     */
    s_ptr = _XMGetSelectionPtr(p_ptr, (s_num - 1));
    if (s_ptr == NULL) return(XM_FAILURE);

    /*
     * Calloc the XMSelect structure.
     */
    select = (XMSelect *)calloc(1, sizeof(XMSelect));
    if (select == NULL) {
	_XMErrorCode = XME_CALLOC;
	return(XM_FAILURE);
    }

    /*
     * Determine label size.
     */
    label_length = strlen(label);
    label_width = XTextWidth(menu->s_fnt_info, label, label_length);


    /*
     * Fill the XMSelect structure.
     */
    if (!strcmp (label, "--") || !strcmp (label, "---"))
      {
	select->type = SEPARATOR;
	select->active = 0;
      }
    else
      {
	select->type = SELECTION;
	select->active = active;
      }

    select->active = active;
    select->serial = -1;
    select->label = label;
    select->label_width = label_width;
    select->label_length = label_length;
    select->data = data;
    select->parent_p = p_ptr;

    /*
     * Insert the selection after the selection with the selection
     * number one less than the desired number for the new selection.
     */
    emacs_insque(select, s_ptr);

    /*
     * Update the selection count.
     */
    p_ptr->s_count++;

    /*
     * Schedule a recompute.
     */
    menu->recompute = 1;

    /*
     * Return the selection number just inserted.
     */
    _XMErrorCode = XME_NO_ERROR;
    return(s_num);
}