DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T m ┃
Length: 39828 (0x9b94) Types: TextFile Names: »menu.c«
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS └─ ⟦91c658230⟧ »DATA« └─⟦5d656759a⟧ └─⟦8fb0c967c⟧ └─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3 └─ ⟦fc9b38f02⟧ »DATA« └─⟦8e9e227a9⟧ └─⟦8fb0c967c⟧ └─ ⟦this⟧ »menu.c«
#ifdef SCCS static char sccsid[]="@(#)menu.c 1.7 Stellar 87/10/16"; #endif /* * $XConsortium: menu.c,v 1.10 88/10/05 11:16:29 jim Exp $ */ #include <X11/copyright.h> /* * 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. */ #include <stdio.h> #include <X11/Xlib.h> #include <X11/StringDefs.h> #include <X11/Intrinsic.h> #include <X11/Shell.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/cursorfont.h> #include "menu.h" #include <setjmp.h> #include <signal.h> #include "ptyx.h" #include "data.h" #ifdef RIOS #include <signal.h> #endif /* RIOS */ #ifndef lint static char rcs_id[] = "$XConsortium: menu.c,v 1.10 88/10/05 11:16:29 jim Exp $"; #endif lint #define DEFMENUBORDER 2 #define DEFMENUPAD 3 #define XOR(a,b) ((a&(~b)) | ((~a)&b)) #define SetStateFlags(item) item->itemFlags = (item->itemFlags &\ ~(itemStateMask | itemChanged)) |\ ((item->itemFlags & itemSetMask) >>\ itemSetMaskShift) static char Check_MarkBits[] = { 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 }; static GC MenuGC, MenuInverseGC, MenuInvertGC, MenuGrayGC; static int gotGCs = FALSE; Pixmap Gray_Tile, Check_Normal_Tile, Check_Inverse_Tile, Check_Tile; Menu Menu_Default; Cursor Menu_DefaultCursor; char *Menu_DefaultFont; int default_menuBorder = DEFMENUBORDER; int default_menuPad = DEFMENUPAD; static XtResource resourceList[] = { {"menuBorder", "MenuBorder", XtRInt, sizeof(int), XtOffset (Menu *, menuBorderWidth), XtRInt, (caddr_t)&default_menuBorder}, {"menuPad", "MenuPad", XtRInt, sizeof(int), XtOffset (Menu *, menuItemPad), XtRInt, (caddr_t) &default_menuPad} }; static Draw_Item(); static Draw_Menu(); static Map_Menu(); static Move_Menu(); static Recalc_Menu(); /* * AddMenuItem() adds a menu item to an existing menu, at the end of the * list, which are number sequentially from zero. The menuitem index is * return, or -1 if failed. */ AddMenuItem(menu, text) register Menu *menu; register char *text; { register MenuItem *menuitem, **next; register int i; extern char *malloc(); if(!menu || !text || (menuitem = (MenuItem *)malloc(sizeof(MenuItem))) == (MenuItem *)0) return(-1); bzero((char *)menuitem, sizeof(MenuItem)); menuitem->itemText = text; menuitem->itemTextLength = strlen(text); for(i = 0, next = &menu->menuItems ; *next ; i++) next = &(*next)->nextItem; *next = menuitem; menu->menuFlags |= menuChanged; return(i); } void InitMenu(name) register char *name; { register XtermWidget xw = term; register char *cp; static int didthisonce = FALSE; Display *dpy = XtDisplay(xw); Pixel background = xw->core.background_pixel; Pixel foreground = xw->screen.foreground; if (didthisonce) return; didthisonce = TRUE; /* * If the gray tile hasn't been set up, do it now. */ if(!Gray_Tile) Gray_Tile = XtGrayPixmap(XtScreen(xw)); if (!Check_Tile) { extern Pixmap Make_tile(); Check_Normal_Tile = Make_tile(checkMarkWidth, checkMarkHeight, Check_MarkBits, foreground, background, (unsigned int)DefaultDepth(dpy,DefaultScreen(dpy))); Check_Inverse_Tile = Make_tile(checkMarkWidth, checkMarkHeight, Check_MarkBits, background, foreground, (unsigned int)DefaultDepth(dpy,DefaultScreen(dpy))); Check_Tile = Check_Normal_Tile; } Menu_Default.menuFlags = menuChanged; Menu_Default.menuInitialItem = -1; XtGetSubresources((Widget)xw, (caddr_t)&Menu_Default, "menu", "Menu", resourceList, XtNumber(resourceList), NULL, 0); Menu_Default.menuFontInfo = vt100_resource.f_m; if (Menu_Default.menuFontInfo == NULL) { if (xw->screen.fnt_norm) { Menu_Default.menuFontInfo = xw->screen.fnt_norm; MenugcFontMask = VTgcFontMask; } else { Display *dpy = XtDisplay (xw); Menu_Default.menuFontInfo = XQueryFont (dpy, DefaultGC (dpy, DefaultScreen (dpy))->gid); MenugcFontMask = 0; } } }; /* * ItemFlags returns the state of item "n" of the menu. */ ItemFlags(menu, n) register Menu *menu; register int n; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(-1); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); return((item->itemFlags & itemSetMask) >> itemSetMaskShift); } /* * ItemText changes the text of item "n" of the menu. */ ItemText(menu, n, text) register Menu *menu; register int n; char *text; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0 || !text) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); item->itemText = text; menu->menuFlags |= menuChanged; return(1); } /* * NewMenu() returns a pointer to an initialized new Menu structure, or NULL * if failed. * * The Menu structure _menuDefault contains the default menu settings. */ Menu *NewMenu (name) char *name; { register Menu *menu; register XtermWidget xw = term; XGCValues xgc; extern char *malloc(); extern XFontStruct *XLoadQueryFont(); register Display *dpy = XtDisplay(xw); Pixel background = xw->core.background_pixel; Pixel foreground = xw->screen.foreground; /* * If the GrayTile hasn't been defined, InitMenu() was never * run, so exit. */ if(!Gray_Tile) return((Menu *)0); /* * Allocate the memory for the menu structure. */ if((menu = (Menu *)malloc(sizeof(Menu))) == (Menu *)0) return((Menu *)0); /* * Initialize to default values. */ *menu = Menu_Default; /* * If the menu cursor hasn't been given, make a default one. */ if(!menu->menuCursor) { if(!Menu_DefaultCursor) { if(!(Menu_DefaultCursor = XCreateFontCursor(dpy, XC_left_ptr))) return((Menu *)0); } menu->menuCursor = Menu_DefaultCursor; } /* * Initialze the default background and border pixmaps and foreground * and background colors (black and white). */ menu->menuFgColor = foreground; menu->menuBgColor = background; if(!gotGCs) { xgc.foreground = menu->menuFgColor; xgc.function = GXinvert; xgc.plane_mask = XOR(menu->menuFgColor, menu->menuBgColor); MenuInvertGC = XCreateGC(dpy, DefaultRootWindow(dpy), GCForeground+GCFunction+GCPlaneMask, &xgc); xgc.foreground = menu->menuFgColor; xgc.background = menu->menuBgColor; xgc.font = menu->menuFontInfo->fid; xgc.function = GXcopy; xgc.fill_style = FillSolid; MenuGC = XCreateGC(dpy, DefaultRootWindow(dpy), MenugcFontMask+GCForeground+GCBackground+GCFunction+GCFillStyle, &xgc); xgc.foreground = menu->menuBgColor; xgc.background = menu->menuFgColor; xgc.font = menu->menuFontInfo->fid; xgc.function = GXcopy; xgc.fill_style = FillSolid; MenuInverseGC = XCreateGC(dpy, DefaultRootWindow(dpy), MenugcFontMask+GCForeground+GCBackground+GCFunction+GCFillStyle, &xgc); xgc.foreground = menu->menuFgColor; xgc.background = menu->menuBgColor; xgc.function = GXcopy; xgc.stipple = Gray_Tile; xgc.fill_style = FillStippled; MenuGrayGC = XCreateGC(dpy, DefaultRootWindow(dpy), GCStipple+GCFillStyle+MenugcFontMask +GCForeground+GCBackground+GCFunction, &xgc); gotGCs = TRUE; } /* * Set the menu title. If name is NULL or is an empty string, no * title will be displayed. */ if(name && *name) { menu->menuTitleLength = strlen(menu->menuTitle = name); menu->menuTitleWidth = XTextWidth(menu->menuFontInfo, name, menu->menuTitleLength); menu->menuItemTop = menu->menuFontInfo->ascent + menu->menuFontInfo->descent + 2 * menu->menuItemPad + 1; } else menu->menuTitleLength = menu->menuTitleWidth = menu->menuItemTop = 0; return(menu); } /* * SetItemCheck sets the check state of item "n" of the menu to "state". */ SetItemCheck(menu, n, state) register Menu *menu; register int n; int state; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); if(state) item->itemFlags |= itemSetChecked; else item->itemFlags &= ~itemSetChecked; if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) != (item->itemFlags & itemStateMask)) { item->itemFlags |= itemChanged; menu->menuFlags |= menuItemChanged; } else item->itemFlags &= ~itemChanged; return(1); } /* * SetItemDisable sets the disable state of item "n" of the menu to "state". */ SetItemDisable(menu, n, state) register Menu *menu; register int n; int state; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); if(state) item->itemFlags |= itemSetDisabled; else item->itemFlags &= ~itemSetDisabled; if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) != (item->itemFlags & itemStateMask)) { item->itemFlags |= itemChanged; menu->menuFlags |= menuItemChanged; } else item->itemFlags &= ~itemChanged; return(1); } static Menu *menu; static MenuItem *item; static int i; static MenuItem *hilited_item; static int drawn; static int changed; int y, n, hilited_y, hilited_n, in_window; static MenuItem *Mouse_InItem(), *Y_InItem(); static Unmap_Menu(); /*ARGSUSED*/ void MenuExposeWindow(w, closure, event) Widget w; caddr_t closure; XEvent *event; { register XtermWidget xw = (XtermWidget) w; /* * If we have a saved pixmap, display it. Otherwise * redraw the menu and save it away. */ if (event->type == NoExpose) return; Draw_Menu(menu); /* * If the menu has changed in any way and we want to * save the menu, throw away any existing save menu * image and make a new one. */ XFlush(XtDisplay(xw)); /* * See which item the cursor may currently be in. If * it is in a non-disabled item, hilite it. */ if(hilited_item = Mouse_InItem(menu, &hilited_y, &hilited_n)) XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y, (unsigned int)menu->menuWidth, (unsigned int)hilited_item->itemHeight); drawn++; } /*ARGSUSED*/ void MenuMouseMoved(w, closure, event) Widget w; caddr_t closure; XMotionEvent *event; { register XtermWidget xw = (XtermWidget) w; if(!drawn || !in_window) return; /* * See which item the cursor may currently be in. If * the item has changed, unhilite the old one and * then hilited the new one. */ y = event->y; if((item = Y_InItem(menu, &y, &n)) != hilited_item) { if(hilited_item) XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y, (unsigned int)menu->menuWidth, (unsigned int)hilited_item->itemHeight); if(hilited_item = item) { XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y = y, (unsigned int)menu->menuWidth, (unsigned int)item->itemHeight); hilited_n = n; } } } /*ARGSUSED*/ void MenuEnterWindow(w, closure, event) Widget w; caddr_t closure; XEvent *event; { in_window = TRUE; MenuMouseMoved(w, closure, (XMotionEvent*)event); } /*ARGSUSED*/ void MenuLeaveWindow(w, closure, event) Widget w; caddr_t closure; XEvent *event; { register XtermWidget xw = (XtermWidget) w; if(!drawn) return; /* * Unhilite any window that is currently hilited. */ if(hilited_item) { XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y, (unsigned int)menu->menuWidth, (unsigned int)hilited_item->itemHeight); hilited_item = (MenuItem *)0; } in_window = FALSE; } int menu_grab = FALSE; /*ARGSUSED*/ void MenuButtonReleased(w, closure, event) Widget w; caddr_t closure; XButtonEvent *event; { register XtermWidget xw = (XtermWidget) w; extern FinishModeMenu(); /* * return the index number of any selected menu * item. */ if (! AllButtonsUp(event->state, event->button)) return; XUngrabPointer(XtDisplay(xw), CurrentTime); menu_grab = FALSE; if(in_window) { y = event->y; if((item = Y_InItem(menu, &y, &n)) != hilited_item) { if(hilited_item) XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y, (unsigned int)menu->menuWidth, (unsigned int)hilited_item->itemHeight); if(hilited_item = item) { XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuInvertGC, 0, hilited_y = y, (unsigned int)menu->menuWidth, (unsigned int)hilited_item->itemHeight); hilited_n = n; } } } XFlush(XtDisplay(xw)); menu->menuFlags &= ~(menuChanged | menuItemChanged); Unmap_Menu(menu); drawn = 0; if(hilited_item) FinishModeMenu(menu->menuInitialItem = hilited_n, event->time); else FinishModeMenu(-1, event->time); } /* * TrackMenu does most of the work of displaying the menu and tracking the * mouse. */ TrackMenu(lmenu, event) register Menu *lmenu; register XButtonPressedEvent *event; { register XtermWidget xw = term; XButtonReleasedEvent ev; XSetWindowAttributes attr; menu = lmenu; hilited_item = (MenuItem *)0; /* * Check that things are reasonable. */ if(!menu || !event || !menu->menuItems || event->type != ButtonPress) return(-1); /* * Set the changed flag and clear the menu changed flags. */ changed = menu->menuFlags & (menuChanged | menuItemChanged); /* * If the entire menu has changed, throw away any saved pixmap and * then call RecalcMenu(). */ if(changed & menuChanged) { if(!Recalc_Menu(menu)) return(-1); changed &= ~menuItemChanged; } /* * Now if the window was never created, go ahead and make it. Otherwise * if the menu has changed, resize the window. */ if(!menu->menuWindow) { #define SETARG( XtN, XtV ) XtSetArg( args[argi], XtN, XtV ); argi++ Arg args[2]; int argi = 0; SETARG( XtNgeometry, NULL ); /* Never let user set this. */ #undef SETARG menu->menuWidget = XtCreatePopupShell ("Xterm Menu", transientShellWidgetClass, xw, args, (Cardinal)argi); XtResizeWidget (menu->menuWidget, menu->menuWidth, menu->menuHeight, menu->menuBorderWidth); XtRealizeWidget (menu->menuWidget); menu->menuWindow = XtWindow (menu->menuWidget); attr.override_redirect = True; attr.border_pixmap = XtGrayPixmap(XtScreen(xw)); attr.background_pixel = menu->menuBgColor; attr.cursor = menu->menuCursor; attr.save_under = True; XChangeWindowAttributes (XtDisplay(xw), menu->menuWindow, (CWBorderPixmap | CWBackPixel | CWOverrideRedirect | CWCursor | CWSaveUnder), &attr); XtAddEventHandler(menu->menuWidget, ExposureMask, FALSE, MenuExposeWindow, (caddr_t)NULL); XtAddEventHandler(menu->menuWidget, EnterWindowMask, FALSE, MenuEnterWindow, (caddr_t)NULL); XtAddEventHandler(menu->menuWidget, LeaveWindowMask, FALSE, MenuLeaveWindow, (caddr_t)NULL); XtAddEventHandler(menu->menuWidget, PointerMotionMask, FALSE, MenuMouseMoved, (caddr_t)NULL); XtAddEventHandler(menu->menuWidget, ButtonReleaseMask, FALSE, MenuButtonReleased, (caddr_t)NULL); } else if(changed & menuChanged) XtResizeWidget(menu->menuWidget, menu->menuWidth, menu->menuHeight, menu->menuBorderWidth); /* * Figure out where the menu is supposed to go, from the initial button * press, and move the window there. Then map the menu. */ if(!Move_Menu(menu, event) || !Map_Menu(menu)) return(-1); in_window = TRUE; XGrabPointer(XtDisplay(xw), menu->menuWindow, FALSE, EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, menu->menuCursor, CurrentTime); return 0; } /* * Recalculate all of the various menu and item variables. */ static Recalc_Menu(menu) register Menu *menu; { register MenuItem *item; register int max, height, fontheight; /* * We must have already gotten the menu font. */ if(!menu->menuFontInfo) return(0); /* * Initialize the various max width variables. */ fontheight = menu->menuFontInfo->ascent + menu->menuFontInfo->descent; height = menu->menuItemTop; menu->menuMaxTextWidth = menu->menuTitleWidth; /* * The item height is the maximum of the font height and the * checkbox height. */ max = fontheight; if(checkMarkHeight > max) max = checkMarkHeight; /* * Go through the menu item list. */ for(item = menu->menuItems ; item ; item = item->nextItem) { /* * If the item text is a single dash, we assume this is * a line separator and treat it special. */ if(XStrCmp(item->itemText, "-") == 0) height += (item->itemHeight = lineSeparatorHeight); else { height += (item->itemHeight = max); /* * Check the text width with the max value stored in * menu. */ if((item->itemTextWidth = XTextWidth( menu->menuFontInfo, item->itemText, strlen(item->itemText))) > menu->menuMaxTextWidth) menu->menuMaxTextWidth = item->itemTextWidth; } /* * If the itemChanged flag is set, set the state bits. */ if(item->itemFlags & itemChanged) { item->itemFlags = (item->itemFlags & ~itemStateMask) | ((item->itemFlags & itemSetMask) >> itemSetMaskShift); item->itemFlags &= ~itemChanged; } } /* * Set the menu height and then set the menu width. */ menu->menuHeight = height; menu->menuWidth = 3 * menu->menuItemPad + menu->menuMaxTextWidth + checkMarkWidth; return(1); } /* * Figure out where to popup the menu, relative to the where the button was * pressed. */ static Move_Menu(menu, ev) register Menu *menu; XButtonPressedEvent *ev; { register int n, x, y; register XtermWidget xw = term; int total_width; /* * Try to popup the menu so that the cursor is centered within the * width of the menu, but compensate if that would run it outside * the display area. */ total_width = menu->menuWidth + 2 * menu->menuBorderWidth; if((x = ev->x_root - total_width / 2) < 0) x = 0; else if(x + total_width > DisplayWidth(XtDisplay(xw), DefaultScreen(XtDisplay(xw)))) x = DisplayWidth(XtDisplay(xw), DefaultScreen(XtDisplay(xw))) - total_width; /* * If the menu extends above outside of the display, warp * the mouse vertically so the menu will all show up. */ if((y = ev->y_root) < 0) { /* don't bother warping pointer XWarpPointer(XtDisplay(xw), None, DefaultRootWindow(XtDisplay(xw)), 0, 0, 0, 0, ev->x_root, 0); */ y = 0; } else if((n = y + menu->menuHeight + 2 * menu->menuBorderWidth - DisplayHeight(XtDisplay(xw), DefaultScreen(XtDisplay(xw)))) > 0) { /* don't bother warping pointer XWarpPointer(XtDisplay(xw), None, DefaultRootWindow(XtDisplay(xw)), 0, 0, 0, 0, ev->x_root, ev->y_root - n); */ y -= n; } XtMoveWidget(menu->menuWidget, x, y); return(1); } /* * Map the menu window. */ static Map_Menu(menu) register Menu *menu; { register XtermWidget xw = term; /* * Actually map the window. */ XRaiseWindow (XtDisplay(xw), menu->menuWindow); XtPopup (menu->menuWidget, XtGrabNone); menu->menuFlags |= menuMapped; return(1); } /* * Draw the entire menu in the blank window. */ static Draw_Menu(menu) register Menu *menu; { register MenuItem *item; register int top = menu->menuItemTop; register int x = menu->menuItemPad; register int dim; register XtermWidget xw = term; /* * If we have a menu title, draw it first, centered and hilited. */ if(menu->menuTitleLength) { XFillRectangle(XtDisplay(xw), menu->menuWindow, MenuGC, 0, 0, (unsigned int)menu->menuWidth, (unsigned int)top - 1); XDrawImageString(XtDisplay(xw), menu->menuWindow, MenuInverseGC, (menu->menuWidth - menu->menuTitleWidth) / 2, menu->menuItemPad+menu->menuFontInfo->ascent, menu->menuTitle, menu->menuTitleLength); } /* * For each item in the list, first draw any check mark and then * draw the rest of it. */ for(item = menu->menuItems ; item ; item = item->nextItem) { SetStateFlags(item); dim = (item->itemFlags & itemDisabled); /* * Draw the check mark, possibly dimmed, wherever is necessary. */ if(item->itemFlags & itemChecked) { XCopyArea(XtDisplay(xw), Check_Tile, menu->menuWindow, dim ? MenuGrayGC : MenuGC, 0, 0, checkMarkWidth, checkMarkHeight, x, top + (item->itemHeight - checkMarkHeight) / 2); } /* * Draw the item, possibly dimmed. */ Draw_Item(menu, item, top, dim); top += item->itemHeight; } } /* * Modify the item at vertical position y. This routine is table driven and * the state and set bits are each 2 bits long, contiguous, the least * significant bits in the flag word and with the state bits in bits 0 & 1. */ #define drawCheck 0x10 #define removeCheck 0x08 #define dimCheck 0x04 #define drawItem 0x02 #define dimItem 0x01 static char Modify_Table[] = { 0x00, 0x02, 0x08, 0x0a, 0x01, 0x00, 0x09, 0x08, 0x10, 0x12, 0x00, 0x12, 0x15, 0x14, 0x05, 0x00 }; #if 0 * static Modify_Item(menu, item, top) * register Menu *menu; * register MenuItem *item; * int top; * { * register int x = menu->menuItemPad; * register int y; * register int center = top + item->itemHeight / 2; * register int func = Modify_Table[item->itemFlags & * (itemStateMask | itemSetMask)]; * register XtermWidget xw = term; * * /* * * If we really won't be making a change, return. * */ * if(func == 0) * return; * /* * * Draw the check mark if needed, possibly dimmed. * */ * y = center - (checkMarkHeight / 2); * if(func & (drawCheck | dimCheck)) * XCopyArea(XtDisplay(xw), * Check_Tile, menu->menuWindow, * (func & dimCheck) ? MenuGrayGC : MenuGC, * 0, 0, checkMarkWidth, checkMarkHeight, x, * y = top + (item->itemHeight - checkMarkHeight) / 2); * /* * * Remove the check mark if needed. * */ * if(func & removeCheck) * XClearArea(XtDisplay(xw), menu->menuWindow, * x, y, checkMarkWidth, checkMarkHeight, FALSE); * /* * * Call Draw_Item if we need to draw or dim the item. * */ * if((x = func & dimItem) || (func & drawItem)) * Draw_Item(menu, item, top, x); * /* * * Update state flags. * */ * SetStateFlags(item); * } #endif /* 0 */ /* * Draw the item (less check mark) at vertical position y. * Dim the item if "dim" is set. */ static Draw_Item(menu, item, y, dim) register Menu *menu; register MenuItem *item; register int y; int dim; { register int x = 2 * menu->menuItemPad + checkMarkWidth; register int center = y + item->itemHeight / 2; register XtermWidget xw = term; /* * If the item text is a single dash, draw a separating line. */ if(XStrCmp(item->itemText, "-") == 0) { XDrawLine(XtDisplay(xw), menu->menuWindow, MenuGC, 0, center, menu->menuWidth, center); return; } /* * Draw and/or dim the text, centered vertically. */ y = center - ((menu->menuFontInfo->ascent + menu->menuFontInfo->descent)/ 2); if(dim) { XDrawString(XtDisplay(xw), menu->menuWindow, MenuGrayGC, x, y+menu->menuFontInfo->ascent, item->itemText, item->itemTextLength); } else XDrawImageString(XtDisplay(xw), menu->menuWindow, MenuGC, x, y+menu->menuFontInfo->ascent, item->itemText, item->itemTextLength); } /* * Determine which enabled menu item the mouse is currently in. Return the * top position of this item and its item number. Set inwindow to whether * we are or not. */ static MenuItem *Mouse_InItem(menu, top, n) register Menu *menu; int *top, *n; { int x, y, rootx, rooty; unsigned int mask; Window subw, root; static MenuItem *Y_InItem(); register XtermWidget xw = term; /* * Find out where the mouse is. If its not in the menu window, * return NULL. */ XQueryPointer(XtDisplay(xw), menu->menuWindow, &root, &subw, &rootx, &rooty, &x, &y, &mask); if((x <0) || (y < 0) || (x > menu->menuWidth) || (y > menu->menuHeight)) { return((MenuItem *)0); } /* * Call Y_InItem(). */ *top = y; return(Y_InItem(menu, top, n)); } /* * Return which enabled item the locator is in. Also return the * top position of this item and its item number. Initial y passed * in top. */ static MenuItem *Y_InItem(menu, top, n) register Menu *menu; int *top, *n; { register MenuItem *item; register int t, i; register int y = *top; /* * Go through the item list. "t" is the vertical position of the * current item and "i" is its item number. */ t = menu->menuItemTop; /* * If the mouse is before the first item, return. */ if(y < t) return((MenuItem *)0); for(i = 0, item = menu->menuItems ; item ; i++, item = item->nextItem) { /* * If the y coordinate is within this menu item, then return. * But don't return disable items. */ if(t + item->itemHeight > y) { if(item->itemFlags & itemDisabled) return((MenuItem *)0); *top = t; *n = i; return(item); } t += item->itemHeight; } /* * Should never get here. */ return((MenuItem *)0); } /* * Unmap_Menu() unmaps a menu, if it is currently mapped. */ static Unmap_Menu(menu) register Menu *menu; { register int i; /* register XtermWidget xw = term; */ if(!menu || !(menu->menuFlags & menuMapped)) return; XtPopdown (menu->menuWidget); menu->menuFlags &= ~menuMapped; } MenuResetGCs (bgp, fgp) Pixel *bgp, *fgp; { register XtermWidget xw = term; Display *dpy = XtDisplay (xw); XGCValues xgc; *bgp = xw->core.background_pixel; *fgp = xw->screen.foreground; if (MenuInvertGC) { xgc.foreground = *fgp; xgc.plane_mask = XOR(*fgp, *bgp); XChangeGC (dpy, MenuInvertGC, (GCForeground | GCPlaneMask), &xgc); } if (MenuGC) { xgc.foreground = *fgp; xgc.background = *bgp; XChangeGC (dpy, MenuGC, (GCForeground | GCBackground), &xgc); } if (MenuInverseGC) { xgc.foreground = *bgp; xgc.background = *fgp; XChangeGC (dpy, MenuInverseGC, (GCForeground | GCBackground), &xgc); } if (MenuGrayGC) { xgc.foreground = *fgp; xgc.background = *bgp; xgc.function = *fgp ? GXor : GXand; XChangeGC (dpy, MenuGrayGC, (GCForeground | GCBackground | GCFunction), &xgc); } if (Check_Tile) { Check_Tile = ((Check_Tile == Check_Normal_Tile) ? Check_Inverse_Tile : Check_Normal_Tile); } return; } \f static void do_securekbd(), do_allowsends(), do_visualbell(), do_logging(), do_redraw(), /* do_suspend(), do_continue(), do_interrupt(), do_hangup(), */ /* do_terminate(), do_kill(), */ do_quit(), do_scrollbar(), do_jumpscroll(), do_reversevideo(), do_autowrap(), do_reversewrap(), do_autolinefeed(), do_appcursor(), do_appkeypad(), do_scrollkey(), do_scrollttyoutput(), do_allow132(), do_cursesemul(), do_marginbell(), do_altscreen(), do_softreset(), do_hardreset(); static void handle_send_signal (gw, sig) Widget gw; int sig; { register TScreen *screen = &term->screen; if (screen->pid > 1) killpg (screen->pid, sig); } /* * action routines */ void DoSecureKeyboard (time) Time time; { do_securekbd ( NULL, NULL); } static void do_securekbd (closure, data) caddr_t closure, data; { register TScreen *screen = &term->screen; Time time = CurrentTime; /* XXX - wrong */ if (screen->grabbedKbd) { XUngrabKeyboard (screen->display, time); ReverseVideo (term); screen->grabbedKbd = FALSE; } else { if (XGrabKeyboard (screen->display, term->core.parent->core.window, True, GrabModeAsync, GrabModeAsync, time) != GrabSuccess) { XBell (screen->display, 100); } else { ReverseVideo (term); screen->grabbedKbd = TRUE; } } } static void do_allowsends (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->allowSendEvents = !screen->allowSendEvents; } static void do_visualbell (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->visualbell = !screen->visualbell; } static void do_logging (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; if (screen->logging) { CloseLog (screen); } else { StartLog (screen); } } static void do_redraw (gw, closure, data) Widget gw; caddr_t closure, data; { Redraw (); } /* * The following cases use the pid instead of the process group so that we * don't get hosed by programs that change their process group */ #if 0 * static void do_suspend (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * #ifdef SIGTSTP * handle_send_signal (gw, SIGTSTP); * #endif * } * * * static void do_continue (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * #ifdef SIGCONT * handle_send_signal (gw, SIGCONT); * #endif * } * * * static void do_interrupt (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * handle_send_signal (gw, SIGINT); * } * * * static void do_hangup (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * handle_send_signal (gw, SIGHUP); * } * * * static void do_terminate (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * handle_send_signal (gw, SIGTERM); * } * * * static void do_kill (gw, closure, data) * Widget gw; * caddr_t closure, data; * { * handle_send_signal (gw, SIGKILL); * } * #endif /* 0 */ static void do_quit (gw, closure, data) Widget gw; caddr_t closure, data; { Cleanup (0); } /* * vt menu callbacks */ static void do_scrollbar (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; if (screen->scrollbar) { ScrollBarOff (screen); } else { ScrollBarOn (term, FALSE, FALSE); } } static void do_jumpscroll (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; term->flags ^= SMOOTHSCROLL; if (term->flags & SMOOTHSCROLL) { screen->jumpscroll = FALSE; if (screen->scroll_amt) FlushScroll(screen); } else { screen->jumpscroll = TRUE; } } static void do_reversevideo (gw, closure, data) Widget gw; caddr_t closure, data; { term->flags ^= REVERSE_VIDEO; ReverseVideo (term); } static void do_autowrap (gw, closure, data) Widget gw; caddr_t closure, data; { term->flags ^= WRAPAROUND; } static void do_reversewrap (gw, closure, data) Widget gw; caddr_t closure, data; { term->flags ^= REVERSEWRAP; } static void do_autolinefeed (gw, closure, data) Widget gw; caddr_t closure, data; { term->flags ^= LINEFEED; } static void do_appcursor (gw, closure, data) Widget gw; caddr_t closure, data; { term->keyboard.flags ^= CURSOR_APL; } static void do_appkeypad (gw, closure, data) Widget gw; caddr_t closure, data; { term->keyboard.flags ^= KYPD_APL; } static void do_scrollkey (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->scrollkey = !screen->scrollkey; } static void do_scrollttyoutput (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->scrollttyoutput = !screen->scrollttyoutput; } static void do_allow132 (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->c132 = !screen->c132; } static void do_cursesemul (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; screen->curses = !screen->curses; } static void do_marginbell (gw, closure, data) Widget gw; caddr_t closure, data; { register TScreen *screen = &term->screen; if (!(screen->marginbell = !screen->marginbell)) screen->bellarmed = -1; } static void do_altscreen (gw, closure, data) Widget gw; caddr_t closure, data; { /* do nothing for now; eventually, will want to flip screen */ } static void do_softreset (gw, closure, data) Widget gw; caddr_t closure, data; { VTReset (FALSE); } static void do_hardreset (gw, closure, data) Widget gw; caddr_t closure, data; { VTReset (TRUE); } /* * public handler routines */ static void handle_toggle (proc, var, params, nparams, w, closure, data) void (*proc)(); int var; String *params; Cardinal nparams; Widget w; caddr_t closure, data; { int dir = -2; switch (nparams) { case 0: dir = -1; case 1: if (XmuCompareISOLatin1 (params[0], "on") == 0) dir = 1; else if (XmuCompareISOLatin1 (params[0], "off") == 0) dir = 0; else if (XmuCompareISOLatin1 (params[0], "toggle") == 0) dir = -1; } switch (dir) { case -2: Bell(); break; case -1: (*proc) (w, closure, data); break; case 0: if (var) (*proc) (w, closure, data); else Bell(); break; case 1: if (!var) (*proc) (w, closure, data); else Bell(); break; } return; } void HandleAllowSends(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_allowsends, (int) term->screen.allowSendEvents, params, *param_count, w, NULL, NULL); } void HandleVisualBell(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_visualbell, (int) term->screen.visualbell, params, *param_count, w, NULL, NULL); } void HandleLogging(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_logging, (int) term->screen.logging, params, *param_count, w, NULL, NULL); } void HandleRedraw(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { do_redraw(w, NULL, NULL); } void HandleSendSignal(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { static struct sigtab { char *name; int sig; } signals[] = { #ifdef SIGTSTP { "suspend", SIGTSTP }, { "tstp", SIGTSTP }, #endif #ifdef SIGCONT { "cont", SIGCONT }, #endif { "int", SIGINT }, { "hup", SIGHUP }, { "term", SIGTERM }, { "kill", SIGKILL }, { NULL, 0 }, }; if (*param_count == 1) { struct sigtab *st; for (st = signals; st->name; st++) { if (XmuCompareISOLatin1 (st->name, params[0]) == 0) { handle_send_signal (w, st->sig); return; } } /* one could allow numeric values, but that would be a security hole */ } Bell(); } void HandleQuit(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { do_quit(w, NULL, NULL); } void HandleScrollbar(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_scrollbar, (int) term->screen.scrollbar, params, *param_count, w, NULL, NULL); } void HandleJumpscroll(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_jumpscroll, (int) term->screen.jumpscroll, params, *param_count, w, NULL, NULL); } void HandleReverseVideo(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_reversevideo, (int) (term->flags & REVERSE_VIDEO), params, *param_count, w, NULL, NULL); } void HandleAutoWrap(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_autowrap, (int) (term->flags & WRAPAROUND), params, *param_count, w, NULL, NULL); } void HandleReverseWrap(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_reversewrap, (int) (term->flags & REVERSEWRAP), params, *param_count, w, NULL, NULL); } void HandleAutoLineFeed(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_autolinefeed, (int) (term->flags & LINEFEED), params, *param_count, w, NULL, NULL); } void HandleAppCursor(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_appcursor, (int) (term->keyboard.flags & CURSOR_APL), params, *param_count, w, NULL, NULL); } void HandleAppKeypad(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_appkeypad, (int) (term->keyboard.flags & KYPD_APL), params, *param_count, w, NULL, NULL); } void HandleScrollKey(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_scrollkey, (int) term->screen.scrollkey, params, *param_count, w, NULL, NULL); } void HandleScrollTtyOutput(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_scrollttyoutput, (int) term->screen.scrollttyoutput, params, *param_count, w, NULL, NULL); } void HandleAllow132(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_allow132, (int) term->screen.c132, params, *param_count, w, NULL, NULL); } void HandleCursesEmul(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_cursesemul, (int) term->screen.curses, params, *param_count, w, NULL, NULL); } void HandleMarginBell(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { handle_toggle (do_marginbell, (int) term->screen.marginbell, params, *param_count, w, NULL, NULL); } void HandleAltScreen(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { /* eventually want to see if sensitive or not */ handle_toggle (do_altscreen, (int) term->screen.alternate, params, *param_count, w, NULL, NULL); } void HandleSoftReset(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { do_softreset(w, NULL, NULL); } void HandleHardReset(w, event, params, param_count) Widget w; XEvent *event; String *params; Cardinal *param_count; { do_hardreset(w, NULL, NULL); }