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

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

GraphicConverter 10.4.3 - $39.95
GraphicConverter is an all-purpose image-editing program that can import 200 different graphic-based formats, edit the image, and export it to any of 80 available file formats. The high-end editing... Read more
Google Chrome 60.0.3112.78 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
PDFpenPro 9.1 - Advanced PDF toolkit for...
PDFpenPro allows users to edit PDF's easily. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Create fillable forms and tables of content... Read more
PDFpen 9.1 - $74.95
PDFpen allows users to easily edit PDF's. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Features... Read more
DiskCatalogMaker 7.1.3 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Amadeus Pro 2.4 - Multitrack sound recor...
Amadeus Pro lets you use your Mac for any audio-related task, such as live audio recording, digitizing tapes and records, converting between a variety of sound formats, etc. Thanks to its outstanding... Read more
Little Snitch 4.0.1 - Alerts you about o...
Little Snitch gives you control over your private outgoing data. Track background activity As soon as your computer connects to the Internet, applications often have permission to send any... Read more
Sparkle Pro 2.2.1 - $79.99
Sparkle Pro will change your mind if you thought building websites wasn't for you. Sparkle is the intuitive site builder that lets you create sites for your online portfolio, team or band pages, or... Read more
iWatermark Pro 2.0.0fc4 - Easily add wat...
iWatermark Pro is the essential watermarking app for professional, business, and personal use. Easily secure and protect your photos with text, a graphic, a signature, or a QR watermark. Once added... Read more
Together 3.8.7 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Together Features Smart storage. With simple drag-and-... Read more

Latest Forum Discussions

See All

Mix and match magical brews in Miracle M...
Miracle Merchant, the charming fantasy card game by Tiny Touch Tales, is arriving next week. The development team, which also brought you Card Crawl and Card Thief, announced the game's launch with a pleasant little trailer that showcases the game'... | Read more »
Last Day on Earth: Zombie Survival guide...
Last Day on Earth: Zombie Survival is the latest big hit in the survival game craze. The gist of the game is pretty cut and dry -- try your best to survive in a world overrun by flesh-eating zombies. But Last Day on Earth justifies the hype... | Read more »
Eden: Renaissance (Games)
Eden: Renaissance 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Eden: Renaissance is a thrilling turn-based puzzle adventure set in a luxurious world, offering a deep and moving... | Read more »
Glyph Quest Chronicles guide - how to ma...
Glyph Quest returns with a new free-to-play game, Glyph Quest Chronicles. Chronicles offers up more of the light-hearted, good humored fantasy fun that previous games featured, but with a few more refined tricks up its sleeve. It's a clever mix of... | Read more »
Catch yourself a Lugia and Articuno in P...
Pokémon Go Fest may have been a bit of a disaster, with Niantic offering fans full refunds and $100 worth of in-game curency to apologize for the failed event, but that hasn't ruined trainers' chances of catching new legendary Pokémon. Lugia nad... | Read more »
The best deals on the App Store this wee...
There are quite a few truly superb games on sale on the App Store this week. If you haven't played some of these, many of which are true classics, now's the time to jump on the bandwagon. Here are the deals you need to know about. [Read more] | Read more »
Realpolitiks Mobile (Games)
Realpolitiks Mobile 1.0 Device: iOS Universal Category: Games Price: $5.99, Version: 1.0 (iTunes) Description: PLEASE NOTE: The game might not work properly on discontinued 1GB of RAM devices (iPhone 5s, iPhone 6, iPhone 6 Plus, iPad... | Read more »
Layton’s Mystery Journey (Games)
Layton’s Mystery Journey 1.0.0 Device: iOS Universal Category: Games Price: $15.99, Version: 1.0.0 (iTunes) Description: THE MUCH-LOVED LAYTON SERIES IS BACK WITH A 10TH ANNIVERSARY INSTALLMENT! Developed by LEVEL-5, LAYTON’S... | Read more »
Full Throttle Remastered (Games)
Full Throttle Remastered 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Originally released by LucasArts in 1995, Full Throttle is a classic graphic adventure game from industry legend Tim... | Read more »
Stunning shooter Morphite gets a new tra...
Morphite is officially landing on iOS in September. The game looks like the space shooter we've been needing on mobile, and we're going to see if it fits the bill quite shortly. The game's a collaborative effort between Blowfish Studios, We're Five... | Read more »

Price Scanner via MacPrices.net

USB 3.0 Promoter Group Announces USB 3.2 Upda...
The USB 3.0 Promoter Group has announced the pending release of the USB 3.2 specification, an incremental update that defines multi-lane operation for new USB 3.2 hosts and devices. USB Developer... Read more
Save on MacBook Pros with Apple Refurbished 2...
Apple recently dropped prices on Certified Refurbished 2016 15″ and 13″ MacBook Pros with models now as much as $590 off original MSRP. An Apple one-year warranty is included with each model, and... Read more
13-inch 2.3GHz/256GB MacBook Pros on sale for...
B&H Photo has 13″ 2.3GHz/256GB MacBook Pros in stock today and on sale for $100 off MSRP including free shipping plus NY & NJ sales tax only: – 13-inch 2.3GHz/256GB Space Gray MacBook Pro (... Read more
Clearance 2016 13-inch MacBook Airs, Apple re...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $809. An Apple one-year warranty is included with each MacBook, and shipping is free: – 13″ 1.6GHz/8GB/128GB MacBook Air: $... Read more
PHOOZY World’s First Thermal Capsules to Summ...
Summer days spent soaking up the sun can be tough on smartphones, causing higher battery consumption and overheating. To solve this problem, eXclaim IP, LLC has introduced the PHOOZY Thermal Capsule... Read more
2018 Honda Ridgeline with Android Auto and Ap...
The 2018 Honda Ridgeline is arriving in dealerships nationwide with a Manufacturer’s Suggested Retail Price (MSRP1) starting at $29,630. The 2017 Honda Ridgeline was named North American Truck of the... Read more
comScore Ranks Top 15 U.S. Smartphone Apps fo...
comScore, Inc. recently released data from comScore Mobile Metrix, reporting the top smartphone apps in the U.S. by audience reach for June 2017. * “Apple Music,” as it appears in comScore’s monthly... Read more
13-inch 3.1GHz MacBook Pros on sale for $100...
B&H Photo has the new 2017 13″ 3.1GHz Space Gray MacBook Pros in stock today and on sale for $100 off MSRP including free shipping. B&H charges sales tax in NY and NJ only: – 13″ 3.1GHz/256GB... Read more
Apple refurbished Mac minis available startin...
Apple has Certified Refurbished Mac minis available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: $419 $80 off MSRP – 2.6GHz Mac... Read more
Apple’s 2017 Back to School Promotion: Free B...
Purchase a new Mac using Apple’s Education discount, and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free. As part... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Poole -...
Job Summary The people here at Apple don't just create products - they create the kind of wonder that's revolutionised entire industries. It's the diversity of those Read more
SW Engineer *Apple* TV - Apple Inc. (United...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
Frameworks Engineering Manager, *Apple* Wat...
Frameworks Engineering Manager, Apple Watch Job Number: 41632321 Santa Clara Valley, California, United States Posted: Jun. 15, 2017 Weekly Hours: 40.00 Job Summary Read more
Product Manager - *Apple* Pay on the *Appl...
Job Summary Apple is looking for a talented product manager to drive the expansion of Apple Pay on the Apple Online Store. This position includes a unique Read more
*Apple* Retail - Multiple Positions - Apple...
SalesSpecialist - Retail Customer Service and SalesTransform 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.