timd@ur-tut.UUCP (02/23/87)
/* I cleaned this up so that lines only take up one, ie. no wrap around. If ** i missed somthing you have my appologies. ** --td */ #include <QuickDraw.h> #include <MenuMgr.h> #include <Memorymgr.h> #include <WindowMgr.h> #include <TextEdit.h> #include <OSUtil.h> #include <Eventmgr.h> #include <pascal.h> typedef short int16; typedef long int32; #define mDrawMsg 0 #define mChooseMsg 1 #define mSizeMsg 2 #define POINTERH ((*theMenu)->menuWidth - 4) #define POINTERV 8 #define MENUV 20 #define FRAMEH 2 #define FRAMEV 2 #define DELAY 2L /*-------------------------------------------------------------------- **doc: pin(i,l,u):int **doc> return a value in a bounded range ** ** INPUTS: ** i - test value ** l - lower bound ** u - upper bound ** ** OUTPUTS: NONE ** ** Description ** returns a value in the range of "l" to "u". If ** the value is greater the "u" returns "u", if value ** is less than "l" returns "l", else returns "i". ** ** */ pin(i,l,u) int16 i; int16 l; int16 u; { if (i<l) return (l); else if (i>u) return (u); else return (i); } /*-------------------------------------------------------------------- **doc: MenuDefProc(message, theMenu,menuRect,hitPt,whichItem):int **doc> return a value in a bounded range ** ** INPUTS: ** message - type of action requested ** theMenu - Handle to the menu ** menuRect - Not sure ** hitPt - where the mouse was pressed ** whichItem - which item was selected from ** the menu ** ** OUTPUTS: NOT SURE ** ** Description ** uses a standard menu routine for the menu def proc. ** not really sure what it does. ** ** ** */ MenuDefProc(message, theMenu,menuRect,hitPt,whichItem) int16 message; MenuHandle theMenu; Rect *menuRect; Point *hitPt; int16 *whichItem; { ProcPtr pFuncPnt; Handle tmpHand; HLock(theMenu); /* careful... */ tmpHand = (*theMenu)->menuProc; HLock(tmpHand); /* careful... */ pFuncPnt = (ProcPtr) *tmpHand; CallPascal(message,theMenu,menuRect,*hitPt,whichItem,pFuncPnt); HUnlock(tmpHand); HUnlock(theMenu); } /*-------------------------------------------------------------------- **doc: PopUpSelcet(theMenu,hitPt):int **doc> the item number of the item selcted ** ** INPUTS: ** theMenu - Handle to the menu ** hitPt - where the mouse was pressed ** ** OUTPUTS: NONE ** ** Description ** Handles all the overhead of pop up menus. This routine ** does the work. It sets up the section of the screen to ** be used for the pop up menu, and does a bit copy of the ** screen under where the menu is placed to restore the ** screen when it's done. Returns the item number for the ** item selected or zero if no item was selected. ** ** */ int32 PopUpSelect(theMenu,hitPt) MenuHandle theMenu; Point *hitPt; { GrafPtr port; GrafPtr wMngPort; BitMap **theMenuBits; BitMap *menuBits; int16 rowBytes; int16 rows; Rect menuRect; SysPPtr tmpsysPtr; int16 whichItem; int16 blink; int32 nilPt; int32 dticks; dticks = DELAY; if (!WaitMouseUp()) return(0L); LoadResource((*theMenu)->menuProc); HLock((*theMenu)->menuProc); /* ERROR CHECKING NEEDED HERE */ /* find out what size the menu will be. */ MenuDefProc(mSizeMsg,theMenu,&menuRect,&hitPt,&whichItem); /* create a rectangle of that size, within the boundries of the screen */ SetRect(&menuRect,0,MENUV,(*theMenu)->menuWidth, MENUV + (*theMenu)->menuHeight); InsetRect(&menuRect,-FRAMEH,-FRAMEV); rowBytes = ((menuRect.right - menuRect.left + 15)>>4)<<1; rows = menuRect.bottom - menuRect.top; /* ** allocate memory to store the portion of the screen we're going to ** over write. */ theMenuBits = (BitMap **) NewHandle(rowBytes * rows + (int32)sizeof(BitMap)); if (!theMenuBits) return (0L); HLock(theMenuBits); menuBits = *theMenuBits; menuBits->baseAddr = (char *)(menuBits + 1); menuBits->rowBytes = rowBytes; menuBits->bounds = menuRect; GetPort(&port); GetWMgrPort(&wMngPort); /* could be changed to the window pointer */ SetPort(wMngPort); SetOrigin( pin(POINTERH - hitPt->h, (*theMenu)->menuWidth - wMngPort->portRect.right + FRAMEH, 1-FRAMEH), pin(MENUV+POINTERV - hitPt->v, MENUV + (*theMenu)->menuHeight - wMngPort->portRect.bottom + FRAMEV, 1 - FRAMEV)); ClipRect(&wMngPort->portRect); /* ** copy the section of the screen that we're going to cover over ** so that we can restore it when we're done. ** */ CopyBits(&wMngPort->portBits,menuBits,&menuBits->bounds, &menuBits->bounds,0,0L); /* ** next 10 lines of code are here to set up the "menu rectangle" */ InsetRect(&menuRect,FRAMEH,FRAMEV); EraseRect(&menuRect); InsetRect(&menuRect,-1,-1); FrameRect(&menuRect); InsetRect(&menuRect,1,1); PenNormal(); MoveTo(menuRect.left+1,menuRect.bottom+1); Line((*theMenu)->menuWidth,0); Line(0,-(*theMenu)->menuHeight); ClipRect(&menuRect); /* ** draw the menu using the standard menu def proc. set the hit point ** to be what would normally be in the menu bar so that the menu name ** will be hilighted. ** */ whichItem =0; SetPt(hitPt,0,0); MenuDefProc(mDrawMsg,theMenu,&menuRect,&hitPt,&whichItem); do { MenuDefProc(mChooseMsg,theMenu,&menuRect,&hitPt,&whichItem); GetMouse(&hitPt); } while(WaitMouseUp()); /* ** Blink the selected item several times. */ if (whichItem) { tmpsysPtr = GetSysPPtr(); for (blink = ((tmpsysPtr->misc)>>2) & 0x3;blink;blink--) { nilPt = 0L; MenuDefProc(mChooseMsg,theMenu,&menuRect,&nilPt,&whichItem); Delay(DELAY,&nilPt); MenuDefProc(mChooseMsg,theMenu,&menuRect,&hitPt,&whichItem); Delay(DELAY,&nilPt); } } HUnlock((*theMenu)->menuProc); ClipRect(&wMngPort->portRect); /* set back to do CopyBits() */ /* ** restore the screen so that what ever was underneath our menu looks ** like it did before the menu wrote over it. ** */ CopyBits(menuBits,&wMngPort->portBits,&menuBits->bounds, &menuBits->bounds,0,0L); HUnlock(theMenuBits); DisposHandle(theMenuBits); SetOrigin(0,0); ClipRect(&wMngPort->portRect); SetPort(port); return (whichItem?((int32)(*theMenu)->menuID<<16)+whichItem:0L); } main() { extern pascal int pdumfuc(); MenuHandle menu; EventRecord event; GrafPtr port; Rect box; int32 returncde; InitGraf(&thePort); InitFonts(); InitWindows(); TEInit(); InitDialogs(0L); InitMenus(); InitCursor(); GetWMgrPort(&port); SetPort(port); ClipRect(&port->portRect); SetRect(&box,32,32,64,64); PlotIcon(&box,GetIcon(0)); menu = NewMenu(1,""); AppendMenu(menu,"\PBeep;(-;Quit"); while(1) { GetNextEvent(everyEvent,&event); if(event.what == mouseDown) if(PtInRect(event.where,&box)) { returncde = PopUpSelect(menu,&event.where); switch (LoWord(returncde)) { case 1: SysBeep(4); break; case 3: ExitToShell(); break; } } } } /* I hope this helps those of you who wanted popup menu info ** -- timd ** University of Rochester */