Annotation of 43BSD/contrib/X/uwm/Menu.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *rcsid_Menu_c = "$Header: Menu.c,v 10.3 86/02/01 16:23:11 tony Rel $";
                      3: #endif lint
                      4: 
                      5: /************************************************************************
                      6:  *                                                                     *
                      7:  *                     Copyright (c) 1986 by                           *
                      8:  *             Digital Equipment Corporation, Maynard, MA              *
                      9:  *                      All Rights Reserved.                           *
                     10:  *                                                                     *
                     11:  *     Permission to use, copy, modify, and distribute this software   *
                     12:  *     and its documentation is hereby granted only to licensees of    *
                     13:  *     The Regents of the University of California pursuant to their   *
                     14:  *     license agreement for the Berkeley Software Distribution        *
                     15:  *     provided that the following appears on all copies.              *
                     16:  *                                                                     *
                     17:  *            "LICENSED FROM DIGITAL EQUIPMENT CORPORATION             *
                     18:  *                      COPYRIGHT (C) 1986                             *       
                     19:  *                 DIGITAL EQUIPMENT CORPORATION                       *
                     20:  *                         MAYNARD, MA                                 *
                     21:  *                     ALL RIGHTS RESERVED.                            *
                     22:  *                                                                     *
                     23:  *      THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  * 
                     24:  *     NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL   *
                     25:  *     EQUIPMENT CORPORATION.  DIGITAL MAKES NO REPRESENTATIONS        *
                     26:  *     ABOUT SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS       *
                     27:  *     SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.           *
                     28:  *                                                                     *       
                     29:  *     IF THE UNIVERSITY OF CALIFORNIA OR ITS LICENSEES MODIFY         *       
                     30:  *     THE SOFTWARE IN A MANNER CREATING DERIVATIVE COPYRIGHT          *       
                     31:  *     RIGHTS APPROPRIATE COPYRIGHT LEGENDS MAY BE PLACED ON THE       *
                     32:  *     DERIVATIVE WORK IN ADDITION TO THAT SET FORTH ABOVE."           *       
                     33:  *                                                                     *
                     34:  ************************************************************************/
                     35:  
                     36: 
                     37: /*
                     38:  * MODIFICATION HISTORY
                     39:  *
                     40:  * 000 -- M. Gancarz, DEC Ultrix Engineering Group
                     41:  */
                     42: 
                     43: #ifndef lint
                     44: static char *sccsid = "@(#)Menu.c      3.8     1/24/86";
                     45: #endif
                     46: 
                     47: #include "uwm.h"
                     48: 
                     49: #define DisplayLine(w, pane, width, height, str, fg, bg) \
                     50:          XPixSet(w, 0, pane, width, height, bg); \
                     51:          XTextMask(w, HMenuPad, pane + VMenuPad, str, strlen(str), MFont, fg);
                     52: 
                     53: #define NVERTS 5                       /* Number of vertices for hi-liter. */
                     54: 
                     55: static Vertex vlist[NVERTS];           /* Vertex list for hi-liter. */
                     56: 
                     57: Bool Menu(window, mask, button, x, y, menu)
                     58: Window window;                         /* Event window. */
                     59: int mask;                              /* Button/key mask. */
                     60: short button;                          /* Button event detail. */
                     61: int x, y;                              /* Event mouse position. */
                     62: MenuInfo *menu;
                     63: {
                     64:     XButtonEvent button_event;         /* Button event packet. */
                     65:     Bool func_stat;                    /* Function status return. */
                     66:     int cur_x, cur_y;                  /* Current mouse position. */
                     67:     Window sub_window;                 /* Current subwindow. */
                     68:     int cur_item = 0;                  /* Current menu item. */
                     69:     int hi_lite = 0;                   /* Current highlighted item. */
                     70:     int i;                             /* Iteration counter. */
                     71:     short hlfg, hlbg;                  /* Hi-liter pixels. */
                     72:     MenuLine *ml;                      /* Menu lines pointer. */
                     73:     char *hlname;                      /* Pointer to hi-liter name. */
                     74:     char *strbuf;                      /* String buffer for IsTextNL. */
                     75:     char *malloc();
                     76: 
                     77:     /*
                     78:      * Change the cursor.
                     79:      */
                     80:     status = XGrabButton(RootWindow, MenuCursor, mask, EVENTMASK);
                     81:     if (status == FAILURE)
                     82:         Error("Menu -> Unable to grab button and change cursor.");
                     83: 
                     84:     /*
                     85:      * Map the menu.
                     86:      */
                     87:     MapMenu(menu, x, y);
                     88: 
                     89:     /*
                     90:      * Main loop.
                     91:      */
                     92:     while (TRUE) {
                     93: 
                     94:         /*
                     95:          * If no button event, check the current mouse position.
                     96:          */
                     97:         status = XUpdateMouse(menu->w, &cur_x, &cur_y, &sub_window);
                     98:         if (status == FAILURE) continue;
                     99: 
                    100:         /*
                    101:          * If the mouse has moved out of the menu sideways, abort
                    102:          * the menu operation. Reset the cursor and unmap the menu.
                    103:          */
                    104:         if (cur_x < 0 || cur_x > menu->width) {
                    105:             UnmapMenu(menu, mask);
                    106:             return(FALSE);
                    107:         }
                    108: 
                    109:         /*
                    110:          * If the mouse has moved below or above the menu, but is still
                    111:          * within the same vertical plane, then simply adjust the values
                    112:          * so the user doesn't fall off the edge.
                    113:          */
                    114:         if (cur_y >= menu->height) cur_y = menu->height - 1;
                    115:         else if (cur_y < 0) cur_y = 0;
                    116: 
                    117:         /*
                    118:          * If the mouse has moved to another item in the menu,
                    119:          * highlight the new item.
                    120:          */
                    121:         cur_item = cur_y / menu->iheight;
                    122:         if (cur_item != hi_lite) {
                    123: 
                    124:             /*
                    125:              * Remove highlighting on old item.
                    126:              */
                    127:             if (hi_lite) {
                    128:                 DisplayLine(menu->w, hi_lite * menu->iheight,
                    129:                             menu->width, menu->iheight, hlname,
                    130:                             hlfg, hlbg);
                    131:             }
                    132: 
                    133:             /*
                    134:              * Highlight new item.
                    135:              */
                    136:             if (cur_item) {
                    137:                 for(i = 1, ml = menu->line; ml; i++, ml = ml->next) {
                    138:                     if (i == cur_item) break;
                    139:                 }
                    140:                 DisplayLine(menu->w, cur_item * menu->iheight,
                    141:                             menu->width, menu->iheight, ml->name,
                    142:                             menu->hlfg.pixel, menu->hlbg.pixel);
                    143:                 vlist[0].y = cur_item * menu->iheight + 1;
                    144:                 XDraw(menu->w, vlist, NVERTS, 1, 1,
                    145:                       menu->hlfg.pixel, GXcopy, AllPlanes);
                    146:             }
                    147:             hi_lite = cur_item;
                    148:             hlfg = ml->fg.pixel;
                    149:             hlbg = ml->bg.pixel;
                    150:             hlname = ml->name;
                    151:         }
                    152: 
                    153:         /*
                    154:          * Check to see if we have a change in the mouse buttons.
                    155:          * This means the user has selected an item or aborted the
                    156:          * operation.
                    157:          */
                    158:         if (XPending() && GetButton(&button_event)) {
                    159: 
                    160:             /*
                    161:              * Was button released?
                    162:              */
                    163:             if ((button_event.type == ButtonReleased) &&
                    164:                 ((button_event.detail & ValueMask) == button)) {
                    165:                 break;
                    166:             } else {
                    167: 
                    168:                 /*
                    169:                  * Some other button event occurred, so abort the menu
                    170:                  * operation.
                    171:                  */
                    172:                 UnmapMenu(menu, mask);
                    173:                 return(TRUE);
                    174:             }
                    175:         }
                    176:     }
                    177: 
                    178:     /*
                    179:      * If no item was selected, simply close the menu and return.
                    180:      */
                    181:     if (!cur_item) {
                    182:         UnmapMenu(menu, mask);
                    183:         return(TRUE);
                    184:     }
                    185: 
                    186:     /*
                    187:      * Get a pointer to the menu line selected.
                    188:      */
                    189:     --cur_item;
                    190:     for(i = 0, ml = menu->line; ml; i++, ml = ml->next) {
                    191:         if (i == cur_item) break;
                    192:     }
                    193: 
                    194:     /*
                    195:      * Perform the selected menu line action.
                    196:      */
                    197:     switch (ml->type) {
                    198: 
                    199:         case IsShellCommand:
                    200:             UnmapMenu(menu, mask);
                    201:             system(ml->text);
                    202:             break;
                    203: 
                    204:         case IsText:
                    205:             UnmapMenu(menu, mask);
                    206:             XStoreBytes(ml->text, strlen(ml->text));
                    207:             break;
                    208: 
                    209:         case IsTextNL:
                    210:             UnmapMenu(menu, mask);
                    211:             strbuf = (char *)malloc(strlen(ml->text) + 2);
                    212:             strcpy(strbuf, ml->text);
                    213:             strcat(strbuf, "\n");
                    214:             XStoreBytes(strbuf, strlen(strbuf));
                    215:             free(strbuf);
                    216:             break;
                    217: 
                    218:         case IsUwmFunction:
                    219:             GetContext(&sub_window, &cur_x, &cur_y);
                    220:             UnmapMenu(menu, mask);
                    221:             if (sub_window != menu->w)
                    222:                 (*ml->func) (sub_window, mask, button, cur_x, cur_y);
                    223:             break;
                    224: 
                    225:         case IsImmFunction:
                    226:             UnmapMenu(menu, mask);
                    227:             (*ml->func) (sub_window, mask, button, cur_x, cur_y);
                    228:             break;
                    229: 
                    230:         case IsMenuFunction:
                    231:             while (TRUE) {
                    232:                 if (!GetButton(&button_event)) continue;
                    233:                 if (button_event.type != ButtonPressed) continue;
                    234:                 if ((KeyMask(button_event.detail) != KeyMask(mask)) ||
                    235:                     ((button_event.detail & ButtonMods) != button)) {
                    236:                     UnmapMenu(menu, mask);
                    237:                     return(TRUE);
                    238:                 }
                    239:                 break;
                    240:             }
                    241:             UnmapMenu(menu, mask);
                    242:             func_stat = Menu(menu->w, mask, button, x, y, ml->menu);
                    243:             return(func_stat);
                    244:             break;
                    245: 
                    246:         default:
                    247:             Error("Menu -> Internal type error.");
                    248:     }
                    249:     return(TRUE);
                    250: }
                    251: 
                    252: /*
                    253:  * Create the menu windows for later use.
                    254:  */
                    255: CreateMenus()
                    256: {
                    257:     MenuLink *ptr;
                    258: 
                    259:     /*
                    260:      * If MaxColors isn't set, then jam it to an impossibly high
                    261:      * number.
                    262:      */
                    263:     if (MaxColors == 0)
                    264:         MaxColors = 25000;
                    265: 
                    266:     for(ptr = Menus; ptr; ptr = ptr->next)
                    267:         InitMenu(ptr->menu);
                    268: }
                    269: 
                    270: /*
                    271:  * Initialize a menu.
                    272:  */
                    273: InitMenu(menu)
                    274: MenuInfo *menu;
                    275: {
                    276:     MenuLine *ml;              /* Menu lines pointer. */
                    277:     int width;                 /* Width of an item name. */
                    278:     int maxwidth;              /* Maximum width of item names. */
                    279:     int len;                   /* Length of an item name. */
                    280:     int count = 1;             /* Number of items + 1 for name. */
                    281: 
                    282:     /*
                    283:      * Determine the name of the longest menu item.
                    284:      */
                    285:     maxwidth = XQueryWidth(menu->name, MFont);
                    286:     if (maxwidth == 0)
                    287:         Error("InitMenu -> Couldn't get length of menu name");
                    288: 
                    289:     for(ml = menu->line; ml; ml = ml->next) {
                    290:         if ((len = strlen(ml->name)) == 0)
                    291:             break;
                    292:         width = XQueryWidth(ml->name, MFont);
                    293:         if (width == 0) Error("InitMenu -> Couldn't get length of menu item name");
                    294:         if (width > maxwidth) maxwidth = width;
                    295:         count++;
                    296:     }
                    297: 
                    298:     /*
                    299:      * Get the color cells for the menu items.
                    300:      */
                    301:     GetMenuColors(menu);
                    302: 
                    303:     /*
                    304:      * Stash the menu parameters in the menu info structure.
                    305:      */
                    306:     menu->iheight = MFontInfo.height + (VMenuPad << 1);
                    307:     menu->height = menu->iheight * count;
                    308:     menu->width = maxwidth + (HMenuPad << 1);
                    309:     menu->image = NULL;
                    310: 
                    311:     /*
                    312:      * Create the menu window.
                    313:      */
                    314:     menu->w = XCreateWindow(RootWindow,
                    315:                             0, 0,
                    316:                             menu->width,
                    317:                             menu->height,
                    318:                             MBorderWidth,
                    319:                             MBorder, MBackground);
                    320:     if (menu->w == NULL) Error("InitMenu -> Couldn't create menu window");
                    321: 
                    322:     /*
                    323:      * Store the window name.
                    324:      */
                    325:     XStoreName(menu->w, menu->name);
                    326: 
                    327:     /*
                    328:      * Define a cursor for the window.
                    329:      */
                    330:     XDefineCursor(menu->w, MenuCursor);
                    331: }
                    332: 
                    333: /*
                    334:  * Map a menu.
                    335:  */
                    336: MapMenu(menu, x, y)
                    337: MenuInfo *menu;
                    338: int x, y;
                    339: {
                    340:     int item;
                    341:     Window w;
                    342:     MenuLine *ml;
                    343: 
                    344:     w = menu->w;
                    345: 
                    346:     /*
                    347:      * Move the menu into place, normalizing the coordinates, if necessary;
                    348:      * then map it.
                    349:      */
                    350:     x -= (menu->width >> 1);
                    351:     if (x < 0) x = 0;
                    352:     else if (x + menu->width >= ScreenWidth)
                    353:         x = ScreenWidth - menu->width - (MBorderWidth << 1);
                    354:     if (y < 0) y = 0;
                    355:     else if (y + menu->height >= ScreenHeight)
                    356:         y = ScreenHeight - menu->height - (MBorderWidth << 1);
                    357:     XMoveWindow(w, x, y);
                    358: 
                    359:     /*
                    360:      * Map the window and draw the text items.
                    361:      */
                    362:     XMapWindow(w);
                    363:     DisplayLine(w, 0, menu->width, menu->iheight, menu->name,
                    364:                 menu->bg.pixel, menu->fg.pixel);
                    365: 
                    366:     SetUpVlist(menu);
                    367:     vlist[0].x = 1;
                    368:     vlist[0].y = 1;
                    369:     XDraw(menu->w, vlist, NVERTS, 1, 1, menu->bg.pixel, GXcopy, AllPlanes);
                    370:     item = menu->iheight;
                    371:     for(ml = menu->line; ml; ml = ml->next) {
                    372:         DisplayLine(w, item, menu->width, menu->iheight, ml->name,
                    373:                     ml->fg.pixel, ml->bg.pixel);
                    374:         item += menu->iheight;
                    375:     }
                    376: 
                    377:     /*
                    378:      * Position the mouse cursor in the menu header (or in the first item
                    379:      * if "autoselect" is set).
                    380:      */
                    381:     if (Autoselect)
                    382:         XWarpMouse(w, (menu->width >> 2) * 3, (menu->iheight >> 1) * 3);
                    383:     else XWarpMouse(w, (menu->width >> 2) * 3, menu->iheight >> 1);
                    384: 
                    385:     XFlush();
                    386: }
                    387: 
                    388: /*
                    389:  * Unmap a menu, restoring the contents of the screen underneath
                    390:  * if necessary. (Restore portion is a future.)
                    391:  */
                    392: UnmapMenu(menu, mask)
                    393: MenuInfo *menu;
                    394: int mask;
                    395: {
                    396:     /*
                    397:      * Restore the main cursor.
                    398:      */
                    399:     Grab((short)mask);
                    400: 
                    401:     /*
                    402:      * Unmap and flush.
                    403:      */
                    404:     XUnmapWindow(menu->w);
                    405:     XFlush();
                    406: }
                    407: 
                    408: /*
                    409:  * Get the context for invoking a window manager function.
                    410:  */
                    411: GetContext(w, x, y)
                    412: Window *w;
                    413: int *x, *y;
                    414: {
                    415:     XButtonEvent button_event;  /* Button input event. */
                    416: 
                    417:     while (TRUE) {
                    418: 
                    419:         /*
                    420:          * Get the next mouse button event.  Spin our wheels until
                    421:          * a button event is returned (ie. GetButton == TRUE).
                    422:          * Note that mouse events within an icon window are handled
                    423:          * in the "GetButton" function or by the icon's owner if
                    424:          * it is not uwm.
                    425:          */
                    426:         if (!GetButton(&button_event)) continue;
                    427: 
                    428:         /*
                    429:          * If the button event received is not a ButtonPressed event
                    430:          * then continue until we find one.
                    431:          */
                    432:         if (button_event.type != ButtonPressed) continue;
                    433: 
                    434:         /*
                    435:          * Okay, determine the event window and mouse coordinates.
                    436:          */
                    437:         status = XInterpretLocator(RootWindow,
                    438:                                     x, y,
                    439:                                     w,
                    440:                                     button_event.location);
                    441: 
                    442:         if (status == FAILURE) continue;
                    443: 
                    444:         if (*w == 0)
                    445:             *w = RootWindow;
                    446: 
                    447:         return;
                    448:     }
                    449: }
                    450: 
                    451: /*
                    452:  * Get the color cells for a menu.  This function is slightly brain-damaged
                    453:  * in that once MaxColors <= 1, then it refuses to even try to allocate any
                    454:  * more colors, even though the colors may have already been allocated.  It
                    455:  * probably ought to be done right someday.
                    456:  */
                    457: GetMenuColors(menu)
                    458: MenuInfo *menu;
                    459: {
                    460:     register MenuLine *ml;             /* Menu lines pointer. */
                    461: 
                    462:     /*
                    463:      * If we have more than 2 colors available, then attempt to get
                    464:      * the color map entries requested by the user.
                    465:      * Otherwise, default to standard black and white.
                    466:      */
                    467:     if (DisplayCells() > 2) {
                    468: 
                    469:         /*
                    470:          * Get the menu header colors first.
                    471:          */
                    472:         if (!(menu->foreground && menu->background && MaxColors > 1 &&
                    473:               XParseColor(menu->foreground, &menu->fg) &&
                    474:               XGetHardwareColor(&menu->fg) &&
                    475:               XParseColor(menu->background, &menu->bg) &&
                    476:               XGetHardwareColor(&menu->bg))) {
                    477:             menu->fg.pixel = MTextForground;
                    478:             menu->bg.pixel = MTextBackground;
                    479:         } else {
                    480:             AdjustMaxColors(menu->fg.pixel);
                    481:             AdjustMaxColors(menu->bg.pixel);
                    482:         }
                    483: 
                    484:         /*
                    485:          * Get the menu highlight colors.
                    486:          */
                    487:         if (!(menu->fghighlight && menu->bghighlight && MaxColors > 1 &&
                    488:               XParseColor(menu->fghighlight, &menu->hlfg) &&
                    489:               XGetHardwareColor(&menu->hlfg) &&
                    490:               XParseColor(menu->bghighlight, &menu->hlbg) &&
                    491:               XGetHardwareColor(&menu->hlbg))) {
                    492:             menu->hlfg.pixel = MTextBackground;
                    493:             menu->hlbg.pixel = MTextForground;
                    494:         } else {
                    495:             AdjustMaxColors(menu->hlfg.pixel);
                    496:             AdjustMaxColors(menu->hlbg.pixel);
                    497:         }
                    498: 
                    499:         /*
                    500:          * Get the menu item colors.
                    501:          */
                    502:         for(ml = menu->line; ml; ml = ml->next) {
                    503:             if (!(ml->foreground && ml->background && MaxColors > 1 &&
                    504:                   XParseColor(ml->foreground, &ml->fg) &&
                    505:                   XGetHardwareColor(&ml->fg) &&
                    506:                   XParseColor(ml->background, &ml->bg) &&
                    507:                   XGetHardwareColor(&ml->bg))) {
                    508:                 ml->fg.pixel = MTextForground;
                    509:                 ml->bg.pixel = MTextBackground;
                    510:             } else {
                    511:                 AdjustMaxColors(ml->fg.pixel);
                    512:                 AdjustMaxColors(ml->bg.pixel);
                    513:             }
                    514:         }
                    515: 
                    516:     } else {
                    517: 
                    518:         /*
                    519:          * Only 2 colors available, so default to standard black and white.
                    520:          */
                    521:         menu->fg.pixel = MTextForground;
                    522:         menu->bg.pixel = MTextBackground;
                    523:         menu->hlfg.pixel = MTextBackground;
                    524:         menu->hlbg.pixel = MTextForground;
                    525:         for(ml = menu->line; ml; ml = ml->next) {
                    526:             ml->fg.pixel = MTextForground;
                    527:             ml->bg.pixel = MTextBackground;
                    528:         }
                    529:     }
                    530: }
                    531: 
                    532: /*
                    533:  * Decrement "MaxColors" if this pixel value has never been used in a
                    534:  * menu before.
                    535:  */
                    536: AdjustMaxColors(pixel)
                    537: int pixel;
                    538: {
                    539:     register MenuLink *mptr;
                    540:     register MenuLine *lptr;
                    541:     int count = 0;
                    542: 
                    543:     for(mptr = Menus; mptr; mptr = mptr->next) {
                    544:         if (mptr->menu->fg.pixel == pixel) ++count;
                    545:         if (mptr->menu->bg.pixel == pixel) ++count;
                    546:         if (mptr->menu->hlfg.pixel == pixel) ++count;
                    547:         if (mptr->menu->hlbg.pixel == pixel) ++count;
                    548:         for(lptr = mptr->menu->line; lptr; lptr = lptr->next) {
                    549:             if (lptr->fg.pixel == pixel) ++count;
                    550:             if (lptr->bg.pixel == pixel) ++count;
                    551:         }
                    552:         if (count > 1) return;
                    553:     }
                    554:     --MaxColors;
                    555: }
                    556: 
                    557: /*
                    558:  * Set up the vertex list for the hi-liter.
                    559:  */
                    560: SetUpVlist(menu)
                    561: MenuInfo *menu;
                    562: {
                    563:     vlist[1].x = menu->width - 3;
                    564:     vlist[1].y = 0;
                    565:     vlist[2].x = 0;
                    566:     vlist[2].y = menu->iheight - 3;
                    567:     vlist[3].x = (short)(0 - menu->width + 3);
                    568:     vlist[3].y = 0;
                    569:     vlist[4].x = 0;
                    570:     vlist[4].y = (short)(0 - menu->iheight + 3);
                    571:     vlist[1].flags = vlist[2].flags = vlist[3].flags =
                    572:     vlist[4].flags = VertexRelative;
                    573: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.