;EASE$$$ READ ONLY COPY of file ÒMdefProc.aÓ; 1.6	PKE 08/22/1989 Rolling in from reality sources (YAY);<1.7>	PKE 08/21/1989 NEEDED FOR 6.0.4: (really dba) Fix bug in bug fix. GrayRect takes;		its parameter in A0, so A0 must be set up with TempRect before calling;		GrayRect. I tried to fix the earlier bug by not relying on A0 -- big mistake.;		Instead, get TempRect into a0.; 1.5	PKE 08/15/1989  Rolling in from Reality sources;<1.6>	dba 08/15/1989  NEEDED FOR 6.0.4: fix bug in GetItemHeight where it relies;		on GetIconSize not trashing A0;<1.5>	RLC 08/10/1989 Changed selector message to Help Mgr Pack to MOVEQ;		#select,D0; 1.1	CCH 11/11/1988 Fixed Header.; 1.0	CCH 11/ 9/1988 Adding to EASE.; OLD REVISIONS BELOW;¥1.3	EMT 10/3/88 Roll in latest bug fixes.; END EASE MODIFICATION HISTORY ;----------------------------------------------------------------;	© Apple Computer, Inc.	1982, 1983, 1984, 1985, 1986, 1987, 1988;	All Rights Reserved;----------------------------------------------------------------;File mDefProc.ASM;------------------------------------------------------------;;	Standard Menu Definition Procedure for Text Menus;;	written by Andy Hertzfeld	July 1982;;	Here is the default menu definition procedure for text menus.  It knows how to;	draw a text menu, or select from within a text menu.  It is always called from the;	window manager port with clipping set to the menuRect. (Not CalcMenuSize);; MODIFICATION HISTORY:;	27-Dec-82	AJH	Broke off into separate file for resources;	28-Jan-83	AJH	made "GrayRect" use FillRect and a hardwired gray;	17-Mar-83	AJH	Fixed 4 pixel choosing offset;	17-Mar-83	AJH	no more forcing bold;	28-Apr-83	AJH	added "calcMenuSize" message;	30-Oct-83	AJH	changed disabling;	06-Nov-83	AJH	back to old disabling; special-cased "-" item;	13-Feb-84	AJH	speeded up CalcMenuSize message (linear instead of N squared);	11-Jan-85	JTC	convert to MDS;	14-Feb-85	JTC	named rsrc.;	15-Feb-85	SC	fixed applemark/commandMark bug in command keys;	10-Apr-85	EHB	fixed CalcMenuSize for items with 0 length;	29-Jul-85	EHB	converted back to porkshop;v3	01-Aug-85	EHB	adapted for variable height system fonts;v4	26-Aug-85	EHB	ROM/Ram version (tests ROM85);v5	27-Sep-85	EHB	Added International menu display.;					Added emergency menu scrolling.;	30-Sep-85	EHB	Made scrolling smoother.;	11-Oct-85	EHB	Do test byte of low memory justification word, so intl. people;					can use the high byte for further discrimination (yuck).;	15-Oct-85	EHB	Fixed bugs in display of menu icons;;------------------	Lonely Hearts ROMs ------------------------;;		Dec-85	EHB	Different low memory locations if on old ROMs;; -----------------	System File 3.0 ---------------------------;;	07-Jan-86	EHB	Fixed enable bug for items > 31 (see C466 below);	07-Jan-86	EHB	Don't leave extra space at bottom of screen (reversed 30 Jan);	30-Jan-86	EHB	Re-did scrolling so icons would work;;	01-Oct-86	DAF	Changed include headers;	30-Oct-86	FJL	C222	Fixes for hierarchical menus;	04-Nov-86	FJL	CXXX	General clean up of menu manager.;							When #ScriptMenuCmd ($1C) in itemCmd field item;							to be printed in script whose ID is in the itemIcon field --;							also, command keys draw as cmdletter/cmdchar rather;							than normal cmdchar/cmdletter (for International).;							Also slow down scrolling.;	08-Dec-86	FJL	C408	Added color support;	25-Nov-86	FJL	C466	Fixed ENABLETEST (local label) so enables items > 31 unless whole;							menu disabled.;	10-Feb-87	FJL	C792	Add scrolling indicator to top and bottom of scrollable menus.;	20-Feb-87	FJL	C838	Sped up menu scrolling by an amazing amount.;	20-Feb-87	FJL	C844	New routine PopUpMenuSelect.;	06-Mar-87	FJL			Clean up all OnNuMac conditionals for System Disk --> Universal defproc;	09-Mar-87	FJL			Add variable speed menu scrolling;	17-Mar-87	FJL			Do invert for MacPlus/MacSE rather than redraw (for MacDraw custom menu);							when choosing item;	30-Mar-87	FJL	PMAB155 Don't reference MenuDisable in mdefproc.a on 64K ROMs.;	08-Apr-87	DBG&JTC S171 Save D2 (volatile register) around call to CalcMenuSize in PopUpMenu;							message.;	14-Apr-87	FJL	PMAB177 Use CopyBits instead of CopyMask for drawing hierarchical and scrolling;							arrows.  Do moveq #BitMapRec, d0 instead of move.w #BitMapRec, d0;							before call to NewHandle.;;------------------------------- System 4.2 and beyond -----------------------------------;;	14-Jul-87	FJL	PMAB205 Juggler support -- support shrunken and small icons;	21-Aug-87	FJL	PMAB239 Calculate menu width correctly when have shrunken or small icons;	15-Sep-87	FJL	PMAB276 Allow item = 0 to popupmenuselect;	PMAB364	23Jan88	EMT		Fix Pop-up menus to come up on any screen;	S394	12Feb88	DBG		Fixed errant branch, which was reversed, causing crash on +/SE;	S422	08Mar88 MED		Fixed mdefproc.a to use SetScriptFont uniformally instead of inaccurate calculation;	S476	22Apr88	EMT		Fixed hierchical menus being forced below menu bar;	S550	27Jul88	EMT		Removed references to WMgrPort for ROM;							Fixed problems when teSysJust set for right-to-left drawing;							Treat dash as special only if no icon or cmd.  Primarily for MultiFinder;							Handle color icons other than 32x32;							And some miscellaneous code cleanup;---------------------------------------------------------------;; PROCEDURE TextMenuProc(	message		:Integer,;							theMenu		:menuHandle,;						VAR menuRect	:Rect,;							hitPt		:Point,;						VAR whichItem	:Integer);;;Msg		theMenu		menuRect			hitPt		whichItem;------		-----------	-----------			-------		-----------; 0 Draw	handle		entry: ptr to		not used	not used;						return: no chg; 1	Choose	handle		entry: ptr to		mouse pt	entry: ptr to currently selected item;						return: no chg					return: newly selected item; 2 Calc	handle		not used			not used	not used; 3 PopUp	handle		entry: none			top/left	entry: CrsrItem to be placed at HitPt;						return:	menu rect				return: TopMenuItem			BLANKS		ON			STRING		ASIS;----------------------------------------------------------------------------------------;;	Conditional Definitions;;----------------------------------------------------------------------------------------	IF (&TYPE('forTESTING') = 'UNDEFINED') THENforTESTING EQU 0	ENDIF	IF (&TYPE('forRAM') = 'UNDEFINED') THENforRAM EQU 0	ENDIF			INCLUDE	'inc.sum.a'			LOAD	'nequ.d'			INCLUDE	'colorequ.a'	IF forTESTING THEN							; uggghhhlllyyy			INCLUDE 'myEquates.a'	ENDIFShrunkenIconCmd	EQU		$1D						; itemCmd == $1D ==> large icon plotted in 16x16SmallIconCmd	EQU		$1E						; itemCmd == $1E ==> small icon plotted;----------------------------------------------------------------------------------------;;	StackFrame and Global Definitions;;----------------------------------------------------------------------------------------MDEF0			PROC	EXPORT;; Stack Frame Definition for TextMenuProc;MFHeight		EQU		-2				; <1Aug85> cell heightMWidMax			EQU		MFHeight - 2	; <1Aug85>MDescent		EQU		MWidMax - 2		; <1Aug85>MAscent			EQU		MDescent - 2	; <1Aug85>MInfoRec		EQU		MAscent			; <1Aug85>MSpaceWidth		EQU		MInfoRec - 2	; <S550	27Jul88	EMT>saveForeColor	EQU		MSpaceWidth - 6	; <FJL C408>saveBackColor	EQU		saveForeColor-6	; <FJL C408>pixelDepth		EQU		saveBackColor-2 ; <FJL C408>colorOffset		EQU		pixelDepth - 2	; <FJL C408>invertFlag		EQU		colorOffset - 2	; <FJL C408>	0 = normal item, 1 = inverted itemscrollFlag		EQU		invertFlag - 2	; <FJL 17Mar87>	0 = scrolling item, 1 = choosing itemHItemFlag		EQU		scrollFlag - 2	; <FJL 17Mar87>	0 = no sub menu, 1 = item has submenuiconHandle		EQU		HItemFlag - 4	; <FJL C408>HierArrowRect	EQU		iconHandle - 8	; <FJL 25Jan87>OrigMenuRect	EQU		HierArrowRect-8	; <FJL C792>ScrollSpeed		EQU		OrigMenuRect - 4; <FJL 09Mar87>SlowPixels		EQU		ScrollSpeed - 2	; <FJL 09Mar87>onColorMachine	EQU		SlowPixels-2	; <FJL 06Mar87>lastItemStrPtr	EQU		onColorMachine-4	; <KSM/RLC	31May89>lastAttrPtr		EQU		lastItemStrPtr-4	; <KSM/RLC	31May89>LinkSize		EQU		lastAttrPtr		; <FJL C792>MWHICHITEM		EQU		8MPopUpItem		EQU		MWhichItem		; <FJL C844>MPOINT			EQU		MWHICHITEM+4MLeftTop		EQU		MPoint			; <FJL C844>MMENURECT		EQU		MPOINT+4MMENUHANDLE		EQU		MMENURECT+4MMESSAGE		EQU		MMENUHANDLE+4FastSpeed		EQU		0SlowSpeed		EQU		10FirstMDMsg		EQU		0				; first messageLastMDMsg		EQU		3				; last message;----------------------------------------------------------------------------------------;;	Start of Code -- save work registers and dispatch on message number;;----------------------------------------------------------------------------------------			BRA.S	StartMDEF; Standard Header			DC.W	0					; flags word			DC.B	'MDEF'				; type			DC.W	0					; ID			DC.W	12					; version 4 = MacPlus										; version 5 = Alladin										; version 6 = onNuMac ROM										; version 10= Universal										; version 11= Universal 4.2					<FJL PMAB205>										; version 12= Universal 6.0					<PMAB364	23Jan88	EMT>StartMDEF			LINK	A6,#LinkSize		; set up a stack frame						<1Aug85>			MOVEM.L D3-D7/A2-A4,-(SP)	; save a whole bunch of work registers			MOVE.L	MMENUHANDLE(A6),A3	; keep menuHandle in A3			move.l	a3, a0				;											<FJL 27Jan87>			_HLock						; lock it down			clr		invertFlag(a6)		; most drawing done in normal (not inverted) mode <FJL C408>			clr		scrollFlag(a6)		; only set this flag when call InvertItem	<FJL 17Mar87>										; while scrolling			clr		onColorMachine(a6)	; clear color machine flag					<FJL 06Mar87>			cmpi.w	#$3FFF, ROM85		; color machine ?			sls		onColorMachine(a6)	; set byte to 1's if yes			lea		GoMdefProc, a0		; get the dispatch table base				<FJL>			move.w	mMessage(a6), d0	; get the message type			cmpi	#LastMDMsg, d0		; is the message within bounds?				<FJL>			bhi.s	@InvalidMsg			; oops, its too high			cmpi	#FirstMDMsg, d0		;			blo.s	@InvalidMsg			; oops, its too low			add.w	d0, d0				; double to get words			add.w	GoMdefProc(d0), a0	; compute the dispatch address			jsr		(a0)				; and dispatch@InvalidMsg			move.l	a3, a0				; get menuHandle			_HUnlock					; and unlock it before we leave			MOVEM.L (SP)+,D3-D7/A2-A4	; restore work registers			UNLK	A6					; unbuild the stack frame			MOVE.L	(SP)+,A0			; get return address			ADD		#18,SP				; strip parameters			JMP		(A0)				; return to caller; Dispatch TableGoMdefProc		dc.w	DoDrawMsg-GoMdefProc			; draw is message			#0				dc.w	DoChooseMsg-GoMdefProc			; choose menu size is msg	#1				dc.w	DoCalcMsg-GoMdefProc			; calc menu is msg			#2				dc.w	DoPopUpItemMsg-GoMdefProc		; calc top of popup item	#3;********************************************************************************************;*																							*;* IF YOU ADD ANOTHER MESSAGE YOU MUST UPDATE THE VARIABLE "LastMDMsg" FOUND ABOVE !!!!!!	*;*																							*;********************************************************************************************;----------------------------------------------------------------------------------------;;	Msg #1 -- Choose -- examine the mouse position and hilite the appropriate item;;----------------------------------------------------------------------------------------DoChooseMsg;; --------------------------	DO SETUP STUFF	---------------------------;			bsr		GetSizes			; get font info into stackframe			MOVE.L	MWHICHITEM(A6),A4	; get pointer to whichItem			MOVE.W	(A4),D3				; remember oldWhichItem			CLR		(A4)				; set whichItem to zero			MOVE.L	MMENURECT(A6),A2	; get the menu rect							<27Sep85>										; store original menurect in the stackframe	<FJL C792>			move.l	Top(a2), OrigMenuRect+Top(a6)			move.l	Bottom(a2), OrigMenuRect+Bottom(a6)			move.l	#FastSpeed,	ScrollSpeed(a6) ; assume fast-speed					<FJL 09Mar87>			move	MFHeight(a6), d0	; get height of scroll arrow				<FJL 09Mar87>			asr		#1, d0				; num pixels for slow scroll = height/2		<FJL 09Mar87>			move	d0, SlowPixels(a6)			clr		HItemFlag(a6)		; assume "old" item has no submenu			<FJL 17Mar87>			move	d3, d0				; get item			move.l	(a3),a0				; get menuPtr			bsr		GetItemRecord		; look it up			cmp.b	#HMenuCmd, ItemCmd(a1)	; does item have sub-menu?			bne.s	@NoSubMenu			; no	==> leave flag cleared			move	#1, HItemFlag(a6)	; yes ==> set flag@NoSubMenu	MOVE.W	TopMenuItem,D4		; get top of (scrolled) menu			<30Jan86>			MOVE.L	MPOINT(A6),D5		; get the mouse point					<27Sep85>			BEQ		NOITEMSEL			; => special case for flashing			<27Sep85>;; -------------------	ADJUST MENURECT BASED ON SCROLLING ARROWS	----------------;			move	AtMenuBottom, d0	; check for down scrolling arrow			<FJL C792>			cmp		Bottom(a2), d0		; is AtMenuBottom > bottom of menu rect ?			ble.s	@NoScroll			; no, so chk top			move	MFHeight(a6), d0	; yes, so make menuRect smaller by down scrolling arrow rect			sub		d0, Bottom(a2)@NoScroll			move	TopMenuItem, d0		; check for up scrolling arrow			cmp		Top(a2), d0			; is TopMenuItem < top of menu rect ?			bge.s	@NoScroll2			; no, so just do PtInRect			move	MFHeight(a6), d0	; yes, so make menuRect smaller by up scrolling arrow rect			add		d0, Top(a2)@NoScroll2;; If the point isn't in the adjusted menuRect, check for autoscrolling;			CLR.W	-(SP)				; make room for PtInRect result			MOVE.L	D5,-(SP)			; push the point			MOVE.L	A2,-(SP)			; push the rect			_PtInRect					; test if the point is in the rect			TST.B	(SP)+				; was it?			BNE		@3					; => yes, go select something;-----------------------	CHECK FOR AUTOSCROLLING DOWN	-------------------------------;; Only scroll if mouse pt directly above/below menu.  This allows; hierarchical menus to work properly -- scroll when mouse above/below menu,; -- return to a previous menu if outside of the scrolling rectangles.;			cmp		left(a2), d5		; to left of menu's left side?			<FJL C222>			blt		NoItemSel			; yes, so no item selected				<FJL C222>			cmp		right(a2), d5		; to right of menu's right side?		<FJL C222>			bgt		NoItemSel			; yes, so no item selected				<FJL C222>			MOVE.W	MFHeight(A6),D7		; get distance for scroll					<30Sep85>			SWAP	D5					; get mouse.v into low word					<27Sep85>			CMP.W	top(A2),D5			; above top?								<27Sep85>			BGE		@2					; => no, check bottom						<27Sep85>			ADD.W	D7,D4				; try to go up an item						<27Sep85>			CMP.W	top(A2),D4			; menu top must be <= to MenuRect.Top		<30Jan86>			BGT		NOITEMSEL			; => can't go up							<27Sep85>										; how far is mouse into scrolling arrow?	<FJL 09Mar87>			move	top(a2), d0			; get top of menu into d0					<FJL 09Mar87>			sub		d5, d0				; subtract mouse.v							<FJL 09Mar87>			cmp		SlowPixels(a6), d0	; is it more than slow num ?				<FJL 09Mar87>			bgt.s	@ContDown					; yes ==> do it fast				<FJL 09Mar87>			move.l	#SlowSpeed, ScrollSpeed(a6)	; no	==> do it slow				<FJL 09Mar87>@ContDown;+++			move	AtMenuBottom, d0	;										<FJL C792>;+++			cmp		Bottom(a2), d0		; is AtMenuBottom<> bottom of menu?;+++			bne.s	@1					; yes, so just do scrolling			move	AtMenuBottom, D0	;											<FJL PMAB205>			cmp		Bottom(A2), D0		; is AtMenuBottom > bottom of menu ?			bgt.s	@1					; yes -> no scrolling arrow needed			add		MFHeight(a6), d0			cmp		Bottom(A2), D0		; is AtMenuBottom+scrollamt > bottom of menu ?	<FJL PMAB276>			ble.s	@1					; yes -> no scrolling arrow needed				<FJL PMAB276>; If we get here then we are scrolling down and the last item is showing.  Therefore; we want to draw the down scroll arrow before scrolling.			move.l	a2, a0				; BlitScrollIndic expects menuRect ptr in A0			bsr		BlitDownScrollIndic			move	MFHeight(a6), d0	; move bottom of menuRect up so arrow doesn't get scrolled			sub		d0, Bottom(a2)		; and fall into scrolling code;-----------------------	DO THE AUTOSCROLLING	--------------------------------------@1			MOVE.W	D3,D0				; get the current selection				<30Sep85>			BSR	InvertItem				; and deselect it						<30Sep85>; When a HMenu is up and the item with the HMenu is the topmost or bottommost item; garbage is left on the screen unless we bring down the HMenu first.; Solution: 1) Don't scroll if an HMenu is up.;			2) DrawMenu clears a flag in mbSaveLoc every time a menu is drawn.;			3) If that flag is clear, then we set the flag and skip scrolling.;				This gives MenuSelect a chance to bring down the HMenu before;				the MDEF is called again.;			4) If the flag is set, then it is okay to scroll.;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>		IF forRAM THEN			cmp.w		#$FFFF, ROM85			; on old Mac or MacXL?			beq.s		@OkToScroll				; yes -> skip HMenu specific stuff												; RADIUS patches out complete menu mgr ==> could												;	have GetItemCmd installed, but mbSaveLoc												;	not initialized.			cmpi.l		#$FFFFFFFF, mbSaveLoc	; has the MBDF data structure been initialized?			beq.s		@OkToScroll			move.w		#$009F, d0				; load _Unimplemented number			_GetTrapAddress						; load _Unimplemented address			move.l		a0, d1					; copy routine address			move.w		#$004E, d0				; load _GetItemCmd number			_GetTrapAddress	,newTool			; load _GetItemCmd address			cmp.l		a0, d1					; new HMenu Mgr installed?			beq.s		@OkToScroll				; no -> skip HMenu specific stuff		ENDIF	; if forRAM;<<<<<--------------------------------------<<<<<			move.l	mbSaveLoc, a0		; get mbUglyScroll in mbSaveLoc			move.l	(a0), a0			tst		mbUglyScroll(a0)	; is mbUglyScroll set ?			bne.s	@OkToScroll			; yes, so HMenu was already brought down			move	#1, mbUglyScroll(a0); no, so set field			bra.s	@DoneScroll			; and skip scrolling this time through@OkToScroll			MOVE.W	D4,topMenuItem		; stuff new topItem						<27Sep85>			CLR.L	-(SP)				; room for region #1					<30Sep85>			_NewRgn						; get it								<30Sep85>			MOVE.L	(SP),D6				; save in D6							<30Jan86>			CLR.L	-(SP)				; room for region #2					<30Jan86>			_NewRgn						; get it								<30Jan86>			bsr		SaveCurrentColors	; save current colors in stack frame			<FJL C408>			move	#mctRGB2, colorOffset(a6)	; this offset is unimportant here		<FJL C408>												; since all we care about is bkgd color	<FJL C408>			bsr		SetColors			; set proper colors	for ScrollRect				<FJL C408>;; Delay depending on how far cursor is into the scroll arrow.							<FJL 09Mar87>;			bsr		DoScrollWait@DoTheScroll			MOVE.L	A2,-(SP)			; push rect								<27Sep85>			CLR.W	-(SP)				; dh = 0								<30Sep85>			MOVE.W	D7,-(SP)			; dv = itemHeight						<30Sep85>			MOVE.L	D6,-(SP)			; push update region			_ScrollRect					; scroll the menu						<30Sep85>			bsr		ChkScrollArrows		; chk if scrolling arrows should still be up	<FJL C792>			bsr		ResetPreviousColors	; reset colors stored in stackframe				<FJL C408>			MOVE.L	(SP),-(SP)			; point to region #2					<30Jan86>			_GetClip					; save the clip in it					<30Jan86>			MOVE.L	D6,-(SP)			; point to update region				<30Jan86>			_SetClip					; set clip to it						<30Jan86>			BSR		DrawScrolledItem	; call fast routine to draw item		<FJL C838>			ADD		D7, AtMenuBottom	; update new menu bottom				<FJL C838>			MOVE.L	(SP),-(SP)			; point to saved clip					<30Jan86>			_SetClip					; and restore it						<30Jan86>			_DisposRgn					; dispose of region #2					<30Jan86>			_DisposRgn					; dispose of region #1					<30Jan86>;; When scrolling, no item is selected, so clear the Item in MenuDisable global	<FJL C792>;@DoneScroll		IF forRAM THEN			tst.w	ROM85				; on old Mac or MacXL?			bmi.s	@NoMenuDisable		; yes -> MenuDisable is not available in low-memory , so skip		ENDIF	;forRAM			clr		MenuDisable+2		; clear Item only, not ID@NoMenuDisable			BRA		DoChooseDone		; and return							<27Sep85>;-----------------------	CHECK FOR AUTOSCROLLING UP	----------------------------------@2			MOVE.W	bottom(A2),D0		; get bottom							<30Jan86>			CMP.W	D0,D5				; below bottom?							<30Jan86>			BLT		NOITEMSEL			; => no									<27Sep85>			CMP.W	atMenuBottom,D0	; done scrolling?							<30Jan86>			BGE		NOITEMSEL			; => yes, nothing below us				<30Jan86>			NEG.W	D7					; change direction of scroll			<30Sep85>			ADD.W	D7,D4				; else scroll down						<27Sep85>										; how far is mouse into scrolling arrow?<FJL 09Mar87>			move	d5, d0				; get mouse.v into d0					<FJL 09Mar87>			sub		bottom(a2), d0		; subtract bottom of menu				<FJL 09Mar87>			cmp		SlowPixels(a6), d0	; is it more than slow num ?			<FJL 09Mar87>			bgt.s	@ContUp						; yes ==> do it fast			<FJL 09Mar87>			move.l	#SlowSpeed, ScrollSpeed(a6)	; no	==> do it slow			<FJL 09Mar87>@ContUp			move	TopMenuItem, d0		;										<FJL C792>			cmp		Top(a2), d0			; is TopMenuItem <> top of menu rect ?			bne		@1					; yes, so just do scrolling; If we get here then we are scrolling up and the first item is showing.  Therefore; we want to draw the up scroll arrow before scrolling.			move.l	a2, a0				; BlitScrollIndic expects menuRect ptr in A0			bsr		BlitUpScrollIndic			move	MFHeight(a6), d0	; move top of menuRect up so arrow doesn't get scrolled			add		d0, Top(a2)			; and fall into scrolling code			bra		@1;--------------------------------	DO THE CHOOSE	------------------------------------; the point is in the menu, so waltz through the itemList keeping track of vertical; position seeing which item it's in.  In the following loop, D4 holds the item number; while D2 has the cumulative vertical space;@3;; With popup menus it is possible to have the mouse pt above TopMenuItem			<FJL 22Mar87>; but no down-scrolling taking place because TopMenuItem may be below top; of the menuRect.  "Choose" must recognize this case and branch to NoItemSel.;			CMP		Top(a2), D4			; is TopMenuItem > top of menuRect ?			BLE.S	@DoChoose			; no	==> ok to choose			CMP		MPoint+V(a6), D4	; yes ==> is TopMenuItem > mouse pt ?			BGT.S	NoItemSel			; yes ==> no choice@DoChoose	MOVE.W	D4,D2				; top of menu into D2						<30Jan86>			MOVEQ	#1,D4				; start with first item						<30Jan86>MSELOOP		MOVE.L	(A3),A0				; get menuPtr			MOVE	D4,D0				; get item number			BSR		GETITEMRECORD		; look it up			BEQ.S	NOITEMSEL			; if so, nothing selected			BSR		GetItemHeight		; get item height in D0						<1Aug85>			ADD		D0,D2				; update vertical							<1Aug85>			CMP		MPOINT+V(A6),D2		; compare with mouse point			BGT.S	GOTSEL				; when D2 is bigger, we found it;; we didn't reach it yet, so keep stepping down till we do;NEXTMSEL	ADDQ	#1,D4				; bump to next item			BRA.S	MSELOOP				; loop till we find it;; we found it so update whichItem.  First we better make sure it's enabledGOTSEL;; put item rect in mbSaveLoc so MenuSelect has it to do Hierarchical menu drag		<FJL C222>; must store this regardless of whether item changed (consider case where an item; has a HMenu and you move to the HMenu, and then back into the item with that HMenu).;			LEA		TEMPRECT,A0			; get pointer to temporary rectangle			MOVE.L	MMENURECT(A6),A1	; point to menuRect			MOVE.L	(A1)+,(A0)			; copy menuRect into tempRect			MOVE.L	(A1),4(A0)			MOVE	D2,BOTTOM(A0)		; D2 has the bottom coordinate			SUB		D0,D2				; subtract the height			MOVE	D2,TOP(A0)			; set up the top;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>		IF forRAM THEN			cmp.w		#$FFFF, ROM85			; on old Mac or MacXL?			beq.s		@SkipRectStore			; yes -> skip HMenu specific stuff												; RADIUS patches out complete menu mgr ==> could												; have GetItemCmd installed, but mbSaveLoc												; not initialized.			cmpi.l		#$FFFFFFFF, mbSaveLoc	; has the MBDF data structure been initialized?			beq.s		@SkipRectStore			move.w		#$009F, d0				; load _Unimplemented number			_GetTrapAddress						; load _Unimplemented address			move.l		a0, d1					; copy routine address			move.w		#$004E, d0				; load _GetItemCmd number			_GetTrapAddress	,newTool			; load _GetItemCmd address			cmp.l		a0, d1					; new HMenu Mgr installed?			beq.s		@SkipRectStore			; no -> skip HMenu specific stuff		ENDIF	; if forRAM;<<<<<--------------------------------------<<<<<			move.l	mbSaveLoc, a0					; get handle to save loc			move.l	(a0), a0						; dereference			move.l	TempRect, mbItemRect(a0)		; save top, left			move.l	TempRect+4, mbItemRect+4(a0)	; save bottom, right@SkipRectStore			BSR		ENABLETEST			; make sure whole menu is enabled			BEQ.S	DoInverting			; if not, no selection			MOVE	D4,(A4)				; menu is enabled, so store item			bra.s	DoInverting			; and continue;; At this label the mouse is not in any item, so clear d4 so we return the			<FJL C531>; correct value in low-memory MenuDisable.  Can only reach here by a branch.;NOITEMSEL	clr		d4					; at this label no item selected;; see if whichItem changed; if it has, unselect the old item and select the new one;DoInverting			CMP		(A4),D3				; have they changed?			BEQ.S	GetDisabledItem		; if not, we're all done, no hiliting change			MOVE	D3,D0				; unhilite old item			BSR		INVERTITEM			;			MOVE	(A4),D0				; hilite new item			not		invertFlag(a6)		; tell InvertItem to draw in reverse colors		<FJL C408>			BSR		INVERTITEM			;			clr		invertFlag(a6)		; reset invertFlag								<FJL C408>;; "User ed" requested that apps be able to find out if a disabled menu item was chosen.	<FJL C531>; We return the ID and item in the global MenuDisable.  If the item is zero then		<FJL C531>; no item was chosen (i.e. the mouse was outside the menu), or was in the title.		<FJL C531>;GetDisabledItem			move.l	(a3), a0			; get menu ptr			swap	d4					; put item in hi-byte			move	menuID(a0), d4		; put menuID in lo-byte			swap	d4					; restore d4		IF forRAM THEN			tst.w	ROM85				; on old Mac or MacXL?			bmi.s	@NoMenuDisable		; yes -> MenuDisable is not available in low-memory , so skip		ENDIF	;forRAM			move.l		d4, MenuDisable	; put in low-memory where apps can query it if they want@NoMenuDisableDoChooseDone			move.l	OrigMenuRect(a6), Top(a2)	; reset menuRect in case we changed it<FJL C792>			move.l	OrigMenuRect+Bottom(a6), Bottom(a2)			rts							; return to dispatcher			;-------------------------------	DONE CHOOSE MSG	------------------------------------;---------------------------------------;	Utility -- DoScrollWait															<FJL 09Mar87>;---------------------------------------;; Delay for ScrollSpeed ticks.  If cursor moves out of slow scroll area then leave wait loop.;DoScrollWait			tst.l	ScrollSpeed(a6)		; how fast should we scroll?			beq.s	@NoWait				; zero means fast as possible			move.l	d3, -(sp)			; save temp reg on the stack			subq	#4, sp				; space for result			_TickCount					; get current tick count			move.l	(sp)+, d3			add.l	ScrollSpeed(a6), d3	; we want to wait until tick count in d3@Loop		subq	#4, sp				; space for VAR parameter			move.l	sp, -(sp)			; push address of parameter			_GetMouse			move.l	(sp)+, d5			; get mouse pt			swap	d5					; get .v into lo-word			tst		d7			bge.s	@ScrollingDown										; how far is mouse into scrolling arrow?	<FJL 09Mar87>			move	d5, d0				; get mouse.v into d0						<FJL 09Mar87>			sub		bottom(a2), d0		; subtract bottom of menu					<FJL 09Mar87>			cmp		SlowPixels(a6), d0	; is it more than slow num ?				<FJL 09Mar87>			bgt.s	@DoneWait			; yes	==> do it fast ==> stop waiting		<FJL 09Mar87>			bra.s	@ContLoop@ScrollingDown							; how far is mouse into scrolling arrow?			move	top(a2), d0			; get top of menu into d0			sub		d5, d0				; subtract mouse.v			cmp		SlowPixels(a6), d0	; is it more than slow num ?			bgt.s	@DoneWait			; yes ==> do it fast ==> stop waiting@ContLoop			subq	#4, sp				; space for result			_TickCount			cmp.l	(sp)+, d3			; reached desired tick count yet?			bgt.s	@Loop				; no	==> keep looping										; yes ==> we're done waiting@DoneWait			move.l	(sp)+, d3			; restore work register@NoWait			rts;---------------------------------------;	Utility -- ChkScrollArrows;---------------------------------------; if scrolling up, and if last item is appearing, then lower clip by height of		<FJL C792>; rectangle containing indicator arrow, and erase arrow rectangle.ChkScrollArrows			tst		d7			bge.s	@ChkScrollDown		; if D7 >= 0 then scrolling down not up			move	d7, d0				; get amount of scroll			neg		d0					; take negative since to make it positive			add		MFHeight(a6), d0	; add in height of scroll arrow			add		Bottom(a2), d0		; add to bottom of menuRect			cmp		AtMenuBottom, d0	; is new bottom of menuRect >= AtMenuBottom			blt.s	@NotLastItem		; no ==> not showing last item; last item is being drawn -> open clip so scroll arrow gets erased and last item gets drawn <FJL C792>			move.l	d6, a0				; change the bottom of the update region			move.l	(a0), a0			; get ptr to rgn			move	MFHeight(a6), d0	; get menu item height			add		d0, 2+Bottom(a0)	; Bottom = Bottom + menu item height			add		d0, Bottom(a2)		; update bottom of menuRect						<FJL C838>			move.l	d6, -(sp)			; and erase the whole region			_EraseRgn@NotLastItem			rts; if scrolling down, and if first item is appearing, then increase clip by height of	<FJL C792>; rectangle containing indicator arrow, and erase arrow rectangle.; NOTE: TopMenuItem has already been adjusted by scroll amount, so don't subtract it here@ChkScrollDown			move	Top(a2), d0			; get Top of menuRect			sub		MFHeight(a6), d0	; sub height of scroll arrow			cmp		TopMenuItem, d0		; is new top of menuRect <= TopMenuItem			bgt.s	@NotFirstItem		; no ==> not showing first item; first item is being drawn -> open clip so scroll arrow gets erased and first item gets drawn <FJL C792>			move.l	d6, a0				; change the top of the update region			move.l	(a0), a0			; get ptr to rgn			move	MFHeight(a6), d0	; get menu item height			sub		d0, 2+Top(a0)		; Top = Top - menu item height			sub		d0, Top(a2)			; update top of menuRect						<FJL C838>			move.l	d6, -(sp)			; and erase the whole region			_EraseRgn@NotFirstItem			rts;---------------------------------------;	Utility -- GetSizes;---------------------------------------; GetSizes reads the size of the current font into the stack frame.  It puts; ascent+descent+leading into the leading field and tweaks width for chicagoGetSizes	LEA		MInfoRec(A6),A2		; point to our info rec						<1Aug85>			MOVE.L	A2,-(SP)			; push a pointer							<1Aug85>			_GetFontInfo				; and get the font's info					<1Aug85>			MOVE.W	(A2)+,D0			; get ascent								<1Aug85>			ADD.W	(A2)+,D0			; add descent								<1Aug85>; fudge width if font is Chicago so that space between command key and command		<FJL 21Jan87>; character look better.  Can't assume that a width of 14 means chicago, so check; explicitly.			TST.W	ROM85				; running on new roms?			BMI.S	@ChkCurFM			; => no, then only check CurFMFamily			TST.W	SysFontFam			; We ar on post-MacPlus so can check SysFontFamily			BNE.S	@NotChicago			; If SysFontFam <> 0 then not Chicago										; If on post-MacPlus then check CurFMFamily too.@ChkCurFM	TST.W	CurFMFamily			; is CurFMFamily == 0 ?			BNE.S	@NotChicago			; no, so not Chicago			SUBQ	#2,(A2)				; yes its Chicago, so fudge width					<1Aug85>@NotChicago	ADDQ	#2,A2				; skip over widmax									<1Aug85>			ADD.W	D0,(A2)				; add leading, store total height in MFHeight(A6)	<1Aug85>			SUBQ.L	#2, SP				; Make room in stack						<S550	27Jul88	EMT>			MOVE.W	#' ', -(SP)			; ch = space								<S550	27Jul88	EMT>			_CharWidth					; See how wide it is						<S550	27Jul88	EMT>			MOVE.W	(SP)+, MSpaceWidth(A6)	; Put it in our stack frame				<S550	27Jul88	EMT>			RTS;---------------------------------------;	Utility -- GetIconSize;---------------------------------------; GetIconSize is a utility which returns the height and width of an icon.  The item pointer is in; A1 and the result is returned in D1.  The height is in the high word.			<S550	27Jul88	EMT>GetIconSize			cmpi.b	#ScriptMenuCmd, itemCmd(a1)	; is there a script defined?	<FJL CXXX>			beq.s	@noIcon				; yes, icon field stores scriptID		<FJL CXXX>			TST.B	ITEMICON(A1)		; does it have an icon?					<1Aug85>			BNE.S	@hasIcon			; skip around if it does				<1Aug85>@noIcon			MOVEQ.L	#0, D1				; No icon - return 0					<S550	27Jul88	EMT>			RTS							; Go home								<S550	27Jul88	EMT>@hasIcon			tst.b	onColorMachine(a6)	; If color, than check color icon		<S550	27Jul88	EMT>			beq.s	@noColor			;										<S550	27Jul88	EMT>; Get the cicn resource because its faster than calling GetCIcon				<S550	27Jul88	EMT>			SUBQ.L	#4, SP				; make room for function result			<S550	27Jul88	EMT>			MOVE.L	#'cicn',-(SP)		; push the resource type				<S550	27Jul88	EMT>			MOVE.W	#$0100,D0			; menu icons are 256-511				<S550	27Jul88	EMT>			MOVE.B	ITEMICON(A1),D0		; 										<S550	27Jul88	EMT>			MOVE.W	D0,-(SP)			; push icon number						<S550	27Jul88	EMT>			_GetResource				; get handle to cicn resource			<S550	27Jul88	EMT>			MOVE.L	(SP)+, D1			; get it in D1							<S550	27Jul88	EMT>			BEQ.S	@noColor			; no color icon, must be regular icon	<S550	27Jul88	EMT>			MOVE.L	D1, -(SP)			; Since we don't know what resLoad is	<S550	27Jul88	EMT>			_LoadResource				; call LoadResource to be sure			<S550	27Jul88	EMT>			MOVE.L	D1, A0				; get cicn resource handle in a0		<S550	27Jul88	EMT>			MOVE.L	(A0), A0			; dereference, cicn begins with pixMap	<S550	27Jul88	EMT>			MOVE.L	pBounds+botRight(A0), D1	; get bottom,right in D1		<S550	27Jul88	EMT>			SUB.L	pBounds+topLeft(a0), D1	; height = bottom,right - top,left	<S550	27Jul88	EMT>			BRA.S	@testShrunk			;										<S550	27Jul88	EMT>@noColor								;										<S550	27Jul88	EMT>			MOVE.L	#$00200020, D1		; Large b/w icons are 32 x 32			<S550	27Jul88	EMT>@testShrunk								;										<S550	27Jul88	EMT>			cmpi.b	#ShrunkenIconCmd, itemCmd(A1)	; is there a shrunken icon?	<FJL PMAB205>			beq.s	@0					; yes -> branch			cmpi.b	#SmallIconCmd, itemCmd(A1)	; is there a small icon?		<FJL PMAB205>			bne.s	@1					; no	-> branch						<S550	27Jul88	EMT>@0			LSR.L	#1, D1				; Divide by 2 to get smaller size		<S550	27Jul88	EMT>			BCLR	#15, D1				; Clear out because height could be odd	<S550	27Jul88	EMT>@1			RTS;---------------------------------------;	Utility -- GetItemHeightA4												<FJL PMAB205>;---------------------------------------; GetItemHeight gets the height of the current menu item into D0.; The item pointer is in A4.  Use GetItemHeight.GetItemHeightA4			MoveM.L	A1, -(SP)			; save work register			Move.L	A4, A1				; set up for call to GetItemHeight			Bsr.S	GetItemHeight			MoveM.L	(SP)+, A1			; restore work register			Rts;---------------------------------------;	Utility -- GetItemHeight;---------------------------------------; GetItemHeight gets the height of the current menu item into D0.; The item pointer is in A1.  Width of icon (if any) is in the high word of D1.GetItemHeight			BSR.S	GetIconSize			; Returns height, width in D1			<S550	27Jul88	EMT>			SWAP	D1					; Get height in low word				<S550	27Jul88	EMT>			MOVE.W	MFHeight(A6),D0		; get menu item height					<1Aug85>			ADDQ.W	#4, D1				; Add 4 for good measure				<S550	27Jul88	EMT>			CMP.W	D0, D1				; Is height + 4 > MFHeight?				<S550	27Jul88	EMT>			BLT.S	@1					; Nope, skip around						<S550	27Jul88	EMT>			MOVE.W	D1, D0				; Yes, use height + 4 instead			<S550	27Jul88	EMT>@1			RTS;---------------------------------------;	Utility -- EnableTest;---------------------------------------; EnableTest is a utility which tests if an item is enabled.  It expects a menuHandle; in A3 and the item number in D4.  It returns the result in the Z-flagENABLETEST	MOVE.L	(A3),A0				; get menu pointer			MOVE.L	MENUENABLE(A0),D0	; get enable flags			CMPI.W	#31,D4				; is item > 32						<7Jan86><FJL C466>			BGT.S	@0					; => no enable/disable				<7Jan86><FJL C466>			BTST	D4,D0				; is item enabled?			BEQ.S	ETDONE				; if not, return 0@0			BTST	#0,D0				; test menu bit			BEQ.S	ETDONE				; if off, return 0					<S550	27Jul88	EMT>			MOVE.W	D4, D0				; Put item number in D0				<S550	27Jul88	EMT>			BSR		GetItemRecord		; Go get it							<S550	27Jul88	EMT>			BSR		IsDash				; Is it a dash?						<S550	27Jul88	EMT>ETDONE		RTS							; return to caller;---------------------------------------;	Utility -- InvertItem;---------------------------------------; InvertItem is an internal utility that hilites/unHilites an item.  The item number is; passed in D0.  It also assumes A3 has the menuHandle.  If the high bit of D0; is set, bit-clear with gray instead of inverting the item (used by DoDrawMsg routine).INVERTITEM	MOVEM.L D3-D4,-(SP)			; save work registers			MOVE	D0,D3				; keep item number in safe place			BEQ		INVERTDONE			; if zero, ignore			MOVE.W	TopMenuItem,D2		; start at top of menu				<30Jan86>			MOVEQ	#1,D4				; D4 hold item index				<27Sep85>IILOOP		MOVE	D4,D0				; get item			MOVE.L	(A3),A0				; get menuPtr			BSR		GETITEMRECORD		; look it up			beq		InvertDone			; z-flag ==> can't find it			<FJL 22Mar87>			BSR.S	GetItemHeight		; get item height into D0			<1Aug85>			CMP.B	D3,D4				; found the item we want yet?			BEQ.S	GOINVERT			; if so, go invert it			ADD		D0,D2				; add total to cumulative v position			ADDQ	#1,D4				; bump to next position			BRA.S	IILOOP				; loop till we find it; it's time to invert the item.  The menuRect contains the horizontal bounds, D2 contains; the top of the vertical, D0 has the vertical sizeGOINVERT	MOVE.B	1(A0),D1			; remember 1st char of item			LEA		TEMPRECT,A0			; get pointer to temporary rectangle			MOVE.L	MMENURECT(A6),A1	; point to menuRect			MOVE.L	(A1)+,(A0)			; copy menuRect into tempRect			MOVE.L	(A1),4(A0)			MOVE	D2,TOP(A0)			; D2 has the top coordinate			ADD		D0,D2				; add in the height			MOVE	D2,BOTTOM(A0)		; set up the bottom;; Instead of inverting the item's rectangle we redraw it.  If the invertFlag(a6)	<FJL C408>; is set then SetColors will invert the colors properly for us.  If it isn't set	<FJL C408>; then the item will just be redrawn in normal colors.								<FJL C408>;			movem.l	a2-a4/d3-d7, -(sp)	; save same work registers as does DrawMsg			move	#srcOr,	-(sp)			_TextMode					; set mode to srcOr; set up for call to DrawTheItem.  Before doing this, we must clip to the item's rectangle; so that outline and shadowed text will not draw outside of the item rect.  But, because; scrolling with icons can produce "parts of items", we must clip to the intersection of the; menu rect and the item rect.  AND we must clip to screen in case menu draws past screen bounds.			subq	#4, sp				; space for result			_NewRgn			move.l	(sp), -(sp)			; make copy of region so can delete later			_GetClip			subq	#2, sp				; space for boolean result			move.l	MMenuRect(a6), -(sp); push menurect address			pea		TempRect			; push itemrect address			pea		HierArrowRect(a6)	; push dest rect (reuse stackframe variable)			_SectRect			addq	#2, sp				; ignore result			subq	#4, sp				; get current portRect			move.l	sp, -(sp)			; make space on stack for return			_GetPort			move.l	(sp)+, a0			; get port			subq	#2, sp				; space for boolean result			pea		portRect(a0)		; push portRect address			pea		HierArrowRect(a6)	; push clip rect address			pea		HierArrowRect(a6)	; push dest address			_SectRect			addq	#2, sp				; ignore result			pea		HierArrowRect(a6)	; push clip rect			_ClipRect			tst		scrollFlag(a6)		; being called from scroll routine?			bne.s	@DoRedraw			; yes, so do the drawing; On MacPlus and MacSE do InvertRect instead of redrawing when choosing an item.	<FJL 17Mar87>; Do this because MacDraw's custom "line" menu does not handle "choose item" message properly.; Of course it's not as easy as that since we use the Choose message as a way to clean up; the garbage left over when a hierarchical menu is brought down, and this assumes that; the item is redrawn, NOT inverted.  If this is the case then HItemFlag will be set.			tst		onColorMachine(a6)	; on MacII ?			bne.s	@DoRedraw			; yes ==> always redraw			tst		HItemFlag(a6)		; does item have submenu?			bne.s	@DoRedraw			; yes ==> then redraw to eliminate garbage beneath submenu			pea		TempRect			; push ptr to item's rectangle			_InverRect					; invert it			bra.s	@RedrawDone			; and leave@DoRedraw; erase the rect to the proper background color			bsr		SaveCurrentColors	; save current colors in stack frame			<FJL C408>			move	#mctRGB2, colorOffset(a6)	; this offset is unimportant here		<FJL C408>												; since all we care about is bkgd color	<FJL C408>			bsr		SetColors			; set proper colors	for EraseRect				<FJL C408>			pea		TempRect			; push a pointer to the rectangle			_EraseRect					; erase it			bsr		ResetPreviousColors ; reset colors after EraseRect; and draw the item			lea		TempRect, a0		; get address of item's rectangle			move	Top(a0), d3			; get top			add		MAscent(a6),d3		; add in the ascent for baseline;			move	Left(a0), d5		; move left edge into d5					<S550	27Jul88	EMT>;			move	Right(a0), d6		; move right edge into d6					<S550	27Jul88	EMT>;																					<S550	27Jul88	EMT>;			move	d4,d0				; get item									<S550	27Jul88	EMT>;			move.l	(a3),a0				; get menuPtr								<S550	27Jul88	EMT>;			bsr		GetItemRecord		; look it up								<S550	27Jul88	EMT>;			move.l	a0,a2				; keep string pointer in A2					<S550	27Jul88	EMT>;			move.l	a1,a4				; keep properties in A4						<S550	27Jul88	EMT>			bsr		DrawTheItem			; call drawing routine (it calls ResetPreviousColors)@RedrawDone	move.l	(sp), -(sp)			; reset clip to region it was before drawing item			_SetClip			_DisposRgn			movem.l	(sp)+, a2-a4/d3-d7	; restore work registersINVERTDONE	MOVEM.L (SP)+,D3-D4			; recover work regs			RTS;---------------------------------------;	Utility -- GrayRect;---------------------------------------;	GrayRect is a utility that bit-clears the current "tempRect" with gray;; We assume that this routine is only called by Draw msg, that SaveCurrentColors	<FJL C408>; has been called already, and that ResetPreviousColors will be called after this.	<FJL C408>GRAYRECT			MOVE.L	A0,-(SP)			; push rect address			MOVE.L	(A5),A0				; get QuickDraw globals			PEA		Gray(A0)			; push gray			_PenPat						; set pen to it			MOVE	#PatBIC,-(SP)		; push patBIC penMode			_PenMode					; set penMode			move	#mctRGB2, colorOffset(a6)	; use text color for fore color	<FJL C408>			bsr		SetColors			; set colors for bit clear				<FJL C408>			_PaintRect					; "OR" on the dim pattern			_PenNormal			RTS;---------------------------------------;	Utility -- TweakPos;---------------------------------------; TweakPos is passed an element size in D0.  It gets a horizontal offset into; D2 depending on whether things are right justified or not.  It also adjusts; D5 and D6 (the left and right positions).TweakPos			MOVE	D5,D2				; assume left to right					<27Sep85>;			ADDQ	#2,D2				; and indent element a little			<27Sep85>	<S550	27Jul88	EMT>			ADD.W	D0,D5				; assume bump past icon					<27Sep85>			TST.B	TESysJust+1			; check for right just					<11oct85>			BPL.S	@1					; => guessed right						<27Sep85>			SUB.W	D0,D6				; else back up for icon					<27Sep85>			SUB.W	D0,D5				; and fix up left						<27Sep85>			MOVE.W	D6,D2				; and set position						<27Sep85>@1			RTS;---------------------------------------;	Utility -- DrawScrolledItem													<FJL C838>;---------------------------------------; DrawScrolledItem is a faster way to draw the item that appears after a menu is scrolled.; The old method was to redraw the whole menu, and because clipping was set to just; the item that appeared no flashing occured.  The problem is that with the new features,; most noticeably color and hierarchical menus, scrolling can be fairly slow.  Actually this; method turns out to speed up scrolling by a factor of 2-3!!;DrawScrolledItem			MOVE.W	D4,D2				; top of menu into D2			MOVEQ	#1, D4				; start with first item			TST		D7			BGE.S	@ScrollingDown		; if D7 >= 0 then scrolling down not up@ScrollingUp			MOVE	Bottom(a2), D3		; fake mouse pt to be just above bottom of menu			SUBQ	#1, D3				; one pixel above menu bottom, or down scroll arrow			BRA.S	@Loop@ScrollingDown			MOVE	Top(a2), D3			; fake mouse pt to be just below top of menu			ADDQ	#1, D3				; one pixel below menu top, or up scroll arrow@Loop		MOVE.L	(A3),A0				; get menuPtr			MOVE	D4,D0				; get item number			BSR		GetItemRecord		; look it up			BEQ.S	@LastItemSel		; if none then must be last item			BSR		GetItemHeight		; get item height in D0			ADD		D0,D2				; update vertical			CMP		D3,D2				; compare with mouse point			BGT.S	@GotSel				; when D2 is bigger, we found it;; we didn't reach it yet, so keep stepping down till we do;			ADDQ	#1,D4				; bump to next item			BRA.S	@Loop				; loop till we find it;; we found it so draw the item;@LastItemSel			SUBQ	#1, D4				; back up one item@GotSel		MOVE	D4, D0				; InvertItem wants item number in D0			MOVE	#1, scrollFlag(a6)	; set flag for InvertItem					<FJL 17Mar87>			BSR		InvertItem			; InvertItem will draw the item; Because of fucking icons, there could be just part of the scrolled item showing, so if; we are scrolling up then redraw the item above too, or if scrolling down then redraw the; item below.			TST		D7			BGE.S	@ScrollingDown2		; if D7 >= 0 then scrolling down not up@ScrollingUp2			SUBQ	#1, D4				; draw item above this one			MOVE	D4, D0			BSR		InvertItem			BRA.S	@NoItemSel@ScrollingDown2			ADDQ	#1, D4				; draw item below this one			MOVE	D4, D0			BSR		InvertItem@NoItemSel	CLR		scrollFlag(a6)		; clear flag after InvertItem call			<FJL 17Mar87>			rts;----------------------------------------------------------------------------------------;;	Msg #0 -- Draw Menu -- bits behind have been saved, menu structure has been drawn,;							and menu rectangle is cleared to proper color (all by mbarproc);;----------------------------------------------------------------------------------------;; here is the part of the TextMenuProc that draws the menu.  For most of this routine,; A3 holds the menuHandle, D4 is the item counter and D3 holds the cumulative; vertical position.  DrawMenu is broken off for use in scrolling.;; To clear up a very tricky scrolling menu bug, we need to NOT SCROLL when a hierarchical menu; is up in the last item (i.e. topmost or bottommost).  If we don't bring the HMenu down first; a little bit of garbage is left on the screen.  We clear the field mbUglyScroll each; time a menu is drawn, then set it when the first time into the scrolling routine.  Thereafter; we check it and realize that the HMenu is already down, so it's ok to scroll.;; Changed so that caller sets global TopMenuItem so that can be forced to draw from <FJL C844>DoDrawMsg			bsr		GetSizes			; get font info into stackframe			MOVE.L	MMenuRect(A6),A0	; get menu rect pointer						<30Jan86>			clr		atMenuBottom		; clear bottom memory						<FJL C222>;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>		IF forRAM THEN			cmp.w		#$FFFF, ROM85			; on old Mac or MacXL?			beq.s		@SetTMI					; yes -> skip HMenu specific stuff												; RADIUS patches out complete menu mgr ==> could												; have GetItemCmd installed, but mbSaveLoc												; not initialized.			cmpi.l		#$FFFFFFFF, mbSaveLoc	; has the MBDF data structure been initialized?			beq.s		@SetTMI			move.w		#$009F, d0				; load _Unimplemented number			_GetTrapAddress						; load _Unimplemented address			move.l		a0, d1					; copy routine address			move.w		#$004E, d0				; load _GetItemCmd number			_GetTrapAddress	,newTool			; load _GetItemCmd address			cmp.l		a0, d1					; new HMenu Mgr installed?			bne.s		@ScrollClrOK			; yes -> MenuSelect sets TopMenuItem properly@SetTMI		MOVE.L		MMenuRect(A6),A0		; get menu rect pointer					<30Jan86>			MOVE.W		top(A0),topMenuItem		; no	-> say to draw from top			<30Jan86>			bra.s		@SkipScrollClr			; and skip HMenu specific stuff@ScrollClrOK		ENDIF	; if forRAM;<<<<<--------------------------------------<<<<<			move.l	mbSaveLoc, a0		; clear mbUglyScroll every time draw a menu	<FJL C792>			move.l	(a0), a0			clr		mbUglyScroll(a0)@SkipScrollClr			bsr.s	DrawMenu			; call draw menu			bsr.s	ChkScrollIndic		; draw scrolling indicator (if necessary) <FJL C792>			rts;---------------------------------------;	Utility -- DrawMenu;---------------------------------------DRAWMENU	MOVEM.L a2-A4/D3-D7,-(SP)	; save some regs						<27Sep85>			MOVEQ	#1,D4				; start with first item			MOVE.W	topMenuItem,D3		; and point to top of first item			ADD.W	MAscent(A6),D3		; add in the ascent for baseline; apps that screw around with the wmgrport textfont and textface unwittingly, have	<FJL CXXX>; menu items show up in the wrong font/face/etc....			CLR.L	-(SP)				; push empty set for TextFace and TextFont			_TextFace					; change textface to normal			_TextFont					; change textfont to normal			move	#srcOr, -(sp)		; set text mode to srcOr					<FJL C408>			_TextMode					;											<FJL C408>DRAW1MLOOP	MOVE.L	MMENURECT(A6),A0	; get menuRect pointer						<27Sep85>;			MOVE.L	(A0)+,D5			; get left edge								<27Sep85>	<S550	27Jul88	EMT>;			MOVE.L	(A0),D6				; get right edge, too						<27Sep85>	<S550	27Jul88	EMT>;																								<S550	27Jul88	EMT>;			MOVE	D4,D0				; get item number in D0									<S550	27Jul88	EMT>;			MOVE.L	(A3),A0				; get menu pointer										<S550	27Jul88	EMT>;			BSR		GETITEMRECORD		; look it up											<S550	27Jul88	EMT>;																								<S550	27Jul88	EMT>;			MOVE.L	A0,A2				; keep string pointer in A2								<S550	27Jul88	EMT>;			MOVE.L	A1,A4				; keep properties in A4									<S550	27Jul88	EMT>			bsr		DrawTheItem			; call drawing routine			BEQ.S	DONEDRAW			; if null item, EXIT W/atBottom TRUE		<27Sep85>	<S550	27Jul88	EMT>;; we're done with this item so bump to the next one;			cmpi.b	#ScriptMenuCmd, itemCmd(a4)	; is there a script defined?		<FJL CXXX>			beq.s	@1					; yes, icon field stores scriptID			<FJL CXXX>			TST.B	ITEMICON(A4)		; does it have an icon?			BEQ.S	@1					; skip if it doesnt			MOVE.W	D7,D0				; get delta height			LSR.W	#1,D0				; divide by 2			SUB.W	D0,D7				; and get remainder			ADD		D7,D3				; bump the rest of the difference for icon@1			ADD		MFHeight(A6),D3		; bump to next baseline			ADDQ	#1,D4				; bump to next item			BRA.s	DRAW1MLOOP			; loop till done; When we return to DoneDraw, D3 points to the baseline of the cell that would follow the; last cell.  Back up to the bottom of the last cell and save as menubottom.DONEDRAW	SUB.W	MAscent(A6),D3		; back up to "top of cell"					<30Jan86>			MOVE.W	D3,AtMenuBottom		; update bottom								<30Jan86>			MOVEM.L (SP)+,a2-A4/D3-D7	; restore some regs							<27Sep85>			RTS;---------------------------------------;	Utility -- ChkScrollIndic														<FJL C792>;---------------------------------------; Blit up the scrolling down arrow if we need to;ChkScrollIndic			move.l	MMenuRect(a6), a0		; get menu rect ptr			move	AtMenuBottom, d0		; get AtMenuBottom			cmp		Bottom(a0), d0			; is AtMenuBottom > bottom of MenuRect			ble.s	@CkUpIndic				; no ==> don't need down arrow, see if need up arrow			bsr.s	BlitDownScrollIndic		; yes ==> blit the down arrow@CkUpIndic	move.l	MMenuRect(a6), a0		; get menu rect ptr						<FJL C844>			move	TopMenuItem, d0			; get TopMenuItem			cmp		Top(a0), d0				; is TopMenuItem < top of MenuRect			bge.s	@DoneChk				; no ==> don't need up arrow			bsr.s	BlitUpscrollIndic		; yes ==> blit the up arrow@DoneChk	rts;---------------------------------------;	Utility -- BlitDownScrollIndic / BlitUpScrollIndic													<FJL C792>;---------------------------------------; Blit up the scrolling arrows;BlitDownScrollIndic			movem.l	a3-a4/d4, -(sp)			; store work registers; calculate where bottom of menu is			move	Bottom(a0), HierArrowRect+Bottom(a6)	; store bottom			move	Bottom(a0), HierArrowRect+Top(a6)		; top = bottom - MFHeight			move	MFHeight(a6), d0			sub		d0, HierArrowRect+Top(a6)			move	Left(a0), HierArrowRect+Left(a6)		; store left			move	Right(a0), HierArrowRect+Right(a6)		; store right			lea		DownArrow, a4			; store arrow address in a4 for DoTheBlit			bra.s	DoTheBlitBlitUpScrollIndic			movem.l	a3-a4/d4, -(sp)			; store work registers; calculate where top of menu is			move	Top(a0), HierArrowRect+Top(a6)			; store top			move	Top(a0), HierArrowRect+Bottom(a6)		; bottom = top + MFHeight			move	MFHeight(a6), d0			add		d0, HierArrowRect+Bottom(a6)			move	Left(a0), HierArrowRect+Left(a6)		; store left			move	Right(a0), HierArrowRect+Right(a6)		; store right			lea		UpArrow, a4			; store arrow address in a4 for DoTheBlit										; and drop into DoTheBlitDoTheBlit			bsr		SaveCurrentColors		; save current colors in stack frame			move	#-1, d4					; force SetColors to get the title color											;	entry not an item entry			move	#mctRGB2, colorOffset(a6)	; set fore/back colors for this item			bsr		SetColors				; set proper colors for blit; erase rect now that the fore/back colors are set properly			pea		HierArrowRect(a6)			_EraseRect; create bitMap for arrow			moveq	#bitMapRec, d0			; alloc bitmap for 16Vert x 16Horiz x 1Deep bit map			_NewHandle			_HLock			move.l	(a0), a3				; dereference			move	#2, rowBytes(a3)		; 16 x 1 bits wide			move.l	#$00000000,bounds(a3)	; top = 0, left = 0			move.l	#$00100010,bounds+4(a3)	; bottom = $10, right = $10			move.l	a4, baseAddr(a3)		; store correct arrow bitmap in baseAddr; set arrow rect;+++;	left = left + MWidMax;+++;	right = newleft + MWidMax + 4;+++			move	MWidMax(a6), d0;+++			add		d0, HierArrowRect+Left(a6);+++			move	HierArrowRect+Left(a6), HierArrowRect+Right(a6);+++			add		#4, d0;+++			add		d0, HierArrowRect+Right(a6); left = MenuRect.left + MWidMax									<FJL PMAB205>; right = left + min(16,MFHeight(A6)); bottom = top + min(16,MFHeight(A6))			move	MWidMax(A6), d0			add		HierArrowRect+Left(A6), d0			move	d0, HierArrowRect+Left(A6)			move	d0, HierArrowRect+Right(A6)			moveq	#16, d0			cmp.w	MFHeight(A6), d0			bge.s	@1			move	MFHeight(A6), d0@1			add		d0, HierArrowRect+Right(A6)			move	HierArrowRect+Top(A6), HierArrowRect+Bottom(A6)			add		d0, HierArrowRect+Bottom(A6); get current portRect			subq	#4, sp			move.l	sp, -(sp)				; make space on stack for return			_GetPort			move.l	(sp)+, a0				; get port; copy from the bitMap into the port			move.l	a3, -(sp)				; push src bitMap ptr			pea		portBits(a0)			; push dest pointer (for the screen)			pea		bounds(a3)				; push src bounds rect			pea		HierArrowRect(a6)		; push dest bounds rect			move	#srcOr, -(sp)			; srcOr			clr.l	-(sp)					; no maskRgn			_CopyBits			move.l	a3, a0					; get bitMap ptr			_RecoverHandle					; get bitMap handle			_DisposHandle					; and toss it			movem.l	(sp)+, a3-a4/d4			; restore work registers			bsr		ResetPreviousColors		; reset colors stored in stackframe			rts			;---------------------------------------;	Utility -- IsDash;---------------------------------------; IsDash is a utility which tests if an item is the special dash separator.; It returns the result in the Z-flag												<S550	27Jul88	EMT>IsDash			CMP.B	#$2D,1(A0)			; first char a dash?			BNE.S	@NoDash				; No dash, skip.			TST.B	itemIcon(A1)		; Does it have an icon?			BNE.S	@NoDash				; No dash, skip.			TST.B	itemCmd(A1)			; Does it have a cmd?@NoDash			RTS							; Return result in Z;----------------------------------------;	Utility -- DrawTheItem;----------------------------------------; separated actual drawing routine out so; can ChooseMsg can call it since we now; redraw the selected item rather than; just inverting it.;; Used to be:																		<S550	27Jul88	EMT>; On entry:		d3		Item's baseline, top of item + font's ascent;				d4		Item Number;				d5		left edge, pixels;				d6		right edge, pixels;				a2		item's string pointer;				a4		item's properties pointer;				--		GetSizes has been called;; Now:																				<S550	27Jul88	EMT>; On entry:		D3		Item's baseline, top of item + font's ascent;				D4		Item Number;				A0		Menu rectangle pointer (for left and right edge);				A3		Menu handle;				--		GetSizes has been called;				--		GetItemRecord has been called;				--		D5, D6, A2, and A4 are all set up just like old times;; On exit:		Z		Set if the item does not exist;DrawTheItem			MOVE.W	Left(A0), D5		; Get the left edge							<S550	27Jul88	EMT>			MOVE.W	Right(A0), D6		; Get the right edge						<S550	27Jul88	EMT>			MOVE.W	D4, D0				; Prepare item number for GetItemRecord		<S550	27Jul88	EMT>			MOVE.L	(A3), A0			; Dereference menu handle					<S550	27Jul88	EMT>			BSR		GetItemRecord		; Go get it									<S550	27Jul88	EMT>			BEQ		NoDrawItem			; Skip whole mess if not a valid item		<S550	27Jul88	EMT>			MOVE.L	A0, A2				; Store string pointer in A2				<S550	27Jul88	EMT>			MOVE.L	A1, A4				; And properties in A4						<S550	27Jul88	EMT>			bsr		SaveCurrentColors	; save fore/back colors in stackframe		<FJL C408>			MOVE.L	A2, A0				; Get string pointer for IsDash				<S550	27Jul88	EMT>			MOVE.L	A4, A1				; And properties too						<S550	27Jul88	EMT>			BSR.S	IsDash				; Is it a dash?								<S550	27Jul88	EMT>			BNE.S	NotDash				; If not, draw item normally				<S550	27Jul88	EMT>;---------------------------------------;	Utility -- DrawDash;---------------------------------------; handle the case of a dash item by drawing a lineDrawDash			move	#mctRGB2, colorOffset(a6) ; use the item color if there is an entry <FJL C408>			bsr		SetColors			; set colors									<FJL C408>			MOVE.L	(A5),A0				; get QuickDraw globals			PEA		Gray(A0)			; set pattern to gray			_PenPat			MOVE.W	D3,-(SP)			; save y position			MOVE.W	D5,-(SP)			; push x position			MOVE.W	MFHeight(A6),D0	; center the dash			LSR.W	#1,D0				; by backing up to top of cell			SUB.W	MAscent(A6),D0		; and going halfway down			ADD.W	D0,D3				; add to current position			MOVE.W	D3,-(SP)			; push new y position			_MoveTo			MOVE.W	D6,-(SP)			; push	right edge			MOVE	D3,-(SP)			; push	y			_LineTo						; draw	the line			MOVE.W	(SP)+,D3			; restore baseline			_PenNormal					; pen back to normal			BRA		DoneDrawItem		; dive	back into mainstreamNotDash			ADDQ.W	#2, D5				; Add the 2 pixels here instead				<S550	27Jul88	EMT>			cmpi.b	#ScriptMenuCmd, itemCmd(a4)	; is there a script defined?		<FJL CXXX>			beq.s	DrawMark			; yes, icon field stores scriptID			<FJL CXXX>			MOVE.B	ITEMICON(A4),D0		; does it have an icon?			BEQ.S	DrawMark			; if not, skip; for icon, center the baseline in the item's rect			Bsr		GetItemHeightA4		; get item's height in D0			SUB.W	MFHeight(A6),D0		; subtract font height						<1Aug85>			MOVE.W	D0,D7				; save font height in D7					<1Aug85>			LSR.W	#1,D0				; get delta									<1Aug85>			ADD.W	D0,D3				; keep baseline in D3						<1Aug85>; ---------------------	draw the mark	--------------------------DrawMark	MOVE.W	MWidMax(A6),D0		; get char width							<27Sep85>			BSR		TweakPos			; get hpos into D2, adjust d5,d6			<27Sep85>;			When itemCmd == HMenuCmd ($1B) the itemMark field is used to store		<FJL C222>;			the hierarchical menu number so don't draw a mark by mistake.			<FJL C222>			cmpi.b	#HMenuCmd, itemCmd(a4)	; hierarchical menu for this item?		<FJL C222>			beq.s	ChkDrawIcon			TST.B	ITEMMARK(A4)		; does it have a mark?			BEQ.S	CHKDRAWICON			; if not, skip			MOVE.W	D2,-(SP)			;			MOVE	D3,-(SP)			; push v position			_MoveTo						; position pen			move	#mctRGB1, colorOffset(a6) ; tell SetColors to get the MARK		<FJL C408>			bsr		SetColors			; set mark colors							<FJL C408>			CLR	D0						; clear out high part			MOVE.B	ITEMMARK(A4),D0		; get the mark character			MOVE.W	D0,-(SP)			; push it			_DrawChar; ---------------------	draw the icon	--------------------------CHKDRAWICON;			when itemCmd == ScriptMenuCmd ($1C) the itemIcon field is used to		<FJL CXXX>;			store the script ID number, so don't draw an icon by mistake.			<FJL CXXX>;			when itemCmd == ShrunkenIconCmd ($1D) we draw the icon into a 16x16		<FJL PMAB205>;			area instead of the normal 32x32;			when itemCmd == SmallIconCmd ($1E) we draw a small icon into a 16x16	<FJL PMAB205>;			area;			cmpi.b	#ScriptMenuCmd, itemCmd(a4)	; script for this item?				<FJL CXXX>;			beq		DrawCmdChar;;			TST.B	ITEMICON(A4)		; does it have an icon?						<15Oct85>			MOVE.L	A4, A1				; Copy A4 into A1 for GetIconSize			<S550	27Jul88	EMT>			BSR		GetIconSize			; Get the height, width of the icon			<S550	27Jul88	EMT>			TST.L	D1					; Is there one?								<S550	27Jul88	EMT>			BEQ		DrawCmdChar			; if not, skip;; get horizontal position into D2;;			MOVEQ	#40,D0				; get field size (width) for large icon		<27Sep85>;;			Cmpi.b	#ShrunkenIconCmd, itemCmd(A4)	;is this a shrunken icon ?		<FJL PMAB205>;			Beq.s	@SmallDst			; yes	-> branch							<FJL PMAB205>;			Cmpi.b	#SmallIconCmd, itemCmd(A4)		;is this a small icon ?;			Bne.s	@DoTweak			; no	-> branch;@SmallDst	Bsr		GetItemHeightA4		; get item height for small icons into D0;@DoTweak	BSR		TweakPos			; get hpos into D2, adjust D5,D6			<27Sep85>; draw the icon.  First back up to top of rect			LEA		TEMPRECT,A0			; get pointer to rectangle			MOVE.L	A0,-(SP)			; push rect for plotIcon call			MOVE.L	D1, -(SP)			; Save height, width on stack				<S550	27Jul88	EMT>			MOVE.W	D3,D1				; get baseline								<1Aug85>			MOVE.W	D7,D0				; font height from D7						<15Oct85>			LSR.W	#1,D0				; get delta									<15Oct85>			SUB.W	D0,D1				; subtract delta							<15Oct85>			SUB.W	MAscent(A6),D1		; subtract font height						<15Oct85>			ADDQ.W	#2,D1				; down from top of item						<15Oct85>			MOVE.L	(SP)+, D0			; Restore it into D0 instead				<S550	27Jul88	EMT>;			cmpi.b	#ShrunkenIconCmd, itemCmd(A4); is this a shrunken icon ?		<FJL PMAB205>;			beq.s	@SetupSmallDstIcon			; yes -> branch						<FJL PMAB205>;			cmpi.b	#SmallIconCmd, itemCmd(A4)	; is this a smallicon ?;			bne.s	@SetupRegularIcon;;@SetupSmallDstIcon;			move	D1, (A0)+			; and stuff top;			move	D2, (A0)			; push left;			subq.w	#3, (A0)+			; fudge to line up small icon on the left;			move.l	-4(A0),(A0)			; copy bottom/right;			add		#16, (A0)+			; bottom := top + 16;			add		#16, (A0)			; right := left + 16;			bra.s	@DoneSetup;;;@SetupRegularIcon			MOVE.W	D1,(A0)+			; and stuff top							<1Aug85>			MOVE.W	D5, D2				; Assume left-to-right					<S550	27Jul88	EMT>			TST.B	TESysJust+1			; Test for right just					<S550	27Jul88	EMT>			BPL.S	@LeftRight			; Guessed right							<S550	27Jul88	EMT>			MOVE.W	D6, D2				; Otherwise get right side				<S550	27Jul88	EMT>			SUB.W	D0, D2				; And subtract out width				<S550	27Jul88	EMT>@LeftRight								;										<S550	27Jul88	EMT>			MOVE.W	D2,(A0)+			; push left								<27Sept85>	<S550	27Jul88	EMT>;			ADDQ.W	#3,(A0)+			; indent a little						<15Oct85>			MOVE.L	-4(A0),(A0)			; copy bottom right			ADD.L	D0, (A0)			; Add height, width to get bottom, right	<S550	27Jul88	EMT>;			ADD		#32,(A0)+			; bottom := top + 32;			ADD		#32,(A0)			; right := left + 32;@DoneSetup			ADD.W	MSpaceWidth(A6), D0	; Add single space to width of icon			<S550	27Jul88	EMT>			BSR		TweakPos			; get hpos into D2, adjust D5,D6			<S550	27Jul88	EMT>;>>>>>------------- NuMac ------------------>>>>>;+++		IF onNuMac THEN			tst.b	onColorMachine(a6)			beq.s	@DoPlotIcon; attempt to get color icon first and if unsuccessful then get regular icon		<FJL C408>			subq	#4, sp				; make room for function result			move	#$0100, d0			; menu icons are 256-511			move.b	itemIcon(a4), d0	; get icon number - 256			move	d0, -(sp)			; push icon number			_GetCIcon			move.l	(sp)+, iconHandle(a6)	; get icon handle, and save in stackframe			beq.s	@DoPlotIcon			; no color icon, must be regular icon; check to be sure icon is <= 32 x 32; no longer care about icon size												<S550	27Jul88	EMT>;			move.l	iconHandle(a6), a0	; get icon handle;			move.l	(a0), a0			; dereference, a0 points at pixMap;			move.l	pBounds+Top(a0), d0	; get top, left;			move.l	pBounds+Bottom(a0), d1	; get bottom, right;			sub		d0, d1				; width = right - left;			cmp		#32, d1				; width == 32 ?;			bne.s	@DispIcon			; if not then don't plot it;			swap	d0;			swap	d1;			sub		d0, d1				; height = bottom - top;			cmp		#32, d1				; height == 32?;			bne.s	@DispIcon			; if not then don't plot it; force colors to black on white for PlotCIcon regardless of InvertFlag,; unless it's 1 or 2 bit mode in which case we want it white on black so icon mask; is inverted properly			cmpi.w	#4, PixelDepth(a6)	; is this 4+ mode ?			blt.s	@FunkySettings		; no, so branch and do funky color setting			pea		RGBBlack			; in 4+ mode force black on white always			_RGBForeColor			pea		RGBWhite			_RGBBackColor			bra.s	@1@FunkySettings							; in 1 or 2 bit, use black on white for normal										; and white on black for selected			pea		RGBBlack			pea		RGBWhite			tst		invertFlag(a6)		; invert mode?			bne.s	@2					; yes --> branch			_RGBBackColor			_RGBForeColor			bra.s	@1@2			_RGBForeColor			_RGBBackColor; everything checks out so plot it@1			move.l	iconHandle(a6), -(sp)	; got a color icon so push it on the stack			_PlotCIcon						; rect is already on the stack;@DispIcon does not properly clean up stack.  Good thing we don't use it anymore.			move.l	iconHandle(a6), -(sp)	; dispose of CIcon			_DisposCIcon			bra.s	DrawCmdChar				; and continue;+++		ENDIF;<<<<<--------------------------------------<<<<<@DoPlotIcon			Cmpi.B	#SmallIconCmd, itemCmd(A4)	; is it a small icon ?			<FJL PMAB205>			Bne.S	@GetLargeIcon		; no	-> get large icon			Clr.L	-(SP)				; yes -> get small icon			Move.L	#'SICN', -(SP)		; push res type			Bra.S	@GetIconCommon		; and use common code@GetLargeIcon			CLR.L	-(SP)				; make room for function result			MOVE.L	#'ICON',-(SP)		; push the resource type@GetIconCommon			MOVE.W	#$0100,D0			; menu icons are 256-511			MOVE.B	ITEMICON(A4),D0		; does it have an icon?			MOVE	D0,-(SP)			; push icon number			_GetResource				; get the icon handle			move.l	#$00100010, D0		; assume src icon is 16x16			moveq	#2, D1				; and rowbytes is 2			cmpi.b	#SmallIconCmd, itemCmd(a4)	; is it?			beq.s	@PushIconSrcSize	; yes -> branch			add.l	d0,d0				; double it to make 32x32			add.l	d1,d1				; double rowbytes too@PushIconSrcSize			move.l	d0,-(sp)			; push size			move	d1,-(sp)			; push rowbytes			move	#mctRGB2, colorOffset(a6) ; use the item color if there is an entry <FJL C408>			bsr		SetColors			; set colors									<FJL C408>@PlotIt		bsr		PlotAnySizeIcon	; plot the icon										<FJL PMAB205>@DonePlot; ---------------------	draw the command character	--------------------------DrawCmdChar			TST.B	ITEMCMD(A4)			; is there one?			BEQ.S	DRAWITEXT			; if not, skip			cmpi.b	#ScriptMenuCmd, itemCmd(a4)	; script for this item?					<FJL CXXX>			beq.s	DrawIText			; if so, skip									<FJL CXXX>			cmpi.b	#ShrunkenIconCmd, itemCmd(a4)	; shrunken icon?					<FJL PMAB205>			beq.s	DrawIText			; if so, skip			cmpi.b	#SmallIconCmd, itemCmd(a4)	; small icon?							<FJL PMAB205>			beq.s	DrawIText			; if so, skip			move	#mctRGB3, colorOffset(a6) ; tell SetColors to get the CMD			<FJL C408>			bsr		SetColors			; set colors for command character				<FJL C408>			MOVE.W	MWidMax(A6),D0		; get width										<27Sep85>			ADD.W	D0,D0				; *2											<27Sep85>			SUB.W	D0,D6				; assume it will go on right					<27Sep85>			MOVE	D6,-(SP)			; put it on stack								<27Sep85>			TST.B	TESysJust+1			; check for right just							<11oct85>			BPL.S	@1					; => guessed right								<27Sep85>			ADDQ	#2,D5				; else indent a little FIRST					<S550	27Jul88	EMT>			MOVE.W	D5,(SP)				; else do it from left							<27Sep85>			ADD.W	D0,D5				; and bump left position						<27Sep85>			ADD.W	D0,D6				; else back up for icon							<27Sep85>@1			MOVE.W	D3,-(SP)			; push vertical position			_MoveTo						; position pen;; if this item has a sub-menu, then blit an arrow in the command key					<FJL C222>; field to indicate its existence .														<FJL C222>;			cmpi.b	#HMenuCmd, itemCmd(a4)	; is there a H Menu?						<FJL C222>			bne.s	@NormalCmd				; no, so do as normal						<FJL C222>			bsr		BlitHierArrow			; draw the Hierarchical arrow			bra.s	DrawIText				; continue									<FJL C222>@NormalCmd	MOVE.B	TESysJust+1,D1		; need special justification?					<FJL CXXX>			EXT.W	D1					; make it a signed word							<FJL CXXX>			BNE.S	@JustifiedCmd		; => yes										<FJL CXXX>			MOVE.W	#commandMark,-(SP)	; push command mark (propeller)					<15Feb85>			_DrawChar					; draw the character			CLR	D0						; clear high part			MOVE.B	ITEMCMD(A4),D0		; get command character			MOVE.W	D0,-(SP)			; push command char			_DrawChar					; draw it			bra.s	DrawIText			; and continue@JustifiedCmd							; draw commandletter/propeller					<FJL CXXX>			CLR	D0						; clear high part			MOVE.B	ITEMCMD(A4),D0		; get command character			MOVE.W	D0,-(SP)			; push command char			_DrawChar					; draw it			MOVE.W	#commandMark,-(SP)	; push command character						<15Feb85>			_DrawChar					; draw the character; ----------------	draw the text of the item (position in D5)	----------------------DRAWITEXT			move	#mctRGB2, colorOffset(a6) ; tell SetColors to get the TEXT			<FJL C408>			bsr		SetColors			; set colors for text							<FJL C408>			CLR	D0						; clear it out			MOVE.B	ITEMSTYLE(A4),D0	; push the style parameter			MOVE.W	D0,-(SP)			; push style parameter			_TextFace					; get into that face; if there is a script for this font then set it			cmpi.b	#ScriptMenuCmd, itemCmd(a4)	; script for this item?			<FJL CXXX>			bne.s	@1					; no, so skip							<FJL CXXX>			move.b	itemIcon(a4), d0	; pass script number					<S422	08Mar88 MED>			bsr		SetScriptFont		; yes, so set the proper font			<FJL CXXX>@1			MOVE.B	TESysJust+1,D1		; need special justification?			<11oct85>			EXT.W	D1					; make it a signed word					<11oct85>			BNE.S	@DrawIntl			; => yes								<27Sep85>			MOVE.W	D5,-(SP)			; and baseline left						<27Sep85>			MOVE.W	D3,-(SP)			; else push baseline vertical			<27Sep85>			_MoveTo						; push the pen							<27Sep85>			MOVE.L	A2,-(SP)			; point to the string					<27Sep85>			_DrawString					; and draw it							<27Sep85>			BRA.S	@2;; do International stuff here if TESysJust is negative;@DrawIntl	LEA		TempRect,A0			; build rect for TextBox				<27Sep85>			SUBQ	#1,D5				; textBox indents by one				<27Sep85>			MOVE.W	D3,(A0)				; get y position						<27Sep85>			MOVE.W	MAscent(A6),D0		; move up to top of rect				<27Sep85>			SUB.W	D0,(A0)+			;										<27Sep85>			MOVE.W	D5,(A0)+			; D5 is left							<27Sep85>			MOVE.W	D3,(A0)				; as top and bottom						<27Sep85>			MOVE.W	MDescent(A6),D0		; and move down to bottom				<27Sep85>			ADD.W	D0,(A0)+			;										<27Sep85>			MOVE.W	D6,(A0)				; and setup right						<27Sep85>			MOVEQ	#0,D0				; get length							<27Sep85>			MOVE.B	(A2)+,D0			; into D0								<27Sep85>			MOVE.L	A2,-(SP)			; push text pointer						<27Sep85>			MOVE.L	D0,-(SP)			; and length							<27Sep85>			PEA		TempRect			; push rect of rects					<27Sep85>			MOVE.W	D1,-(SP)			; and justification word				<11oct85>			_TextBox@2			CLR.L	-(SP)				; push empty set for TextFace and TextFont			_TextFace					; restore textface to normal			_TextFont					; restore textfont to normal;; if the item is disabled, gray it out;			BSR		ENABLETEST			; is it enabled?			BNE.S	DoneDrawItem		; branch if it is			bsr.s	BitClearItem		; bit clear the item, notice that colors are set properlyDoneDrawItem			bsr		ResetPreviousColors	; restore colors saved in the stackframe <FJL C408>			MOVEQ	#1, D0				; Force Z flag off for normal return	<S550	27Jul88	EMT>NoDrawItem								;										<S550	27Jul88	EMT>; Z flag is already set															<S550	27Jul88	EMT>			rts							; and return to caller;---------------------------------------;	Utility -- BitClearItem				; attempt to speed graying of menu items	<FJL 26Jan87>;---------------------------------------; Paint the item with gray.  Speed up is about 20%!!;;	On Entry:	D4		item number;BitClearItem			movem.l	d3/d7, -(sp)		; save work registers			TST.B	ITEMICON(A4)		; does it have an icon?			BEQ.S	@1					; skip if it doesnt			MOVE.W	D7,D0				; get delta height			LSR.W	#1,D0				; divide by 2			SUB.W	D0,D7				; and get remainder			ADD		D7,D3				; bump the rest of the difference for icon@1			ADD	MFHeight(A6),D3	; bump to next baseline			LEA		TEMPRECT,A0			; get pointer to temporary rectangle			MOVE.L	MMenuRect(a6), A1	; get pointer to menu rect			MOVE.L	(A1),(A0)			; copy menuRect into tempRect			MOVE.L	4(A1),4(A0)			SUB		MAscent(A6), D3		; move up by the fon't ascent to get bottom of item			MOVE	D3, Bottom(A0)		; store as bottom			Bsr		GetItemHeightA4		; get item height into D0				<FJL PMAB205>			Sub.W	D0, D3			lea		TempRect,a0			; get rectangle in A0					<1.7>			MOVE	D3,top(a0)			; D3 has the height						<1.6> <1.7>			BSR		GRAYRECT			; bit clear tempRect with gray@ClearDone			movem.l	(sp)+, d3/d7		; restore work registers			rts;---------------------------------------;	Utility -- SetScriptFont;---------------------------------------; Input		d0:		script number;; set the script's base font.  No need to check if script manager is installed; since AddResMenu has already done that;SetScriptFont			clr.l		-(sp)				; make room for long result;;			clr			d0					; clear lo-word;;			move.b		itemIcon(a4), d0	; get script number; make d0 an argument, the script number									<S422	08Mar88 MED>			and.w		#$00FF,d0			; get bottom byte for script	<S422	08Mar88 MED>			move		d0, -(sp)			; push script number			move		#smScriptSysFond, -(sp)	; push base font verb			_GetScript			move.l		(sp)+, d0			; get result			blt.s		@verbErr			; verb error if d0 < 0			move		d0, -(sp)			; push font number			_TextFont@verbErr	rts;---------------------------------------;	Utility -- BlitHierArrow;---------------------------------------; Blit up the hierarchical arrow;BlitHierArrow			movem.l	a3/d4, -(sp)			; store work registers; calculate where arrow should go			subq	#4, sp			move.l	sp, -(sp)				; reserve space on stack for result			_GetPen			move.l	(sp)+, d4				; get y,x			swap	d4						; get x,y			sub		MAscent(a6), d4			; move up by the fon't ascent to get top of item			swap	d4						; have top, left of where will blit arrow			move.l	d4, HierArrowRect(a6)	; store top, left			move.l	d4, HierArrowRect+4(a6)	; calculate bottom, right			move	MFHeight(a6), d4		; get height			cmpi	#16, d4					; make height/width = 16 unless smaller than 16.<FJL PMAB205>			ble.s	@1			move	#16, d4@1			add		d4, HierArrowRect+Bottom(a6); bottom = top + height			add		d4, HierArrowRect+Right(a6)	; right = left + width; create bitMap for arrow			moveq	#bitMapRec, d0			; alloc bitmap for 16Vert x 16Horiz x 1Deep bit map			_NewHandle			_HLock			move.l	(a0), a3				; dereference			move	#2, rowBytes(a3)		; 16 x 1 bits wide			move.l	#$00000000,bounds(a3)	; top = 0, left = 0			move.l	#$00100010,bounds+4(a3)	; bottom = 0, right = 0			lea		HierArrow, a1			; get mask data address			move.l	a1, baseAddr(a3)		; store it; get current portRectCommonBlit	subq	#4, sp			move.l	sp, -(sp)				; make space on stack for return			_GetPort			move.l	(sp)+, a0				; get port; copy from the bitMap into the port			move.l	a3, -(sp)				; push src bitMap ptr			pea		portBits(a0)			; push dest pointer (for the screen)			pea		bounds(a3)				; push src bounds rect			pea		HierArrowRect(a6)		; push dest bounds rect			move	#srcOr, -(sp)			; srcOr			clr.l	-(sp)					; no maskRgn			_CopyBits			move.l	a3, a0					; get bitMap ptr			_RecoverHandle					; get bitMap handle			_DisposHandle					; and toss it			movem.l	(sp)+, a3/d4			; restore work registers			rts;---------------------------------------;	Utility -- GetItemRecord;---------------------------------------;	GetItemRecord is the main utility used for accessing the menu item data structure.;	It has a register interface to save code.  On entry, A0 points to a menuInfo block,;	while D0 has the item number of interest.  On exit, A0 points to the item string;	of interest while A1 points to that item's attribute byte list.  If the item can't;	be found, A0 and A1 both return NIL.;; TODO:	If this is called inside a loop, then we have a factorial function!!;		Therefore look where this is called from and see if we can't be smarter about;		how to move thru the menulistGETITEMRECORD			TST D0						; make sure item number is valid			BLE.S	NOITEM				; if it's not, don't bother;			MOVEQ	#0,D1				; clear D1 for byte arithmetic			LEA		MENUDATA(A0),A1		; get menuData handle			MOVE.B	(A1)+,D1			; get title length			ADD		D1,A1				; skip over title string;; here is the item search loop.  A1 points to the beginning of the next item.;GETILOOP	SUBQ	#1,D0				; is this the one we're looking for?			BEQ.S	GOTITEM				; if so, we got it			MOVE.B	(A1)+,D1			; get length of current item			BEQ.S	NOITEM				; length zero marks end of list;			ADDQ	#4,D1				; there are 4 bytes of item properties			ADD		D1,A1				; bump to next item			BRA.S	GETILOOP			; loop till done;;	the item couldn't be found so return NIL;NOITEM		SUB.L	A0,A0				; zero A0			MOVE.L	A0,A1				; and A1 too			MOVE.L	A0,D0				; and set the z-flag			CLR.L	lastItemStrPtr(A6)	; <KSM/RLC	31May89>			CLR.L	lastAttrPtr(A6)		; <KSM/RLC	31May89>			RTS							; return to caller;; we found the item so return a pointer to it in A0 and a pointer to the item properties; in A1;GOTITEM		TST.B	(A1)				; is this the NIL item?			BEQ.S	NOITEM				; if so, we really didn't get one;			MOVE.L	A1,A0				; A0 points to item string			MOVE.B	(A1)+,D1			; get length			ADD		D1,A1				; bump to item properties			MOVE.L	A0,lastItemStrPtr(A6)	; <KSM/RLC	31May89>			MOVE.L	A1,lastAttrPtr(A6)		; <KSM/RLC	31May89>			RTS							; return to caller;----------------------------------------------------------------------------------------;;	Msg #2 -- Calc Menu Size;;----------------------------------------------------------------------------------------; Calculate the menu size for the given text menu.  The handle is in A3.;; DONE: <FJL PMAB205> Menus with icons did not show scroll arrows properly after you had;						scrolled all the way up, then start to scroll down again.  The reason;						was that the menu height is not an even multiple of MFHeight.;						This code returns an even multiple of MFHeight if the menu scrolls.DoCalcMsg		IF forRAM THEN			SUBQ	#4,SP			MOVE.L	SP,-(SP)				; point to top of stack			_GetPort						; get the current port;			CMP.W	#$3FFF, ROM85			; color machine ?							<PMAB364	23Jan88	EMT>			TST.B	onColorMachine(A6)		; color machine ?							<S394	12Feb88	DBG>			BEQ.S	@SetBWPort				;											<PMAB364	23Jan88	EMT>			MOVE.L	WMgrCPort, -(SP)		; get color port							<PMAB364	23Jan88	EMT>			BRA.S	@SetPort				;											<PMAB364	23Jan88	EMT>@SetBWPort									;											<PMAB364	23Jan88	EMT>			MOVE.L	WmgrPort,-(SP)			; push the wmgr port, do not use color port here.@SetPort									;											<PMAB364	23Jan88	EMT>			_SetPort						; set it									<PMAB364	23Jan88	EMT>		ENDIF	; if forRAM; since calc msg could be called at any time, we need to reset the wmgr's textfont here else; could get incorrectly sized menus			clr		-(sp)					; clear stack for TextFont					<FJL CXXX>			_TextFont						; use system font in menus					<FJL CXXX>			bsr		GetSizes				; get font sizes from wmgr port				<FJL CXXX>			SUBQ.L	#4, SP					;											<PMAB364	23Jan88	EMT>			MOVE.L	SP, -(SP)				;											<PMAB364	23Jan88	EMT>			_GetPort						; Get the current port						<PMAB364	23Jan88	EMT>			MOVE.L	(SP)+, A0				; Put it in A0								<PMAB364	23Jan88	EMT>;			MOVE.L	WMgrPort,A0				; get the port								<27Sep85>			MOVE.W	PortRect+bottom(A0),D5	; get the screen bottom						<27Sep85>			SUB.W	portRect+top(A0), D5	; subtract the top							<S476	22Apr88	EMT>; the maximum size for a menu is screen height minus menubar height minus a fudge factor.GetMBHeight			TST.W	ROM85					; running on new roms?						<EHB 26Aug85>			BMI.S	@0						; => no, use old menubar height				<EHB 26Aug85>			SUB.W	MBarHeight,D5			; get what low memory says					<EHB 5Aug85>			BNE.S	@1						; => it's a good height						<EHB 5Aug85>@0			SUB.W	#20,D5					; else stuff default height					<EHB 5Aug85>@1			sub		#16, d5					; hierarchical menus need a little more margin	<FJL C222>; make d5 an even multiple of MFHeight so that scrolling with different sized items	<FJL PMAB205>; will work properly.;+++			dc.w	$a9ff;+++			Divu	MFHeight(A6), d5	; (max menu height) div (MFHeight);+++			Move	D5,D6				; get quotient;+++			MoveQ	#0,D5				; clear D5;+++			Move	D6,D5				; return quotient;+++			Mulu	MFHeight(A6), D5	; max menu height = MFHeight x quotient			MOVEQ	#0,D6				; set initial <height,width> to 0			MOVEQ	#1,D0				; find item 1			MOVE.L	(A3),A0				; point to the menuRecord			BSR.S	GetItemRecord		; point to first item			BEQ		DoCalcDone1			; if zero, we're done							<EHB 10-Apr-85>			MOVE.L	A0,A4				; keep pointer in A4;; here is the main loop of calcMenuSize.  Process each item one at a time, keeping the; height and maximum width in D6;CMLOOP			MOVEQ	#0,D7				; set "extra" width to zero			MOVE.L	(A3),A0				; handle -> pointer			MOVEQ	#0,D0				; clear out high part			MOVE.B	(A4),D0				; get length of item			BEQ		DoCalcDone			; if zero, we're done with this menu			LEA		1(A4,D0),A1			; point A1 at the properties; handle the vertical			BSR		GetItemHeight		; get height of item into D0			SWAP	D1					; Get width of icon into low word			<S550	27Jul88	EMT>			MOVE.W	D1, D7				; Copy width into D7						<S550	27Jul88	EMT>			ADD.W	MSpaceWidth(A6), D7	; Add in width of a single space			<S550	27Jul88	EMT>;			cmpi.b	#ScriptMenuCmd, itemCmd(a1)	; is there a script defined?	<FJL CXXX>;			beq.s	@0					; yes, icon field stores scriptID		<FJL CXXX>;;			TST.B	ITEMICON(A1)		; is there an icon for this item?;			BEQ.S	@0					; if not, don't adjust height;			MOVEQ	#40,D7				; add 40 to width for icons;			MOVEQ	#36,D0				; and 36 to height for icons			<27Sep85>;;			Cmpi.B	#ShrunkenIconCmd, itemCmd(A1)	; is there a shrunken icon?	<FJL PMAB205>;			Beq.s	@NewWidth			; yes	-> different width;			Cmpi.B	#SmallIconCmd, itemCmd(A1)	; is there a small icon ?;			Bne.S	@0					; no	-> branch;@NewWidth	MoveQ	#20, D7				; yes -> width is half size of regular icon;			Bsr		GetItemHeight		;		get height into D0@0			SWAP	D6					; get vertical into low word				<27Sep85>			ADD.W	D0,D6				; increment vertical height					<27Sep85>			CMP.W	D5,D6				; past bottom of screen?					<27Sep85>			BLT.S	@1					; => no										<27Sep85>			SUB.W	D0,D6				; yes, don't make menu taller				<27Sep85>; handle the horizontal@1			SWAP	D6					; but get vertical in high first			<27Sep85>			MOVE.W	MWidMax(A6),D1		; get char width							<1Aug85>			ADD.W	D1,D7				; add once for mark							<1Aug85>			cmpi.b	#ScriptMenuCmd, itemCmd(a1)	; is there a script defined?		<FJL CXXX>			beq.s	@2					; yes, then no command						<FJL CXXX>			cmpi.b	#ShrunkenIconCmd, itemCmd(a1) ; is there a shrunken icon?		<FJL PMAB239>			beq.s	@2					; yes, then no command						<FJL PMAB239>			cmpi.b	#SmallIconCmd, itemCmd(a1)		; is there a small icon defined?	<FJL PMAB239>			beq.s	@2					; yes, then no command						<FJL PMAB239>			TST.B	ITEMCMD(A1)			; is there a commmand?			BEQ.S	@2					; if not, skip			ADD.W	D1,D7				; add twice for command equivalent			<1Aug85>			ADD.W	D1,D7				;											<1Aug85>			ADD.W	#8,D7				; plus an eight pixel margin				<1Aug85>@2			MOVEQ	#0,D1				; clear out high byte			MOVE.B	ITEMSTYLE(A1),D1	; get style setting@3			MOVE.W	D1,-(SP)			; push the style			_TextFace					; tell LisaGraf about new style;; If there is a script defined for this item, then set font for proper string width calc,; do calc, and restore font to #0.;			cmpi.b	#ScriptMenuCmd, itemCmd(a1)	; is there a script defined?	<FJL CXXX>			bne.s	@NoScript			; yes, icon field stores scriptID		<FJL CXXX>;;			clr		d0					; clear it out							<FJL CXXX>;;			move.b	itemCmd(a1), d0		; get scriptID							<FJL CXXX>;;			mulu	#512, d0			; calculate font num = ID*512-512+$4000	<FJL CXXX>;;			addi	#$3C00, d0			;										<FJL CXXX>;;			move	d0, -(sp)			; push font num							<FJL CXXX>;;			_TextFont					; and set font							<FJL CXXX>; use utility routine for setting the font from the script			move.b	itemIcon(a1), d0	; pass script number					<S422	08Mar88 MED>			bsr		SetScriptFont		; set TextFont according to script		<S422	08Mar88 MED>						clr		-(sp)				; make room for StringWidth result		<FJL CXXX>			move.l	a4, -(sp)			; move string pointer					<FJL CXXX>			_StringWidth				; find out the width					<FJL CXXX>			clr		-(sp)				; restore font to normal				<FJL CXXX>			_TextFont					;										<FJL CXXX>			bra.s	@ContCalc			; and continue with the calculation		<FJL CXXX>@NoScript	CLR		-(SP)				; make room for stringWidth result			MOVE.L	A4,-(SP)			; move string pointer			_StringWidth				; find out the width@ContCalc	ADD.W	(SP)+,D7			; add width to extra			CMP		D7,D6				; compare with maxWidth			BGE.S	CALCNEXT			; if max is bigger, go process next one			MOVE	D7,D6				; this one was the biggest;; go process next item; loop till we get a null one;CALCNEXT			MOVEQ	#0,D0				; zero high part			MOVE.B	(A4),D0				; get the length of current item			LEA		5(A4,D0),A4			; point to the next item			BRA		CMLOOP				; loop till done;	we've scanned all the items update menuHeight and menuWidthDoCalcDone	ADDQ.W	#4,D6				; add some extra for right marginDoCalcDone1								; if NIL menu, return 0				<EHB 10-Apr-85>; Ensure that the menu is not too wide.			SUBQ.L	#4, SP					;											<PMAB364	23Jan88	EMT>			MOVE.L	SP, -(SP)				;											<PMAB364	23Jan88	EMT>			_GetPort						; Get the current port						<PMAB364	23Jan88	EMT>			MOVE.L	(SP)+, A0				; Put it in A0								<PMAB364	23Jan88	EMT>			MOVE.W	portRect+Right(A0), D0	; Get right edge							<PMAB364	23Jan88	EMT>			SUB.W	portRect+Left(A0), D0	; Subtract left edge to get width			<PMAB364	23Jan88	EMT>			SUB.W	#16, D0					; Subtract a little more for margin			<PMAB364	23Jan88	EMT>			CMP.W	D0, D6					; Is menu too wide?							<PMAB364	23Jan88	EMT>			BLE.S	@1						; Nope, move along							<PMAB364	23Jan88	EMT>			MOVE.W	D0, D6					; Too wide, clip its wings					<PMAB364	23Jan88	EMT>@1											;											<PMAB364	23Jan88	EMT>			MOVE.L	(A3),A0					; get menu pointer			MOVE.W	D6,MENUWIDTH(A0)		; update menu width			SWAP	D6; if menu is taller than max allowable (which is now an even multiple of MFHeight)	<FJL PMAB205>; then make it equal to the max allowable.;+++			Cmp.W	D5,D6				; too tall ?;+++			Blt.S	@SizeOK				; => no;+++			Move.W	D5,D6				; yes, make it equal to max allowable@SizeOK			MOVE.W	D6,MENUHEIGHT(A0)		; update menu height			CLR.W	-(SP)					; better restore style to normal			_TextFace						; set the style		IF forRAM THEN			_SetPort						; restore original grafPort					<PMAB364	23Jan88	EMT>		ENDIF	; if forRAM			rts								; all done! so return to dispatcher;----------------------------------------------------------------------------------------;;	Msg #3 -- Calc TopMenuItem and MenuRect so that the top of PopUpItem is at TopLeft;;----------------------------------------------------------------------------------------; Begin by calculating how far the top of WhichItem is from the top of the menu.; Then place the menu.  The various possibilities are:;	1. The whole menu fits on the screen and PopUpItem lines up with TopLeft;	2. The whole menu fits on the screen and PopUpItem cannot line up with TopLeft without;		causing the menu to scroll.  In this case adjust menuRect so that complete menu is;		is on the screen, but PopUpItem is as close to TopLeft as possible.;	3. The whole menu is not on the screen.  In this case adjust the menuRect so that as much;		of the menu is showing as possible on the screen, and position PopUpItem so that;		it is showing and as close as possible to TopLeft.;; Return the MenuRect and TopMenuItem.  TopMenuItem is returned in the VAR PopUpItem param.;;; Historical Note:	It would be desireable to have popups change vertical size as they scrolled,;					instead of having all that white space when the scrolling menu is first;					displayed.  The reason for this is due to the design of the MBDF.;					The MBDF saves the bits behind and draws the drop shadow at the same;					time.  If there were two messages instead, one to save the bits behind;					and one to draw the drop shadow, the we could save all of the bits behind;					the menurect, from the top of the screen to the bottom, and then change;					the menu's vertical height without worrying about saving more bits each;					time it got bigger.  But we can't, so...;;	<FJL PMAB205> Pass PopUpItem = 0 and force top of menuRect to Top parameterDoPopUpItemMsg			BSR		GetSizes			; get font info into the stack			MOVE.L	MPopUpItem(A6), A4	; get ptr to PopUpItem			MOVE	(A4), D3			; store item in D3			CLR		D2					; top of menu starts at zero			CLR		D6					; ditto;+++			Tst.W	D3					; item == 0 ?						<FJL PMAB234><FJL PMAB276>;+++			Beq.S	@LoopComplete		; yes -> special case				<FJL PMAB234><FJL PMAB276>				MOVEQ	#1, D4				; start with first item@Loop		CMP	D3,D4					; have we reached the PopUpItem yet?			BGT.S	@1					; no ==> continue calculating			<FJL PMAB205><FJL PMAB234>			MOVE	D6, D2				; yes ==> save item's vertical in D2, and continue;; We didn't reach it yet, so get the height and keep stepping down.;@1			MOVE.L	(A3),A0				; get menuPtr			MOVE	D4,D0				; get item number			BSR		GetItemRecord		; look it up			BEQ.S	@LoopComplete		; if item not found then must be end of item list			BSR		GetItemHeight		; get item height in D0			ADD		D0,D6				; update vertical			ADDQ	#1,D4				; bump to next item			BRA.S	@Loop				; loop till we get to end of item list; If we couldn't find the item then default to item number 1@LoopComplete			TST		D2					; is D2 still zero ?			BNE.S	@GotItem			; no ==> got the item, and it's vertical is in D2			MOVEQ	#1, D4				; yes ==> couldn't find item, use item #1; Distance from top of menu to top of PopUpItem is now in D2.@GotItem	MOVE.L	(A3), A0			; get menu ptr			TST.L	MenuWidth(A0)		; is the size valid?			BPL.S	@SkipCalcSize		; yes, so no need to recalc (oooohhhh, recursion)			MOVE.L	D2, -(SP)			; Save D2 around call <S171 DBG&JTC 08Apr87>			MOVE.L	A3, -(SP)			; push menu handle			_CalcMenuSize				; get valid height and width			MOVE.L	(SP)+, D2			; Restore D2 <S171 DBG&JTC 08Apr87>@SkipCalcSize;; First check if menu has to scroll, i.e. its height is larger than the screen size; minus 8 pixels of slop.  <FJL PMAB205, no longer include menubar height in this calc>;; Register Usage:-- A0		menuRect ptr;					A1		port ptr;					A2		menu ptr;					A3		menu handle;					A4		PopUpItem ptr;				-- D2		Distance from top of menu to PopUpItem;					D3		PopUpItem;					D4		TopMenuItem;					D5		Desired top of PopUpItem, the "Top" in MLeftTop;					D6		Total menu height, including all menu items;			SUBQ	#4, SP				; get current portRect			MOVE.L	SP, -(SP)			; make space on stack of return			_GetPort			MOVE.L	(SP)+, A1			; put port in A1			MOVE.L	MMenuRect(A6), A0	; put ptr to menuRect in A0			MOVE.L	(A3), A2			; put menu ptr in A2			MOVE	MLeftTop+2(a6), D5	; put desired Top of PopUpItem in D5			MOVE	D5, D4				; put TopMenuItem = D5 - D2 in D4			SUB		D2, D4			Cmpi.w	#0, D3				; is PopUpItem = 0 ?					<FJL PMAB205>			Bne.s	@StdPopUp			; no	-> branch			Move	portRect+Bottom(A1),D0	; calc max allowable menu height = bottom of			Sub		D5, D0					;	screen - 8 - Top of PopUpItem			Sub		#8, D0			Cmp		D6, D0				; is max allowable menu height < total menuHeight ?			Blt.s	@HasToScroll			Bra.S	@WontScroll@StdPopUp	MOVE	portRect+Bottom(A1),D0	; calculate max allowable menu height based on			SUB		portRect+Top(A1), D0	;	screen height - 8 pixels of slop			SUB		#8, D0			CMP		D6, D0				; is max allowable menu height < total menuHeight ?			BLT.S	@HasToScroll		; yes ==> has to scroll;-------------------------------------------------------------------------------------------------; If here, then the complete menu WILL fit on the screen;-------------------------------------------------------------------------------------------------; Check the following possibilities:;	1. Top and bottom are both on the screen ==> leave it alone, PopUpItem and TopLeft will match;	2. Top is on screen, bottom is not ==> move bottom of menurect up until it is at least;			5 pixels above the bottom of the screen.  Leave TopMenuItem alone;	3. Bottom is on screen, top is not ==> move top of menurect down until it is at least;			5 pixels below the top of the screen.  Leave TopMenuItem alone@WontScroll	MOVE	D4, Top(A0)			; assume TopMenuItem, and top and bottom of menu are ok			MOVE	D4, (A4)			; return TopMenuItem in VAR PopUpItem			MOVE	D4, Bottom(A0)			ADD		D6, Bottom(A0)			MOVE	portRect+Top(A1),D0	; get the top of the screen			ADD		MBarHeight, D0		; move down 2 pixels from menubar			ADD		#2, D0			CMP		D0, D4				; is TopMenuItem < 2 pixels below menu bar?			BGE.S	@ChkBottom			; no ==> therefore Top is ok										; yes ==> therefore move top down by multiple of MFHeight										;			until we get at least 2 pixels below the menu bar			MOVE	D4, D1				; start at TopMenuItem@TopLoop	ADD		MFHeight(a6), D1	; move down to next item			CMP		D0, D1				; is top of menu >= 2 pixels below menu bar?			BLT.S	@TopLoop			; no	==> haven't moved top down far enough yet			MOVE	D1, Top(A0)			; yes ==> store new top			ADD		D6, D1			MOVE	D1, Bottom(A0)		; store bottom of menu			BRA.S	@AdjustLeftRight	; do left/right adjustment						<PMAB364	23Jan88	EMT>@ChkBottom	MOVE	D4, D0				; find bottom of menu = TopMenuItem + total menu height			ADD		D6, D0			MOVE	portRect+Bottom(A1),D1	; calc bottom of screen - 5 pixels			SUB		#5, D1			CMP		D1, D0				; is Bottom of menu > 5 pixels above screen bottom ?			BLE.S	@AdjustLeftRight	; no ==> therefore Bottom is ok too				<PMAB364	23Jan88	EMT>										; yes ==> move bottom up by multiple of MFHeight until										;			we get at least 5 pixels above the screen bottom@BotLoop	SUB		MFHeight(a6), D0	; move up to next item			CMP		D1, D0				; is bottom of menu <= 5 pixels above screen bottom ?			BGT.S	@BotLoop			; no	==> haven't moved bottom up far enough yet			MOVE	D0, Bottom(A0)		; store bottom			SUB		D6, D0				; calc top of menu			MOVE	D0, Top(a0)			BRA.S	@AdjustLeftRight	; do left/right adjustment						<PMAB364	23Jan88	EMT>;-------------------------------------------------------------------------------------------------; If here then the complete menu WILL NOT fit on the screen;-------------------------------------------------------------------------------------------------; Leave TopMenuItem alone, but calculate where menurect should go so that when the items scroll; they fill up the menu exactly, i.e. as the menu is scrolled, TopMenuItem will match the; top of the menu rect at some point exactly.  If we don't do this there may be strange; behavior when the menu is scrolled completely down, i.e. the top item is showing.;; If PopUpItem = 0 then force top of menu to be at Top/Left			<FJL PMAB205>;;@HasToScroll			MOVE	D4, (A4)			; return TopMenuItem in VAR PopUpItem			Move	D4, D1				; set up D1								<FJL PMAB205>			Move	D1, Top(A0)			; assume PopUpItem = 0 and store Top of menuRect			Cmpi.w	#0, D3				; is PopUpItem = 0 ?			Beq.s	@CalcBottom			; yes	-> branch and only calc the bottom of the rect			MOVE	portRect+Top(a1), D0; calc 2 pixels below the top of the screen <FJL PMAB205>			ADDQ	#2, D0				;			CMP		D0, D4				; is TopMenuItem >	2 pixels below top of screen?			BLE.S	@CalcBelow			; no	==> branch and calc top of menuRect as										;			(MFHeight x N) **BELOW** TopMenuItem										; yes ==> fall thru and calc top of menuRect as										;				(MFHeight x N) **ABOVE** TopMenuItem;; Start at TopMenuItem, and move **UP** by increments of MFHeight until we reach at;	least 2 pixels below the menubar.;			MOVE	D4, D1				; start at TopMenuItem@UpLoop		SUB		MFHeight(a6), D1	; move up one MFHeight			CMP		D0, D1				; is top of menu rect < 2 pixels below the menubar ?			BGE.S	@UpLoop				; no	==> keep moving up			ADD		MFHeight(a6), D1	; yes ==> force top of menurect to be on the screen			MOVE	D1, Top(a0)			; store top of menurect			BRA.S	@CalcBottom			; calc bottom of menurect;; Start at TopMenuItem, and move **DOWN** by increments of MFHeight until we reach at;	least 2 pixels below the menubar.;@CalcBelow	MOVE	D4, D1				; start at TopMenuItem@DownLoop	ADD		MFHeight(a6), D1	; move down one MFHeight			CMP		D0, D1				; is top of menu rect >= 2 pixels below the menubar ?			BLT.S	@DownLoop			; no	==> keep moving down			MOVE	D1, Top(a0)			; store top of menurect;; Start at top of menurect and move down by multiples of MFHeight until the bottom of the;		menurect is about 5 pixels above the screen bottom.  This makes the menurect an exact;	multiple of MFHeight.;@CalcBottom	MOVE	portRect+Bottom(a1), D0	; calc 5 pixels above screen bottom			SUBQ	#5, D0@BotLoop2	ADD		MFHeight(a6), D1	; move down by one MFHeight			CMP		D0, D1				; is bottom of menurect > 5 pixels above screen bottom ?			BLE.S	@BotLoop2			; no	==> keep moving down			SUB		MFHeight(a6), D1	; yes ==> force bottom of menurect onto the screen			MOVE	D1, Bottom(a0)		; store bottom of menuRect;-------------------------------------------------------------------------------------------------; Now adjust menuLeft and menuRight if menu hangs over left or right edge of the screen.;-------------------------------------------------------------------------------------------------@AdjustLeftRight			MOVE	MLeftTop(A6), D0	; get left edge			MOVE.W	portRect+Left(A1), D2	; Get left edge of screen					<PMAB364	23Jan88	EMT>			ADDQ.W	#4, D2				; Leave room for border							<PMAB364	23Jan88	EMT>			CMP.W	D2, D0				; Compare with left edge of screen				<PMAB364	23Jan88	EMT>			BGE.S	@TryRight			; If greater, it's OK							<PMAB364	23Jan88	EMT>; Adjust so the menu fits on the screen.			MOVE	D2, D0				; make left edge equal to (fake) screen edge	<PMAB364	23Jan88	EMT>@TryRight			MOVE.W	D0, D1				;												<PMAB364	23Jan88	EMT>			ADD.W	MenuWidth(A2), D1	; calc right edge								<PMAB364	23Jan88	EMT>			MOVE.W	portRect+Right(A1), D2	; Get right edge of screen					<PMAB364	23Jan88	EMT>			SUBQ.W	#4, D2				; Leave room for border							<PMAB364	23Jan88	EMT>			CMP.W	D2, D1				; Compare with right edge of screen				<PMAB364	23Jan88	EMT>			BLE.S	@StoreLeftRight		; if smaller, we're cool; Adjust so the menu fits on the screen.			MOVE	D2, D1				; make right edge equal to (fake) screen edge	<PMAB364	23Jan88	EMT>			MOVE.W	D1, D0				;												<PMAB364	23Jan88	EMT>			SUB.W	menuWidth(A2), D0	; left = right - menuWidth						<PMAB364	23Jan88	EMT>@StoreLeftRight			MOVE.W	D0, Left(A0)		; store left									<PMAB364	23Jan88	EMT>			MOVE.W	D1, Right(A0)		; store right									<PMAB364	23Jan88	EMT>			RTS;----------------------------------------;	Utility -- SaveCurrentColors											<FJL C408>;----------------------------------------; Save the current fore/back colors in the stackframe.; Get the device's pixel depth in the stackframe too.; Only need to save if color machineSaveCurrentColors;>>>>>------------- NuMac ------------------>>>>>;+++		IF	onNuMac THEN			tst.b	onColorMachine(a6)			beq.s	@SaveEnd			pea		saveForeColor(a6)	; push location to save fore color			pea		saveBackColor(a6)	; push location to save back color			_GetBackColor				; and get 'em			_GetForeColor			SUBQ	#4,SP			MOVE.L	SP,-(SP)				; point to top of stack			_GetPort						; get the current port			move.l	(sp)+, a0			subq	#4, sp					; space for GDHandle return			pea		portRect(a0)			; draw menus on main screen			_GetMaxDevice					; get max pixel device			MOVE.L	(sp)+, A0				; get the grafDevice			MOVE.L	(A0),A0					; hndl->ptr			MOVE.L	GDPMap(A0),A1			; get the device's pixmap			MOVE.L	(A1),A1					; hndl->ptr			move.w	pixelSize(a1), PixelDepth(a6)	; and store the value;+++		ENDIF@SaveEnd;<<<<<--------------------------------------<<<<<			rts;----------------------------------------;	Utility -- ResetPreviousColors											<FJL C408>;----------------------------------------; Restore the fore/back colors from those saved; in the stackframe in SaveCurrentColors.; Need to reset on both color and b/w machines.  Assume b/w machine always have; black on white.ResetPreviousColors;>>>>>------------- NuMac ------------------>>>>>;+++		IF	onNuMac THEN			tst.b	onColorMachine(a6)			beq.s	@ResetBW			pea		saveForeColor(a6)	; push location of saved fore color			pea		saveBackColor(a6)	; push location of saved back color			_RGBBackColor			_RGBForeColor			bra.s	@ResetEnd;+++		ELSE							;===============================================@ResetBW			moveq	#BlackColor, d0		; always reset to black on white			move.l	d0, -(sp)			_ForeColor			moveq	#WhiteColor, d0			move.l	d0, -(sp)			_BackColor;+++		ENDIF;<<<<<--------------------------------------<<<<<@ResetEnd			rts;----------------------------------------;	Utility -- SetColors													<FJL C408>;----------------------------------------;; On Entry:		A3					MenuHandle;				D4					Item Number;				colorOffset(a6)		Offset into menu color table indicating mark/text/cmd; Used:		A0, D1SetColors;>>>>>------------- NuMac ------------------>>>>>;+++		IF	onNuMac THEN			tst.b	onColorMachine(a6)			beq		@SetBW			cmpi.w	#2, PixelDepth(a6)	; is this 2+ mode and color ?			blt.s	@SetDefault			; if 1 bit mode then use Black/White only			tst		invertFlag(a6)		; normal or inverted colors ?			beq.s	@1					; 0 = normal colors, so branch; for inverted menu colors always invert the background color with the item name's color			move	#mctRGB2, colorOffset(a6)@1			subq	#4, sp				; save space for result			move.l	(a3), a0			; get menu ptr			move	menuID(a0), -(sp)	; push ID			move	d4, -(sp)			; push Item			_GetMCEntry					; get item's color entry			move.l	(sp)+, d1			; get the result, and set/un-set z-flag			beq.s	@TryTitleEntry		; couldn't find item entry so try title entry			move.l	d1, a0				; get color record ptr in A0			move	colorOffset(a6), d0	; offset for mark/cmd/char			pea		(a0, d0)			; push foreground color			pea		mctRGB4(a0)			; push background color			bra.s	@DoTheSet			; branch to do actual color setting@TryTitleEntry			subq	#4, sp				; save space for result			move.l	(a3), a0			; get menu ptr			move	menuID(a0), -(sp)	; push ID			clr		-(sp)				; Item = 0 ===> title entry			_GetMCEntry					; get title's color entry			move.l	(sp)+, d1			; get the result, and set/un-set z-flag			beq.s	@TryMenuBarEntry	; couldn't find title entry so try menu bar entry			move.l	d1, a0				; get color record ptr in A0			move	#mctRGB3, d0		; offset for items default color			pea		(a0, d0)			; push foreground color			pea		mctRGB4(a0)			; push background color			bra.s	@DoTheSet			; branch to do actual color setting@TryMenuBarEntry			subq	#4, sp				; save space for result			clr.l	-(sp)				; ID = 0, Item = 0 ===> menu bar entry			_GetMCEntry					; get menu bar's color entry			move.l	(sp)+, d1			; get the result, and set/un-set z-flag			beq.s	@SetDefault			; couldn't find menu bar entry so use black/white			move.l	d1, a0				; get color record ptr in A0			move	#mctRGB3, d0		; offset for items default color			pea		(a0,d0)				; push foreground color			pea		mctRGB2(a0)			; push background color			bra.s	@DoTheSet			; and branch to do the actual color setting@SetDefault			pea		RGBBlack			; use black as default forecolor			pea		RGBWhite			; use white as default background color@DoTheSet	tst		invertFlag(a6)		; normal or inverted colors ?			beq.s	@2					; 0 = normal colors, so branch			_RGBForeColor				; set fore/back colors			_RGBBackColor			bra.s	@SetColorsDone@2			_RGBBackColor				; set back/fore colors			_RGBForeColor			bra.s	@SetColorsDone;+++		ELSE							;===============================================@SetBW			moveq	#BlackColor, d0			move.l	d0, -(sp)			moveq	#WhiteColor, d0			move.l	d0, -(sp)			tst		invertFlag(a6)		; normal or inverted colors ?			beq.s	@3					; 0 = normal colors, so branch			_ForeColor			_BackColor			bra.s	@SetColorsDone@3			_BackColor			_ForeColor;+++		ENDIF;<<<<<--------------------------------------<<<<<@SetColorsDone			rts;-----------------------------------------------------------------------------------------------; PROCEDURE PlotAnySizeIcon(theRect: Rect; theIcon: IconHandle; iconSize: Point;;							rowBytes: Integer)										<FJLPMAB205>;;	Plots a given icon of arbitrary size at a given place in your local coordinate system.;PlotAnySizeIcon				LEA		ICONBITMAP,A1			;get address of icon mgr bitMap				MOVE.L	10(SP),D0				;get the icon handle				BEQ.S	DONEIPLOT				;if NIL, dont plot				MOVE.L	D0,A0					;get iconHandle in address reg;				MOVE.L	(A0),(A1)+				;icon mptr is the base address				MOVE	4(sp),(A1)+				;set up rowBytes				CLR.L	(A1)+					;set up topLeft				MOVE.L	6(SP),(A1)				;set up botRight;				MOVE.L	14(SP),D1				;get theRect				LEA		IconBitMap,A1			;point A1 at bitmap again;; push parameters for copyBits call;				MOVE.L	A1,-(SP)				;source bitMap is iconBitMap				MOVE.L	GrafGLOBALS(A5),A0		;get lisaGraf global baseaddress				MOVE.L	THEPORT(A0),A0			;get thePort				PEA		PORTBITS(A0)			;that's the destination bitmap;				PEA		BOUNDS(A1)				;boundsRect of bitmap is source				MOVE.L	D1,-(SP)				;theRect is the destination				CLR.W	-(SP)					;theMode is srcCopy (0)				CLR.L	-(SP)					;no mask region				_CopyBits						;let Bill blit those bitsDONEIPLOT		MOVE.L	(SP)+,A0				;get return address				ADD		#14,SP					;strip 12 bytes of parameters				JMP		(A0)					;return to caller;;--------------------------------------------------------------------------------------------;;	End of Code.  Begin Data Definitions.;;--------------------------------------------------------------------------------------------			; bounds rect for hier arrow is top=0, left=0, bottom=$10, right=$10HierArrow	DC.W	$0000, $0000, $0020, $0030, $0038, $003C, $003E, $003F			DC.W	$003E, $003C, $0038, $0030, $0020, $0000, $0000, $0000			; bounds rect for down arrow is top=0, left=0, bottom=$10, right=$10DownArrow	DC.W	$0000, $0000, $0000, $0000, $0000, $7FF0, $3FE0, $1FC0			DC.W	$0F80, $0700, $0200, $0000, $0000, $0000, $0000, $0000			; bounds rect for up arrow is top=0, left=0, bottom=$10, right=$10UpArrow		DC.W	$0000, $0000, $0000, $0000, $0000, $0200, $0700, $0F80			DC.W	$1FC0, $3FE0, $7FF0, $0000, $0000, $0000, $0000, $0000			END						; of menu defproc!!