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

unix.superglobalmegacorp.com

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