Annotation of 43BSDTahoe/new/X/uwm/Menu.c, revision 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.