TweetFollow Us on Twitter

Easy to Use Help!
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

 
AAPL
$100.96
Apple Inc.
-0.83
MSFT
$47.52
Microsoft Corpora
+0.84
GOOG
$596.08
Google Inc.
+6.81

MacTech Search:
Community Search:

Software Updates via MacUpdate

Airfoil 4.8.9 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
WhatRoute 1.13.0 - Geographically trace...
WhatRoute is designed to find the names of all the routers an IP packet passes through on its way from your Mac to a destination host. It also measures the round-trip time from your Mac to the... Read more
Chromium 37.0.2062.122 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. FreeSMUG-Free OpenSource Mac User Group build is... Read more
Attachment Tamer 3.1.14b9 - Take control...
Attachment Tamer gives you control over attachment handling in Apple Mail. It fixes the most annoying Apple Mail flaws, ensures compatibility with other email software, and allows you to set up how... Read more
Duplicate Annihilator 5.0 - Find and del...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator detects... Read more
jAlbum Pro 12.2 - Organize your digital...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code!... Read more
jAlbum 12.2 - Create custom photo galler...
With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly, with pro results Simply drag and drop photos into groups, choose a design... Read more
Quicken 2015 2.0.4 - Complete personal f...
Quicken 2015 helps you manage all your personal finances in one place, so you can see where you're spending and where you can save. Quicken automatically categorizes your financial transactions,... Read more
iMazing 1.0 - Complete iOS device manage...
iMazing (formerly DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and... Read more
Xcode 6.0.1 - Integrated development env...
Apple Xcode is Apple Computer's integrated development environment (IDE) for OS X. The full Xcode package is free to ADC members and includes all the tools you need to create, debug, and optimize... Read more

Latest Forum Discussions

See All

View Source – HTML, JavaScript and CSS...
View Source – HTML, JavaScript and CSS 1.0 Device: iOS Universal Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: View Source is an app plus an iOS 8 Safari extension that makes it easy to do one key web developer... | Read more »
Avenged Sevenfold’s Hail To The King: De...
Avenged Sevenfold’s Hail To The King: Deathbat is Coming to iOS on October 16th Posted by Jessica Fisher on September 19th, 2014 [ permalink ] Just in time for Halloween, on October 16 Avenged Sevenfold will be launching | Read more »
Talisman Has Gone Universal – Can Now be...
Talisman Has Gone Universal – Can Now be Played on the iPhone Posted by Jessica Fisher on September 19th, 2014 [ permalink ] | Read more »
Tap Army Review
Tap Army Review By Jennifer Allen on September 19th, 2014 Our Rating: :: SHOOT EM ALLUniversal App - Designed for iPhone and iPad Mindless but fun, Tap Army is a lane-based shooter that should help you relieve some stress.   | Read more »
Monsters! Volcanoes! Loot! Epic Island f...
Monsters! Volcanoes! Loot! | Read more »
Plunder Pirates: Tips, Tricks, Strategie...
Ahoy There, Seadogs: Interested in knowing our thoughts on all this plundering and pirating? Check out our Plunder Pirates Review! Have you just downloaded the rather enjoyable pirate-em-up Plunder Pirates and are in need of some assistance? Never... | Read more »
Goat Simulator Review
Goat Simulator Review By Lee Hamlet on September 19th, 2014 Our Rating: :: THE GRUFFEST OF BILLY GOATSUniversal App - Designed for iPhone and iPad Unleash chaos as a grumpy goat in this humorous but short-lived casual game.   | Read more »
A New and Improved Wunderlist is Here fo...
A New and Improved Wunderlist is Here for iOS 8 Posted by Jessica Fisher on September 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Evernote Update for iOS 8 Adds Web Clipp...
Evernote Update for iOS 8 Adds Web Clipping, Quick Notes, and More Posted by Ellis Spice on September 19th, 2014 [ permalink ] | Read more »
Apple Names Ultimate Productivity Bundl...
Apple Names Ultimate Productivity Bundle by Readdle as the Essential Bundle on the App Store Posted by Jessica Fisher on September 19th, 2014 [ permalink | Read more »

Price Scanner via MacPrices.net

Updated Price Trackers
We’ve updated our Mac Price Trackers with the latest information on prices, bundles, and availability on systems from Apple’s authorized internet/catalog resellers: - 15″ MacBook Pros - 13″ MacBook... Read more
Mac Pros available for up to $260 off MSRP
Adorama has Mac Pros on sale for up to $260 off MSRP. Shipping is free, and Adorama charges sales tax in NY & NJ only: - 4-core Mac Pro: $2839.99, $160 off MSRP - 6-core Mac Pro: $3739.99, $260... Read more
13-inch 2.6GHz/256GB Retina MacBook Pros avai...
B&H Photo has the 13″ 2.6GHz/256GB Retina MacBook Pro on sale for $1379 including free shipping plus NY sales tax only. Their price is $120 off MSRP. Read more
Previous-generation 15-inch 2.0GHz Retina Mac...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros now available for $1599 including free shipping plus NY sales tax only. Their price is $400 off original MSRP. B&H... Read more
21″ 2.7GHz iMac available for $1179, save $12...
Adorama has 21″ 2.7GHz Hawell iMacs on sale for $1179.99 including free shipping. Their price is $120 off MSRP. NY and NJ sales tax only. Read more
iOS 8 Adoption Rate Slower than iOS 7, 6, Hit...
Apple began pushing out iOS 8 updates to eligible devices around 1pm ET on September 17, 2014. However, unlike with iOS 7, which boasted a wide variety of differences from its predecessor iOS 6, in... Read more
LIkely Final Definitive OS X 10.9.5 Mavericks...
Apple has released what will almost certainly be the last incremental version number update of OS X 10.9 Mavericks (save for futire security updates) before OS X 10.10 Yosemite is released next month... Read more
Fingerprints, Apple Pay and Identity Theft Wa...
On Sep 9th, CEO Tim Cook unveiled Apple Pay, along with the new iPhone 6 and iWatch. Apple Pay is a newly developed technology that utilizes a near field communication (NFC) to enable customer... Read more
Amazon Introduces Two All-New Kindles
Amazon on Thursday introduced the 7th generation of its Kindle dedicated e-reader device: Kindle Voyage, its top-of-the-line e-reader, and the new $79 Kindle, with a 20% faster processor, twice the... Read more
Save up to $300 on the price of a new Mac wit...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.