⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menus.c

📁 安装DDD之前
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************//**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **//**                          Salt Lake City, Utah                           **//**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **//**                        Cambridge, Massachusetts                         **//**                                                                         **//**                           All Rights Reserved                           **//**                                                                         **//**    Permission to use, copy, modify, and distribute this software and    **//**    its documentation  for  any  purpose  and  without  fee is hereby    **//**    granted, provided that the above copyright notice appear  in  all    **//**    copies and that both  that  copyright  notice  and  this  permis-    **//**    sion  notice appear in supporting  documentation,  and  that  the    **//**    names of Evans & Sutherland and M.I.T. not be used in advertising    **//**    in publicity pertaining to distribution of the  software  without    **//**    specific, written prior permission.                                  **//**                                                                         **//**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **//**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **//**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **//**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **//**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **//**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **//**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **//**    OR PERFORMANCE OF THIS SOFTWARE.                                     **//*****************************************************************************//**************************************************************************** * This module is based on Twm, but has been significantly modified  * by Rob Nation  ****************************************************************************//*********************************************************************** * The rest of it is all my fault -- MLM * mwm - "LessTif Window Manager" ***********************************************************************/#include <LTconfig.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <Xm/Xm.h>#include <Xm/MwmUtil.h>#include <X11/keysym.h>#include "mwm.h"static int menu_on = 0;static MenuRoot *ActiveMenu = NULL;	/* the active menu */static MenuItem *ActiveItem = NULL;	/* the active menu item */int menuFromFrameOrWindowOrTitlebar = False;int Stashed_X, Stashed_Y;static int MenuY = 0;static MenuRoot *PrevMenu = NULL;static MenuItem *PrevItem = NULL;static int PrevY = 0;/* * Calculate the pixel offsets to the start of the character position we * want to underline and to the next character in the string.  Shrink by * one pixel from each end and the draw a line that long two pixels below * the character... */static voiddraw_underline(ScreenInfo *scr, Window w, GC gc, int x, int y,	       char *txt, int posn){    int off1 = XTextWidth(scr->components[MWM_MENU].font,			  txt, posn);    int off2 = XTextWidth(scr->components[MWM_MENU].font,			  txt, posn + 1) - 1;    XDrawLine(dpy, w, gc, x + off1, y + 2, x + off2, y + 2);}/* * Draws two horizontal lines to form a separator */static voiddraw_separator(Window w, GC TopGC, GC BottomGC, int x1, int y1, int x2, int y2,	       int extra_off){    XDrawLine(dpy, w, TopGC, x1, y1, x2, y2);    XDrawLine(dpy, w, BottomGC, x1 - extra_off, y1 + 1, x2 + extra_off, y2 + 1);}/* *  Draws a little Triangle pattern within a window */static voiddraw_arrow(Window w, GC GC1, GC GC2, GC GC3, int l, int u, int r, int b){    int m;    m = (u + b) / 2;    XDrawLine(dpy, w, GC1, l, u, l, b);    XDrawLine(dpy, w, GC2, l, b, r, m);    XDrawLine(dpy, w, GC3, r, m, l, u);}/* * add relief lines to a rectangular window */static voidrelieve_rectangle(Window win, int x, int y, int w, int h, GC Hilite, GC Shadow){    XDrawLine(dpy, win, Hilite, x, y, w + x - 1, y);    XDrawLine(dpy, win, Hilite, x, y, x, h + y - 1);    XDrawLine(dpy, win, Shadow, x, h + y - 1, w + x - 1, h + y - 1);    XDrawLine(dpy, win, Shadow, w + x - 1, y, w + x - 1, h + y - 1);}/* * add relief lines to the sides only of a rectangular window */static voidrelieve_half_rectangle(Window win, int x, int y, int w, int h,		       GC Hilite, GC Shadow){    XDrawLine(dpy, win, Hilite, x, y - 1, x, h + y);    XDrawLine(dpy, win, Hilite, x + 1, y, x + 1, h + y - 1);    XDrawLine(dpy, win, Shadow, w + x - 1, y - 1, w + x - 1, h + y);    XDrawLine(dpy, win, Shadow, w + x - 2, y, w + x - 2, h + y - 1);}/* * Checks the function described in menuItem mi, and sees if it * is an allowed function for window Tmp_Win, * according to the motif way of life. *  * This routine is used to determine whether or not to grey out menu items. * FIXME: This needs to be beefed up to handle other functions (like * f.send_msg) -- MLM */static Booleanfunction_allowed(MwmWindow *tmp, MenuItem *mi){    /* Complex functions are a little tricky... ignore them for now */    /* Move is a funny hint. Keeps it out of the menu, but you're still     * allowed * to move. */    if ((mi->func == F_MOVE) && tmp && !(tmp->functions & MWM_FUNC_MOVE))	return False;    if (mi->func == F_RESIZE && tmp && !(tmp->functions & MWM_FUNC_RESIZE))	return False;    /* Cannot iconify if the window is already iconified or the window       does not allow minimize */    if ((mi->func == F_ICONIFY && tmp) &&          ((tmp->flags & ICONIFIED) ||           !(tmp->functions & MWM_FUNC_MINIMIZE)))	return False;        /* Cannot resize if iconified */    if (mi->func == F_RESIZE && tmp && (tmp->flags & ICONIFIED))        return False;    /* Can only normalize if iconified or maximized */    if (mi->func == F_NORMALIZE && tmp &&        !(tmp->flags & ICONIFIED) && !(tmp->flags & MAXIMIZED))	return False;    if (mi->func == F_MAXIMIZE && tmp && !(tmp->functions & MWM_FUNC_MAXIMIZE))	return False;    if (mi->func == F_CLOSE && tmp && !(tmp->functions & MWM_FUNC_CLOSE))	return False;    return True;}/* * draws a single entry in a poped up menu */static voidpaint_entry(ScreenInfo *scr, MwmWindow *tmp, MenuRoot * mr, MenuItem *mi){    int y_offset, text_y, d, y_height;    GC ShadowGC, ReliefGC, currentGC;    y_offset = mi->y_offset;    y_height = mi->y_height;    text_y = y_offset + scr->components[MWM_MENU].f_y;    ShadowGC = scr->components[MWM_MENU].bot_GC;    ReliefGC = scr->components[MWM_MENU].top_GC;    if ((!mi->prev) || (!mi->prev->state))	XClearArea(dpy, mr->w, 0, y_offset - 1, mr->width, y_height + 2, 0);    else	XClearArea(dpy, mr->w, 0, y_offset + 1, mr->width, y_height - 1, 0);    if ((mi->state) && (mi->func != F_TITLE) &&	(mi->func != F_NOP) && *mi->item)    {	relieve_rectangle(mr->w, 3, y_offset, mr->width - 5, mi->y_height,			  ReliefGC, ShadowGC);	relieve_rectangle(mr->w, 2, y_offset - 1,			  mr->width - 3, mi->y_height + 2,			  ReliefGC, ShadowGC);    }    relieve_half_rectangle(mr->w, 0, y_offset - 1, mr->width,			   y_height + 2, ReliefGC, ShadowGC);    if (mi->func == F_TITLE)    {	text_y += HEIGHT_EXTRA >> 1;	XDrawLine(dpy, mr->w, ShadowGC, 2, y_offset + y_height - 2,		  mr->width - 3, y_offset + y_height - 2);	XDrawLine(dpy, mr->w, ShadowGC, 2, y_offset + y_height - 4,		  mr->width - 3, y_offset + y_height - 4);    }    else	text_y += HEIGHT_EXTRA >> 1;    if (mi->func == F_NOP && *mi->item == 0)    {	draw_separator(mr->w, ShadowGC, ReliefGC,		       2, y_offset - 1 + HEIGHT_SEPARATOR / 2,		       mr->width - 3, y_offset - 1 + HEIGHT_SEPARATOR / 2, 0);    }    if (mi->next == NULL)	draw_separator(mr->w, ShadowGC, ShadowGC, 1, mr->height - 2,		       mr->width - 2, mr->height - 2, 1);    if (mi == mr->first)	draw_separator(mr->w, ReliefGC, ReliefGC, 0, 0, mr->width - 1, 0, -1);    if (function_allowed(tmp, mi))	currentGC = scr->components[MWM_MENU].normal_GC;    else {    /* MLM: FIXME: SHOULD GRAY OUT ITEM */	currentGC = scr->components[MWM_MENU].grayed_GC;    }    if (*mi->item)	XDrawString(dpy, mr->w, currentGC, mi->x, text_y,		    mi->item, mi->strlen);    if (mi->strlen2 > 0 && mi->item2 && *mi->item2)	XDrawString(dpy, mr->w, currentGC, mi->x2, text_y,		    mi->item2, mi->strlen2);    /* pete@tecc.co.uk: If the item has a hot key, underline it */    if (mi->hotkey > 0)	draw_underline(scr, mr->w, currentGC, mi->x, text_y,		       mi->item, mi->hotkey - 1);    if (mi->hotkey < 0)	draw_underline(scr, mr->w, currentGC, mi->x2, text_y,		       mi->item2, -1 - mi->hotkey);    d = (scr->components[MWM_MENU].f_height + HEIGHT_EXTRA - 7) / 2;    if (mi->func == F_POPUP)    {	if (mi->state)	    draw_arrow(mr->w, ShadowGC, ReliefGC, ShadowGC, mr->width - d - 8,		       y_offset + d - 1, mr->width - d - 1, y_offset + d + 7);	else	    draw_arrow(mr->w, ReliefGC, ShadowGC, ReliefGC, mr->width - d - 8,		       y_offset + d - 1, mr->width - d - 1, y_offset + d + 7);    }}/* * draws the entire menu */static voidpaint_menu(ScreenInfo *scr, MwmWindow *tmp, MenuRoot * mr, XEvent *e){    MenuItem *mi;    for (mi = mr->first; mi != NULL; mi = mi->next)    {	/* be smart about handling the expose, redraw only the entries	 * that we need to	 */	if (e->xexpose.y < (mi->y_offset + mi->y_height) &&	    (e->xexpose.y + e->xexpose.height) > mi->y_offset)	{	    paint_entry(scr, tmp, mr, mi);	}    }    XSync(dpy, 0);}/* * Updates menu display to reflect the highlighted item */static intfind_entry(ScreenInfo *scr, MwmWindow *tmp){    MenuItem *mi;    MenuRoot *actual_mr;    int retval = MENU_NOP;    MenuRoot *PrevPrevMenu;    MenuItem *PrevPrevItem;    int PrevPrevY;    int x, y, ChildY;    Window Child;    XQueryPointer(dpy, scr->root_win, &JunkRoot, &Child,		  &JunkX, &ChildY, &x, &y, &JunkMask);    XQueryPointer(dpy, ActiveMenu->w, &JunkRoot, &JunkChild,		  &JunkX, &ChildY, &x, &y, &JunkMask);    /* look for the entry that the mouse is in */    for (mi = ActiveMenu->first; mi; mi = mi->next)	if (y >= mi->y_offset && y < mi->y_offset + mi->y_height)	    break;    if (x < 0 || x > ActiveMenu->width)	mi = NULL;    /* if we weren't on the active entry, let's turn the old active one off */    if ((ActiveItem) && (mi != ActiveItem))    {	ActiveItem->state = 0;	paint_entry(scr, tmp, ActiveMenu, ActiveItem);    }    /* if we weren't on the active item, change the active item and turn it     * on */    if ((mi != ActiveItem) && (mi != NULL) && function_allowed(tmp, mi))    {	mi->state = 1;	paint_entry(scr, tmp, ActiveMenu, mi);    }    ActiveItem = mi;    if (ActiveItem)    {	/* create a new sub-menu */	if (ActiveItem->func == F_POPUP)	{	    PrevPrevMenu = PrevMenu;	    PrevPrevItem = PrevItem;	    PrevPrevY = PrevY;	    PrevY = MenuY;	    PrevMenu = ActiveMenu;	    PrevItem = ActiveItem;	    retval = MENU_PopupMenu(scr, ActiveItem->menu);	    /* Unfortunately, this is needed (why?) for multi-screen	     * operation */	    MISC_FlushExpose(ActiveMenu->w);	    for (mi = ActiveMenu->first; mi != NULL; mi = mi->next)		paint_entry(scr, tmp, ActiveMenu, mi);	    XSync(dpy, 0);	    MenuY = PrevY;	    PrevMenu = PrevPrevMenu;	    PrevItem = PrevPrevItem;	    PrevY = PrevPrevY;	}    }    /* end a sub-menu */    if (XFindContext(dpy, Child,		     MenuContext, (XPointer *)&actual_mr) == XCNOENT)    {	return retval;    }    if (actual_mr != ActiveMenu)    {	if (actual_mr == PrevMenu)	{	    if ((PrevItem->y_offset + PrevY > ChildY) ||		((PrevItem->y_offset + PrevItem->y_height + PrevY) < ChildY))	    {		return SUBMENU_DONE;	    }	}	else	    return SUBMENU_DONE;    }    return retval;}/* * Function called from update_menu instead of Keyboard_Shortcuts() * when a KeyPress event is received.  If the key is alphanumeric, * then the menu is scanned for a matching hot key.  Otherwise if * it was the escape key then the menu processing is aborted. * If none of these conditions are true, then the default processing * routine is called. */static voidmenu_shortcuts(ScreenInfo *scr, XEvent *ev){    MenuItem *mi;    KeySym keysym = XLookupKeysym(&ev->xkey, 0);    /* Try to match hot keys */    if (((keysym >= XK_a) && (keysym <= XK_z)) ||	/* consider alphabetic */	((keysym >= XK_0) && (keysym <= XK_9)))    {				/* ...or numeric keys  */	/* Search menu for matching hotkey */	for (mi = ActiveMenu->first; mi; mi = mi->next)	{	    char key;	    if (mi->hotkey == 0)		continue;	/* Item has no hotkey   */	    key = (mi->hotkey > 0) ?	/* Extract hot character */		mi->item[mi->hotkey - 1] : mi->item2[-1 - mi->hotkey];	    /* Convert to lower case to match the keysym */	    if (isupper(key))		key = tolower(key);	    if (keysym == key)	    {		/* Force a menu exit */		ActiveItem = mi;		ev->type = ButtonRelease;		return;	    }	}    }    switch (keysym)    {    case XK_Escape:	/* escape exits menu */	ActiveItem = NULL;	ev->type = ButtonRelease;	break;	/* Nothing special --- Allow other shortcuts (cursor movement)    */    default:	MISC_KeyboardShortcut(scr, ev, ButtonRelease);	break;    }}/* * pop up a pull down menu */static Booleanpop_up_menu(ScreenInfo *scr, MenuRoot * menu, int x, int y){    if ((!menu) || (menu->w == None) || (menu->items == 0) || (menu->in_use))	return False;    menu_on++;    COLOR_PushRootColorMap(scr);    Stashed_X = x;    Stashed_Y = y;    /* pop up the menu */    ActiveMenu = menu;    ActiveItem = NULL;    /* clip to screen */    if (x + menu->width > scr->d_width - 2)	x = scr->d_width - menu->width - 2;    if (x < 0)	x = 0;    if (y + menu->height > scr->d_height - 2)	y = scr->d_height - menu->height - 2;    if (y < 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -