![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/images/you_are_here_red.gif)
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/default/files/beta-site.gif)
|
Volume Number: | 5 | |
Issue Number: | 1 | |
Column Tag: | Assembly Lab |
Related Info: List Manager
Help! An Easy to Use Help Function
By John Holder, Blue Lake, CA, MacTutor Contributing Editor
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
What’s this all about?
This article will show you a way of presenting a Help function (hereafter called DoHelp) for any of your programs that is very easy to implement and use. DoHelp must be XREF’ed (XREF DoHelp) at the beginning of the source file that calls it. To use it I just add a ‘Help...’ menu in an appropriate place in your application (I put it right below the standard ‘About Application...’ menu item in the apple menu). Call it by simply doing a BSR DoHelp when the item has been selected by the user.
DoHelp was created with the Macintosh 68000 Development System. First assemble the file ‘DoHelp.Asm’, then run the linker on your applications Linker file to Link DoHelp with the rest of your code, and finally run RMaker on your Rmaker file. You can create the needed ‘help’ resources with ResEdit (or whatever you prefer) and add them to your applications resource file. ‘YourApp.Link’ & ‘YourApp.R’ are shown as examples of how you link your applications code with DoHelp’s code.
The way DoHelp works is to show a list of resource names (a Help topic list created by showing the names of each ‘help’ resource in numeric order) using the List Manager. This makes adding and editing Help topics very easy, by using ResEdit or compiling the needed resources with RMaker. The user can click on any name to access its contents, which is displayed in a scrollable text window (which temporarily replaces the list of Help topics). When the user is done reading this, he can click on the button or within the text itself to return to the Help topics. From here he can choose to look at another topic or select the ‘Done with Help’ button to return to the application.
Why?
I wrote DoHelp to put into my latest shareware application called ‘Form It!’. I wanted to keep it as generic as possible so I could use it for any other applications that I might create in the future. I made it so the calling application wouldn’t need to know anything specific about the help but would just have to call it when the user needs it. It handles everything else.
What’s happening , step by step.
First, all files needed are Included at the beginning and a couple of often used routines for saving and restoring the registers are defined as Macros. A few standard EQUates are also defined along with some values used by the List Manager. The last EQUate is the resource ID# of the DLOG used to display the Help function. Finally the DoHelp routine is XDEF’ed so the Linker will know what the heck is going on when it’s being linked to the code that calls it!
Now a dialog box is created, the default button is hilighted, and we jump to the routine to set up the list of named ‘help’ resources. To accomplish this, we first calculate the useable width of the cells used in the list by checking the size of the User Item’s rectangle (right-left-scrollbarwidth = widthofcells) of the Help dialog box (item #2 in this DLOG). Then we create a new list with _LNew and set its selflags field to allow only one item to be selected at a time.
The routine to add each named ‘help’ resource is then called. We count how many resources of this type there are with _CountResources and set list drawing off so it won’t show each item as it’s being added to the list. Starting from the last resource we cycle through all the resources and add their names to the list with _LAddRow & _LSetCell. After the last resource (the resource id#1 since we’re adding in reverse) has been put in the list, we exit the loop and turn list drawing on and update the list to draw it.
The Dialog filter
After everything is initialized we go into a loop to watch for dialog events. A Dialog Filter is used to handle the List Manager events, all other dialog events are handled by _ModalDialog. The filter is set up to get values off of the stack (passed by _ModalDialog) and create some local variables by using the LINK instruction to set up a stack frame. When a click occurs in the rectangle of the User Item, _LClick is called to handle scrolling or a selection. If a help topic (list item) is clicked on, the rectangle is erased, we change the buttons (item #1) name to an appropriate message (‘Done Viewing’), the cursor is changed to the watch cursor and we jump to the Do_Help_View routine.
A new Text Edit record is made with _TENew and its text size and font is set. The rectangle around the User Item is framed and a scroll bar is created. The selected cells data is retrieved using _LGetCell to get the name of the resource to read in with _GetNamedResource. If the given resource doesn’t exist (why it wouldn’t I don’t know, but it pays to be safe!) we dispose of the TE record and the scroll bar and return to wait for the next event. Otherwise, we copy the data in the ‘help’ resource into the Text Edit Record and calculate how many lines are in the data. If there are more lines than one screenfull, the scroll bar is set up to match the amount of lines in the data. Next, we jump to the routine to handle text scrolling using another Dialog Filter to handle it.
If the scroll bar is clicked on, we check which part of the scroll has been clicked and handle each part individually. If the Thumb is clicked, it’s tracked by _TrackControl until released and then we scroll the text according to the difference between the controls old and new values. The text is scrolled a line at a time or a pagefull at a time depending on the part clicked on. The routine Scroll_The_Text figures how many pixels to scroll by multiplying the height of a line of text (found in the teLineHite field of the TE record) by how many lines of text are to be scrolled.
When either the button or the content of the text in the dialog is clicked, the TE record and the scroll bar are disposed of, the list is updated to show it again, we change the buttons name back to what it was and we return to watch for more list events. If the user clicks on another list item, the whole process starts again. Otherwise if the user clicks the button or hits Return, the dialog and the list handle are disposed of and control is returned to the calling application.
Credits
The basis of some of the routines used in DoHelp (such as the dialog filters and scroll handling routines) are from Dan Weston’s extremely useful books “The Complete Book of Macintosh Assembly Language Programming” (volumes I and II). These books have proved very helpful to my learning to use the power of the Mac with Assembly language!
The End...
There are many ways that DoHelp could be enhanced. For instance, a search feature or a way to print selected help topics could be added. The source code is well commented, so anything that this article doesn’t explain, the comments should be able clear up. Well, that’s it, I hope you find this useful enough to use in your own applications!
;------------------------------------------------------------ ;FileName: DoHelp.Asm ;(C) 1988 by John Holder ;------------------------------------------------------------ ;What it does: ;A generic Help routine: ;Allows user to click in a list of names (these names are ;actually the names of ‘help’ resources), and show the data ;contained in this resource (ACSII text), in a scrollable ;window. Nothing about the dialog (other than its id#) is ;known, so the dialog can be modified without changing this ;code. To make topics for your help routine, just create ;NAMED resources of type ‘help’ (lowercase) in your ;application starting at id#1 and making each id# one more ;than the last one. To create the appearance of subtopics ;just add a few spaces to the beginning of the names of ;the appropriate ‘help’ resources. ;To use this in your application, just make sure you: ;XREF DoHelp ;at the beginning of your source code and you call it by ;doing a: ;BSR DoHelp ;in the appropriate place in your code Include Traps.D ; Traps Include ToolEqu.D; ToolBox equates Include SysEqu.D ; System equates Include FSEqu.D ; File equates Include PackMacs.Txt ; PACKage mgr equates Include QuickEqu.D ; QDraw equates MACRO SaveRegs = MOVEM.LA0-A4/D0-D7,-(SP) | MACRO RestoreRegs= MOVEM.L(SP)+,A0-A4/D0-D7 | true equ $0100 false equ 0 nilequ 0 arraycolumnsequ 1 arrayrows equ 0 celldepth equ 16 ;depth of Cells in List modify EQU 14 ;State of keys and button message equ 2 ;Message returned in EventRecord DialogIDequ 2000 ;res id# of DLOG resource XDEF DoHelp ;Define function DoHelp for Linker ;------------------------------------------------------------ ;<<<< The beginning of the DoHelp routine >>>> ;------------------------------------------------------------ DoHelp saveregs CLR.L -(SP) ;space for ptr move.w #DialogID,-(sp) CLR.L -(SP) ;wstorage MOVE.L #-1,-(SP) _GetNewDialog MOVE.L (SP),DialogPtr(A5) ;save ptr _SetPort ;set up stack for my routine move.l DialogPtr(A5),-(sp) move #1,-(sp) bsr HilightDialogButton ;Set up list of all ‘help’ resources bsr SetUpHelpList _InitCursor Dialog_Loop pea DialogsFilter;use filter to watch pea ItemNumber(A5) ;for List mgr events _ModalDialog WhatsTheHaps21 ;which item was clicked cmp.w #1,ItemNumber(A5) beq Quit_Help;click in ‘Done..’ but bra Dialog_Loop;loop until done Quit_Help ;all done, lets get outta here! ;dispose of the List handle move.l ListHandle(A5),-(sp) _LDispose ;kill the dialog move.l DialogPtr(A5),-(sp) _DisposDialog ;return to calling application! restoreregs rts ;------------------------------------------------------------ ;<< Dialog Filter to watch for list selections in User Item >> ;------------------------------------------------------------ DialogsFilter ;this routine expects parameters to be on the stack (handled ;by _ModalDialog) ;PROCEDURE ;DialogsFilter (thedialog:dialogptr;VAR theEvent:EventRecord ; VAR itemhit:integer): boolean Parambytes SET 12 tItemHit SET 8 ;a ptr to an int! tEvent SET 12 ;event rec tDialogSET 16 ;dialog ptr result SET 20 ;result returned iPoint SET -4 ;mouse point itype SET -6 ;item type iHdl SET -10 ;item hand iBox SET -18 ;item rect localbytes SET -18 link A6,#localbytes saveregs ;get User Item info (rect) move.l tDialog(A6),-(sp) move #2,-(sp) pea iType(A6) pea iHdl(A6) pea iBox(A6) _GetDItem move.l tevent(A6),A0 move evtnum(A0),D0 cmp #KeyDwnEvt,D0 ;was it a key down? beq CheckForEnterorReturn ;yep! move.l tevent(A6),A0 move evtnum(A0),D0 cmp #mButDwnEvt,D0 ;was it a mouse down? bne LetDialogHandleIt ;if not, let ;_ModalDialog ;handle ;was it a mouse click in the List Box (User Item)? lea evtMouse(A0),A0 lea iPoint(A6),A1 move.l (A0)+,(A1)+ pea iPoint(A6) _GlobalToLocal clr -(sp) move.l iPoint(A6),-(sp) pea iBox(A6) _PtInRect move (sp)+,D0 beq LetDialogHandleIt ;not in user item bsr HandleListEvent ;handle list event! ;we’ve taken care of the event move.l tItemHit(A6),A0 move #nil,(A0) ;set itemhit to nil move #true,result(A6) ;stop _ModalDialog bra FilterExit ;from handling! LetDialogHandleIt move #nil,result(A6) FilterExit ;restore stack to the way it was before ;and return restoreregs unlk A6 move.l (sp)+,A0 adda #parambytes,SP jmp (A0);rts ;------------------------------------------------------------ ; <<<< Check for Return or Enter key press >>>> ;------------------------------------------------------------ CheckForEnterorReturn ;if the Enter or Return key was pushed, set the itemhit to #1 ;and set result to false so it will be handled by _ModalDialog move.l tevent(A6),A0 move.l message(A0),D0 cmp.b #$0d,D0 ;return key? beq SetResult;yep! cmp.b #$03,D0 ;Enter key? beq SetResult;yep! bra LetDialogHandleIt ;neither key SetResult move.l tItemHit(A6),A0 move #1,(A0) ;set itemhit to 1 move #true,result(A6) ;let _ModalDialog ;handle it bra FilterExit ;------------------------------------------------------------ ;<<<< Click in List box! >>>> ;------------------------------------------------------------ ;handle a click in the list box area HandleListEvent ;_LClick will handle scrolling & selection of list ;items pea iPoint(A6) _GetMouse clr -(sp) move.l iPoint(A6),-(sp) move tEvent+Modify(A6),-(sp) move.l listhandle(A5),-(sp) _LClick move (sp)+,D0 clr.l TheCell(A5) ;start at cell 0,0 ;for _LGetSelect clr -(sp) move #true,-(sp) pea TheCell(A5) move.l listhandle(A5),-(sp) _LGetSelect move (sp)+,D0 beq Click_Not_In_Cell ;no cell selected ;unselect the selected cell move #false,-(sp) move.l TheCell(A5),-(sp) move.l listhandle(A5),-(sp) _LSetSelect ;de-activate the list move #false,-(sp) move.l listhandle(A5),-(sp) _LActivate bsr Erase_Rect ;clear topic list bsr Set_To_DoneViewing ;change button name bsr GetandSetWatch ;show watch cursor bsr Do_Help_View ;show text from ;’help’ res ;re-activate the list move #true,-(sp) move.l listhandle(A5),-(sp) _LActivate Click_Not_In_Cell rts ;------------------------------------------------------------ ; <<<< Show the user selected help text >>>> ;------------------------------------------------------------ ;open the named resource and view its contents Do_Help_View ;Use all of rect except enough room for scroll bar ;for text window bsr Get_Rect_Of_Item lea DispRect(A5),A2 sub #16,Right(A2) ;create new Text edit record clr.l -(sp) pea DispRect(A5) pea DispRect(A5) _TENew move.l (sp)+,TextHand(A5);store handle ;set TE rec. text to 9 point Monaco move.l TextHand(A5),A1 move.l (A1),A1 move #9,teSize(A1);Text Size! move.l TextHand(A5),A1 move.l (A1),A1 move #Monaco,teFont(A1);Text Font! bsr Frame_The_Rect bsr Get_Rect_Of_Item ;figure rectangle for scroll bar! lea DispRect(A5),A2 move Right(A2),D2 sub #15,D2 ;scroll bar width move D2,Left(A2);left = right - 15 add #1,Right(A2) ;right = right + 1 ;we de because the ;text rect is 1 ;pixel inside the ;User Item’s rect pea DispRect(A5) ;expand top & bottom move #0,-(sp) ;of rect by 1 pixel move #-1,-(sp) _InsetRect ;create scroll bar! clr.l -(sp) move.l DialogPtr(A5),-(sp) pea DispRect(A5) ;scrolls rect move.l #nil,-(sp) move #true,-(sp);visible move #0,-(sp) ;init value move #0,-(sp) ;min value move #0,-(sp) ;max value(start at 0) move #16,-(sp);proc id (16=scroll) clr.l -(sp) ;refCon _NewControl move.l (sp)+,ScrollHand(A5) ;save handle move #255,DataLength(A5) ;max length of ;data allowed ;Get the selected cells data lea AString(A5),A0 ;pt to byte after add.l #1,A0 ;length byte move.l A0,-(sp) ;put ptr on stack pea DataLength(A5) ;data length var move.l TheCell(A5),-(sp) move.l ListHandle(A5),-(sp) _LGetCell ;add length of data to String ptr lea ASTring(A5),A0 move DataLength(A5),D0 move.b D0,(A0) ;get the res. & load it clr.l -(sp) move.l #’help’,-(sp) pea AString(A5) _GetNamedResource move.l (sp),ResHand(A5) _LoadResource ;just to make sure the resource exists! move.l ResHand(A5),A0 cmp.l #nil,A0 ;does res. exist? bne A_Ok;yep,it’s there, go on bsr DumpStuff;no such resource! rts ;return A_Ok move.l ResHand(A5),A0 ;lock handle _HLock ;size of handle (text data) move.l ResHand(A5),A0 _GetHandleSize move.l D0,D2 ;D2 = length of text data ;set up Text Edit Record to use ‘help’ data move.l ResHand(A5),A0 ;need text ptr move.l (A0),-(sp) ;convert handle move.l D2,-(sp) ;text length move.l TextHand(A5),-(sp) _TESetText move.l ResHand(A5),A0 ;unlock handle _HUnLock ;see how many lines of text are in the ;’help’ data move.l TextHand(A5),A1 move.l (A1),A1 move tenLines(A1),d3 ;D3= lines of text! ;see how many lines fit into rect of user ;item of dialog box bsr Calc_Lines_In_One_Windowful move LinesInWind(A5),D1 sub D1,D3 ;sub enough for a cmp #nil,D3 ;window full! ble Wont_Pass_Bottom ;not enough lines ;to adda scroll bar ;set the scroll bars max value by the # of lines move.l ScrollHand(A5),-(sp) move D3,-(sp) ;# of lines _SetMaxCtl Wont_Pass_Bottom ;update the text pea DispRect(A5) move.l TextHand(A5),-(sp) _TEUpDate _InitCursor ;go watch for text events bsr HandleTextEditDialogEvent rts ;done with the text, return ;------------------------------------------------------------ ;<<<< Handle events in Dialog box (with text scrolling)! >>>> ;------------------------------------------------------------ HandleTextEditDialogEvent saveregs D_Loop pea CheckTextScroll ;filter to watch pea ItemNumber(A5) ;for text scrolling _ModalDialog ;check which buttons are clicked here cmp.w #1,ItemNumber(A5) beq Done_With_This ;done viewing text ;if ItemNumber(A5) = 2, that means the user ;clicked in the content of the text of the dialog ;which is handled the same as clicked the ;’Done Viewing’ button cmp.w #2,ItemNumber(A5) beq Done_With_This ;done viewing text bra D_Loop ;keep looping ;------------------------------------------------------------ ; <<<< Finished here with text view >>>> ;------------------------------------------------------------ Done_With_This bsr DumpStuff restoreregs rts ;------------------------------------------------------------ ; <<<< Dump TE rec. & scroll bar >>>> ;------------------------------------------------------------ DumpStuff ;dispose of text edit record move.l TextHand(A5),-(sp) _TEDispose ;dispose of Scroll bar move.l ScrollHand(A5),-(sp) _DisposControl bsr Erase_Rect ;erase the rect ;reset text font & size to System values move #12,-(sp);12 point _TextSize move #0,-(sp) ;Use System Font _TextFont ;re-show the list by causing list update MOVE.L DialogPtr(A5),A1 move.l 24(A1),-(sp) move.l ListHandle(A5),-(sp) _LUpdate bsr Frame_The_Rect ;re-frame list rect bsr Set_To_DoneWithHelp rts ;------------------------------------------------------------ ; <<<< Dialog Filter to watch for text scrolling >>>> ;------------------------------------------------------------ CheckTextScroll ;this routine expects parameters to be on the stack (set up ;by _ModalDialog) ;PROCEDURE ;CheckTextScroll (thedialog:dialogptr;VAR theEvent:EventRecord ; VAR itemhit:integer): boolean Parambytes SET 12 tItemHit SET 8 ;a ptr to an int! tEvent SET 12 ;event rec tDialogSET 16 ;dialog ptr result SET 20 ;result returned iPoint SET -4 ;mouse point itype SET -6 ;item type iHdl SET -10 ;item hand iBox SET -18 ;item rect PartCode SET -20 ;used for scroll localbytes SET -20 link A6,#localbytes saveregs move.l tDialog(A6),-(sp) move #2,-(sp) pea iType(A6) pea iHdl(A6) pea iBox(A6) _GetDItem ;only rect in user item will be scroll bar that ;this dialog filter handles lea iBox(A6),A2 move Right(A2),D2 sub #16,D2 ;scroll bar width move D2,Left(A2);left = right - 16 move.l tevent(A6),A0 move evtnum(A0),D0 cmp #KeyDwnEvt,D0 ;was it a key down? beq CheckForEnterorReturn2;yep! move.l tevent(A6),A0 move evtnum(A0),D0 cmp #mButDwnEvt,D0 ;was it a mouse down? bne LetDialogHandleIt2 ;if not, let ;_ModalDialog ;handle ;change mouse pt into local coordinates lea evtMouse(A0),A0 lea iPoint(A6),A1 move.l (A0)+,(A1)+ pea iPoint(A6) _GlobalToLocal ;was it a mouse click in the Text Box scroll ;bar (User Item)? clr -(sp) move.l iPoint(A6),-(sp) pea iBox(A6) _PtInRect move (sp)+,D0 beq LetDialogHandleIt2 ;not in scroll, ;let dialog handle bsr HandleScroll ;go handle text ;scroll event! ;we’ve taken care of the event move.l tItemHit(A6),A0 move #nil,(A0) ;set itemhit to nil move #true,result(A6) ;set result to true, bra FilterExit2 ;stop _ModalDialog ;from handling LetDialogHandleIt2 move #nil,result(A6) ;set to nil, let ;_ModalDialog handle ;it FilterExit2 ;get out of the routine here! restoreregs unlk A6 move.l (sp)+,A0 adda #parambytes,SP jmp (A0);rts ;------------------------------------------------------------ ; <<<< Check for Return or Enter key press >>>> ;------------------------------------------------------------ CheckForEnterorReturn2 ;if the Enter or Return key was pushed set the itemhit to #1 ;and set result to false so it will be handled! move.l tevent(A6),A0 move.l message(A0),D0 cmp.b #$0d,D0 ;return key? beq SetResult2 ;yep! cmp.b #$03,D0 ;Enter key? beq SetResult2 ;yep! bra LetDialogHandleIt2;neither key SetResult2 move.l tItemHit(A6),A0 move #1,(A0) ;set itemhit to 1 move #true,result(A6) ;let modaldialog bra FilterExit2 ;handle it ;------------------------------------------------------------ ;------------------------------------------------------------ ; <<<< ALL text scrolling routines >>>> ;------------------------------------------------------------ ;------------------------------------------------------------ ;------------------------------------------------------------ ; <<<< Click in Text Scroll bar >>>> ;------------------------------------------------------------ HandleScroll pea iPoint(A6) _GetMouse clr -(sp) move.l iPoint(A6),-(sp) move.l DialogPtr(A5),-(sp) pea WhichControl(A5) _FindControl move (sp)+,PartCode(A6) beq ScrollDone ;not in any control ;was click in the scroll bar? ;compare value returned by _FindControl & the ;scrolls handle we have stored, if they are ;equal then do the scroll routines move.l ScrollHand(A5),D0 move.l WhichControl(A5),D1 cmp.l D0,D1 beq Click_In_Scroll bra ScrollDone ;click not in scroll Click_In_Scroll ;which part of scroll? cmp #inUpButton,PartCode(A6) beq DoUpSCroll cmp #inDownButton,PartCode(A6) beq DoDownSCroll cmp #inPageUp,PartCode(A6) beq DoPageUpSCroll cmp #inPageDown,PartCode(A6) beq DoPageDownSCroll cmp #inThumb,PartCode(A6) beq DoThumb bra ScrollDone ;handle different parts of scroll DoUpSCroll clr -(sp) move.l WhichControl(A5),-(sp) move.l iPoint(A6),-(sp) pea UpActionProc _TrackControl move (sp)+,D0 bra ScrollDone DoDownSCroll clr -(sp) move.l WhichControl(A5),-(sp) move.l iPoint(A6),-(sp) pea DownActionProc _TrackControl move (sp)+,D0 bra ScrollDone DoPageUpSCroll clr -(sp) move.l WhichControl(A5),-(sp) move.l iPoint(A6),-(sp) pea PageUpActionProc _TrackControl move (sp)+,D0 bra ScrollDone DoPageDownSCroll clr -(sp) move.l WhichControl(A5),-(sp) move.l iPoint(A6),-(sp) pea PageDownActionProc _TrackControl move (sp)+,D0 bra ScrollDone ;handle click in thumb of control DoThumb clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D4 ;D4 = old control value clr -(sp) move.l WhichControl(A5),-(sp) move.l iPoint(A6),-(sp) clr.l -(sp) _TrackControl move (sp)+,D0 clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D3 ;D3 = new cntl value sub D3,D4 ;D4-D3=new view value move D4,D6 bsr Scroll_The_Text ;scroll text selected spot bra ScrollDone ;return from HandleScroll ScrollDone rts ;------------------------------------------------------------ ; <<<< Handle Up Scroll arrow >>>> ;------------------------------------------------------------ UpActionProc ;offsets into A6 stack thecontrol set 10 pcode set 8 parambytes set 6 link A6,#0 saveregs tst pcode(A6) beq UpActionDone clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D1 beq UpActionDone ;do nothing if control ;value is already 0 sub #1,D1 ;sub 1 from scroll val move.l WhichControl(A5),-(sp) move D1,-(sp) _SetCtlValue ;set to new value move #1,D6 ;d6 = how many lines bsr Scroll_The_Text ;to scroll! UpActionDone restoreregs unlk A6 move.l (sp)+,A1 adda.w #parambytes,SP jmp (a1);rts ;------------------------------------------------------------ ; <<<< Handle Down Scroll arrow >>>> ;------------------------------------------------------------ DownActionProc ;offsets into A6 stack thecontrol set 10 pcode set 8 parambytes set 6 link A6,#0 saveregs tst pcode(A6) beq DownActionDone clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D2 add #1,D2 ;add 1 to scroll val clr -(sp) move.l WhichControl(A5),-(sp) _GetMaxCtl move (sp)+,D1 ;don’t scroll past controls max setting! cmp D1,D2 bgt DownActionDone move.l WhichControl(A5),-(sp) move D2,-(sp) _SetCtlValue move #-1,D6 ;d6 = how many lines bsr Scroll_The_Text ;to scroll! DownActionDone restoreregs unlk A6 move.l (sp)+,A1 adda.w #parambytes,SP jmp (a1);rts ;------------------------------------------------------------ ; <<<< Handle PageUp Scroll arrow >>>> ;------------------------------------------------------------ PageUpActionProc ;offsets into A6 stack thecontrol set 10 pcode set 8 parambytes set 6 link A6,#0 saveregs tst pcode(A6) beq PageUpActionDone clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D1 move LinesInWind(A5),D0 sub #1,D0 sub D0,D1 move D0,D6 ;d6 = how many lines ;to scroll! ;are we going to go before 1st line? ;if so, figure how many lines from current position ;until 0 (zero) and use that # to scroll text! cmp #nil,D1 bge Not_Past_Begin2 add D1,D6 ;set to proper value ;for scroll move #nil,D1 ;to set ctrl Not_Past_Begin2 move.l WhichControl(A5),-(sp) move D1,-(sp) _SetCtlValue bsr Scroll_The_Text PageUpActionDone restoreregs unlk A6 move.l (sp)+,A1 adda.w #parambytes,SP jmp (a1);rts ;------------------------------------------------------------ ; <<<< Handle PageDown Scroll arrow >>>> ;------------------------------------------------------------ PageDownActionProc ;offsets into A6 stack thecontrol set 10 pcode set 8 parambytes set 6 link A6,#0 saveregs tst pcode(A6) beq PageDownActionDone clr -(sp) move.l WhichControl(A5),-(sp) _GetCtlValue move (sp)+,D7 move D7,D2 move LinesInWind(A5),D0 sub #1,D0 add D0,D2 neg D0 move D0,D6 ;d6 = how many lines ;to scroll! ;are we going to go after last line? ;if so, figure how many lines from current position ;until last line and use that # to scroll text clr -(sp) move.l WhichControl(A5),-(sp) _GetMaxCtl move (sp)+,D3 ;to set ctrl cmp D3,D2 ble Not_Past_End sub D3,D7 ;set to proper value move D7,D6 ;for scroll move D3,D2 ;to set ctrl Not_Past_End move.l WhichControl(A5),-(sp) move D2,-(sp) _SetCtlValue bsr Scroll_The_Text PageDownActionDone restoreregs unlk A6 move.l (sp)+,A1 adda.w #parambytes,SP jmp (a1);rts ;------------------------------------------------------------ ; <<<< Do the actual text scrolling >>>> ;------------------------------------------------------------ Scroll_The_Text ;d6 has how many lines and which direction to scroll ;(depending on whether the value is pos. or neg.) ;use teLineHite to figure how many pixels to scroll ;by multiplying it with the amount of lines clr.l D2 move.l TextHand(A5),A2 move.l (A2),A2 move teLineHite(A2),D2 muls D6,D2 move #nil,-(sp) ;no horiz. scroll move D2,-(sp) ;vert. scroll move.l TextHand(A5),-(sp) _TESCroll rts ;<<<< END of all text scrolling routines >>>> ;------------------------------------------------------------ ; <<<< How many text lines can fit in user item rect >>>> ;------------------------------------------------------------ Calc_Lines_In_One_Windowful saveregs bsr Get_Rect_Of_Item clr.l D4 lea DispRect(A5),A2 move Top(A2),D3 move Bottom(A2),D4 sub D3,D4 ;Top-Bottom = how many ;pixels in text view box ;D4= heighth (in pixels) ;of help window clr.l D5 move.l TextHand(A5),A2 move.l (A2),A2 move teLineHite(A2),D5 ;rect heighth divu D5,D4 ;divided by the ;heighth of one ;line of text = ;how many lines ;can fit! ;D4 now = how many lines of text can fit into one ;screen of the user item of the dialog box! move D4,LinesInWind(A5) restoreregs rts ;------------------------------------------------------------ ; <<<< Erase inside of user item rect of dialog >>>> ;------------------------------------------------------------ Erase_Rect ;erase entire user item rectangle bsr Get_Rect_Of_Item pea DispRect(A5) _EraseRect rts ;------------------------------------------------------------ ; <<<< Get user item rect of dialog >>>> ;------------------------------------------------------------ Get_Rect_Of_Item ;Get info from User Item #2 move.l DialogPtr(A5),-(SP) move #2,-(sp) pea ItemType(A5) pea ItemHandle(A5) pea DispRect(A5) _GetDItem rts ;------------------------------------------------------------ ;<<<< Change button to say ‘Done Viewing’ >>>> ;------------------------------------------------------------ Set_To_DoneViewing bsr Get_Button_Handle move.l ItemHandle(A5),-(sp) pea DoneViewing _SetCTitle rts ;------------------------------------------------------------ ; <<<< Change button to say ‘Done with Help’ >>>> ;------------------------------------------------------------ Set_To_DoneWithHelp bsr Get_Button_Handle move.l ItemHandle(A5),-(sp) pea DoneString _SetCTitle rts ;------------------------------------------------------------ ; <<<< Get handle of button in dialog >>>> ;------------------------------------------------------------ Get_Button_Handle ;Get the buttons handle (for changing the buttons ;title) move.l DialogPtr(A5),-(SP) move #1,-(sp) pea ItemType(A5) pea ItemHandle(A5) pea DispRect(A5) _GetDItem rts ;------------------------------------------------------------ ; <<<< Get watch CURSor and display it >>>> ;------------------------------------------------------------ GetandSetWatch clr.l -(sp) move #watchcursor,-(sp) _GetCursor move.l (sp)+,A0 move.l (A0),-(sp) _SetCursor rts ;------------------------------------------------------------ ; <<<< Frame the user item rect of dialog >>>> ;------------------------------------------------------------ Frame_The_Rect ;frame the outside of the user items rectangle bsr Get_Rect_Of_Item pea DispRect(A5) ;Inset rect by 1 move #-1,-(sp) ;outward move #-1,-(sp) _InSetRect pea DispRect(A5) _FrameRect rts ;------------------------------------------------------------ ; <<<< Hilight A Dialog Button >>>> ;------------------------------------------------------------ ;this routine expects parameters to be on the stack ;PROCEDURE HilightDialogButton (WPtr: Ptr; WhichItem: Int) ;Will hilight a button in a dialog box HilightDialogButton WindPt SET 10 WhichItemSET 8 parambytes SET 6 ;local variables TheTypeSET -4 ;Vars for _GetDItem TheHandleSET -8;handle TheRectSET -16 ;item rect localbytes SET -16 ;for link link A6,#localbytes saveregs move.l WindPt(A6),-(SP) _SetPort move.l WindPt(A6),-(SP) move WhichItem(A6),-(sp) pea TheType(A6) pea TheHandle(A6) pea TheRect(A6) _GetDItem move #3,-(sp) move #3,-(sp) _PenSize pea TheRect(A6) move #-4,-(sp) move #-4,-(sp) _InSetRect pea TheRect(A6) move #16,-(sp) move #16,-(sp) _FrameRoundRect move #1,-(sp) move #1,-(sp) _PenSize restoreregs unlk A6 move.l (sp)+,A0 adda #parambytes,SP jmp (A0);rts ;------------------------------------------------------------ ; <<<< Set up the dialog box with the help info >>>> ;------------------------------------------------------------ SetUpHelpList saveregs bsr Calc_Cell_Width bsr Get_Rect_Of_Item ;must allow room for the lists scroll bar on the right ;side so subtract 15 from the rects right side! lea DispRect(A5),A1 sub #15,right(A1) ;set up the arrayrect (for the cells rows and columns) ;for the List Mgr lea arrayrect(A5),a0 move.l #0,(A0)+ move #arrayRows,(A0)+ move #arraycolumns,(A0)+ move #celldepth,D0 swap D0 move cellWidth(A5),D0 ;create a new List clr.l -(sp) pea DispRect(A5) ;list rect! pea arrayrect(A5) move.l D0,-(sp) ;cell size move #0,-(sp) ;res id of proc. move.l DialogPtr(A5),-(sp) ;window ptr move.w #false,-(sp) ;draw it? move #false,-(sp) ;has grow? move #false,-(sp) ;horiz scroll? move #true,-(sp);vert scroll? _LNew move.l (sp)+,ListHandle(A5) ;set selflags to allow only one selection at a time! move.l ListHandle(A5),A0 move.l (A0),A0 move.b #128,selFlags(A0) ;put all the ‘help’ names (topics) into the list bsr AddHelpNamesToList restoreregs rts ;------------------------------------------------------------ ;<<<< Calculate cell width for list manager >>>> ;------------------------------------------------------------ Calc_Cell_Width bsr Get_Rect_Of_Item move DispRect+right(A5),D2 move DispRect+left(A5),D3 sub D3,D2 sub #16,D2 ;allow for scroll move D2,cellwidth(A5) ;return value rts ;------------------------------------------------------------ ; <<<< Add ‘help’ resource names to List >>>> ;------------------------------------------------------------ AddHelpNamesToList ;this is a routine to add all ‘help’ resource names ;to a list saveregs clr -(sp) move.l #’help’,-(sp) _CountResources move (sp)+,D4 ;how many there are move D4,D7 beq None_Here ;if no ‘help’ res’s ;here, quit! sub #1,D4 ;sub 1 for looping ;(the DBRA later) move #false,-(sp) ;set drawing off move.l ListHandle(A5),-(sp) _LDoDraw move.l #nil,TheCell(A5) ;start with zero cell ;set ResLoad off (so resources are not ;automatically read into memory) move #false,-(sp) _SetResLoad AddhelpLoop clr.l -(sp) move.l #’help’,-(sp) move D7,-(sp) ;res. id # _GetResource move.l (sp),A4 ;leave handle on stack ;for next routine ;get the resources name pea ResId(A5) pea ResType(A5) pea ResName(A5) _GetResInfo lea ResName(A5),A3 clr.l D3 move.b (A3)+,D3 ;how many chars in ;name for later sub #1,D7 ;decrement index # ;D7 = the res id# ;d3 = how many characters in string, ;A3 = ptr to string data ;add a new row clr -(sp) move #1,-(sp) move #0,-(sp) move.l ListHandle(A5),-(sp) _LAddRow move (sp)+,D0 ;set the cells data to the resources name move.l A3,-(sp) ;points to name move D3,-(sp) ;how many chars? move.l TheCell(A5),-(sp) move.l ListHandle(A5),-(sp) _LSetCell dbra D4,AddhelpLoop ;loop until D4 = 0 ;set ResLoad back on move #true,-(sp) _SetResLoad move #true,-(sp);turn drawing on move.l ListHandle(A5),-(sp) _LDoDraw ;update the list to show it MOVE.L DialogPtr(A5),A1 move.l 24(A1),-(sp) move.l ListHandle(A5),-(sp) _LUpdate bsr Frame_The_Rect None_Here restoreregs rts ;------------------------------------------------------------ ; <<<< Constants >>>> ;------------------------------------------------------------ DoneStringdc.b 14,’Done with Help’ .align 2 DoneViewing dc.b 12,’Done viewing’ .align 2 ;------------------------------------------------------------ ; <<<< Global variables >>>> ;------------------------------------------------------------ WhichControlds.l 1 ;used by _FindControl TextHandds.l1 ;TE record Handle ScrollHandds.l 1 ;Handle of scroll bar DialogPtr ds.l 1 ;Ptr to Help Dialog LinesInWind ds 1 ;how many text lines fit in rect AString ds.b256 ;Space for a string ListHandleds.l 1 ;Handle to list TheCell ds.l1 ;Used by the List Mgr ArrayRect ds.l 2 ;Rows & columns for List Mgr cellwidth ds.w 1 ;width of cell in list DataLengthds.w 1 ;Var used by _LGetCell ItemTypeds.l1 ;Vars used by _GetDItem ItemHandleds.l 1 ;Handle of Dialog Item DispRectds.l2 ;Rect of Dialog Item ResHand ds.l1 ;Handle of a ‘help’ resource ResId ds.w1 ;Vars used by _GetResInfo ID# ResType ds.l1 ;res. type ResName ds.b256 ;res. name ItemNumberds.w 1 ;Item# returned by _ModalDialog END * File name: YourApp.R * Example .R file for YourApp, which * is an example application name * that has been linked with DoHelp. * Resource is also an example name, it * should be the name of a resource file * containing all of the needed resources for * YourApp, Including the ‘help’ resources for * DoHelp which you can create using ResEdit * This also creates the DLOG & DITL that * DoHelp needs. MDS1:YourApp APPLTEST Type DLOG ,2000 Help 56 32 318 476 visible NoGoAway 4 0 2000 Type DITL ,2000 3 Button 232 152 256 288 Done with help userItem 8 8 200 434 staticText Disabled 208 96 224 344 Click on a Help topic (above) to view. INCLUDE MDS2:YourApp.Code INCLUDE MDS1:Resources
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/img/search_text.gif)
- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine