[net.sources.mac] Mike Shuster's pop-up menu proc in Aztec C

oz@yetti.UUCP (Ozan Yigit) (05/07/86)

Here is Mike Shuster's pop-up menu procedure in
Aztec C, enclosed in its test routine. Can you
believe it ?? The sources !!!! Thnx Mike !!

oZ

--------------------- popup.c -------------------------
/*
 * Mike Shuster's pop-up menu 
 * routines in Aztec C.
 *
 * Conversion by: oZ
 *
 * For detailed discussion & explanation,
 * See MACTutor Vol. 1 #13 (Dec. 1985)
 * Pp. 15-22 
 *
 * Differences:
 *
 *	Under Aztec C, we do not need the extra
 *	baggage of "envelopes" to make a pascal-type
 *	procedure call. We have a type "pascal" which
 *	tells the compiler to use pascal call type.
 *	Thus, instead of using an envelope, we call
 *	the routine stored in menuProc handle directly.
 *	Neat huh ?
 *
 */
#include <memory.h>
#include <resource.h>
#include <quickdraw.h>
#include <window.h>
#include <textedit.h>
#include <menu.h>
#include <desk.h>
#include <event.h>
#include <osutil.h>
#include <inits.h>

#define GETSYSPTR	((SysPtr) 0x1f8)

#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 BDELAY		2L

#define MENUPROC	(*mproc)

static pin(i, l, u)
{
	if (i<l) 
		return l;
	else if (i>u)
		return u;
	else
		return i;
}

long PopUpSelect(themenu, hitpt)
MenuHandle themenu;
Point *hitpt;
{
	GrafPtr port;
	GrafPtr wmgrport;
	BitMap **themenubits;
	BitMap *menubits;
	int rowbytes;
	int rows;
	Rect menurect;
	int whichitem;
	int blink;
	long nilpt;
	long moupt;

	pascal void (*mproc)();

	if (!WaitMouseUp())
		return(0L);

	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;

	themenubits=(BitMap**)NewHandle(rowbytes*rows+(long)sizeof(BitMap));
	if (!themenubits)
		return(0L);

	HLock(themenubits);
	menubits=*themenubits;

	menubits->baseAddr = (char *) (menubits+1);
	menubits->rowBytes = rowbytes;
	menubits->bounds=menurect;

	GetPort(&port);
	GetWMgrPort(&wmgrport);
	SetPort(wmgrport);

	SetOrigin(
		pin(POINTERH - hitpt->h,
			(*themenu)->menuWidth-wmgrport->portRect.right+
			FRAMEH, 1-FRAMEH),
		pin(MENUV+POINTERV-hitpt->v,
			MENUV+(*themenu)->menuHeight-wmgrport->portRect.bottom+
			FRAMEV, 1-FRAMEV));

	ClipRect(&wmgrport->portRect);
	CopyBits(&wmgrport->portBits, menubits, &menubits->bounds,
			&menubits->bounds, 0, 0L);

	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);

	LoadResource((*themenu)->menuProc);
	HLock((*themenu)->menuProc);

	
	mproc = ((*themenu)->menuProc)[0];


	whichitem = 0;
	moupt = 0L;

	MENUPROC(mDrawMsg, themenu, &menurect, moupt, &whichitem);

	do {
		MENUPROC(mChooseMsg, themenu, &menurect, moupt, &whichitem);
		GetMouse(&moupt);
	} while (WaitMouseUp());
	if(whichitem) {
		for(blink=GETSYSPTR->misc>>2&0x3; blink; blink--) {
			nilpt=0L;
			MENUPROC(mChooseMsg, themenu, &menurect,
					nilpt, &whichitem);
			Delay(BDELAY, &nilpt);	
			MENUPROC(mChooseMsg, themenu, &menurect,
					moupt, &whichitem);
			Delay(BDELAY, &nilpt);	
		}
	}
	HUnlock((*themenu)->menuProc);
	ClipRect(&wmgrport->portRect);
	CopyBits(menubits, &wmgrport->portBits,
		&menubits->bounds, &menubits->bounds, 0, 0L);
	HUnlock(themenubits);
	DisposHandle(themenubits);
	SetOrigin(0,0);
	ClipRect(&wmgrport->portRect);
	SetPort(port);
	return (whichitem ? ((long)(*themenu)->menuID<<16)+whichitem : 0L);
}

main(){
	MenuHandle menu;
	EventRecord event;
	GrafPtr port;
	Rect box;
	char temp;

	InitGraf(&thePort);
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs(0L);
	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) {
		SystemTask();
		temp = GetNextEvent(everyEvent, &event);
		if(event.what == mouseDown) {
			if(PtInRect(pass(event.where), &box)) {
				switch(LoWord(PopUpSelect(menu, &event.where))) 
				{
				case 1:
					SysBeep(4);
					break;
				case 2:
					_exit(0);
					break;
				}
			}
		}
	}
}
 


-- 
The best way to have a 		Usenet: [decvax|ihnp4]!utzoo!yetti!oz
good idea is to have a 		Bitnet: oz@[yusol|yuyetti].BITNET
lot of ideas.			Phonet: [416] 667-3976