Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

popup menus in Lightspeed C

2 views
Skip to first unread message

ti...@ur-tut.uucp

unread,
Feb 23, 1987, 1:57:11 PM2/23/87
to

/* 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
*/

0 new messages