📄 menu.c
字号:
#ifndef lintstatic char *rcsid_Menu_c = "$Header: Menu.c 88/08/09 08:57:49 Xusr Exp $";#endif/* * Copyright 1987 by Digital Equipment Corporation, Maynard, 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 permission notice appear in * supporting documentation, and that the name of Digital Equipment * Corporation not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 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. *//* * MODIFICATION HISTORY * * 000 -- M. Gancarz, DEC Ultrix Engineering Group * 001 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab * February 16, 1987 * Change menu implementation so that it uses EnterWindow, LeaveWindow, * and MouseMotion events to track the mouse, instead of polling. * 002 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab * April 30, 1987. Convert to X11. * 003 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab * June 18, 1987. Change call to system to handle signals move smoothly. */#ifndef lintstatic char *sccsid = "@(#)Menu.c 3.8 1/24/86";#endif#include <signal.h>#include "uwm.h"Bool alternateGC = True; /* true if only 2 colors are used */#define DisplayLine(w, pane, width, height, str, fg, bg, inv) \ if (alternateGC) { \ if (inv) \ XFillRectangle(dpy, w, MenuInvGC, 0, pane, width, height); \ else \ XDrawString(dpy, w, MenuGC, HMenuPad, pane + VMenuPad + MFontInfo->ascent, str, strlen(str)); \ } else { \ XSetForeground(dpy, MenuGC, bg); \ XFillRectangle(dpy, w, MenuGC, 0, pane, width, height); \ XSetForeground(dpy, MenuGC, fg); \ XDrawString(dpy, w, MenuGC, HMenuPad, pane + VMenuPad + MFontInfo->ascent, str, strlen(str)); \ }#ifdef SYSV#ifndef hpux#define vfork() fork()#endif /* hpux */#endif /* SYSV *//* the following procedure is a copy of the implementation of system, * modified to reset the handling of SIGINT, SIGQUIT, and SIGHUP before * exec-ing */execute(s)char *s;{ int status, pid, w; register void (*istat)(), (*qstat)(); if ((pid = vfork()) == 0) { signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGHUP, SIG_DFL); execl("/bin/sh", "sh", "-c", s, 0); _exit(127); } istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; signal(SIGINT, istat); signal(SIGQUIT, qstat); return(status);}Bool Menu(window, mask, button, x, y, menu)Window window; /* Event window. */int mask; /* Button/key mask. */int button; /* Button event detail. */int x, y; /* Event mouse position. */MenuInfo *menu;{ XEvent button_event; /* Button event packet. */ int event_x, event_y; /* location of button event */ Bool func_stat; /* Function status return. */ Window sub_window; /* Current subwindow. */ int cur_item = 0; /* Current menu item. */ int hi_lite = 0; /* Current highlighted item. */ int i; /* Iteration counter. */ int hlfg, hlbg; /* Hi-liter pixels. */ MenuLine *ml; /* Menu lines pointer. */ char *hlname; /* Pointer to hi-liter name. */ char *strbuf; /* String buffer for IsTextNL. */ Bool checkMotion = TRUE; /* To Restore Cursor Position */ char *malloc(); /* * Change the cursor. */ XChangeActivePointerGrab(dpy, EVENTMASK, MenuCursor, CurrentTime); /* * Map the menu. */ MapMenu(menu, x, y); if (Autoselect) { event_x = (menu->width >> 2) * 3; event_y = (menu->iheight >> 1) * 3; XWarpPointer(dpy, None, menu->w, 0, 0, 0, 0, event_x, event_y); goto hilite; } else { XWarpPointer(dpy, None, menu->w, 0, 0, 0, 0, (menu->width >> 2) * 3, menu->iheight >> 1); XFlush(dpy); } /* * Main loop. */ while (TRUE) { /* * Get next event for menu. */ if (!GetButton(&button_event)) continue; switch (button_event.type) { case LeaveNotify: /* * If the mouse has moved out of the menu sideways, abort * the menu operation. Reset the cursor and unmap the menu. */ event_x = ((XLeaveWindowEvent * )&button_event)->x; event_y = ((XLeaveWindowEvent * )&button_event)->y; if (event_x < 0 || event_x > menu->width) { ResetCursor(button); UnmapMenu(menu); return(FALSE); } goto hilite; case EnterNotify: event_x = ((XEnterWindowEvent * )&button_event)->x; event_y = ((XEnterWindowEvent * )&button_event)->y; goto hilite; case MotionNotify: { event_x = ((XPointerMovedEvent * )&button_event)->x; event_y = ((XPointerMovedEvent * )&button_event)->y; if ((checkMotion == TRUE) && ((event_x != (menu->width >> 2) * 3) || (event_y != (menu->iheight >> 1)))) checkMotion = FALSE; /* Mouse Has Moved From Top Pane */hilite: /* * If the mouse has moved below or above the menu, but is still * within the same vertical plane, then simply adjust the values * so the user doesn't fall off the edge. */ if (event_y >= menu->height) event_y = menu->height - 1; else if (event_y < 0) event_y = 0; /* * If the mouse has moved to another item in the menu, * highlight the new item. */ cur_item = event_y / menu->iheight; if (cur_item != hi_lite) { /* * Remove highlighting on old item. */ if (hi_lite) { DisplayLine(menu->w, hi_lite * menu->iheight, menu->width, menu->iheight, hlname, hlfg, hlbg, 1); XFlush(dpy); } /* * Highlight new item. */ hi_lite = cur_item; if (cur_item) { for(i = 1, ml = menu->line; ml; i++, ml = ml->next) { if (i == cur_item) break; } DisplayLine(menu->w, cur_item * menu->iheight, menu->width, menu->iheight, ml->name, menu->hlfg.pixel, menu->hlbg.pixel, 1);/* XSetForeground(dpy, MenuGC, menu->hlfg.pixel ); XDrawRectangle(dpy, menu->w, MenuGC, 1, cur_item * menu->iheight + 1, menu->width - 3, menu->iheight - 3);*/ XFlush(dpy); hlfg = ml->fg.pixel; hlbg = ml->bg.pixel; hlname = ml->name; } } break; case ButtonRelease: /* have we released the invoking button? */ if (((XButtonReleasedEvent *)&button_event)->button == button) { /* * If no item was selected, * close the menu, reset the pointer's position and return */ if (!cur_item) { /* If Needed Reset The Cursor Position */ if (checkMotion == TRUE) XWarpPointer (dpy, None, RootWindow(dpy, scr), 0, 0, 0, 0, x, y); ResetCursor(button); UnmapMenu(menu); return(TRUE); } /* * Get a pointer to the menu line selected. */ --cur_item; for(i = 0, ml = menu->line; ml; i++, ml = ml->next) { if (i == cur_item) break; } /* * Perform the selected menu line action. */ switch (ml->type) { case IsShellCommand: UnmapMenu(menu); execute(ml->text); break; case IsText: UnmapMenu(menu); XStoreBytes(dpy, ml->text, strlen(ml->text)); break; case IsTextNL: UnmapMenu(menu); strbuf = (char *)malloc(strlen(ml->text) + 2); strcpy(strbuf, ml->text); strcat(strbuf, "\n"); XStoreBytes(dpy, strbuf, strlen(strbuf)); free(strbuf); break; case IsUwmFunction: /* change cursor and grab next button event * to select the target window */ if (XGrabPointer( dpy, RootWindow(dpy, scr), TRUE, EVENTMASK, GrabModeAsync, GrabModeAsync, None, TargetCursor, CurrentTime ) != GrabSuccess ) Error( "Could not grab pointer" ); GetContext( &sub_window, &event_x, &event_y); UnmapMenu(menu); if (sub_window != menu->w) func_stat = (*ml->func) ( sub_window, mask, button, event_x, event_y); else func_stat = FALSE; if (!func_stat) { /* eat the next ButtonRelease */ while (TRUE) { if (GetButton(&button_event) && button_event.type == ButtonRelease) break; } } XUngrabPointer( dpy, CurrentTime ); break; case IsImmFunction: UnmapMenu(menu); (*ml->func) ( sub_window, mask, button, event_x, event_y); break; case IsMenuFunction: while (TRUE) { if (!GetButton(&button_event)) continue; if (button_event.type != ButtonPress) continue; if ((((XButtonPressedEvent *)&button_event)->state != mask) || (((XButtonPressedEvent *)&button_event)->button != button)) { UnmapMenu(menu); return(TRUE); } break; } UnmapMenu(menu); func_stat = Menu(menu->w, mask, button, x, y, ml->menu); return(func_stat); break; default: Error("Menu -> Internal type error."); } return(TRUE); } /* else a different button was released. Fall through: */ default: /* * Some other button event occurred, so abort the menu * operation. */ ResetCursor(button); /* If Needed Reset The Cursor Position */ if (checkMotion == TRUE) XWarpPointer (dpy, None, RootWindow(dpy, scr),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -