; ; File: ButtonCDEF.a ; ; Contains: Standard Button Definition Procedure for the MacIntosh Control Manager ; This file contains the control definition procedures that define ; the standard "button" type controls. These include PushButtons, ; CheckBoxes, and a checkBox variant called RadioButton. ; ; Written by: Andy Hertzfeld August, 1982 ; ; Copyright: © 1982-1992 by Apple Computer, Inc., all rights reserved. ; ; This file is used in these builds: Mac32 HcMac MacPP BigBang Sys606 ; ; Change History (most recent first): ; ; 10/22/92 CSS Change short branches to word branches. ; <14> 4/11/91 gbm csd, KSM, BRC#86464: Fix many references to the control ; rectangle which are invalid because the control handle can be ; unlocked. ; <13> 3/4/91 dba dty: get rid of SysVers conditionals ; <12> 12/14/90 VL (ksm) Use PaintRoundRect instead of PaintRect for dithering ; text. Also, changed PenMode to TextMode since grayishTextOr is a ; text mode. ; <11> 8/23/90 SAM Removed the MoveHHi from the DrawPBut routine so that MacApp ; will work (it assumes that handles will be ok across calls to ; DrawControl -- idiots!) ; <10> 8/17/90 dvb Change grayish textMode pnMode to txMode ; <9> 8/13/90 VL Fixed test for portVersion to avoid trashing portVersion's ; value. ; <8> 8/2/90 VL Replaced SysVers switch with UseTrueGrayText (for ROM build). ; <7> 8/1/90 VL Make text to be drawn in TrueGray when disabled (in a color ; grafport). ; <6> 6/14/90 DDG NEEDED FOR SIXPACK: Moved the control manager handle with ; _MoveHHi before we lock it down while we are drawing. This ; should prevent out-of memory problems. ; <5> 5/29/90 DDG NEEDED FOR SIXPACK: Added the proper tag to the previous ; comment. ; <4> 5/29/90 DDG NEEDED FOR SIXPACK: Fix a bug where the button title is left ; unlocked for the duration of the drawing call. ; <3> 5/1/90 DDG Removed the temporary conditionals that I added for Sys605. ; <2> 3/2/90 DDG Adding conditionals for Sys605 ; <1.4> 11/17/89 dba took out checks for 64K ROMs ; <1.3> 8/22/89 SES removed references to nFiles; updated equates accordingly ; <1.2> 2/9/89 EMT added new messages for 32-bit clean Control Manager. ; <1.1> 11/11/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH adding to EASE. ; <¥1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.0> 2/12/88 BBM Adding file for the first time into EASEÉ ; 11/8/87 DAF Updated romres sources from system disk sources ; SMAB156> 3/30/87 DAF Tested ROM version before using teSysJust. ; 2/14/87 DAF Converted nuMac PaintRoundRgn to be unified with other MacsÕ ; Erase stopped setting backColor when drawing text. ; 1/26/87 DAF Universal version of ButtonCDEF.a (version 10) ; 1/14/87 DAF Changed textMode back to srcOR from srcCopy (sigh...) ; 12/21/86 DAF Added Mark DavisÕ code to allow reversed checkmarks for intl ; 11/18/86 DAF converted a BSET/BCLR to an HLock/HUnlock, in CalcPBut ; 11/16/86 DAF changed textMode (again) to srcCopy, as per CaryÕs ; recommendation ; 10/8/86 DAF updated color support on nuMac for RGBColors changed textMode to ; srcOr. ; 6/30/86 DAF added color support for nuMac (mucho chango) ; 8/26/85 EHB made variable sized fonts work (ROM85>0 only) ; 5/20/85 EHB implemented Multi-Line buttons ; 5/16/85 EHB only return "254" if point in control! ; 3/12/85 JTC changed occurrences of LGlobals to GrafGlobals ; 2/14/85 JTC added res name ; 1/14/85 JTC convert to MDS ; 12/31/83 AJH made text of checkBox/radioButtons grayed out if disabled ; 10/17/83 AJH back to "gray-out" button disabling ; 10/12/83 AJH changed button disabling ; 9/27/83 AJH made variants > 7 not force the system font ; 8/29/83 AJH fixed scrambling bug in CalcPBut ; 6/7/83 AJH fixed scrambling bug, changed check draw for new QuickDraw ; 4/4/83 AJH made it force size 12 for text ; 4/1/83 AJH made it use hardwired gray ; 3/27/83 AJH made it respect initial clip in button drawing ; 3/11/83 AJH fixed up check box drawing ; 12/28/82 AJH Put button definitions in their own file ; 11/16/82 AJH Made branch tables offset based ; 11/14/82 AJH Improved PushButton roundness scaling; removed box in arrowBits ; 10/17/82 AJH Made controlProcs preserve A1 ; 10/10/82 AJH Converted for QuickDraw Trap Interface ; 10/5/82 AJH Fixed checkBox flashing, added code saving optimizations ; 10/3/82 AJH Fixed bug in scrollBar positioning -- wasnÕt ctl relative ; 9/29/82 AJH Added CheckBox control definition procedure ; 8/29/82 AJH Added "255" hiliting, ; 8/25/82 AJH Fixed corner-clobber bug in pushButProc ; 8/22/82 AJH Added clipping, centering to PushButProc ; ; To Do: ; PRINT PUSH,OFF LOAD 'StandardEqu.d' INCLUDE 'ColorEqu.a' PRINT POP ;---------------------------------------------------------------------------------------------------- CDEF0 PROC EXPORT ; FUNCTION PushButProc( selector: INTEGER; 18 ; theControl: ControlHandle; 14 ; message: INTEGER; 12 ; param: LongInt): LongInt; 8 : 20 ; ; PushButProc is the control definition procedure for simple pushButtons, one of the ; standard control types supported by the user interface toolBox. ; And a stack frame definition CtlHndl EQU 14 ;incoming control handle param DAF SavePen EQU -20 Align EQU -21 ;a dead byte for IsColor DAF IsColor EQU -22 ;do we have colorQD and toolbox [boolean] DAF IndicatorRect EQU -30 AuxCtlHndl EQU -34 ;handle of auxCtl ColorTable DAF AuxCtlPtr EQU -38 ;ptr to auxCtl ColorTable DAF ContentRGB EQU -44 ;window content color DAF SavFgCol EQU -50 ;window portÕs RGBFgColor DAF SavBkCol EQU -56 ;window portÕs RGBBkColor DAF useGrayText EQU -58 FrameSize EQU -58 BRA.S @0 ; skip header ; standard header DC.W 0 ; flags DC.L ('CDEF') DC.W 0 DC.W 11 ; version # @0 LINK A6,#FrameSize ; set up a stack frame to address parameters DAF MOVEM.L D3-D7/A1-A4,-(SP) ; save work registers ; ; buttons only handle messages 0,1,2,10,11 <1.2> ; CMP.W #calcCtlMsg,12(A6) ; inspect message value <1.2> BLS.S @MsgOK ; if <2, itÕs OK <1.2> CMP.W #calcWholeCtlMsg,12(A6) ; <1.2> BEQ.S @MsgOK ; 10 is OK too <1.2> CMP.W #calcThumbCtlMsg,12(A6) ; <1.2> BNE DoneP1 ; And 11 <1.2> @MsgOK ; ; save the penState and set it our way ; PEA SavePen(A6) ; push pointer to savePenState _GetPenState ; remember current penState _PenNormal ; set the pen the way we want it ; Determine type of system. We need to know if we have color QuickDraw and a color ; window manager port. CMP.W #$3FFF,ROM85 ; do we have color QD? SLS IsColor(A6) ; set boolean depending on color or B&W system BHI @BWSys ; no, this system has B&W QD CSS ; save the current portÕs colors and textMode DAF MOVE.L GrafGlobals(A5),A0 ; get pointer to grafGlobals DAF MOVE.L thePort(A0),A0 ; get pointer to thePort DAF MOVE.W txMode(A0),-(SP) ; save the current text mode DAF MOVE.W #srcOR,-(SP) ; push text mode DAF _TextMode ; DAF PEA SavFgCol(A6) ; save foreColor _GetForeColor ; PEA SavBkCol(A6) ; save backColor too _GetBackColor ; ; ; get the CtlAuxRec for this guy and lock its colortable DAF ; CLR.L -(SP) ; return the handle here CLR.B -(SP) ; space for boolean func return MOVE.L CtlHndl(A6),-(SP) ; push the control handle PEA 6(SP) ; push a pointer to placeholder _GetAuxCtl ; get its auxRec ADDQ #2,SP ; donÕt need boolean result MOVE.L (SP)+,A0 ; get auxCtl handle MOVE.L (A0),A0 ; a pointer to the auxCtlRec MOVE.L acCTable(A0),A0 ; get colortableÕs handle <1.3> MOVE.L A0,AuxCtlHndl(A6) ; save the handle _HLock ; lock the handle MOVE.L (A0),AuxCtlPtr(A6) ; save a pointer ; ; get the WinAuxRec that this control is in and copy its content color to ; the stack frame. ; CLR.L -(SP) ; make a placeholder for a handle CLR.B -(SP) ; room for a boolean result MOVE.L CtlHndl(A6),A0 ; get the controlHandle again MOVE.L (A0),A0 ; get a pointer MOVE.L contrlOwner(A0),-(SP) ; push the owning window pointer PEA 6(SP) ; pointer to the placeholder _GetAuxWin ; get the window auxRec ADDQ #2,SP ; bag the boolean MOVE.L (SP)+,A0 ; get the WinAuxRec handle MOVE.L (A0),A0 ; handle->ptr MOVE.L awCTable(A0),A0 ; get the colortable handle <1.3> MOVE.L (A0),A0 ; handle->ptr MOVE.W CTSize(A0),D0 ; get the table count MULU.W #8,D0 ; get a table index @1 TST.W CTTable+value(A0,D0) ; is it wContentColor (=0)? BEQ.S @2 ; SUBQ #8,D0 ; move to previous colorSpec BGE.S @1 ; and loop back CLR.L D0 ; if not found, just use the first one @2 MOVE.L CTTable+rgb(A0,D0),ContentRGB(A6) ; copy the color over MOVE.W CTTable+rgb+4(A0,D0),ContentRGB+4(A6) ; @BWSys ; ; fetch the parameters into registers ; LEA 8(A6),A0 ; get ptr to first parameter MOVE.L (A0)+,D3 ; get param in D3 MOVE.W (A0)+,D0 ; get message MOVE.L (A0)+,A3 ; get the control handle MOVE.W (A0)+,D6 ; get selection index MOVE.W D6,D7 ; remember raw selection code AND #7,D6 ; strip high part of selection code CLR.L (A0) ; clear out function result MOVE.L (A3),A0 ; get control pointer in A0 ; ; case out on the message number ; msgAdjust EQU calcWholeCtlMsg-calcCtlMsg-1 ; So that 10 becomes 3, 11 becomes 4 <1.2> CMP.W #calcCtlMsg, D0 ; Does message need adjusting? <1.2> BLS @LoMsg ; DonÕt adjust if not. <1.2> SUBQ.W #msgAdjust, D0 ; Adjust message for address calculation <1.2> @LoMsg ADD D0,D0 ; double for word index LEA GoPushBut,A1 ; get table address ADD 0(A1,D0),A1 ; compute dispatch address JSR (A1) ; dispatch to appropriate routine ; ; clean up color stuff TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor1 ; if on B&W, then skip MOVE.L AuxCtlHndl(A6),A0 ; unlock the CDEF _HUnlock PEA SavFgCol(A6) ; restore the port colors _RGBForeColor ; PEA SavBkCol(A6) ; _RGBBackColor ; _TextMode ; restore the textMode DAF @noColor1 ; END OF A COLOR-ONLY SECTION ; ; restore original pen state ; PEA SavePen(A6) ; push savePenState _SetPenState ; restore original pen state ; ; weÕre done -- restore registers and return to caller ; DoneP1 MOVEM.L (SP)+,D3-D7/A1-A4 ; restore work registers UNLK A6 ; unlink stack frame TenBytExit MOVE.L (SP)+,A0 ; get return address ADD #12,SP ; strip parameters JMP (A0) ; return to caller ; ; PushButProc dispatch table -- entries must be long branches! ; GoPushBut DC.W DrawPBut-GoPushBut ; draw is message 0 DC.W HitPBut-GoPushBut ; hit test is message 1 DC.W CalcPBut-GoPushBut ; calc regions is message 2 DC.W CalcWholePBut-GoPushBut ; calc whole regions is message 10 <1.2> DC.W CalcThumbPBut-GoPushBut ; calc thumb regions is message 11 <1.2> ButStub RTS ; SetUpColor takes a window part identifier in D0, finds the corresponding ; part in the AuxWinTable (the part code is in the .value field) and returns ; a pointer to its RGB on the stack. If the requested part is not found, ; the first color table element is used (IÕd use frameColor, but that might ; not be there!). Trashes A0/D0. SetUpColor MOVE.L D1,-(SP) ; save a register MOVE.L AuxCtlPtr(A6),A0 ; get the color table pointer MOVE.W CTSize(A0),D1 ; get the color table size MULU #8,D1 ; convert to color table index LegalIndex CMP.W CTTable+value(A0,D1),D0 ; is this the one? BEQ.S FoundIt ; if equal, then done SUB.W #8,D1 ; try the previous one BGE.S LegalIndex ; loop while index positive MOVEQ #0,D1 ; OK, use the first one FoundIt LEA CTTable+rgb(A0,D1),A0 ; get the address of the color to use MOVE.L A0,D0 ; weÕll need A0 in a second MOVE.L (SP)+,D1 ; restore the register MOVE.L (SP)+,A0 ; get the return address MOVE.L D0,-(SP) ; push the rgb addr on the stack JMP (A0) ; return to caller ; ; DrawPBut draws the pushButton ; DrawPBut TST.B ContrlVis(A0) ; is it visible? BEQ.S ButStub ; if not, weÕre done ; ; calculate roundness as function of rectangle size ; BSR RoundCalc ; compute roundNess factor in D4 TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor2 ; if on B&W, then skip ; ; if pushbutton, paint bk to body color; if checkmark then erase to window content DAF ; @9 TST.B D6 ; is it a pushButton? BEQ.S @4 ; ; set the window content color to the back for the eraseRRect DAF PEA ContentRGB(A6) ; push the pointer to content color BRA.S @5 ; set the body color for button DAF @4 MOVE.L (A3),A0 ; get control rec pointer MOVE.B contrlHilite(A0),D0 ; get the hilite byte SUBQ.B #1,D0 ; make 0->$FF CMP.B #$FD,D0 ; is the control hilited? BHS.S @8 ; no, so continue MOVEQ #cTextColor,D0 ; if it is, paint the button in text color BRA.S @0 @8 MOVEQ #cBodyColor,D0 ; if its not, then paint body color @0 BSR.S SetUpColor ; get info on the stack ; ; erase the bounding rectangle (if necessary) ; @5 _RGBBackColor ; set it MOVE.L (A3),A0 ; get controlHandle again @NoColor2 ; END OF A COLOR-ONLY SECTION LEA ContrlRect(A0),A4 ; get pointer to bounding rect TST.B D6 ; is it a pushButton? BEQ.S EraseCBound ; push buttons are always erased TST.B D3 ; draw all? BNE.S SkipCErase ; if not, donÕt bother to erase ; EraseCBound MOVE.L A4,-(SP) ; push rect MOVE.L D4,-(SP) ; push rounding factor _EraseRoundRect ; paint it the background color ; ; save the current font and force the system font ; SkipCErase MOVE.L GrafGlobals(A5),A0 ; get GrafGlobals base MOVE.L ThePort(A0),A0 ; get current port MOVE.L txFont(A0),-(SP) ; remember the font,face MOVE.W txSize(A0),-(SP) ; remember the size SUBQ #8,D7 ; was code 8 or greater? BGE.S @gotFont ; if so, use windowÕs font CLR.L txFont(A0) ; force system font, normal face MOVE.W SysFontSize,D0 ; get default size BNZ.S @gotSize ; => itÕs 0! MOVE.B FMDefaultSize,D0 ; get default size @gotSize MOVE.W D0,txSize(A0) ; set size of font @gotFont MOVE.L ClipRgn(A0),-(SP) ; push the current clipRgn handle ; save old clip region and clip to the bounding rectangle sected with oldClip CLR.L -(SP) ; make space for region handle _NewRgn ; allocate a region MOVE.L (SP),A2 ; remember region but leave on stack _GetClip ; remember the current clipRgn MOVE.L (A3),A0 ; get control pointer PEA ContrlRect(A0) ; push pointer to its bounding rect _ClipRect ; make that the clipping region MOVE.L A2,-(SP) ; push the old ClipRgn MOVE.L 4(SP),-(SP) ; the answer goes into current clip _SectRgn ; intersect new and old ; Save off some registers for mondo button title calculations, then ; set them up for our use MOVE.L A3,A0 ; copy control handle to A0 for memory calls _HGetState MOVE.L D0,-(SP) ; save the state of the control handle for later ;;; _MoveHHi ; move it up, before we lock it down <11> SAM (Removed) _HLock ; lock it down MOVEM.L D4/A2-A3,-(SP) ; save registers MOVE.L (A3),A0 ; get pointer to control LEA contrlTitle(A0),A2 ; get title into A2 LEA contrlRect(A0),A4 ; get rect into A4 MOVEQ #0,D7 ; MOVE.B (A2),D7 ; get string length into D7 BEQ NoTitle ; quick check for nothing ; now count the number of lines in the title. Lines are separated by CRÕs MOVEQ #0,D4 ; save number of lines in D4 @2 ADDQ #1,D4 ; count next line BSR Pt2Next ; point to next line (index in D7) TST.B D7 ; D7 < 0 if done BPL.S @2 ; => get next line MOVE.B (A2),D7 ; get string length back ; now get a font info record on stack, pointer to it in A3 SUBQ #8,SP ; make room for 4 INTEGERS MOVE.L SP,A3 ; save pointer in A3 MOVE.L A3,-(SP) ; push pointer to record _GetFontInfo ; and fill the record ; Set up D5 to point to the baseline of the last line BSR GetHeight ; get height of line into D0 MULU D4,D0 ; #lines times height MOVE.W bottom(A4),D1 ; get bottom of rect MOVE.W D1,D5 ; D5 will be baseline SUB.W top(A4),D1 ; get height of rect SUB.W D0,D1 ; get unused space ASR.W #1,D1 ; and DIV by 2 SUB.W D1,D5 ; move up from bottom SUB.W leading(A3),D5 ; to bottom of descender SUB.W descent(A3),D5 ; to first baseline DoNextLine ; get the width of the current line into D0 BSR Pt2Next ; next line in D7, len in D3 CLR.W -(SP) ; make room for result MOVE.L A2,-(SP) ; push title pointer MOVE.W D7,D0 ; get our offset into string ADDQ.B #2,D0 ; bump past length (or CR) MOVE.W D0,-(SP) ; push true offset into string MOVE.W D3,-(SP) ; push number of bytes _TextWidth ; get the stringÕs width MOVE.W (SP)+,D0 ; and save result in D0 ; if itÕs a checkbox, donÕt center it, just move to right a little TST.B D6 ; is it a check box? BEQ.S ElCentro ; => no, go center the string ; adjust positioning for push button tst.w teSysJust ; right to left? beq.s LeftBox ; no, normal case RightBox MOVE.W right(A4),D1 ; get the right edge SUB.W left(A4),D1 ; get the width SUB.W D0,D1 ; subtract stringÕs width sub.w #18,d1 ; subtract room for box ADD.W left(A4),D1 ; and add into left BRA.S DrawBTitle ; back to common code LeftBox MOVE.W Left(A4),D1 ; get the left edge ADD.W #18,D1 ; leave room for check box BRA.S DrawBTitle ; back to common code ElCentro ; center the line in the rect MOVE.W right(A4),D1 ; get the right edge SUB.W left(A4),D1 ; get the width SUB.W D0,D1 ; subtract stringÕs width ASR.W #1,D1 ; get centering offset ADD.W left(A4),D1 ; and add into left DrawBTitle MOVE.W D1,-(SP) ; push horizontal position MOVE.W D5,-(SP) ; and vertical position _MoveTo ; move the pen there ; now that registers are free, push colors on stack DAF MOVE.L GrafGlobals(A5),A0 ; Save the pen mode MOVE.L thePort(A0),A0 ; MOVE.W txMode(A0),-(SP) ; <12> TST.B IsColor(A6) ; are we on a color system? BEQ.S @notColor ; no, skip the gray text checking stuff totally MOVE.W portVersion(A0),D0 ; get portVersion into D0 for comparison AND.W #$C000,D0 ; are we using a color grafport? SNE useGrayText(A6) ; yes, set boolean useGrayText to true for future reference BRA.S @doneCheckingForGrayText @notColor ; MOVE.B #0,useGrayText(A6) ; set boolean useGrayText to false @doneCheckingForGrayText TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor4 ; if on B&W, then skip MOVE.L CtlHndl(A6),A0 ; get the control handle (not A3 in this section) MOVE.L (A0),A0 ; get control pointer MOVE.B ContrlHilite(A0),D0 ; need to handle the case of 254/5 hiliting BEQ.S @1 ; skip if hiliteValue == 0 CMP.B #$FE,D0 ; Is the button hilited? BHS.S @Hilited ; skip if hiliteValue > 254 (i.e. disabled) TST.B D6 ; Is it a check box or radio button? BNE.S @1 ; yes => Want to set the forecolor to CTextColor in 7.0 MOVE.W #cBodyColor,D0 ; no => use cBodyColor as ForeColor in 6.0 BRA.S @4 ; (because BackColor is cTextColor) @Hilited ; TST.B useGrayText(A6) ; can we use GrayText? BEQ.S @1 ; MOVE.W #grayishTextOr,-(SP) ; yes => set the pen mode to grayishTextCopy _TextMode ; @1 MOVE.W #cTextColor,D0 ; use cTextColor as ForeColor @4 BSR SetUpColor ; deposit appropriate values on stack _RGBForeColor @NoColor4 MOVE.L A2,-(SP) ; point to string MOVE.W D7,D0 ; get our offset into string ADDQ.B #2,D0 ; bump past length (or CR) MOVE.W D0,-(SP) ; push true offset into string MOVE.W D3,-(SP) ; push length in bytes _DrawText ; this is where we draw the line _TextMode ; <12> ; bump baseline point up to next line, test for end BSR GetHeight ; get line height into D0 SUB.W D0,D5 ; go up to next base line TST.B D7 ; done yet? BPL DoNextLine ; => nope ADDQ #8,SP ; strip font record NoTitle MOVEM.L (SP)+,D4/A2-A3 ; and all those registers MOVE.L A3,A0 ; copy control handle to A0 for HSetState MOVE.L (SP)+,D0 ; get the state off the stack and set it back _HSetState ; <14> ; WARNING! Setting the state of the control record handle here may leave it unlocked! Several ; references are made below to items in the control record (mostly the control rect). ; Each reference must include reloading the control record pointer from the control ; record handle contained in register a3. ; ; We now return you to your regularly scheduled program. ; <14> ; restore original font, face and size MOVE.L GrafGlobals(A5),A0 ; get GrafGlobals base MOVE.L ThePort(A0),A0 ; get current port MOVE.W (SP)+,txSize(A0) ; restore the size MOVE.L (SP)+,txFont(A0) ; restore the font,face ; ; set the pen color to FrameColor DAF ; TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor5 ; if on B&W, then skip MOVEQ #cFrameColor,D0 ; BSR SetUpColor ; _RGBForeColor ; @NoColor5 ; END OF A COLOR-ONLY SECTION TST.B D6 ; is it a checkBox? BNE PlotCheck ; if so, go draw it move.l (a3), a0 ; get control pointer <14> lea contrlRect(a0), a4 ; point to the control rect <14> MOVE.L A4,-(SP) ; push the rectangle pointer MOVE.L D4,-(SP) ; push rounding factor _FrameRoundRect ; frame the button ; ; perform SpecialHilite if necessary ; TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor6 ; if on B&W, then skip TST.B useGrayText(A6) ; did we use GrayText? BNE.S @skipSpecialHilite ; yes => skip SpecialHilite since GrayText represents hilite state already MOVE.L (A3),A0 ; get control pointer CMP.B #$FE,ContrlHilite(A0) ; is it the special hilite state? BHS.S SpecialHilite ; if so, go do it @skipSpecialHilite BRA.S @Common6 ; and continue... @NoColor6 ; ; hilite the button if necessary ; MOVE.L (A3),A0 ; get control pointer MOVE.B ContrlHilite(A0),D0 ; is it hilited? BEQ.S DoneDrwBut ; if not, weÕre done ; TST.B useGrayText(A6) ; did we use GrayText? BNE.S @Common6 ; yes, skip SpecialHilite since GrayText represents hilite state already CMP.B #$FE,D0 ; is it the special hilite state? BHS.S SpecialHilite ; if so, go do it ; lea contrlRect(a0), a4 ; point to the control rect <14> MOVE.L A4,-(SP) ; push rectangle MOVE.L D4,-(SP) ; push rounding factor _InverRoundRect ; hilite by inverting @Common6 ; ; restore original clipping region and weÕre done ; DoneDrwBut _PenNormal ; set the pen back to normal MOVE.L A2,-(SP) ; push old clip region _SetClip ; restore it MOVE.L A2,-(SP) ; dispose of temporary region _DisposRgn ; de-allocate it RTS ; all done! ;------------ ; Utility Pt2Next -- Point to next line within the title ; On Entry: A2 Title pointer ; D7 offset to end of next line to do ; On Exit: D7 offset to next line-2 (D7<0 if last line) ; D3 length of next line CR EQU $0D ; CR = carriage return Pt2Next MOVEQ #0,D3 ; clear out count TST.B D7 ; pointing at count? BEQ.S @2 ; => yes, a leading CR @1 CMP.B #CR,0(A2,D7) ; is char a CR? BEQ.S @2 ; => yes, all done ADDQ #1,D3 ; else bump count by one SUBQ.B #1,D7 ; and move back in string BNE.S @1 ; => not end of string @2 SUBQ.B #1,D7 ; prepare for next string RTS ; D7 < 0 if last line ;------------ ; Utility GetHeight -- return in D0 the height of on line ; On Entry: A3 Font Record ; On Exit: D0 Line height GetHeight MOVEQ #0,D0 ; clear out height ADD.W ascent(A3),D0 ; height = ascent + descent + leading ADD.W descent(A3),D0 ; ADD.W leading(A3),D0 ; RTS ; SpecialHilite handles drawing the disabled button SpecialHilite BSR.S DisableText BRA.S DoneDrwBut DisableText TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor7 ; if on B&W, then skip TST.B D6 ; is it a pushbutton? BNE.S @NoColor7 ; a checkbox, so go MOVEQ #cTextColor,D0 ; set the colors apropos BSR SetUpColor ; _RGBForeColor ; MOVEQ #cBodyColor,D0 ; BSR SetUpColor ; _RGBBackColor ; @NoColor7 ; END OF A COLOR-ONLY SECTION move.l (a3), a0 ; get control pointer <14> lea contrlRect(a0), a4 ; point to the control rect <14> MOVE.L A4,-(SP) ; push rectangle MOVE.L #$00010001,-(SP) ; <12> _InsetRect MOVE.L A4,-(SP) ; push rectangle MOVE.L D4,-(SP) ; push the rounding factor <12> MOVE.L (A5),A0 PEA Gray(A0) _PenPat MOVE #patBIC,-(SP) _PenMode _PaintRoundRect ; gray it out <12> _PenNormal move.l (a3), a0 ; get control pointer <14> lea contrlRect(a0), a4 ; point to the control rect <14> MOVE.L A4,-(SP) MOVE.L #$FFFFFFFF,-(SP) ; <12> _InsetRect RTS ; RoundCalc calculates the rounding factor in D4 based on the controlÕs rect RoundCalc TST.B D6 ; is it a checkBox? BNE.S CheckRound ; if so, special case it ; MOVE.W ContrlRect+Bottom(A0),D4 ; get bottom coordinate SUB.W ContrlRect+Top(A0),D4 ; figure out vertical height LSR #1,D4 ; scale it down by a factor of 2 MOVE D4,D0 ; fill both halves with it SWAP D4 ; get in high part MOVE D0,D4 ; and in low part RTS ; CheckRound MOVEQ #0,D4 ; checkBoxes are square! RTS ; ; HitPBut handles the button hit-test ; HitPBut MOVE.B ContrlHilite(A0),D4 ; get hiliteState ADDQ.B #1,D4 ; is it 255? BEQ.S @1 ; if so, skip CLR.W -(SP) ; make room for function result MOVE.L D3,-(SP) ; push the point PEA ContrlRect(A0) ; push address of rect _PtInRect ; in the rectangle? TST.B (SP)+ ; examine result BEQ.S @1 ; if not, weÕre done ADDQ.B #1,D4 ; 254 hiliting? BEQ.S Return254 ; => say it is so MOVE #inButton,22(A6) ; return that it was TST.B D6 ; a checkBox? BEQ.S @1 ; if not, weÕre done ADDQ #1,22(A6) ; if so, flag it @1 RTS Return254 MOVE #254,22(A6) ; indicate its 254-disabled RTS CalcWholePBut CalcThumbPBut MOVE.B #1, 23(A6) ; return 1 to show that we respond ; ; CalcPBut returns the bounding region of the button ; CalcPBut TST.B D6 ; is it a checkBox? BNE.S CalcSquare ; check box bounds are just rects ; BSR.S RoundCalc ; calculate rounding factor _HidePen ; dont draw anything _OpenRgn MOVE.L A3,A0 ; copy to A0 for HLock DAF _HLock ; lock it down DAF MOVE.L (A3),A0 ; get pointer to control PEA ContrlRect(A0) ; push rectangle pointer MOVE.L D4,-(SP) ; push rounding factor _FrameRoundRect ; frame the button MOVE.L D3,-(SP) ; push the region _CloseRgn ; make the rounded rectangular region _ShowPen MOVE.L A3,A0 ; copy to A0 for HLock DAF _HUnlock ; unlock the control DAF ; ; set the pattern for indicator dragging ; DragGray MOVE.L (A5),A0 ; get qDraw globals LEA Gray(A0),A0 ; point to gray pattern MOVE.L (A0)+,DragPattern ; move in the 1st half MOVE.L (A0),DragPattern+4 ; move in the 2nd half RTS ; all done! ; CalcSquare MOVE.L D3,-(SP) ; push the region PEA ContrlRect(A0) ; push the rectangle pointer _RectRgn ; make a rectangular region BRA.S DragGray ; all done -- go set drag pattern ; ; PlotCheck takes care of drawing the actual check box of the check box button. It ; figures out where to draw the box, draws it, and then checks it or not based on ; the current value and hilite state of the button ; PlotCheck ; first set the window content color DAF TST.B IsColor(A6) ; are we on a color system? BEQ.S @NoColor8 ; if on B&W, then skip PEA ContentRGB(A6) _RGBBackColor ; @NoColor8 ; END OF A COLOR-ONLY SECTION move.l (a3), a0 ; get control pointer <14> lea contrlRect(a0), a4 ; point to the control rect <14> SUBQ #8,SP ; allocate a rectangle on the stack MOVE.W bottom(A4),D0 ; get rect height MOVE.W D0,D1 ; save a copy SUB.W top(A4),D0 ; get height SUB.W #12,D0 ; sub box height ASR.W #1,D0 ; div by 2 SUB.W D0,D1 ; get offset from bottom MOVE D1,Bottom(SP) ; set up the bottom SUB #12,D1 ; compute the top MOVE D1,Top(SP) ; set up the top tst.w teSysJust ; right to left? beq.s LeftBoxTitle ; no, normal case RightBoxTitle MOVE Right(A4),D1 ; get left edge of boundsRect subq #2,D1 ; indent 2 pixels MOVE D1,Right(SP) ; thatÕs the left of the checkRect sub #12,D1 ; compute right edge MOVE D1,Left(SP) ; update the right edge bra.s EraseCheck ; continue LeftBoxTitle MOVE Left(A4),D1 ; get left edge of boundsRect ADDQ #2,D1 ; indent 2 pixels MOVE D1,Left(SP) ; thatÕs the left of the checkRect ADD #12,D1 ; compute right edge MOVE D1,Right(SP) ; update the right edge EraseCheck ; ; erase the check box ; MOVE.L SP,-(SP) ; push rectangle pointer _EraseRect ; erase it ; ; OK, now we must fill in the checkBox rectangle based on the value and hilite state ; of the control ; MOVE.L (A3),A0 ; get control pointer <14> MOVE.W ContrlValue(A0),D5 ; get the value MOVE.B ContrlHilite(A0),D0 ; is it hilited? BEQ.S FrameCheck ; if not, skip ; ; its hilited so up the penSize to indicate its hilited ; CMP.B #$FE,D0 ; disabled? BLO.S SkipDis ; if so, skip doubling ; TST.B useGrayText(A6) ; did we use GrayText? BNE.S FrameCheck ; yes => skip DisableText since GrayText represents disabled state BSR DisableText BRA.S FrameCheck SkipDis MOVE.L #$00020002,-(SP) _PenSize ; up the penSize FrameCheck MOVE.L SP,-(SP) ; push the rectangle CMP.B #2,D6 ; test for radio button BEQ.S @1 ; if its a radio button, go do it _FrameRect ; frame it BRA.S @2 @1 _FrameOval @2 _PenNormal ; ; now we can draw the check if weÕre supposed to ; LSR #1,D5 ; check out the low bit of D5 BCC.S DonePCheck ; if its off, weÕre done ; CMP.W #2,D6 ; test for radio button BEQ.S DrawRButton ; if its a radio button, go do it ; MOVE.L SP,-(SP) ; push the rectangle pointer MOVE.L OneOne,-(SP) ; push the inset factor _InsetRect ; inset the rectangle MOVE.L TopLeft(SP),-(SP) ; push top left _MoveTo ; move to it MOVE.L BotRight(SP),-(SP) ; push bottom right _LineTo ; draw one line of the cross ; MOVE Right(SP),-(SP) ; push right MOVE Top+2(SP),-(SP) ; push top SUBQ #1,(SP) ; bias the top _MoveTo ; move to it MOVE Left(SP),-(SP) ; push left SUBQ #1,(SP) ; bias the left MOVE Bottom+2(SP),-(SP) ; push bottom _LineTo ; draw the line BRA.S DonePCheck ; ; draw the radio button check mark -- a little circle ; DrawRButton MOVE.L SP,-(SP) ; push pointer to rect MOVE.L #$00030003,-(SP) ; push inset factor _InsetRect ; inset it MOVE.L SP,-(SP) ; push rect again _PaintOval ; draw the circle? ; DonePCheck ADDQ #8,SP ; pop off the rectangle BRA DoneDrwBut ; all done! END