TweetFollow Us on Twitter

Font Dialog
Volume Number:4
Issue Number:7
Column Tag:Assembly Language Lab

Font Dialog Box Using List Manager

By Ray A. Cameron, Brunswick, Victoria, Australia

Ray. A. Cameron is an Electrical Engineer from Brunswick, Victoria in Australia, employed by Telecom, the Australian Telecommunication Commission. He is currently involved in the introduction of optical fibre into the Customer Access Network. This is his first article for MacTutor.

MacTutor Down Under

Before I start writing about my routines l’d like to say how fantastic MacTutor is for the service that it is providing to Mac programmers in disseminating programming ideas and techniques. It doesn’t matter which language we program in, it is possible to gain information from every article published in MacTutor.

Something that I know would be beneficial to all readers of MacTutor is if the writers of articles include in their description not only how the program works (as published) but what problems they have encountered along the way or techniques thay have employed and why. Also any idiosyncrasies in the system software that don’t appear to be fully explained in Inside Macintosh.

What This Program Does

The FontDialog routine displays a Modal Dialog box for the user to select a font name, size and style. The routine is designed to be incorporated into a program, as I have done with the “Window” example (distributed with the old MDS software and included here), which is on this month’s source disk. There are two routines that I have written, the first routine (SetupFontMap) creates a record of all the ‘FONT’ resources available to the user in the system file. It doesn’t look for ‘FOND’ or ‘NFNT’ resources or fonts attached to documents. The next routine (FontDialog) creates a Modal Dialog box (Fig 1) so that the user can choose a font name, size and style. The font name and size lists are created with the List Manager from data stored in the FontMap record. The routine also includes a UserFilter with the Modal Dialog to handle events.

Some of the procedures and functions used in the FontDialog routine take up a number of lines and are used often so l’ve converted them into Macros to save space. I won’t describe the Macro file as it should be self explanatory.

Fig. 1 Our Font Dialog Box selects text, size & style

User Interface

The Dialog box presented in this example is similar to the one in Microsoft Word. Now that we can all use nested menus to select font, size and style, you might want to be old fashioned and go back to a text dialog box instead! You can select a font name by either clicking on a font name or by typing a character to select the first name starting with that character (or the first name to follow in alphabetical order). As you continue to type additional characters (up to 31) any file that matches the characters you type is found and selected. If you pause while typing, the next character is considered to be a new request, rather than a continuation of your first request. The Delay Until Repeat setting which you set in the (Control Panel) determines how long you can pause before additional characters are considered to be a new request. Hence our dialog box is fairly intelligent in that it includes a sort and search routine and uses the list manager, useful techniques for a variety of dialog functions.

The Font Size Selection Window displays the sizes that are currently available on the system (for the selected font name). If no font name is selected then the Font Size Selection Window is blank, this doesn’t affect the font size in the textedit window. A font size can be selected by clicking on the desired size or by typing in the font size. Numbers and the ‘back space’ character are assumed to be an input to alter the font size, whilst all other characters (except ‘cr’ & ‘enter’) are used to find a matching font name. The font style has been separated into two sections, ‘spacing’ (condense and extend) and ‘style’ (outline, bold, etc). When the dialog box is first displayed the radio buttons and check boxes reflect the current settings. If their settings are altered it is possible to reset them to their original values by clicking on the group title concerned (either ‘spacing’ or ‘style’). The settings are only reset if the mouse is released inside the title. To indicate that the mouse is inside the title the thickness of the frame around the group doubles. This type of facility (interface) lends itself to having the groups set to normal or plain if a double click occurs in the title, something which I haven’t implemented here.

At the bottom of the dialog box is displayed some (sample) text showing the affect of the selected settings. The sample text will only be displayed if the current settings of font name and size are valid. A valid font size can be from 4 to 127, normal quickdraw limitations.

If the Ok button is selected or the ‘cr’ or ‘enter’ keys are pressed while the current settings are invalid an alert box is displayed indicating which setting isn’t valid.

Fig. 2 After text selection, our sample text window allows typing in the chosen font & style

FontMap

To produce the dialog box I require the names of the available fonts on the system as well as the sizes available for each font. The idea of a font menu with a range of font sizes on it (ie MacWrite) is relatively easy, all that is required is to test if the selected font has a desired size. If it does then the size is shown in outlined style, whilst if it doesn’t its style is plain. To find every size available on the system for a particular font name is a little harder. I decided to produce a relocatable block which would contain the names of all the fonts (in alphabetical order) and the sizes of each font (in numerical order). Doing this reduces the amount of time required to set-up the Font Name and Font Size Selection Windows. Note that even some commercial software doesn’t bother to alphabetize font lists! A graphical representation of the FontMap is shown in Fig 3. The first (word) field contains the number of different fonts minus one. Then there are font references, one reference (of three words) for each font. The first field is the font number, the next is the offset to the font name and the last is the offset to the font size list. Both offsets are from the start of the FontMap. The font references are sorted into the alphabetical order of the font names. The space allocated for each font name is the smallest number of even bytes that the name will fit in. The font sizes for each font are sorted into their numerical order within each font size list. The first word of the font size list is the number of font sizes in the list, then follows the font sizes, one word per font size. The handle to the Map is stored for access by the FontDialog routine and could be used to prepare the font sizes in a menu. By having the names and sizes sorted within FontMap it means that when they are placed into a list their cell position relates to their position in the FontMap.

Fig. 3 Layout of our custom font map structure

Apple have laid down in their user interface guidelines that font sizes that exist on a system be represented in some way, as in outlining in a menu etc. With the new font family resources (‘FOND’s & ‘NFNT’s) it is possible to have a font that already has a style attribute associated with it, like Geneva Shadow. How are these fonts to be represented so that the user can tell them apart from a plain font size? The text sample is one solution and perhaps there are others.

Creating the Font Map

The SetupFontMap routine is called at the start of a program so that the FontMap can be used to set up the font size menu items. The routine, first of all evaluates what size to make the Map (relocatable block). It examines each ‘FONT’ resource on the system and determines if the resource contains a font name or a font size. If the resource is a font name, the font (resource) ID and the pointer to the name are stored on the stack. If the resource is a font size, the font (resource) ID is stored in a non-relocatable block (SizeBlock). As each resource is examined, a running total is kept of how large to make the FontMap and how many different fonts there are. The FontMap is created and the number of font names minus one is loaded into the first field. The font ID’s and name pointers are loaded into the font references from the stack. The font references are then sorted into the alphabetical order of the font names. The font names are then loaded into the Map, disposing of their original non-reloctable block in the process and replacing the name pointer with an offset. SetupFontMap then goes through SizeBlock and loads in all the font sizes associated with the first font. The sizes are then sorted into numerical order. SetupFontMap then continues until all fonts have their sizes loaded and sorted. All temporary blocks are disposed of as the routine is finished with them. The FontMap is then unlocked and control returns to the main program.

This routine should be rewritten so that it examines the font resources (‘FOND ‘, ‘FONT’ and ‘NFNT’) and the font resources associated with a document. It should also be recalled each time a new document is accessed in case there is a new font resource associated with it. But that’s a task l’ll leave for you. [Note that Apple discourages the use of fonts within documents now. -Ed]

Font Dialog Mechanics

The FontDialog routine would generally be accessed by the selection of a menu item. The items associated with a dialog are stored in an item list which contains the item type, whether it’s enabled or not and a pointer to the routine that will draw the item, as well as other variables. The order of the items in the list is very important (as I found out). The items are drawn and accessed in the order that they appear in the item list. If items overlap, the item highest in the list (lowest item number) takes precedent. I wanted to set up the ‘spacing’ and ‘style’ groups as shown in Fig 1 so that if I clicked on either the title or a control, the program returned from the ModalDialog trap. At this stage of writing the program I wasn’t using a UserFilter so I had to create routines to draw the bold frame around the Ok button and thin frames around the control groups. The problem arose when I wanted to draw the frame and the group title so that the frame wasn’t drawn through the title (as per Fig 1). If the frame is drawn then the title, the routine that draws the title erases a section of the frame where the title goes. To do this the useritem would have to have a lower item number than the title. The useritem that represented the frame was disabled so I thought that the other items that were enabled wouldn’t be affected by it. Wrong! By placing the useritem higher in the item list than the other items I had made all the lower items except for the top half of the title effectively invisible/disabled. To get around this problem (before I used a UserFilter) I placed the useritem lower in the item list and wrote a subroutine similar to TrackHeading. The routine created a region consisting of the useritem rect minus the group title rect, and made it the clipping region, it then drew a frame around the useritem rect and reset the clipping region. For details on regions and clipping check Chris Derossi’s article on “Quickdraw Does Regions!” (Pascal Procedures) in MacTutor Vol 1 No 3, February 1985. When a User Filter is used, the programmer isn’t confined to accessing the dialog items in their order, which simplifies the drawing of the items.

The FontDialog routine creates a non-relocatable block into which it stores all its variables. This was done so that memory is allocated only when the routine is called. It allows the main program to check to see if there is enough spare memory before the routine is called, or the routine could become a separate code segment that isn’t loaded into memory until it’s needed. The routine takes copies of the font number, size and face (style) that are passed to it so that these can be altered without affecting the original values, in case the user decides to cancel the dialog. The routine only accepts a single font variation (number, size and style), it isn’t suitable for altering multiple font variations.

The spacing radio buttons and style check boxes are set up to display the original settings. I made the condense and extend style variations radio buttons because there is no point in both variations being selected (they cancel one another out).

The Font Name and Size Selection Windows are then created and the available font names and sizes are loaded into their respective list. Each list has its selection flags set so that only one cell is selected at a time and empty cells aren’t selectable. Even though the selection flag was set so that only one cell is selected, I found that I could select more than one cell by using the LSetSelect trap. I wanted to set a cell and I assumed that the List Manager would deselect the currently selected cell. Instead I had to deselect the currently selected cell and then select the desired cell (as shown in DKeyDown). When the mouse is used to select a cell, only one cell is selected, all others are deselected.

Only enough cells are created in each list to contain the font names and sizes. In some cases there are blank lines in the list. Clicking below the cells deselects the current selection, sometimes. For some reason it is possible to click below the cells in one spot and have the selection deselected while not in others. The area in which this occurs is the height of a cell.

A Sample Display Text Edit Record is then setup so that the ‘STR ‘ resource number 264 is displayed in the useritem rect at the bottom of the dialog box. The string is displayed with the current font settings, if they are valid, if they aren’t valid then no text is displayed. The text is centered horizontally within the useritem rect, and also vertically if all the lines are visible.

The handles of the string resources to be used by the alert window are then loaded into the local variable block.

As the user modifies the settings in the dialog box, the routine checks to make sure that they are valid. If they aren’t valid a flag (OkActive) is cleared. I originally set the Ok button to be hilited with #254 (if the selections are invalid) which is supposed to make the control inactive but still indicate if it has been clicked in. When I did this, I found that the Ok button would be grey but it wouldn’t indicate if it was clicked in. If I dragged the mouse an outline of the Ok button would move in the vertical axis. The problem occured when I let the default Modal Dialog routine handle the mouse or when I caught the event in the UserFilter and used the TrackControl trap. For this reason l’ve left the Ok button active when the settings are invalid and display an alert if the Ok button, ‘cr’ or ‘enter’ are selected. Before the alert is displayed the routine determines which variables aren’t valid and sets up the param strings accordingly. I haven’t checked to see if this still occurs since my Mac has been “enhanced”. From a user interface perspective it is good practice to inform the user what the problem is instead of not accepting their input or sounding a beep.

After the items have all been set up the ModalDialog trap is called.

Dialog Filter Proc

The DUserFilter filters all the events that it needs to handle and lets the default routine handle the remainder (by returning false). DUserFilter handles its events and returns true and an item No. if the main program is to do some variable updating or house keeping due to the event (ie a new font name is selected). When the DUserFilter handles an event and a setting hasn’t altered, ie a click on the selected font name, the event is converted to a null event.

DNull checks to see if the mouse is within the textedit rect, if it is it converts the cursor to a handle, otherwise it sets it to the arrow. This section of code could be sped up by storing the textedit item rect in the local variable block instead of using the GetDItem trap every time. When ever a font attribute is altered the sample text is erased and the routine waits until KeyThresh ticks have occured and then redraws the sample with the new attributes. The DNull code checks to see if KeyTresh ticks have passed and if the sample requires updating. If it does then the DUserFilter returns true and item number 21 (a disabled useritem).

DMouseDown handles the mouse down events within the two group titles and the two list windows. All other mouse down events are handled by the default ModalDialog routines. When a mouse down occurs in either of the two group titles the routine (TrackHeading) tracks the mouse to see if it is released in it or not. If it is, ModalDialog returns with the item number, otherwise the event is set to null. When a mouse down occurs in either of the List Manager windows the routines check to see if the selection has altered. If it has ModalDialog returns with the item number, otherwise the event is set to null.

DKeyDown checks for a ‘cr’ or ‘enter’ key and returns item No 1 (Ok button) if it finds one. It then checks to see if a number or ‘back space’ character has been pressed, if one has it deselects the selected cell in the Font Size Selection Window (if one is selected) and returns false for the default ModalDialog routine to handle it. DKeyDown then uses the character to search for a font name (NameSearch), as described in the User Interface section. The List Manager trap LSearch isn’t suitable because it only checks for exact matches and I required the routine to check strings using the IUMagString trap. The FontMap is searched through because it is quicker than using the List Manager routines to check each cells contents. The routine then makes sure the desired cell is selected and visible.

DUpdate updates all the items in the dialog box. The update event removes the need to have an item number for every item that is drawn. A prime example is the bold box around the Ok button, another is the frame around the textedit item. Items don’t have to be drawn in the order in which they appear in the dialog’s item list. This allows the frames to be drawn around the ‘spacing’ and ‘style’ control item groups before the group titles are drawn. The programmer has complete control over what is drawn in the dialog and could in fact draw something that isn’t related to an item in the item list. When lists are drawn they don’t have a frame drawn around them, so l’ve had to include one on each list. After everything has been updated the event is set to a null event (SetoNull) and returned.

DActivate activates the dialog box (the two list windows and the dialog box’s text edit record). I’ve also included the code to deactivate the dialog box, even though it never gets used. When the ShowWindow trap is called to display the dialog box the window is created, a deactivate event is created for the original front window as is an activate event for the dialog window. The main program’s deactivate code isn’t accessed because its event loop has been broken, the main program has to deactivate the front window before the dialog box routine is called. DActivate has to be able to filter out the (de)activate event for the original front window and not handle it. When the alert is shown, the dialog should be deactivated (just like the case above) with similar code to that in DDeactivate. The LActivate trap removes (hides) scroll bars when the list is deactivated instead of inactivating them so I didn’t include the deactivate code because it was visually undesirable (sloppy).

The routines that handle the result of the ModalDialog trap perform the following functions:

DOk displays an alert if the settings aren’t valid and returns to the ModalDialog loop (WaitOk). If the settings are valid the original values are replaced with the desired values. The routine then passes onto DCancel.

DCancel closes the dialog box and disposes of the unwanted records and the local variable block. When there is a lot of information to be included (displayed) in a dialog, it is best to initially set the dialog to be invisible, setup the items involved and then show the dialog. This creates a clean crisp presentation, as opposed to items appearing slowly with delays between items. The same philosophy applies when the dialog is being closed. It is better to hide the dialog first and then to dispose of the items rather than to see items within the dialog (window) disappear before the window does, very sloppy.

Style resets the control check boxes to their original settings after the user has clicked in the style title. SStyle toggles a check box after it has been clicked in.

Spacing resets the control radio buttons to their original settings after the user clicked in the spacing title. SSpacing sets the radio button that was clicked in and clears the other radio buttons within the group.

The ModalDialog default routine handles a mouse down event in the control items (radio buttons and check boxes) and tracks the mouse and returns (with that items number) if the mouse is released within the item. The main routine then alters the value of the control, knowing that it was clicked in, this allows groups of radio buttons to be organised together.

FontName updates the font number variable after a new font name was selected. The Font Size Selection Window is then updated to show the sizes associated with the new font name. If no font name is selected the Font Size Selection Window is cleared.

FontSize updates the font size variable after a new font size was selected from the Font Size Selection Window. The textedit item (No 20) is then updated to display the new font size. If no font size was selected the textedit item retains its previous value (it isn’t set to zero).

GetEditSize updates the font size variable after the user has altered the textedit item through a key stroke (0 through to 9 or ‘backspace’). The currently selected size in the Font Size Selection Window is deselected. The ModalDialog default routine returns with the textedit item number when the mouse is clicked within its rect even though its value doesn’t change.

FontSample updates the font attributes associated with the sample text at the bottom of the dialog box. The text is then centered vertically within the user item rect if the height of the text lines is less than the height of the rect. The sample is then displayed with the new attributes.

Each of the above routines have code included in them to check if their font variable has in fact altered, if it has the sample text is then erased and isn’t updated until KeyThresh ticks have lapsed.

I’ll leave the remaining description of the routines to the comments placed within each listing. Best of luck with writing your dialog.

Fig. 4 A simple About Box Dialog


Continued in next frame
Volume Number:4
Issue Number:7
Column Tag:Assembly Language Lab

Font Dialog Box Using List Manager (code)


; File Window.Asm
;----------------------------------------------------------
;       Macintosh 68000 Development System
;----------------------------------------------------------
; The Window Sample Program issued with the MDS.
; Modified by Ray.A.Cameron to demonstate a Modal Dialog Box.
; Mon May 4, 1988 21:29:54

This application displays a window within which you can enter and edit text. Program control is through four menus: the Apple menu, the File menu, the Edit menu, and the Font menu.The Apple menu has the standard desk accessories and an About feature. The File menu lets you quit the application. The Edit menu lets you cut, copy, paste, and clear the text in the window or in the desk accessories. Undo is provided for desk accesories only. Command key equivalents for undo, cut, copy, and paste are provided. The Font menu lets you display a Modal Dialog Box to select a Font Name, Size and attributes.

;----------------------- Includes ----------------

Include Traps.D  ; Use System and ToolBox traps
Include ToolEqu.D; Use ToolBox equates
Include QuickEqu.D ; Use QuickDraw equates
Include SysEqu.D ; Use System equates
Include PackMacs.Txt ; Use Package equates

;------------------- Use of Registers -----------

; Operating Sys and Toolbox calls preserve D3-D7, A2-A4.

; Register use: A5-A7 are reserved by the system
;  D1-D3, A0-A1 are unused
;  D0 is used as a temp

ModifyReg Equ    D4  ; modifier bits from GetNextEvent 
MenuReg Equ D5   ; menu ID from MenuSelect,MenuKey
MenuItemReg Equ  D6; item ID from MenuSelect,MenuKey
AppleHReg Equ    D7; handle to the Apple Menu

TextHRegEqu A2   ; handle to TextEdit record
WindowPRegEqu    A3; pointer to editing window
EditHRegEqu A4   ; handle to Edit menu

;------------------- Equates ----------------

; These are equates associated with the resources
; for the Window example.

AppleMenu Equ    1 ; First item in MENU resource
  AboutItem Equ  1 ; First item in Apple menu

FileMenuEqu 2  ; Second item in MENU resource
  QuitItem  Equ  1 ; First item in File menu

EditMenuEqu 3  ; Third item in MENU resource
  UndoItemEqu    1 ; Items in Edit menu
  CutItem Equ    3 ; (Item 2 is a line)
  CopyItemEqu    4
  PasteItem Equ  5
  ClearItem Equ  6
  
FontMenuEqu 4  ; Fourth item in MENU resource
  DialogItemEqu  1 ; Only item in Font menu

AboutDialog Equ  1 ; About dialog is DLOG resource #1
ButtonItemEqu    1 ; First item in DITL used by DLOG #1
ASample Equ 1  ; Sample Window is WIND resource #1

;-------------------- Xdefs ----------------

; Xdef all labels to be symbolically displayed by debugger.

 Xdef   Start
 Xdef   InitManagers
 Xdef   SetupMenu
 Xdef   SetupWindow
 Xdef   SetupTextEdit
 Xdef   Activate
 Xdef   Deactivate
 Xdef   Update
 Xdef   KeyDown
 Xdef   MouseDown
 Xdef   SystemEvent
 Xdef   Content
 Xdef   Drag
 Xdef   InMenu
 Xdef   About
 
 XRef   SetupFontMap ; Routines
 XRef   FontDialog
 
 XRef   FontMap  ; Variable
 
;----------------- Main Program -------------
Start 
 Bsr    InitManagers ; Initialize managers
 Bsr    SetupMenu; Build menus, draw menu bar
 Bsr    SetupWindow; Draw Editing Window
 Bsr    SetupTextEdit; Initialize TextEdit
 Bsr    SetupFontMap ; Initialize the FontMap
EventLoop ; Main Program Loop
 _SystemTask; Update Desk Accessories
 ; ProcedureTEIdle (hTE:TEHandle);
 Move.l TextHReg,-(SP)    ; Get handle to text record
 _TEIdle; blink cursor etc.
 
 ; Function GetNextEvent(eventMask: Integer
 ; Var theEvent: EventRecord) : Boolean
 Clr    -(SP)    ; Clear space for result
 Move   #$0FFF,-(SP) ; Allow 12 low events
 Pea    EventRecord; Place to return results
 _GetNextEvent   ; Look for an event
 Move   (SP)+,D0 ; Get result code
 Beq    EventLoop; No event... Keep waiting
 Bsr    HandleEvent; Go handle event
 Beq    EventLoop; Not Quit, keep going
 Rts    ; Quit, exit to Finder

Note: When an event handler finishes, it returns the Z flag set. If Quit was selected, it returns with the Z flag clear. An Rts is guaranteed to close all files and launch the Finder.

;------------------- InitManagers -------------

InitManagers
 Pea    -4(A5)   ; Quickdraw's global area
 _InitGraf; Init Quickdraw
 _InitFonts ; Init Font Manager
 Move.l #$0000FFFF,D0; Flush all events
 _FlushEvents
 _InitWindows    ; Init Window Manager
 _InitMenus ; Init Menu Manager
 Clr.l  -(SP)    ; No restart Procedure
 _InitDialogs    ; Init Dialog Manager
 _TEInit; Init Text Edit
 _InitCursor; Turn on arrow cursor
 Rts

;--------------------- SetupMenu ---------------

SetupMenu

; Apple Menu Set Up.  

 ; Function GetMenu (menu ID:Integer): MenuHandle;
 Clr.l  -(SP)    ; Space for menu handle
 Move   #AppleMenu,-(SP)  ; Apple menu resource ID 
 _GetRMenu; Get menu handle 
 Move.l (SP),AppleHReg  ; Save for later comparison
 Move.l (SP),-(SP) ; Copy handle for AddResMenu
 
 Clr    -(SP)    ; Append to menu
 _InsertMenu; Which is currently empty

 Move.l #'DRVR',-(SP); Load all drivers 
 _AddResMenu; And Add to Apple menu

; File Menu Set Up

 Clr.l  -(SP)    ; Space for menu handle
 Move   #FileMenu,-(SP) ; File Menu Resource ID 
 _GetRMenu; Get File menu handle

 Clr    -(SP)    ; Append to list
 _InsertMenu; After Apple menu

; Edit Menu Set Up

 Clr.l  -(SP)    ; Space for menu handle
 Move   #EditMenu,-(SP) ; Edit menu resource ID
 _GetRMenu; Get handle to menu
 Move.l (SP),EditHReg; Save for later
        ; Leave on stack for Insert
 
 Clr    -(SP)    ; Append to list
 _InsertMenu; After File menu
 
; Font Menu Set Up

 Clr.l  -(SP)    ; Space for menu handle
 Move   #FontMenu,-(SP) ; Font Menu Resource ID 
 _GetRMenu; Get File menu handle

 Clr    -(SP)    ; Append to list
 _InsertMenu; After Edit menu

 _DrawMenuBar    ; Display the menu bar
 Rts

;---------------- SetupWindow ---------------

SetupWindow

 ; Function GetNewWindow (windowID: Integer; wStorage: Ptr; 
 ;       behind: WindowPtr) : WindowPtr;
 Clr.l  -(SP)    ; Space for window pointer
 Move   #ASample,-(SP)    ; Resource ID for window
 Pea    WindowStorage(A5) ; Storage for window
 Move.l #-1,-(SP); Make it the top window
 _GetNewWindow   ; Draw the window
 Move.l (SP),WindowPReg   ; Save for later 
 
 _SetPort ; Make it the current port
 Rts
 
;------------- SetupTextEdit ----------------

SetupTextEdit

 ; ProcedureTENew (destRect,viewRect: Rect): TEHandle;
 Clr.l  -(SP)    ; Space for text handle 
 Pea    DestRect ; DestRect Rectangle
 Pea    ViewRect ; ViewRect Rectangle
 _TENew ; New Text Record
 Move.l (SP)+,TextHReg  ; Save text handle
 Rts
 
;------------- Event Handling Routines --------

HandleEvent

Use the event number as an index into the Event table. These 12 events are all the things that could spontaneously happen while the program is in the main loop.

Move Modify,ModifyReg ; More useful in a reg

Move What,D0 ; Get event number

Add D0,D0 ; *2 for table index

Move EventTable(D0),D0 ; Point to routine offset

Jmp EventTable(D0) ; and jump to it

EventTable

Dc.w NextEvent-EventTable ; Null Event (Not used)

Dc.w MouseDown-EventTable ; Mouse Down

Dc.w NextEvent-EventTable ; Mouse Up (Not used)

Dc.w KeyDown-EventTable ; Key Down

Dc.w NextEvent-EventTable ; Key Up (Not used)

Dc.w KeyDown-EventTable ; Auto Key

Dc.w Update-EventTable ; Update

Dc.w NextEvent-EventTable ; Disk (Not used)

Dc.w Activate-EventTable ; Activate

Dc.w NextEvent-EventTable ; Abort (Not used)

Dc.w NextEvent-EventTable ; Network (Not used)

Dc.w NextEvent-EventTable ; I/O Driver (Not used)

;-------------------- Event Actions -----------------

Activate

An activate event is posted by the system when a window needs to be activated or deactivated. The information that indicates which window needs to be updated was returned by the NextEvent call.

 Cmp.l  Message,WindowPReg; Was it our window?
 Bne  NextEvent  ; No, get next event
 Btst #activeFlag,ModifyReg ; Activate?
 Beq  Deactivate ; No, go do Deactivate

To activate our window, activate TextEdit, and disable Undo since we don't support it. Then set our window as the port since an accessory may have changed it. This activate event was generated by SelectWindow as a result of a click in the content region of our window. If the window had scroll bars, we would do ShowControl and HideControl here too.

 ; ProcedureTEActivate (hTE: TEHandle);
 Move.l TextHReg,-(SP)    ; Move Text Handle To Stack
 _TEActivate; Activate Text

 ; Procedure DisableItem (menu:MenuHandle; item:Integer);
 Move.l EditHReg,-(SP)    ; Get handle to the menu
 Move   #UndoItem,-(SP)   ; Enable 1st item (undo)
 _DisableItem

SetOurPort; used by InAppleMenu

 Move.l WindowPReg,-(SP)  ; an accessory might have
 _SetPort ; changed it.

NextEvent 
 Moveq #0,D0; Say that it's not Quit
 Rts    ; return to EventLoop
 
Deactivate

 Move.l TextHReg,-(SP)    ; Get Text Handle
 _TeDeActivate   ; Un Activate Text
 Move.l EditHReg,-(SP)    ; Get handle to the menu
 Move   #UndoItem,-(SP)   ; Enable 1st item (undo)
 _EnableItem
 Bra    NextEvent; Go get next event
 
Update  

The window needs to be redrawn. Erase the window and then call TextEdit to redraw it.

 ; ProcedureBeginUpdate (theWindow: WindowPtr);
 Move.l WindowPReg,-(SP)  ; Get pointer to window
 _BeginUpDate    ; Begin the update

 ; EraseRect (rUpdate: Rect);
 Pea    ViewRect ; Erase visible area
 _EraseRect
 
 ; TEUpdate (rUpdate: Rect; hTE: TEHandle);
 Pea    ViewRect ; Get visible area
 Move.l TextHReg,-(SP)    ; and handle to text 
 _TEUpdate; then update the window

 ; ProcedureEndUpdate (theWindow: WindowPtr);
 Move.l WindowPReg,-(SP)  ; Get pointer to window
 _EndUpdate ; and end the update
 Bra    NextEvent; Go get next event
 
KeyDown 

A key was pressed. First check to see if it was a command key. If so, go do it. Otherwise pass the key to TextEdit.

 Btst   #CmdKey,ModifyReg ; Is command key down?
 Bne    CommandDown; handle command key

 ; ProcedureTEKey (key: CHAR; hTE: TEHandle);
 Move   Message+2,-(SP)   ; Get character
 Move.l TextHReg,-(SP)    ; and text record
 _TEKey ; Give char to TextEdit
 Bra    NextEvent; Go get next event
 
CommandDown 

The command key was down. Call MenuKey to find out if it was the command key equivalent for a menu command, pass the menu and item numbers to Choices.

 ; Function MenuKey (ch:CHAR): LongInt;
 Clr.l  -(SP)    ; Space for Menu and Item
 Move   Message+2,-(SP)   ; Get character
 _MenuKey ; See if it's a command
 Move   (SP)+,MenuReg; Save Menu
 Move   (SP)+,MenuItemReg ; and Menu Item
 Bra    Choices  ; Go dispatch command


;---------Mouse Down Events And Their Actions-----

MouseDown 

If the mouse button was pressed, we must determine where the click occurred before we can do anything. Call FindWindow to determine where the click was; dispatch the event according to the result.

 ; Function FindWindow (thePt: Point; 
 ;             Var whichWindow: WindowPtr): Integer;
 Clr    -(SP)    ; Space for result
 Move.l Point,-(SP); Get mouse coordinates
 Pea    WWindow  ; Event Window
 _FindWindow; Who's got the click? 
 Move   (SP)+,D0 ; Get region number
 Add    D0,D0    ; *2 for index into table
 Move   WindowTable(D0),D0; Point to routine offset
 Jmp    WindowTable(D0)   ; Jump to routine
 
WindowTable

 Dc.w   NextEvent-WindowTable ; In Desk (Not used)
 Dc.w   InMenu-WindowTable; In Menu Bar
 Dc.w   SystemEvent-WindowTable ; System Window
 Dc.w   Content-WindowTable ; In Content
 Dc.w   Drag-WindowTable  ; In Drag
 Dc.w   NextEvent-WindowTable ; In Grow (Not used)
 Dc.w   NextEvent-WindowTable ; In Go Away (Not used)

SystemEvent 

The mouse button was pressed in a system window. SystemClick calls the appropriate desk accessory to handle the event.

 ; ProcedureSystemClick (theEvent: EventRecord;
 ;              theWindow: WindowPtr);
 Pea    EventRecord; Get event record
 Move.l WWindow,-(SP); and window pointer
 _SystemClick    ; Let the system do it
 Bra    NextEvent; Go get next event
 
Content 

The click was in the content area of a window. If our window was in front, then call Quickdraw to get local coordinates, then pass the coordinates to TextEdit. We also determine whether the shift key was pressed so TextEdit can do shift-clicking. If our window wasn't in front, Move it to the front, but don't process click.

 Clr.l  -(SP)    ; clear room for result
 _FrontWindow    ; get FrontWindow
 Move.l (SP)+,D0 ; Is front window pointer
 Cmp.l  WindowPReg,D0; same as our pointer?
 Beq.s  @1; Yes, call TextEdit

 We weren't active, select our window.  This causes an activate event.

 ; ProcedureSelectWindow (theWindow: WindowPtr);
 Move.l WWindow,-(SP); Window Pointer To Stack
 _SelectWindow   ; Select Window
 Bra    NextEvent; and get next event

@1 

; We were active, pass the click (with shift) to TextEdit.

 ; ProcedureGlobalToLocal (Var pt:Point);
 Pea    Point    ; Mouse Point
 _GlobalToLocal  ; Global To Local

 ; Procedure   TEClick (pt: Point; extend: Boolean; hTE: TEHandle);
 Move.l Point,-(SP); Mouse Point (GTL)
 Btst   #shiftKey,ModifyReg ; Is shift key down?
 Sne    D0; True if shift down

Note: We want the Boolean in the high byte, so use Move.b. The 68000 pushes an extra, unused byte on the stack for us.

 Move.b D0,-(SP) 
 Move.l TextHReg,-(SP)  ; Identify Text
 _TEClick ; TEClick
 Bra    NextEvent; Go get next event
 
Drag

 Move.l WWindow,-(SP); Pass window pointer
 Move.l Point,-(SP); mouse coordinates
 Pea    WBounds  ; and boundaries
 _DragWindow; Drag Window
 Bra    NextEvent; Go get next event
 
InMenu  

 Clr.l  -(SP)    ; Get Space For Menu Choice
 Move.l Point,-(SP); Mouse At Time Of Event
 _MenuSelect; Menu Select
 Move   (SP)+,MenuReg; Save Menu
 Move   (SP)+,MenuItemReg ; and Menu Item

On entry to Choices, the resource ID of the Menu is saved in the low word of a register, and the resource ID of the MenuItem in another. The routine MenuKey, used when a command key is pressed, returns the sameinfo.

Choices ; Called by command key too

 Cmp  #AppleMenu,MenuReg  ; Is It In Apple Menu?
 Beq  InAppleMenu; Go do Apple Menu
 Cmp  #FileMenu,MenuReg ; Is It In File Menu?
 Beq  InFileMenu ; Go do File Menu
 Cmp  #EditMenu,MenuReg ; Is It In Edit Menu?
 Beq  InEditMenu ; Go do Edit Menu
 Cmp  #FontMenu,MenuReg ; Is It In Font Menu?
 Beq  InFontMenu ; Go do Font Menu
 
ChoiceReturn

 Bsr    UnHiliteMenu ; Unhighlight the menu bar
 Bra    NextEvent; Go get next event
 
InFileMenu

 Cmp    #QuitItem,MenuItemReg ; Is It Quit?
 Bne    ChoiceReturn ; No, Go get next event
 Bsr    UnHiliteMenu ; Unhighlight the menu bar
 Move   #-1,D0   ; say it was Quit
 Rts
 
InEditMenu

; First, call SystemEdit.  If a desk accessory is active that uses the 
Edit menu (such as the Notepad) this lets it use our menu. Decide whether 
it was cut, copy, paste, or clear.  Ignore Undo since we didn't implement 
it.

 Bsr    SystemEdit ; Desk accessory active?
 Bne  ChoiceReturn ; Yes, SystemEdit handled it
 Cmp    #CutItem,MenuItemReg; Is It Cut?
 Beq    Cut ; Yes, go handle it
 Cmp    #CopyItem,MenuItemReg ; Is it Copy?
 Beq    Copy; Yes, go handle it
 Cmp    #PasteItem,MenuItemReg; Is it Paste?
 Beq    Paste    ; Yes, go handle it
 Cmp    #ClearItem,MenuItemReg; Is it Clear?
 Beq    ClearIt  ; Yes, go handle it
 Bra    ChoiceReturn ; Go get next event
 
InFontMenu

 Cmp    #DialogItem,MenuItemReg  ; Is It Dialog?
 Bne    ChoiceReturn ; No, Go get next event
 
 ; ProcedureTEDeActivate (hTE: TEHandle)
 Move.l TextHReg,-(SP)    ; Identify Text
 _TEDeActivate   ; Deactivate Text
 
; Obtain the current Font number, size and attributes to setup the dialog 
box.
 Movea.lTextHReg,A0; Handle to the TE record
 Movea.l(A0),A0  ; Pointer to the TE record
 Move.w teFont(A0),D0;- Font Number
 Cmp.w  #1,D0    ;  Default number?
 Bne.s  @0;  No, -> @0
 Move.w ApFontID,D0;  Yes, load default number
@0 Move.w D0,DtxFont(A5)
 Clr.w  D0;- Font Face
 Move.b teFace(A0),D0;   Place the attribute bits in the
 Move.w D0,DtxFace(A5)  ;  low byte of DtxFace(A5).
 Move.w teSize(A0),D0;- Font Size
 Bne.s  @1;  Default size, No -> @1
 Move.b FMDefaultSize,D0  ; Yes, load default size
@1 Move.w D0,DtxSize(A5)
 
 Clr.w  -(SP)
 Pea    DtxFont(A5); Load the font's number address
 Pea    DtxFace(A5); Load the font's face address
 Pea    DtxSize(A5); Load the font's size address
 Jsr    FontDialog

Test to see if the okButton was pressed (ie install the new Font variables). If the cancelButton was pressed leave the Font variables as they are.

 Move.b (SP)+,D0
 Beq.s  @2

Update the Font number, size, and face fields in the textedit record. The teAscent and teLineHite fields also require up dating. Reset the port to the textedit window, since the current GraphPort has been changed by the FontDialog routine.

 Move.l WindowPReg,-(SP)  
 _SetPort
 Move.w DtxFont(A5),-(SP)
 _TextFont
 Move.w DtxFace(A5),-(SP)
 _TextFace
 Move.w DtxSize(A5),-(SP)
 _TextSize
 
 ; Procedure GetFontInfo (Var Info: FontInfo)
 Pea    Info(A5)
 _GetFontInfo
 
 Movea.lTextHReg,A1; DeReference the Handle
 Movea.l(A1),A1
 Move.w DtxFont(A5),teFont(A1); teFont
 Move.b DtxFace+1(A5),teFace(A1) ; teFace
 Move.w DtxSize(A5),teSize(A1); teSize
 Move.w Info+ascent(A5),teAscent(A1) ; teAscent
 Move.w Info+ascent(A5),D0; teLineHite
 Add.w  Info+descent(A5),D0
 Add.w  Info+leading(A5),D0
 Move.w D0,teLineHite(A1)
 
@2 Bra  GoSetOurPort 

InAppleMenu

 Cmp    #AboutItem,MenuItemReg; Is It About?
 Beq  About ; If So Goto About...
 
 ; ProcedureGetItem (menu: MenuHandle; item: Integer; 
 ;                        Var itemString: Str255);
 Move.l AppleHReg,-(SP)   ; Look in Apple Menu
 Move   MenuItemReg,-(SP) ; What Item Number?
 Pea    DeskName ; Get Item Name
 _GetItem ; Get Item

 ; Function OpenDeskAcc (theAcc: Str255) : Integer;
 Clr    -(SP)    ; Space For Opening Result
 Pea    DeskName ; Open Desk Acc
 _OpenDeskAcc    ; Open It
 Move   (SP)+,D0 ; Pop result
 
GoSetOurPort

 Bsr    SetOurPort ; Set port to us 
 Bra    ChoiceReturn ; Unhilite menu and return
 
;----------- Text Editing Routines ---------

Cut; CUT
 Move.l TextHReg,-(SP)    ; Identify Text
 _TECut ; Cut it and copy it
 Bra    ChoiceReturn ; Go get next event
Copy    ; COPY
 Move.l TextHReg,-(SP)    ; Identify Text
 _TECopy; Copy text to clipboard
 Bra    ChoiceReturn ; Go get next event
Paste   ; PASTE
 Move.l TextHReg,-(SP)    ; Identify Text
 _TEPaste ; Paste
 Bra    ChoiceReturn ; Go get next event
ClearIt ;CLEAR
 Move.l TextHReg,-(SP)    ; Point to text
 _TEDelete; Clear without copying
 Bra    ChoiceReturn ; Go get next event

SystemEdit does undo, cut, copy, paste, and clear for desk accessories. It returns False (Beq) if the active window doesn't belong to a desk accessory.

SystemEdit
 
 ; Function SystemEdit (editCmd:Integer): Boolean;
 Clr    -(SP)    ; Space for result
 Move   MenuItemReg,-(SP) ; Get item in Edit menu
 Subq   #1,(SP)  ; SystemEdit is off by 1
 _SysEdit ; Do It 
 Move.b (SP)+,D0 ; Pop result
 Rts    ; Beq if NOT handled

UnhiliteMenu
 
 ; ProcedureHiLiteMenu (menuID: Integer);
 Clr    -(SP)    ; All Menus
 _HiLiteMenu; UnHilite Them All
 Rts
 

;--------------------Misc Routines------------

About



 ; Function GetNewDialog (dialogID: Integer; dStorage: Ptr; 
 ;                             behind: WindowPtr) : DialogPtr
 Clr.l  -(SP)    ; Space For dialog pointer
 Move   #AboutDialog,-(SP); Identify dialog rsrc #
 Pea    DStorage ; Storage area
 Move.l #-1,-(SP); Dialog goes on top
 _GetNewDialog   ; Display dialog box
 Move.l (SP),-(SP) ; Copy handle for Close
 ; Handle on stack
 _SetPort ; Make dialog box the port
 Move.l TextHReg,-(SP)  ; Identify Text
 _TEDeActivate   ; Deactivate Text

WaitOK

 ; ProcedureModalDialog (filterProc: ProcPtr; 
 ;      Var itemHit: Integer);
 Clr.l  -(SP)    ; Clear space For handle
 Pea    ItemHit  ; Storage for item hit
 _ModalDialog    ; Wait for a response

 Move   ItemHit,D0 ; Look to see what was hit
 Cmp    #ButtonItem,D0  ; was it OK?
 Bne    WaitOK   ; No, wait for OK
 
 _CloseDialog    ; Handle already on stack
  Bra   GoSetOurPort ; Set port to us and return
  
; ----------- Data Starts Here ------------

EventRecord ; NextEvent's Record
 What:  Dc  0    ; Event number
 Message: Dc.l   0 ; Additional information
 When:  Dc.l0    ; Time event was posted 
 Point: Dc.l0    ; Mouse coordinates
 Modify:Dc  0    ; State of keys and button
 WWindow: Dc.l   0 ; Find Window's Result

DStorageDcb.w    DWindLen,0 ; Storage For Dialog
DeskNameDcb.w    16,0; Desk Accessory's Name
WBounds Dc  28,4,308,508  ; Drag Window's Bounds
ViewRectDc  5,4,245,405 ; Text Record's View Rect
DestRectDc  5,4,245,405 ; Text Record's Dest Rect
ItemHit Dc0 ; Item clicked in dialog

;-------------- Nonrelocatable Storage ---------

Variables declared using Ds are placed in a global space relative to A5. When these variables are referenced, A5 must be explicitly mentioned.

DtxFont Ds.w1
DtxFace Ds.w1
DtxSize Ds.w1
Info    Ds.w4    ; FontInfo Record
WindowStorage    Ds.wWindowSize  ; Storage for Window

End

;-------------- FontDialog --------------------

; Written by Ray.A.Cameron
; Version 1
;Wed May 6, 1988 21:00:51


XDef    FontDialog ; Routine's name
XRef    FontMap  ; Variable's name

;---------- Includes -------------

Include Traps.D  ; Use System and ToolBox traps
Include ToolEqu.D; Use ToolBox Equates
Include QuickEqu.D ; Use QuickDraw Equates
Include SysEqu.D ; Use System Equates
Include PackMacs.Txt ; Use Package Equates
Include FontMacros.Txt  ; Use Macro file


; ---------- Equates ----------
FontDPtrEqu A4

FDialog Equ 260  ; Font dialog is DLOG resource #260
ADialog Equ 260  ; Alert dialog is ALRT resource #260
True    Equ 1    ; Boolean True
False   Equ 0    ; Boolean False
enterCode Equ  3 ; ASCII Enter
bsCode  Equ 8    ; ASCII Back Space
crCode  Equ 13   ; ASCII Carriage Return
param0  Equ 0    ; Offset to string 0 in DAStrings
param1  Equ 4    ; Offset to string 1 in DAStrings
param2  Equ 8    ; Offset to string 2 in DAStrings
OkActiveEqu 0    ; OkActive bit within Dialog Flags
SUpdate Equ 1    ; Sample update bit within Dialog Flags


Font Dialog 2
	








Continued from - Font Dialog


SRect   Equ 2    ; Sample rect bit within Dialog Flags
SKey    Equ 3    ; Sample key bit  within Dialog Flags

; --------- Font Dialog Data Record -------

DStorageEqu $0   ; Storage for the Dialog Record
TempFontEqu $AA  ; Currently selected font number
TempFaceEqu $AC  ; Currently selected font style
TempSizeEqu $AE  ; Currently selected font size
DFlags  Equ $B0  ; Dialog Flags
NameListH Equ  $B2 ; Font Name Selection List's Handle
NameCellEqu $B6  ; Font Name selected cell
SizeListH Equ  $BA ; Font Size Selection List's Handle
SizeCellEqu $BE  ; Font Size selected cell
TempCellEqu $C2  ; Temporary Cell variable
Item    Equ $C6  ; Item's handle or procedure
ItemtypeEqu $CA  ; Item's type
ItemBox Equ $CC  ; Item's enclosing rect
ItemHit Equ $D4  ; Item clicked in dialog
loc_pt  Equ $D6  ; mouse location
InitBoundsEqu  $DA ; Init size of Lists
TextCursorEqu  $E2 ; Handle to the IBeam cursor
thename Equ $E6  ; Text string
pnState Equ $1E6 ; Original state of the pen
String1 Equ $1F8 ; Alert text string1
String2 Equ $1FC ; Alert text string2
String3 Equ $200 ; Alert text string3
Sample  Equ $204 ; Sample Text Edit Handle
SampleRectEqu  $208; Sample Text Edit Rect
SampleTicks Equ  $210; Ticks when Sample required updated
info    Equ $214 ; GetFontInfo record
search  Equ $21C ; String to search Font Name List

Globalslength  Equ $23C

; This routine receives the following inputs:
;  teFont: The current font's number
;teFace: The current type face's attributes in low byte
;Bit 0 - Bold    Bit 3 - Outline   Bit 6 - Extend
;Bit 1 - Italic  Bit 4 - Shadow
;Bit 2 - Underline Bit 5 - Condense
;teSize: The current font's size

A ModalDialog box is displayed to allow the user to choose the font attributes that they desire. If the Ok button, enter key or carriage return is pressed the selected values will replace the original values otherwise the values remain the same.

FontDialog

 Link A6,#0 
 ; Boolean result20(A6) ; Ok or Cancel
 ; DtxFont Address 16(A6) ; Address of current Font number
 ; DtxFace Address 12(A6) ; Address of current Font style
 ; DtxSize Address 8(A6)  ; Address of current Font size
 ; Return Address4(A6)
 ; Old A6 (A6)

 Movem.lD0-D7/A0-A4,-(SP) ; Save register values.
 Move.w #False,20(A6); Set up to return False.
 
 ; Create a non-relocatable block for Font Data Record.
 Move.l #Globalslength,D0
 _NewPtr,CLEAR
 Move.l A0,FontDRec(A5)   ; Store the pointer.
 Movea.lA0,FontDPtr

 GetPenStatepnState(A4) ; Save the current pen settings.
 ; Load the present values of the font number, face and size  
 ; into temporary locations.
 Movea.l16(A6),A0; Font number.  
 Move.w (A0),TempFont(A4) 
 Movea.l12(A6),A0; Font face. 
 Move.w (A0),TempFace(A4) 
 Movea.l8(A6),A0 ; Font size.
 Move.w (A0),TempSize(A4)

 ; Obtain the iBeamCursor's resource and lock it down.
 ; Function GetCursor (cursorID: Integer): CursHandle
 Subq.l #4,SP
 Move.w #iBeamCursor,-(SP)
 _GetCursor
 Move.l (SP)+,TextCursor(A4)
 HLock  TextCursor(A4)

 Subq.l #4,SP    ; Space for dialog pointer.
 Move.w #FDialog,-(SP)  ; Identify dialog rsrc #.
 Move.l FontDPtr,-(SP)  ; Storage area.
 Move.l #-1,-(SP); Dialog goes on top.
 _GetNewDialog
 _SetPort
 
 Move.l OneOne,InitBounds+bottom(A4) 
 Bset.b #OkActive,DFlags(A4) ; selections are valid.
 
 ; Lock FontMap while its information is being accessed.
 HLock  FontMap(A5)
 DeRefHndle FontMap(A5),A3

Set up the Style check boxes so that they show the current font's values.

 Move.w TempFace(A4),D0   ; current face (style) byte.
 Move.w #4,-(SP) ; Item No 4.
 Move.w #5,-(SP) ; 5 Items (check boxes).
 Move.w D0,-(SP) ; Bits to set.
 Bsr    SControl

Set up the Spacing radio buttons so that they show the current fonts values.

 Move.w TempFace(A4),D0 ; current face (style) byte.
 Andi.w #%01100000,D0; Examine Condense & Extend.
 Bne.s  @0; If neither are set, then
 Move.w #%00010000,D0; add bit to represent "Normal".
@0 Lsr.W#4,D0
 
 Move.w #11,-(SP); Item No 11.
 Move.w #3,-(SP) ; 3 Items (radio buttons).
 Move.w D0,-(SP) ; Bits to set.
 Bsr    SControl
 
 ; Set up the Font Name Selection Window

 GetDItem FontDPtr,#17,Itemtype(A4),Item(A4),ItemBox(A4)
 
 Subq.l #4,SP    ; Space for the handle.
 Pea    ItemBox(A4)
 Pea    InitBounds(A4)    ; Create one cell.
 Clr.l  -(SP)    ; Cell size for text.
 Move.w #0,-(SP) ; Text definition procedure.
 Move.l FontDPtr,-(SP)
 Move.b #False,-(SP) ; drawIt
 Move.b #False,-(SP) ; hasGrow
 Move.b #False,-(SP) ; scrollHoriz
 Move.b #True,-(SP); scrollVert
 _LNew
 
 Move.l (SP),NameListH(A4); Store the List's handle.
 DeRefHndle (SP)+,A0 ; Set the selection flags.
 Move.b #%10000010,selFlags(A0)    ; lOnlyOne, lNoNilHilite
 Move.l #$FFFF0000,NameCell(A4)    ; (0,-1), no cell     
 Jsr    LdNames  ; Load the Font Names.

; Set up the Font Size Selection Window

 GetDItem FontDPtr,#19,Itemtype(A4),Item(A4),ItemBox(A4)
 
 ; Function LNew (rView, dataBounds: Rect; cSize: Point; 
 ; theProc: Integer; theWindow: WindowPtr; drawIt, hasGrow, 
 ; scrollHoriz, scrollVert: Boolean): ListHandle

 Subq.l #4,SP    ; Space for the handle.
 Pea    ItemBox(A4)
 Pea    InitBounds(A4)    ; Create one cell.
 Clr.l  -(SP)    ; Cell size for text.
 Move.w #0,-(SP) ; Text definition procedure.
 Move.l FontDPtr,-(SP)
 Move.b #False,-(SP) ; drawIt
 Move.b #False,-(SP) ; hasGrow
 Move.b #False,-(SP) ; scrollHoriz
 Move.b #True,-(SP); scrollVert
 _LNew
 
 Move.l (SP),SizeListH(A4); Store the List's handle.
 DeRefHndle (SP)+,A0 ; Set the selection flags.
 Move.b #%10000010,selFlags(A0)    ; 1OnlyOne, lNoNilHilite
 Move.l #$FFFF0000,SizeCell(A4)    
 
 Jsr    LdSizes  ; Load the current Font's Sizes.

; Set up the Font Size Text Edit item 

 Jsr    SetEditSize
 
; Set up the Sample Display Text Edit Record 

 GetDItem FontDPtr,#21,Itemtype(A4),Item(A4),SampleRect(A4)
 ; Function TENew (destRect, viewRect: Rect): TEHandle
 Subq.l #4,SP
 Pea    SampleRect(A4)  ; Create a new text edit record.
 Pea    SampleRect(A4)
 _TENew
 Move.l (SP)+,Sample(A4)  ; Store theTEdit handle.
 HLock  Sample(A4)
 DeRefHndle Sample(A4),A0 ; Setup the variables.
 Move.w #teJustCenter,teJust(A0)
 Move.b MinusOne,teCROnly(A0)
 
 GetResource'STR ',#264 ; Obtain the sample text.
 HLock  (SP); Leave the handle on the stack.
 DeRefHndle (SP),A0; Address of text in A0.
 Clr.l  D0; Length of text in D0.
 Move.b (A0)+,D0
 
 Move.l A0,-(SP) ; Insert the sample string into
 Move.l D0,-(SP) ; the record.
 Move.l Sample(A4),-(SP)
 _TEInsert
 HUnlock(SP)+    ; Unlock the string resource.

 Jsr    SampleWindow ; Update the TEdit variables.
 HUnlockSample(A4)

; Set up the Alert Dialog Variables
 Move.w #-1,ACount ; Reset the Alert stage to 1.
 GetResource   'STR ',#261; Obtain copies of the Alert strings
 Move.l (SP)+,String1(A4) ; handles and store for easy
 GetResource   'STR ',#262; access.
 Move.l (SP)+,String2(A4)
 GetResource   'STR ',#263
 Move.l (SP)+,String3(A4)

; Display the Dialog Window
 ShowWindow FontDPtr ; This posts an Activate event.
 
 
WaitOk  
 Pea    DUserFilter
 Pea    ItemHit(A4)
 _ModalDialog

 Move.w ItemHit(A4),D0  ; Get the itemNo that was Hit.
 Subq.w #1,D0    ; Allow for no item zero.
 Lsl.w  #1,D0    ; *2 for table index.
 Move.w ItemTable(D0),D0  ; Point to routine offset
 Jmp    ItemTable(D0); and jump to it.
 
ItemTable
 Dc.w   DOk-ItemTable; Ok Button
 Dc.w   DCancel-ItemTable ; Cancel Button
 Dc.w   WaitOk-ItemTable  ; Character  Text (Disabled)
 Dc.w   SStyle-ItemTable  ; Bold   Check Box
 Dc.w   SStyle-ItemTable  ; Italic Check Box
 Dc.w   SStyle-ItemTable  ; Underline  Check Box
 Dc.w   SStyle-ItemTable  ; Outline  Check Box
 Dc.w   SStyle-ItemTable  ; Shadow Check Box
 Dc.w   Style-ItemTable   ; Style  Text (Enabled)
 Dc.w   WaitOk-ItemTable  ; ThinBox  User Item
 Dc.w   SSpacing-ItemTable; Normal Radio Button
 Dc.w   SSpacing-ItemTable; Condense Radio Button
 Dc.w   SSpacing-ItemTable; Extend Radio Button
 Dc.w   Spacing-ItemTable ; Spacing  Text (Enabled)
 Dc.w   WaitOk-ItemTable  ; ThinBox  User Item
 Dc.w   WaitOk-ItemTable  ; Font N...  Text (Disabled)
 Dc.w   FontName-ItemTable; NameSel Wind     User Item
 Dc.w   WaitOk-ItemTable  ; Font S...  Text (Disabled)
 Dc.w   FontSize-ItemTable; SizeSel Wind     User Item
 Dc.w   GetEditSize-ItemTable ; Type size    Text Edit
 Dc.w   FontSample-ItemTable; Sample Font          User Item
 
DOk
 ; If the current Dialog selection isn't valid, set up the appropriate 
param text strings and invoke the Caution Alert.
 Btst.b #OkActive,DFlags(A4); Is the selection valid?
 Bne    @3; Yes -> @3
 Clr.w  D0; Set up the three param
 Movea.l#DAStrings,A0; text strings.
 Clr.l  param0(A0)
 Clr.l  param1(A0)
 Clr.l  param2(A0)
 Cmpi.w #-1,TempFont(A4)  ; Is TempFont a valid selection?
 Bne.s  @0; Yes -> @0
 Bset.b #0,D0    ; No -> include related text.
 Move.l String1(A4),param0(A0)
@0 Cmpi.w #0,TempSize(A4) ; Is TempSize a valid selection?
 Bne.s  @1; Yes -> @1
 Bset.b #1,D0    ; No -> include related text.
 Move.l String2(A4),param2(A0)
@1 Cmpi.w #3,D0  ; If both TempFont and TempSize
 Bne.s  @2; are invalid include the conjunctive
 Move.l String3(A4),param1(A0); string (String3).
@2 ; Function CautionAlert (alertID: Integer; filterProc: ProcPtr): Integer
 Subq.l #2,SP
 Move.w #ADialog,-(SP)
 Clr.l  -(SP)
 _CautionAlert
 Addq.l #2,SP
 Bra    WaitOk   ; User to alter their selection.
 
@3 ; 

If the current Dialog selection is valid, replace the original font number, style and size values with the values chosen by the user.

 Movea.l16(A6),A0; Font number.
 Move.w TempFont(A4),(A0)
 Movea.l12(A6),A0; Font style.
 Move.w TempFace(A4),(A0)
 Movea.l8(A6),A0 ; Font size.
 Move.w TempSize(A4),(A0)
 Move.b #True,20(A6) ; Return True.
 
DCancel 
 HideWindow FontDPtr
 LMDisposeNameListH(A4)   ; Font Name List.
 LMDisposeSizeListH(A4)   ; Font Size List.
 TEDisposeSample(A4) ; Sample Text Edit Record.
 CloseDialog   FontDRec(A5)
 HUnLockFontMap(A5); FontMap .
 HUnLockTextCursor(A4)  ; iBeamCursor resource.
 SetPenStatepnState(A4)   ; Restore the pen settings.
 DisposePtr FontDPtr ; Font Dialog Data Record.

 Movem.l(SP)+,D0-D7/A0-A4 ; Restore registers.
 Unlk   A6
 Movea.l(SP)+,A0 ; Pop args & return.
 Add.l  #12,SP
 Jmp    (A0)
 
Style
 Move.w TempFace(A4),D2 ; Store for comparison later.
 Movea.l12(A6),A0; Obtain original style values
 Move.w (A0),D0  ; and retain lower five bits.
 Andi.w #%00011111,D0
 Andi.w #%11100000,TempFace(A4)  ; Clear the lower 5 bits. 
 Or.w   D0,TempFace(A4) ; Combine the two together.
 Bra.s  SetStyle
SStyle  
 Move.w TempFace(A4),D2 ; Store for comparison later.
 Move.w ItemHit(A4),D0  ; Get the itemNo that was hit.
 Subq.w #4,D0
 Bchg.b D0,TempFace+1(A4) ; Toggle the selected item.
SetStyle
 Cmp.w  TempFace(A4),D2   ; Has the face altered?
 Beq.s  @1; No -> @1
 Move.w TempFace(A4),D0
 ; Routine SControl (StItem, NofItems, ValueBits : Integer)
 Move.w #4,-(SP) ; Item No 4.
 Move.w #5,-(SP) ; 5 Items (check boxes).
 Move.w D0,-(SP) ; Bits to set.
 Bsr    SControl
 Btst.b #OkActive,DFlags(A4); Are Dialog selections valid.
 Beq.s  @1; No, don't update the sample.
 Bclr.b #SRect,DFlags(A4) ; Erase Sample if it hasn't
 Beq.s  @0; been already.
 EraseRectSampleRect(A4)
@0 Bset.b #SUpdate,DFlags(A4) ; Window requires updating.
 Move.l Ticks,SampleTicks(A4)
@1 Jmp  WaitOk

Spacing
 Move.w TempFace(A4),D2 ; Store for comparison later.
 Movea.l12(A6),A0; Obtain the original style values.
 Move.w (A0),D0
 Bra.s  SetSpacing
SSpacing
 Move.w TempFace(A4),D2 ; Store for comparison later.
 Move.w ItemHit(A4),D1  ; Get the item No that was hit.
 Sub.w  #11,D1   ; Produce in D0 a byte that
 Move.w #%00010000,D0; represents which bit to set.
 Lsl.b  D1,D0
SetSpacing
 Andi.w #%11100000,D0; Clear the lower 5 bits.
 Andi.w #%00011111,TempFace(A4)  ; Clear the top 3 bits.
 Or.w   D0,TempFace(A4) ; Combine the two together.
 Cmp.w  TempFace(A4),D2 ; Has the face altered?
 Beq.s  @2; No -> @2
 Move.w TempFace(A4),D0 ; Produce in the first 3 bits
 Andi.w #%01100000,D0; of D0 the settings of the
 Bne.s  @0; 3 radio buttons.
 Move.w #%00010000,D0
@0 Lsr.b#4,D0
 ; Routine SControl (StItem, NofItems, ValueBits : Integer)
 Move.w #11,-(SP); Item No 11.
 Move.w #3,-(SP) ; 3 Items (radio buttons).
 Move.w D0,-(SP) ; Bits to set.
 Bsr    SControl
 Btst.b #OkActive,DFlags(A4); Are Dialog selections valid.
 Beq.s  @2; No, don't update the sample.
 Bclr.b #SRect,DFlags(A4); Erase Rect if it hasn't
 Beq.s  @1; been already.
 EraseRectSampleRect(A4)
@1 Bset.b #SUpdate,DFlags(A4) ; Window requires updating.
 Move.l Ticks,SampleTicks(A4)
@2 Jmp  WaitOk


SControl
 ; Routine SControl (StItem, NofItems, ValueBits : Integer)    
 Link   A6,#0
 ; StItem 12(A6) Start Item number
 ; NofItems 10(A6) Number of Items
 ; ValueBits   8(A6) Values of the items
 ; Return address4(A6)
 ; Old A6 (A6)
 
SetControl
 GetDItem FontDPtr,12(A6),Itemtype(A4),Item(A4),ItemBox(A4)
 Clr.w  D0; Set D0 to 1 if the item
 Lsr.W  8(A6)    ; is to be set or 0 if its not.
 Bcc.s  @1
 Addq.w #1,D0
@1 SetCtlValue   Item(A4),D0
 Addq.w #1,12(A6); Increment the item No counter.
 Sub.w  #1,10(A6); Any more items to process?
 Bne.s  SetControl ; Yes -> SetControl.
 
 Unlk   A6
 Movea.l(SP)+,A0 ; Pop args & return.
 Add.l  #6,SP
 Jmp    (A0)
 
 
FontName

The user has made a new selection from the Font Name Selection Window, either a new font name or none. TempFont will change.

 Bclr.b #SRect,DFlags(A4) ; Erase Rect if it hasn't
 Beq.s  @0; been already.
 EraseRectSampleRect(A4)
@0 Move.w NameCell+v(A4),D0 ; Update the font number in
 Bmi.s  @1; TempFont with the number
 Mulu   #6,D0    ; of the font selected .
 Move.w 2(A3,D0.W),TempFont(A4)
 Cmpi.w #0,TempSize(A4)
 Beq.s  @2
 Bset.b #OkActive,DFlags(A4); selections are valid.
 Bset.b #SUpdate,DFlags(A4) ; Window requires updating.
 Move.l Ticks,SampleTicks(A4)
 Bra.s  @3
@1 Move.w #-1,TempFont(A4); No Font Name is selected.
@2 Bclr.b #OkActive,DFlags(A4); selections aren't valid.
@3 Jsr  LdSizes  ; Update Font Size Selection Window.
 GetDItem FontDPtr,#19,Itemtype(A4),Item(A4),ItemBox(A4)
 EraseRect  ItemBox(A4)
 LMUpdate VisRgn(A4),SizeListH(A4)
 Jmp    WaitOk


FontSize

The user has made a new selection from the Font Size Selection Window, either a new font name or none. TempSize might not change.

 Move.w TempSize(A4),D2   ; Store for comparison later.
 Move.w NameCell+v(A4),D0
 Bmi.s  @0; No Font Name selected.
 Mulu   #6,D0
 Move.w 2+4(A3,D0.W),D0 ; Offset to font's size list.
 Lea    (A3,D0.W),A0 ; Address of the size list.
 Move.w SizeCell+v(A4),D0
 Bmi.s  @0; No Font Size selected.
 Lsl.w  #1,D0
 Move.w 2(A0,D0.W),TempSize(A4)  ; Store new font size.
 Cmp.w  TempSize(A4),D2   ; Has the size altered?
 Beq.s  @0; No -> @0
 Jsr    SetEditSize; Update the textedit window.
@0 Jmp  WaitOk
 
 
GetEditSize

Convert the text in the font size text edit window into a number to update TempSize. TempSize might not have changed, if the mouse is clicked within the font size text edit window this routine is called.

 GetDItem FontDPtr,#20,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0
 _StringToNum
 Cmpi.w #4,D0
 Blt    @2; if <4
 Cmpi.w #127,D0
 Bgt    @2; if >127
 Cmp.w  TempSize(A4),D0   ; Has the size altered?
 Beq.s  @1; No -> @1
 Move.w D0,TempSize(A4)   ; Yes -> update TempSize.
 Cmp.w  #-1,TempFont(A4)  ; Is there a valid font name?
 Beq.s  @3; No -> @3
 Bset.b #OkActive,DFlags(A4); selections are valid.
 Bclr.b #SRect,DFlags(A4) ; Erase Rect if it hasn't
 Beq.s  @0; been already.
 EraseRectSampleRect(A4)
@0 Bset.b #SUpdate,DFlags(A4) ; Window requires updating.
 Move.l Ticks,SampleTicks(A4)
@1 Jmp  WaitOk

@2 Clr.wTempSize(A4) ; Indicate its outside limits.
@3 Bclr.b #OkActive,DFlags(A4); selections aren't valid.
 Bclr.b #SRect,DFlags(A4) ; Erase Rect if it hasn't
 Beq.s  @4; been already.
 EraseRectSampleRect(A4)
@4 Jmp  WaitOk


FontSample
 Jsr    SampleWindow ; update the attributes
 TEUpdate SampleRect(A4),Sample(A4)
 Bclr.b #SUpdate,DFlags(A4) ; Window has been updated.
 Bset.b #SRect,DFlags(A4) ; Sample Rect isn't blank.
 Jmp    WaitOk


SetEditSize

Setup the font size text edit item. To access this routine there must be a valid font name.

 GetDItem FontDPtr,#20,Itemtype(A4),Item(A4),ItemBox(A4)
 Clr.l  D7
 Move.w TempSize(A4),D7   
 Cmpi.w #4,D7
 Blt    @1; if <4
 Cmpi.w #127,D7
 Bgt    @1; if >127
 Bset.b #OkActive,DFlags(A4); selections are valid.
 Bclr.b #SRect,DFlags(A4) ; Erase Sample if it hasn't
 Beq.s  @0; been already.
 EraseRectSampleRect(A4)
@0 Bset.b #SUpdate,DFlags(A4) ; Window requires updating.
 Move.l Ticks,SampleTicks(A4)
 Lea    thename(A4),A0    ; Load thename pointer.
 Move.l D7,D0
 _NumToString
 Move.l Item(A4),-(SP)  ; Set the item text to the new
 Move.l A0,-(SP) ; number string.
 _SetIText
 
 Move.l FontDPtr,-(SP)
 Move.w #20,-(SP); Select complete text in the item.
 Move.w #0,-(SP)
 Move.w #255,-(SP)
 _SelIText
 Rts

@1 Clr.wTempSize(A4) ; Indicate it's outside limits.
 Bclr.b #OkActive,DFlags(A4); selections aren't valid.
 Bclr.b #SRect,DFlags(A4) ; Erase Sample if it hasn't
 Beq.s  @2; been already.
 EraseRectSampleRect(A4)
@2 Rts

 
LdNames
 ; Load the NameList  with the font names stored in FontMap.
 ; Function LAddRow (count, rowNum: Integer; lHandle: ListHandle): Integer
 Subq.l #2,SP
 Move.w (A3),-(SP) ; The number of font names - 1.
 Move.w #0,-(SP)
 Move.l NameListH(A4),-(SP)
 _LAddRow
 Addq.l #2,SP
 
 Clr.w  D7; Loop counter (the # of fonts -1).
@0 Move.w D7,D6
 Mulu   #6,D6    ; Point to the next font info.
 Move.w 2(A3,D6.W),D0; Obtain the font's number.
 Cmp.w  TempFont(A4),D0 ; Is this font to be selected?
 Bne.s  @1; No -> @1.
 Move.w D7,NameCell+v(A4) ; cell # into NameCell+v.
@1 Move.w 2+2(A3,D6.W),D6 ; Obtain the font's name offset.

 ; Procedure LSetCell (dataPtr: Ptr; dataLen: Integer; theCell: Cell; 
lHandle: ListHandle)
 Pea    1(A3,D6.W) ; Address of the name (string).
 Clr.w  D0
 Move.b (A3,D6.W),D0 ; Length of the name.
 Move.w D0,-(SP) 
 Move.w #0,-(SP) ; Cell column #.
 Move.w D7,-(SP) ; Cell row #.
 Move.l NameListH(A4),-(SP)
 _LSetCell
 
 Addq.w #1,D7    ; Increment the loop counter.
 Cmp.w  (A3),D7  ; Loaded all font names yet?
 Ble.s  @0; No -> @0.

Select the cell containing the font name which corresponds to the font number passed to the FontDialog Routine. If the font number isn't associated with one of the fonts on the current system file then don't select any name.

 Cmpi.w #-1,NameCell+v(A4); Cell to be selected?
 Beq.s  @2; No -> @2
 LMSetSelect   #True,NameCell(A4),NameListH(A4)
 
 DeRefHndle NameListH(A4),A0; Scroll if selected cell
 Move.w visible+bottom(A0),D6 ; isn't visible, ie 
 ;the last visible cell is
 Cmp.w  NameCell+v(A4),D6 ; less than selected cell.
 Bgt.s  @2
 LMAutoScroll  NameListH(A4)
 
@2 LMDoDraw #True,NameListH(A4)  ; Drawing on.
 Rts
 
LdSizes
 ; load SizeList with font sizes of TempFont in FontMap.
 LMDoDraw #False,SizeListH(A4); Drawing off.
 LMDelRow #0,#0,SizeListH(A4) ; Delete all the rows.
 Move.l #$FFFF0000,SizeCell(A4)
 Move.w TempFont(A4),D4 ;The font number.
 Bmi    @5; -ve, no font number passed to FontDialog.
 
 Clr.w  D7; Loop counter.
@1 Move.w D7,D6
 Mulu   #6,D6    ; Point to the next font info.
; Compare the font number with the font number that was passed 
; to the FontDialog Routine.
 Cmp.w  2(A3,D6.W),D4; Match?
 Beq.s  @2; Yes -> @2.
 Addq.w #1,D7    ; Increment the loop counter.
 Cmp.w  (A3),D7  ; Looked at all font numbers yet?
 Ble.s  @1; No ->@1.
 Bra    @5; Yes & no match was found.
 
@2 Move.w 2+4(A3,D6.W),D7 ; Offset to font size list.
 Move.w (A3,D7.W),D6 ; The number of font sizes.
 ; Procedure LAddRow (count, rowNum: Integer; lHandle: ListHandle): Integer
 Subq.l #2,SP
 Move.w D6,-(SP) ; Number of rows to add.
 Move.w #0,-(SP)
 Move.l SizeListH(A4),-(SP)
 _LAddRow
 Addq.l #2,SP
 
 Clr.w  D6; Setup the loop counter.
@3 Move.w D6,D5  ; Create an offset within size list.
 Lsl.w  #1,D5
 Add.w  D7,D5    ; Offset from the start of FontMap.
 Clr.l  D0; Clear .L for NumToString.
 Move.w 2(A3,D5.W),D0; A font size.
 Cmp.w  TempSize(A4),D0 ; Is this the selected size?
 Bne.s  @4; No -> @4.
 Move.w  D6,SizeCell+v(A4); Store cell number to  select
@4 Lea  thename(A4),A0
 _NumToString
 ; Procedure LSetCell (dataPtr: Ptr; dataLen: Integer; theCell: Cell; 
lHandle: ListHandle)
 Pea    1(A0)    ; Address of the Size (string).
 Clr.w  D0
 Move.b (A0),D0  ; Length of the Size.
 Move.w D0,-(SP)
 Move.w #0,-(SP) ; Cell column #.
 Move.w D6,-(SP) ; Cell row #.
 Move.l SizeListH(A4),-(SP)
 _LSetCell
 
 Addq.w #1,D6    ; Increment the loop counter.
 Cmp.w  (A3,D7.W),D6 ; Loaded all font sizes yet?
 Blt.s  @3; No -> @3.

Select the cell containing the font size which corresponds to the font size passed to the FontDialog Routine. If the font doesn't have the size selected, do nothing.

 Cmpi.w #-1,SizeCell+v(A4); Cell to be selected?
 Beq.s  @5; No -> @5
 LMSetSelect   #True,SizeCell(A4),SizeListH(A4)
 
 DeRefHndle SizeListH(A4),A0
 ; Scroll if the selected cell isn't
 Move.l (A0),A0  ; visible, ie last visible cell is
 Move.w visible+bottom(A0),D6 ; less than selected cell.
 Cmp.w  SizeCell+v(A4),D6
 Bgt.s  @5
 LMAutoScroll  SizeListH(A4)
 
@5 LMDoDraw #True,SizeListH(A4)  ; Drawing on.
 Rts


SampleWindow
 ; Update the sample TextEdit Record with the currently
 ; selected font attributes.
 Btst.b #OkActive,DFlags(A4); Are the selections valid?
 Beq    @0; No -> @0
 TextFont TempFont(A4)    ; Font number
 TextFace TempFace(A4)    ; Font style
 TextSize TempSize(A4)    ; Font size
 GetFontInfoinfo(A4)
 
 DeRefHndle Sample(A4),A0
 Move.w TempFont(A4),teFont(A0)    ; teFont
 Move.b TempFace+1(A4),teFace(A0)  ; teFace
 Move.w TempSize(A4),teSize(A0)    ; teSize
 Move.w info+ascent(A4),teAscent(A0) ; teAscent
 Move.w info+ascent(A4),D0; teLineHite
 Add.w  info+descent(A4),D0
 Add.w  info+leading(A4),D0
 Move.w D0,teLineHite(A0)
 Move.l teViewRect+topLeft(A0),teDestRect+topLeft(A0)
 Move.l teViewRect+botRight(A0),teDestRect+botRight(A0)
 Mulu   teNLines(A0) ,D0  ; Height of the sample text.
 Move.w SampleRect+bottom(A4),D1
 Sub.w  SampleRect+top(A4),D1
 Cmp.w  D0,D1    ; Sample greater than Rect?
 Ble    @0; Yes -> @0
 Sub.w  D0,D1    ; Center the sample
 Lsr.w  #1,D1    ; lines in the middle
 Add.w  D1,teDestRect+top(A0) ; of SampleRect.
@0 Rts


; ------------ Modal Dialog User Filter ---------- 
DUserFilter

 Link A6,#0
 ; Boolean result20(A6)
 ; Dialog (window) pointer16(A6)
 ; Address of the event record12(A6)
 ; Addr of word to fill in item no 8(A6)
 ; Return address4(A6)
 ; Old A6   (A6)

Use the event number as an index into the DEventTable. These 12 events are all the things that could spontaneously happen while the program is in the Modal Dialog event loop.

 Movea.l16(A6),A4; Font Dialog Data Record.
 Move.w #False,20(A6); Set function result to False.
 Movea.l12(A6),A0; Event Records Address.
 Move.w evtNum(A0),D0; Get the event number.
 Lsl.w  #1,D0    ; *2 for table index.
 Move.w DEventTable(D0.W),D0; Point to the routine offset
 Jmp    DEventTable(D0.W) ; and jump to it.
 
DEventTable
 Dc.w DNull-DEventTable   ; Null 
 Dc.w DMouseDown-DEventTable; Mouse Down
 Dc.w DFReturn-DEventTable; Mouse Up (Not used)
 Dc.w DKeyDown-DEventTable; Key Down
 Dc.w DFReturn-DEventTable; Key Up (Not used)
 Dc.w DKeyDown-DEventTable; Auto Key
 Dc.w DUpdate-DEventTable ; Update 
 Dc.w DFReturn-DEventTable; Disk   (Not used)
 Dc.w DActivate-DEventTable ; Activate 
 Dc.w DFReturn-DEventTable; Network  (Not used)
 Dc.w DFReturn-DEventTable; I/O Driver (Not used)

DNull
 GetDItem 16(A6),#20,Itemtype(A4),Item(A4),ItemBox(A4)
 GetMouse loc_pt(A4)
 PtInRect loc_pt(A4),ItemBox(A4) ; Was mouse within the 
 Move.b (SP)+,D0 ; FontSize text edit Rect?
 Beq.s  @0; Yes -> iBeam cursor.
 
 Move.l TextCursor(A4),A0 
 Move.l (A0),-(SP)
 _SetCursor
 Bra    @1
@0 _InitCursor   ; No -> Arrow cursor.

@1 Move.l Ticks,D0 ; If KeyTresh Ticks have passed
 Sub.l  SampleTicks(A4),D0; since last item alteration,
 Cmp.w  KeyThresh,D0 ; update the sample window by
 Blt    DFReturn ; indicating item #21 was hit.
 Btst.b #SUpdate,DFlags(A4)
 Beq    DFReturn
 
 Move.w #21,D0   ; Set the itemNo to 21, Sample
 Bra    DFTReturn


DMouseDown
 Bclr.b #SKey,DFlags(A4)  ; Not a SKey event.
 ; Obtain the (events) mouse location and convert it to 
 ; local coordinates.
 Move.l evtMouse(A0),loc_pt(A4)
 GlobalToLocal loc_pt(A4)
 
; Check to see if the mouse was clicked inside one of the 
; active rectangles. 

Item9
; mouse was pressed down within item No 9? (Style heading) 
 GetDItem FontDPtr,#9,Itemtype(A4),Item(A4),ItemBox(A4)
 PtInRect loc_pt(A4),ItemBox(A4)
 Move.b (SP)+,D0 ; Was the point within the heading?
 Beq.s  Item14   ; No -> check item No 14's Rect.

 ; Routine TrackHeading (theDialog: DialogPtr; itemNo: Integer): Boolean
 Subq.l #2,SP    ; Set up for the result.
 Move.l FontDPtr,-(SP)
 Move.w #9,-(SP)
 Bsr    TrackHeading
 Move.b (SP)+,D0 ; Was the mouse up within the item?
 Beq    SetoNull ; No, Convert event to null & return    .
 Move.w #9,D0    ; Yes, return True & the item No 9.
 Bra    DFTReturn
 
Item14
;mouse was pressed down within item No 14? (Spacing heading).
 GetDItem FontDPtr,#14,Itemtype(A4),Item(A4),ItemBox(A4)
 PtInRect loc_pt(A4),ItemBox(A4)
 Move.b (SP)+,D0 ; Was the point within the heading?
 Beq    Item17   ; No -> check item No 17's Rect.

 Subq.l #2,SP
 Move.l FontDPtr,-(SP)
 Move.w #14,-(SP)
 Bsr    TrackHeading
 Move.b (SP)+,D0 ; Was the mouse up within the item?
 Beq    SetoNull ; No, Convert event to null & return    .
 Move.w #14,D0   ; Yes, return True & the item No 14.
 Bra    DFTReturn

Item17
; mouse was pressed down within item No 17?
; The Font Name Selection Window.
 GetDItem FontDPtr,#17,Itemtype(A4),Item(A4),ItemBox(A4)
 Addi.w #15,ItemBox+right(A4) ; include vertical scroll
 PtInRect loc_pt(A4),ItemBox(A4)
 Move.b (SP)+,D0 ; Was the point within the rect?
 Beq    Item19   ; No -> check item No 19's rect.

If a new selection is made return true and the item number, otherwise set the event to a null event and return.

 ; Function LClick (pt: Point; modifiers: Integer; lHandle: ListHandle): 
Boolean
 Subq.l #2,SP
 Move.l loc_pt(A4),-(SP)
 Movea.l12(A6),A0
 Move.w evtMeta(A0),-(SP)
 Move.l NameListH(A4),-(SP)
 _LClick
 Addq.l #2,SP
 
 Clr.l  TempCell(A4)
 LMGetSelect   #True,TempCell(A4),NameListH(A4)
 Move.b (SP)+,D0 ; Is there a selected cell?
 Bne    @0; Yes -> @0.
 Move.l #$FFFF0000,TempCell(A4)  ; No set TempCell to 0,-1.
@0 Move.l TempCell(A4),D0 ; Has the selected cell changed?
 Cmp.l  NameCell(A4),D0
 Beq    SetoNull ; No -> SetoNull.
 Move.l D0,NameCell(A4) ; Yes, return True & item No 17.
 Move.w #17,D0
 Bra    DFTReturn
 
Item19
; Check to see if the mouse was pressed down within item No 19. 
; The Font Size Selection Window.
 GetDItem FontDPtr,#19,Itemtype(A4),Item(A4),ItemBox(A4)
 Addi.w #15,ItemBox+right(A4) 
 PtInRect loc_pt(A4),ItemBox(A4)
 Move.b (SP)+,D0 ; Was the point within the rect?
 Beq    DFReturn ; No -> DFReturn.
 
 If a new selection is made return true and the item number, otherwise 
set the event to a null event and return.

 Subq.l #2,SP
 Move.l loc_pt(A4),-(SP)
 Movea.l12(A6),A0
 Move.w evtMeta(A0),-(SP)
 Move.l SizeListH(A4),-(SP)
 _LClick
 Addq.l #2,SP
 
 Clr.l  TempCell(A4)
 LMGetSelect   #True,TempCell(A4),SizeListH(A4)
 Move.b (SP)+,D0 ; Is there a selected cell?
 Bne    @0; Yes -> @0.
 Move.l #$FFFF0000,TempCell(A4)
@0 Move.l TempCell(A4),D0 ; Has selected cell changed?
 Cmp.l  SizeCell(A4),D0
 Beq    SetoNull ; No -> SetoNull.
 Move.l D0,SizeCell(A4) ; Yes, return True & item No 19.
 Move.w #19,D0
 Bra    DFTReturn

DKeyDown

Examine the key that was pressed, if it was a 'cr' or 'enter' then that is equivalent to clicking the Ok button.

 Move.l evtMessage(A0),D0 
 Cmpi.b #crCode,D0 ; Was the cr key pressed?
 Beq.s  @1; Yes -> @1.
 Cmpi.b #enterCode,D0; Was the enter key pressed?
 Bne.s  @2; No -> @2.
@1 Move.w #1,D0  ; Set the item No to Ok button.
 Bra    DFTReturn; Item No 1 - Ok.

@2 ; 

If the key pressed was the back space key or a number then deselect the cell in the Font Size Selection Window (if there is one selected), then return, allowing the number or 'bs' to be used to alter the FontSize

 ; text edit data.
 Cmpi.b #bsCode,D0 ; Was the bs key pressed?
 Beq.s  @3; Yes -> @3.
 Cmpi.b #$30,D0
 Blt.s  NameSearch
 Cmpi.b #$39,D0
 Bgt.s  NameSearch
@3 Bclr.b #SKey,DFlags(A4); Not a SKey event.
 Cmpi.l #$FFFF0000,SizeCell(A4)  ; If a cell is selected,
 Beq    DFReturn ; deselect it, 
 LMSetSelect   #False,SizeCell(A4),SizeListH(A4)   ; let the
 ; default routine 
 Move.l #$FFFF0000,SizeCell(A4)  ; handle the event.
 Bra    DFReturn

NameSearch
 Lea    search(A4),A2
 Bset.b #SKey,DFlags(A4)  ; Was last event a SKey event?
 Beq.s  @0; No -> @0
 Move.l evtTicks(A0),D1   ; Yes -> If this key down
 Sub.l  SampleTicks(A4),D1;  within KeyThresh Ticks
 Cmp.w  KeyThresh,D1 ;  continue the search string
 Blt.s  @1; else, reset search string.
@0 Clr.b(A2); Continue.
@1 Addq.b #1,(A2); Reset.
 Move.l evtTicks(A0),SampleTicks(A4) 
 Clr.w  D1; If search string is greater than
 Move.b (A2),D1  ; 32, SetoNull.
 Cmpi.b #31,D1
 Bgt    SetoNull
 Move.b D0,(A2,D1.w) ; Add char to string.
 
 DeRefHndle FontMap(A5),A3
 Clr.w  D7; Set loop counter.
@2 Move.w D7,D6
 Mulu   #6,D6    ; Offset to next font info.
 Move.w 2+2(A3,D6.w),D6 ; Offset to name string.

 ; Function IUMagString (aPtr, bPtr: Ptr; aLen, bLen: Integer): Integer
 Subq.l #2,SP
 Pea    1(A3,D6.w) ; Address of FontName string.
 Pea    1(A2)    ; Address of search string.
 Clr.w  D0
 Move.b (A3,D6.w),D0
 Move.w D0,-(SP) ; Length of FontName string.
 Move.b (A2),D0
 Move.w D0,-(SP) ; Length of search string.
 _IUMagString
 Move.w (SP)+,D0 ; Was the FontName => ?
 Bpl.s  @3; Yes -> @3
 
 Addq.w #1,D7    ; Have all the fonts been 
 Cmp.w  (A3),D7  ; looked at?
 Blt    @2; No -> @2
 
@3 ; Is the desired cell selected?
 ; Yes -> Don't do anything.
 ; No -> Deselect existing cell & select new cell.
 Cmp.w  NameCell+v(A4),D7
 Beq    SetoNull
 LMSetSelect#False,NameCell(A4),NameListH(A4)
 Move.w D7,NameCell+v(A4)
 LMSetSelect#True,NameCell(A4),NameListH(A4)
 
 DeRefHndle NameListH(A4),A0; If selected cell isn't
 Cmp.w  visible+top(A0),D7; visible then AutoScroll.
 Blt.s  @4; else continue.
 Cmp.w  visible+bottom(A0),D7
 Blt.s  @5
@4 LMAutoScroll  NameListH(A4)
@5 Move.w #17,D0
 Bra    DFTReturn


DUpdate
 Bclr.b #SKey,DFlags(A4)  ; Not a SKey event.
 SetPortFontDPtr
 BeginUpdateFontDPtr
 DrawControls  FontDPtr

; Update itemNo 1
 ; The BoldBox around the Ok button.
 GetDItem FontDPtr,#1,Itemtype(A4),Item(A4),ItemBox(A4)
 InsetRectItemBox(A4),#-4,#-4
 PenSize#3,#3
 FrameRoundRect  ItemBox(A4),#16,#16
 _PenNormal
 
; Update itemNo 3 
 ; The Static Text heading "Character Font & Attributes".
 GetDItem FontDPtr,#3,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0  ; Address of the text.
 Clr.l  D0
 Move.b (A0)+,D0 ; Length of the text.
 TextBox  A0,D0,ItemBox(A4),#0
 
; Update the Font Style Selection Window 
 ; The ThinBox around the Style Check Boxes  (item No 10).
 GetDItem FontDPtr,#10,Itemtype(A4),Item(A4),ItemBox(A4)
 FrameRectItemBox(A4)

 ; The Static Text heading "Style" (item No 9).    
 GetDItem FontDPtr,#9,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0  ; Address of the text.
 Clr.l  D0
 Move.b (A0)+,D0 ; Length of the text.
 TextBox  A0,D0,ItemBox(A4),#0
 
; Update the Font Spacing Selection Window
 ; The ThinBox around the Style Check Boxes  (item No 15).
 GetDItem FontDPtr,#15,Itemtype(A4),Item(A4),ItemBox(A4)
 FrameRectItemBox(A4)

 ; The static text heading "Spacing" (item No 14). 
 GetDItem FontDPtr,#14,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0    ; Address of the text.
 Clr.l  D0
 Move.b (A0)+,D0 ; Length of the text.
 TextBox  A0,D0,ItemBox(A4),#0
 
; Update itemNo 16
 ; The Static Text heading "Font Name:".
 GetDItem FontDPtr,#16,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0    ; Address of the text.
 Clr.l  D0
 Move.b (A0)+,D0 ; Length of the text.
 TextBox  A0,D0,ItemBox(A4),#0

; Update itemNo 17
 ; The Font Name Selection Window.
 GetDItem FontDPtr,#17,Itemtype(A4),Item(A4),ItemBox(A4)
 InsetRect  ItemBox(A4),#-1,#-1
 EraseRect  ItemBox(A4)
 FrameRect  ItemBox(A4)
 LMUpdate VisRgn(A4),NameListH(A4)
 
; Update itemNo 18
 ; The Static Text heading "Font Size:".
 GetDItem FontDPtr,#18,Itemtype(A4),Item(A4),ItemBox(A4)
 GetIText Item(A4),thename(A4)
 Lea    thename(A4),A0    ; Address of the text.
 Clr.l  D0
 Move.b (A0)+,D0 ; Length of the text.
 TextBox  A0,D0,ItemBox(A4),#0
 
; Update itemNo 19
 ; The Font Size Selection Window.
 GetDItem FontDPtr,#19,Itemtype(A4),Item(A4),ItemBox(A4)
 InsetRect  ItemBox(A4),#-1,#-1
 EraseRect  ItemBox(A4)
 FrameRect  ItemBox(A4)
 LMUpdate VisRgn(A4),SizeListH(A4)
 
; Update itemNo 20
 ; The TextEdit text item.
 GetDItem FontDPtr,#20,Itemtype(A4),Item(A4),ItemBox(A4)
 EraseRect  ItemBox(A4)
 TEUpdate ItemBox(A4),teHandle(A4)
 InsetRect  ItemBox(A4),#-3,#-3
 FrameRect  ItemBox(A4) ; Frame the textedit item.

; Update itemNo 21
 ; Update the Sample Text Window.
 EraseRect  SampleRect(A4)
 Bclr.b #SRect,DFlags(A4)
 Btst.b #OkActive,DFlags(A4); Are selections valid?
 Beq    @0; No -> @0
 TEUpdate SampleRect(A4),Sample(A4); Yes -> update sample
 Move.l Ticks,SampleTicks(A4) ;  and associated
 Bclr.b #SUpdate,DFlags(A4) ; variables.
 Bset.b #SRect,DFlags(A4)

@0 EndUpdateFontDPtr
 Bra    SetoNull
 
DActivate

Check first to see if this activate event is associated with this Dialog Window, compare the Dialog Window's pointer to that of the Window pointerin the event record. A0 contains the address of the event record.

 Move.l FontDPtr,D0
 Cmp.l  evtMessage(A0),D0
 Bne    DFReturn ; Event not related to Dialog.
 
 Bclr.b #SKey,DFlags(A4)  ; Not a SKey event.
 SetPortFontDPtr
 Movea.l12(A6),A0; Address of the event record.
 Move.w evtMeta(A0),D0  ; Obtain the modify word.
 Lsr    #1,D0    ; Check Bit 0 to see if its
 Bcc    DDeactivate; Activate or Deactivate.
 
 TEActivate teHandle(A4)
 LMActivate #True,NameListH(A4)
 LMActivate #True,SizeListH(A4)
 Bra    SetoNull

DDeactivate
 TEDeactivate  teHandle(A4)
 LMActivate #False,NameListH(A4)
 LMActivate #False,SizeListH(A4)
 Bra    SetoNull 

SetoNull
 Movea.l12(A6),A0; Obtain the address of the Event
 Clr.w  evtNum(A0) ; Record & set it to a null event.
 Bra.s  DFReturn
DFTReturn
 Move.b #True,20(A6) ; Dialog Filter (True) Return.
 Movea.l8(A6),A0
 Move.w D0,(A0)
DFReturn; Dialog Filter Return.
 Unlk   A6
 Movea.l(SP)+,A0 ; Pop args & return.
 Add.l  #12,SP
 Jmp    (A0)
 
TrackHeading
 Link   A6,#-22
 ; Boolean result 14(A6)
 ; theDialog pointer  10(A6)
 ; itemNo   8(A6)
 ; Return address  4(A6)
 ; Old A6     (A6)
 ; Temporary Region Handle No1 -4(A6)
 ; Temporary Region Handle No2    -8(A6)
 ; Vis boolean   -10(A6)
 ; Mouse Location-14(A6)
 ; Temporary Rectangle    -22(A6)
 
 Move.b #False,14(A6); Set up to return False.
 
; Get Rect of user item that surrounds the headings control 
; items (check boxes or radio buttons).
 Addq.w #1,8(A6)
 GetDItem 10(A6),8(A6),Itemtype(A4),Item(A4),-22(A6)
 
; Create a region and store the current clipping region. 
 NewRgn
 Move.l (SP),-4(A6); Store the regions handle.
 _GetClip

Create a new clipping region which is the user item's rect inset by 1 pixel on all sides minus the intersection rectangle of the heading's rect and the newly created rect.

 NewRgn
 Move.l (SP),-8(A6); Store the regions handle.
 InsetRect  -22(A6),#1,#1
 _OpenRgn
 FrameRect-22(A6)

Find the rectangle that is the intersection of ItemBox(A4) and -22(A6). If they intersect then remove that rectangle from the clipping region.

 SectRect ItemBox(A4),-22(A6),TempRect
 Move.b (SP)+,D0 ; Was there an intersection?
 Beq.s  @1; No -> @1.
 FrameRectTempRect
@1 _CloseRgn; handle is already on stack.
 SetClip-8(A6)   ; Set up the new clipping region.

 PenSize  #1,#1
 PenMode#10 ; Inverts what ever is drawn over.
 
; Draw the rectangle in question, giving the user the 
; impression that they have selected the heading.
 FrameRect-22(A6)
 Move.b #True,-10(A6); Set the vis byte to True.
 
Track 
 StillDown
 Move.b (SP)+,D0 ; Is the mouse button still down?
 Beq    @1; No -> @1.
 GetMouse -14(A6)
 PtInRect -14(A6),ItemBox(A4)
 Move.b (SP)+,D0 ; Has the mouse entered or
 Cmp.b  -10(A6),D0 ; left the item's rect?
 Beq.s  Track    ; No -> Track.
 FrameRect-22(A6); Yes -> toggle the rectangle.
 Eori.b #1,-10(A6) ; Toggle the visible byte.
 Bra.s  Track
 
@1 Move.b -10(A6),D0 ; Is the rect visible?
 Beq.s  @2; No -> Return False.
 FrameRect-22(A6); Yes -> Remove the rectangle &   
 Move.b #True,14(A6) ; return True.
@2 _PenNormal  
 SetClip-4(A6)   ; Reset to its original setting.
 DisposeRgn -4(A6) ; Dispose of two temporary regions.
 DisposeRgn -8(A6)
 
 Unlk   A6
 Movea.l(SP)+,A0 ; Pop args & return.
 Add.l  #6,SP
 Jmp    (A0)
 
; ---------- Variables ------ 

FontDRecDs.l1


;--------------- SetupFontMap -----------------

; Written by Ray.A.Cameron
; Version 1.0
; Mon May 4, 1988 21:41:50

XDef    SetupFontMap ; Routine's name
XDef    FontMap  ; Global location for the FontMap's Handle


;---------- Includes -------------

Include Traps.D  ; Use System and ToolBox traps
Include PackMacs.Txt ; Use Package Equates

; ---------- Equates ----------

True    Equ 1
False   Equ 0
FNum    Equ %1111111111000000
FSize   Equ %0000000000111111


SetupFontMap

 Link   A6,#0
 Movem.lD0-D7/A0-A4,-(SP) ; Save register values.
 
 ; Function CountResources (theType: ResType): Integer;
 Clr.w  -(SP)    ; Clear for answer.
 Move.l #'FONT',-(SP); Count number of 'FONT' resources.
 _CountResources
 Clr.l  D7
 Move.w (SP)+,D7 ; Store the result.

Create a non-relocatable block into which will be stored each font resource ID, if the resource has a font size (ie no name).

 Move.l D7,D0  ; Create a size to allow 2 bytes for
 Lsl.w  #1,D0  ; each resource ID.
 _NewPtr,Clear
 Movea.lA0,A4  ; Store pointer to non-relocatable block.
 
 Setup the Resource Manager so that the resources aren't loaded into 
memory.

 ; Procedure SetResLoad (load: Boolean);
 Move.b #False,-(SP) ; Load False
 _SetResLoad
 
 Clr.w  D3; Loop counter (# of font resources).
 Clr.w  D4; Offset into the theID non-relocatable block.
 Clr.w  D5; The number of different fonts.
 Clr.l  D6; The # of bytes to allocate to FontMap.
 ; Setup a non-relocatable block for the name of a resource.
 Move.l #256,D0  ; The # of bytes required.
 _NewPtr,Clear
 Move.l A0,thename(A5)  ; Store pointer.
 
ExamRes 
 Addq.w #1,D3    ; increment loop counter.

Obtain a handle to a resource with type 'FONT' and an index value from 1-to-CountResources.

 ; Function GetIndResource (theType: resType; index: Integer): Handle;
 Clr.l  -(SP)    ; Space for handle
 Move.l #'FONT',-(SP); Font resource type
 Move.w D3,-(SP) ; Index value
 _GetIndResource
 
 ; Use the handle to obtain the resources ID and name.
 ; The handle is already on the stack.
 Pea    theID(A5); point to theID
 Pea    theType(A5); point to theType
 Move.l thename(A5),-(SP) ; load address of name
 _GetResInfo
 
 Move.w theID(A5),D0 ; Examine theID to see if resource
 Andi.w #FSize,D0; has a font size (ie no name).
 Beq.s  NoSize   ; NoSize, ie a name-> NoSize

Place theID of the font resource (which contains a font size) into the non-relocatable block. Then increment the offset.

 Move.w theID(A5),(A4,D4.W)
 Addq.w #2,D4    ; increment the offset
 Bra.s  Testloop
 
NoSize  
 Movea.lthename(A5),A0

Evaluate the number of bytes to allocate to this font's name in the FontMap. Add this to the running total.

 Clr.l  D0
 Move.b (A0),D0  ; Create an even length for the name
 Bset.l #0,D0    ; (ie add padding if its rEquired).
 Addq.l #1,D0
 Add.l  D0,D6    ; Update the running total.
 Move.l A0,-(SP) ;Place the pointer to the name and 
 Move.w theID(A5),-(SP) ; resource ID onto the stack.
 Addq.w #1,D5  ; Increment the number of different fonts.

Create a new non-relocatable block for the next font resource name.

 Move.l #256,D0  ; The # of bytes required.
 _NewPtr,Clear
 Move.l A0,thename(A5)  ; Store pointer

Testloop
 Cmp.w  D3,D7    ; Have all font resources been
 Bne.s  ExamRes  ; examined, No -> ExamRes
 
 ; Dispose of pointer in thename(A5) 
 Movea.lthename(A5),A0
 _DisposPtr

Setup the Resource Manager so that the resources can be loaded into memory.

 ; Procedure SetResLoad (load: Boolean);
 Move.b #True,-(SP); Load True
 _SetResLoad

Evaluate the number of bytes required for the FontMap. Then create a relocatable block for the FontMap. D6 contains the number of bytes to allocate for the font names in the FontMap.

 Addq.l #2,D6  ; 2 bytes for "the number of fonts"
 Clr.l  D0
 Move.w D5,D0  ; The # of different fonts, each font
 Mulu   #6,D0  ; list rEquires 6 bytes.
 Add.l  D0,D6
 Move.l D0,D3  ; Reserved for later.

The amount of space to allocate for the font sizes is 2 x the number of font resources. This allows one word per entry.

 Lsl.l  #1,D7
 Add.l  D7,D6  ; Grand Total in D6
 
 Move.l D6,D0
 _NewHandle 
 Move.l A0,FontMap(A5)  ; Store the FontMap handle.
 Movea.lA0,A2    ; Copy the handle.
 _HLock ; lock it
 
 Movea.l(A2),A2  ; Obtain the address of the FontMap.
 Subq.w #1,D5    ; The number of fonts- 1.
 Move.w D5,(A2)  ; Store # of fonts- 1 in FontMap.
 
 Lea.l  2(A2,D3.W),A1; start of font name list.
 Lea.l  2(A2),A0 ; start of the font info list.
 
 ; Transfer theID and name pointer onto FontMap from stack.

Transfer
 Move.w (SP)+,(A0)+; theID
 Move.l (SP)+,(A0)+; name pointer.
 Cmpa.l A0,A1  ; Have all the resources been transfered?
 Bne.s  Transfer ; No -> Transfer.
 
 ; The information on the FontMap, in the font info list is now sorted 

 ; so that the first font info has the lowest (alphabetically) name
 ; associated with it.
 Move.w (A2),D7
 Mulu   #6,D7    ; Point to last entry in list
@1 Move.w D7,D6
@2 Subq.w #6,D6
 Bmi.s  @3
 Movea.l2+2(A2,D7.W),A1 ; Load pointer to aStr
 Movea.l2+2(A2,D6.W),A0 ; Load pointer to bStr
 ; Compare the two strings.
 ; Function IUMagString (aPtr, bPtr: Ptr; aLen, bLen: Integer): Integer;
 Clr.w  -(SP)    ; Clear for result.
 Pea    1(A1)    ; Address of aStr
 Pea    1(A0)    ; Address of bStr
 Clr.w  D0
 Move.b (A1),D0
 Move.w D0,-(SP) ; Length of aStr
 Move.b (A0),D0
 Move.w D0,-(SP) ; Length of bStr
 _IUMagString    ; Compare aStr and bStr
 Move.w (SP)+,D0
 Cmpi.w #1,D0    ; Was aStr greater than bstr
 Beq.s  @2; Yes -> @2.
 
 ; Swap the theID and the name pointers over
 Move.w 2(A2,D7.W),D0; Swap theIDs over
 Move.w 2(A2,D6.W),2(A2,D7.W)
 Move.w D0,2(A2,D6.W)
 Move.l 2+2(A2,D7.W),D0 ; Swap the pointers over
 Move.l 2+2(A2,D6.W),2+2(A2,D7.W)
 Move.l D0,2+2(A2,D6.W)
 Bra.s  @2
 
@3 Subq.w #6,D7  ; Shorten the search and repeat until
 Bne.s  @1; the table is completely sorted.

Now that the entries in the font info list have been sorted the font names are loaded into the FontMap and the name pointer is now replaced by a two byte offset, As each font name is loaded its non-relocatable block is disposed of.

 Move.w (A2),D5
 Addq.w #1,D5    ; The number of fonts.
 Mulu   #6,D5
 Addq.w #2,D5
 ; D5 contains the offset to the postion of the first font name.
 
 Clr.w  D7; loop counter (the # of fonts - 1)
LoadNames
 Move.w D7,D6
 Mulu   #6,D6    ; Point to the next font info
 Movea.l2+2(A2,D6.W),A3 ; Obtain pointer to the name.
 Move.w D5,2+2(A2,D6.W) ; Store name offset in FontMap.
 
 ; Perform a BlockMove to load the font's name.
 ; Procedure BlockMove (sourcePtr, destPtr: Ptr; byteCount: Size);
 Clr.l  D0
 Move.b (A3),D0
 Bset.l #0,D0
 Addq.l #1,D0    ; # of bytes required to move.
 Lea    (A3),A0  ; load source address
 Lea    (A2,D5.W),A1 ; load destination address
 Add.w  D0,D5  ; point to next name (offset)
 _BlockMove
 Movea.lA3,A0  ; Dispose of the non-relocatable block
 _DisposPtr ; it's no longer required.
 
 Addq.w #1,D7    ; increment counter
 Cmp.w  (A2),D7
 Ble.s  LoadNames
 
 ; Load the font sizes
 Clr.w  D7; loop counter
LdFSizes
 Lea    (A2,D5.W),A0
 Clr.w  (A0)
 Move.w D7,D6
 Mulu   #6,D6    ; Point to the next font info
 Move.w 2(A2,D6.W),D3; theID of the font
 Move.w D5,4+2(A2,D6.W) ; size list offset in FontMap
 Clr.w  D2; Offset into the theID block
@1 Move.w (A4,D2.W),D0    ; Obtain the next theID
 Andi.w #FNum,D0
 Cmp.w  D3,D0
 Bne.s  @2
 Move.w (A4,D2.W),D0
 Andi.w #FSize,D0
 Addq.w #1,(A0)  ; Increment "# of font sizes" counter
 Move.w (A0),D1  ; Offset to place font size in list
 Lsl.w  #1,D1    ; Doubled to allow for word length.
 Move.w D0,(A0,D1.W) ; Store the font size
@2 Addq.w #2,D2  ; Increment offset counter
 Cmp.w  D2,D4    ; Examined the complete block
 Bgt.s  @1; No -> @1.
 
 ; Sort the font size list in order of smallest to largest.
 Move.w (A0),D3  ; The # of font sizes
 Lsl.w  #1,D3    ; Offset to the last font size
Sort1 
 Move.w D3,D2
Sort2
 Subq.w #2,D2
 Beq.s  Sort3
 Move.w (A0,D3.W),D1
 Cmp.w  (A0,D2.W),D1
 Bgt.s  Sort2
 Move.w (A0,D2.W),(A0,D3.W)
 Move.w D1,(A0,D2.W)
 Bra.s  Sort2
Sort3
 Subq.w #2,D3
 Bne.s  Sort1
 
 ; Convert the font "theID" into the font number
 Move.w 2(A2,D6.W),D3
 Lsr.w  #7,D3
 Move.w D3,2(A2,D6.W)

Update the offset in the FontMap (D5) to point to the location of the font sizes associated with the next font.

 Move.w (A0),D0
 Addq.w #1,D0
 Lsl.w  #1,D0
 Add.w  D0,D5
 
 ; Check to see if there are any more fonts to load into the FontMap.

 Addq.w #1,D7
 Cmp.w  (A2),D7
 Ble.s  LdFSizes

The FontMap has been created, and loaded with its information. Dispose of the theID non-relocatable block and unlock the FontMap.

 Movea.lA4,A0
 _DisposPtr
 Movea.lFontMap(A5),A0
 _HUnlock
 
 ; Restore registers to their original values
 Movem.l(SP)+,D0-D7/A0-A4
 Unlk   A6
 
 Rts
 
; ---------- Variables ----------

theID   Ds.w1  
theType Ds.l1
thename Ds.l1
FontMap Ds.l1    ; Handle of the FontMap.

End

;------------------ FontMacros -------------

; Written by Ray.A.Cameron

; -----  Control Manager Routines

 ; Procedure DrawControls (gp: GrafPort)
 .Macro DrawControls
 Move.l %1,-(SP)
 _DrawControls
 .Endm
 
 ; Procedure HiliteControl (theControl: Control Handle; hiliteState: 
Integer)
 .Macro HiliteControl
 Move.l %1,-(SP)
 Move.w %2,-(SP)
 _HiliteControl
 .Endm

 ; Procedure SetCtlValue (theControl: ControlHandle; theValue: Integer)
 .Macro SetCtlValue
 Move.l %1,-(SP)
 Move.w %2,-(SP)
 _SetCtlValue
 .Endm
 
; -----  Dialog Manager Routines
 ; Procedure CloseDialog (theDialog: DialogPtr)
 .Macro CloseDialog
 Move.l %1,-(SP)
 _CloseDialog
 .Endm
 
 ; Procedure GetDItem (theDialog: DialogPtr; itemNo:Integer;
 ; Var type: Integer; Var item: Handle; Var box: Rect)
 .Macro GetDItem
 Move.l %1,-(SP)
 Move.w %2,-(SP)
 Pea    %3
 Pea    %4
 Pea    %5
 _GetDItem
 .Endm

 ; Procedure GetIText (item: Handle; Var text: Str255)
 .Macro GetIText
 Move.l %1,-(SP)
 Pea    %2
 _GetIText
 .Endm
 
 ; Procedure SetDItem (theDialog: DialogPtr; itemNo: Integer; type: Integer; 
item: Handle; box: Rect)
 .Macro SetDItem
 Move.l %1,-(SP)
 Move.w %2,-(SP)
 Move.w %3,-(SP)
 Pea    %4
 Pea    %5
 _SetDItem
 .Endm
 
; -----  Event Manager Routines

 ; Procedure GetMouse (Var mouseLoc: Point)
 .Macro GetMouse
 Pea    %1
 _GetMouse
 .Endm
 
 ; Function StillDown: Boolean
 .Macro StillDown
 Clr.w  -(SP)
 _StillDown
 .Endm

; -----  List Manager Routines

 ; Procedure LActivate (act: Boolean; lHandle: ListHandle)
 .Macro LMActivate
 Move.b %1,-(SP)
 Move.l %2,-(SP)
 _LActivate
 .Endm
 
 ; Procedure LAutoScroll (lHandle: ListHandle)
 .Macro LMAutoScroll
 Move.l %1,-(SP)
 _LAutoScroll
 .Endm
 
 ; Procedure LDelRow (count, rowNum: Integer; lHandle: ListHandle)
 .Macro LMDelRow
 Move.w %1,-(SP)
 Move.w %2,-(SP)
 Move.l %3,-(SP)
 _LDelRow
 .Endm

 ; Procedure LDispose (lHandle: ListHandle)
 .Macro LMDispose
 Move.l %1,-(SP)
 _LDispose
 .Endm

 ; Procedure LDoDraw (drawIt: Boolean; lHandle: ListHandle)
 .Macro LMDoDraw
 Move.b %1,-(SP)
 Move.l %2,-(SP)
 _LDoDraw
 .Endm
 
 ; Function LGetSelect (next: Boolean; Var theCell: Cell; 
 ; lHandle: ListHandle): Boolean
 .Macro LMGetSelect
 Clr.w  -(SP)
 Move.b %1,-(SP)
 Pea    %2
 Move.l %3,-(SP)
 _LGetSelect
 .Endm
 
 ; Procedure LSetSelect (setIt: Boolean; theCell: Cell; lHandle: ListHandle)
 .Macro LMSetSelect
 Move.b %1,-(SP)
 Move.l %2,-(SP)
 Move.l %3,-(SP)
 _LSetSelect
 .Endm
 
 ; Procedure LUpdate (theRgn: RgnHandle; lHandle: ListHandle)
 .Macro LMUpdate
 Move.l %1,-(SP)
 Move.l %2,-(SP)
 _LUpdate
 .Endm

; -----  Memory Manager Routines

 ; Procedure DisposePtr (p: Ptr)
 ; On Entry A0: p (pointer)
 ; On ExitA0: 0
 ; D0: result code (integer)
 .Macro DisposePtr
 Move.l %1,A0
 _DisposPtr
 .Endm
 
 ; Procedure HLock (h: Handle)
 ; On Entry A0 - h (Handle)
 ; On ExitD0 - result code (integer)
 .Macro HLock
 Movea.l%1,A0
 _HLock
 .Endm
 
 ; Procedure HUnLock (h: Handle);
 ; On Entry A0 - h (Handle)
 ; On ExitD0 - result code (integer)
 .Macro HUnLock
 Movea.l%1,A0
 _HUnLock
 .Endm
 
; -----  Quick Draw Routines

 ; Procedure DisposRgn (rgn: RgnHandle)
 .Macro DisposeRgn
 Move.l %1,-(SP)
 _DisposRgn
 .Endm
 
 ; Procedure EraseRect (r: Rect)
 .Macro EraseRect
 Pea    %1
 _EraseRect
 .Endm
 
 ; Procedure FrameRect (r: Rect)
 .Macro FrameRect
 Pea    %1
 _FrameRect
 .Endm
 
 ; Procedure FrameRoundRect
 .Macro FrameRoundRect
 Pea    %1
 Move.w %2,-(SP)
 Move.w %3,-(SP)
 _FrameRoundRect
 .Endm
 
 ; Procedure GetFontInfo (Var info: FontInfo)
 .Macro GetFontInfo
 Pea    %1
 _GetFontInfo
 .Endm

 ; Procedure GetPenState (Var pnState: PenState)
 .Macro GetPenState
 Pea    %1
 _GetPenState
 .Endm
 
 ; Procedure GlobalToLocal (Var pt: Point);
 .Macro GlobalToLocal
 Pea    %1
 _GlobalToLocal
 .Endm

 ; Procedure InsetRect (Var r: Rect; dh,dv: Integer)
 .Macro InsetRect
 Pea    %1
 Move.w %2,-(SP)
 Move.w %3,-(SP)
 _InsetRect
 .Endm
 
 ; Function NewRgn: Rgn Handle
 .Macro NewRgn
 Clr.l  -(SP)
 _NewRgn
 .Endm
 
 ; Procedure PenMode (mode: Integer)
 .Macro PenMode
 Move.w %1,-(SP)
 _PenMode
 .Endm
 
 ; Procedure PenSize (width, height: Integer)
 .Macro PenSize
 Move.w %1,-(SP)
 Move.w %2,-(SP)
 _PenSize
 .Endm
 
 ; Function PtInRect (pt: Point; r: rect): Boolean
 .Macro PtInRect
 Clr.w  -(SP)
 Move.l %1,-(SP)
 Pea    %2
 _PtInRect
 .Endm
 
 ; Function SectRect (srcRectA, srcRectB: Rect; Var dstRect: Rect): Boolean
 .Macro SectRect
 Clr.w  -(SP)
 Pea    %1
 Pea    %2
 Pea    %3
 _SectRect
 .Endm
 
 ; Procedure SetClip (rgn: RgnHandle)
 .Macro SetClip
 Move.l %1,-(SP)
 _SetClip
 .Endm
 
 ; Procedure SetPenState (pnState: PenState)
 .Macro SetPenState
 Pea    %1
 _SetPenState
 .Endm
 
 ; Procedure SetPort (gp: GrafPort)
 .Macro SetPort
 Move.l %1,-(SP)
 _SetPort
 .Endm
 
 ; Procedure TextFace (face: stlye)
 .Macro TextFace
 Move.w %1,-(SP)
 _TextFace
 .Endm
 
 ; Procedure TextFont (font: Integer)
 .Macro TextFont
 Move.w %1,-(SP)
 _TextFont
 .Endm
 
 ; Procedure TextSize (size: Integer)
 .Macro TextSize
 Move.w %1,-(SP)
 _TextSize
 .Endm
 
; -----  Resource Manager Routines

 ; Function GetResource (theType: ResType; theID: Integer): Handle
 .Macro GetResource
 Clr.l  -(SP)
 Move.l #%1,-(SP)
 Move.w %2,-(SP)
 _GetResource
 .Endm

; -----  Text Edit Routines

 ; Procedure TEActivate (hTE: TEHandle)
 .Macro TEActivate
 Move.l %1,-(SP)
 _TEActivate
 .Endm
 
 ; Procedure TEDeactivate (hTE: TEHandle)
 .Macro TEDeactivate
 Move.l %1,-(SP)
 _TEDeactivate
 .Endm

 ; Procedure TEDispose (hTE: TEHandle)
 .Macro TEDispose
 Move.l %1,-(SP)
 _TEDispose
 .Endm
 
 ; Procedure TEUpdate (rUpdate: Rect; hTE: TEHandle)
 .Macro TEUpdate
 Pea    %1
 Move.l %2,-(SP)
 _TEUpdate
 .Endm
 
 ; Procedure TextBox (text: Ptr; length: LongInt; box :Rect;
 ; just: Integer)
 .Macro TextBox
 Move.l %1,-(SP) 
 Move.l %2,-(SP) 
 Pea    %3
 Move.w %4,-(SP)
 _TextBox
 .Endm

; -----  Window Manager Routines

 ; Procedure BeginUpdate (gp: GrafPort)
 .Macro BeginUpdate
 Move.l %1,-(SP)
 _BeginUpdate
 .Endm
 
 ; Procedure EndUpdate (WindowPtr: WindowPtr)
 .Macro EndUpdate
 Move.l %1,-(SP)
 _EndUpdate
 .Endm
 
 ; Procedure HideWindow (theWindow: WindowPtr)
 .Macro HideWindow
 Move.l %1,-(SP)
 _HideWindow
 .Endm
 
 ; Procedure ShowWindow (theWindow: WindowPtr)
 .Macro ShowWindow
 Move.l %1,-(SP)
 _ShowWindow
 .Endm
 
; -----  Miscellaneous Routines

 .Macro DeRefHndle
 Movea.l%1,%2
 Movea.l(%2),%2
 .Endm

; File Window.Link

!Start

/Output Window

[

FontMap
FontDialog
Window

/Include Window.Rsrc

$


* Window.R
* resource file for the program called "Window"
*

Window.Rsrc
????????

Type RACA = STR 
 ,0
© by Ray A. Cameron of Australia \0Dver 4 MAR 1988

Type FREF
,128
APPL 0
,129
TEXT 1

Type BNDL
,128
RACA 0
ICN#
0 128 1 129
FREF 
0 128 1 129

* ------ Multifinder events ---------

* bit 15 = switcher save screen
* bit 14 = accept suspend resume events
* bit 13 = switcher enable option switch
* bit 12 = can do background on null events
* bit 11 = multifinder aware 
*         (activates & deactivates topmost 
*           window at resume, suspend events)

Type SIZE = GNRL
 ,-1
.H
4800    ;; $4800 = bits 14,11 set
.L
128000  ;; (for 150K recomended)
.L
80000 ;; (for 80K minimum)
.I

*
* MENU Resource #1 specifies the menus used by the Window program.
* For proper support of the Desk accessories, the Apple menu
* should be first, and the Edit menu should be third.  The first 5 items
* in the Edit menu should be identical to those used below.  This makes 

* it possible for the desk accessories to share the Edit menu with your
* application.
*

Type MENU
  ,1 (16)
\14
 About This Example...
 (-

  ,2 (16)
File
  Quit/Q

  ,3 (16)
Edit
  (Undo/Z
  (-
  Cut/X
  Copy/C
  Paste/V
  Clear

  ,4 (16)
Font
  Dialog /F

* Dialog Resource #1 specifies properties of the About box.  It points
* to Dialog Item List (DITL) Resource #1 as containing its items.

Type DLOG
  ,1
  
100 100 190 400
Visible  NoGoAway
1
0
1

* Dialog Resource #260 specifies properties of the Font  box.  It points
* to Dialog Item List (DITL) Resource #260 as containing its items.

 ,260
This is the Font Modal Dialog.
30 38 330 473
Invisible  NoGoAway 
1
0
260

* Alert Resource #260 specifies properties of the Font Alert box.  It 
points
* to Dialog Item List (DITL) Resource #261 as containing its items.

Type ALRT
 ,260
30 38 100 473
261
6665

* Dialog Item List Resource #1 specifies the items in the About box.
* By convention, the first item in an item list is the OK button.
* If there is a cancel button, it should be second.  This makes it
* easier to interpret the item number returned by the call to ModalDialog.

Type DITL
  ,1
3

Button
60 230 80 290
OK

StaticText
15 20 36 300
This sample program was written

StaticText
35 20 56 300
just to prove it could be done!

* Dialog Item List Resource #260 specifies the items in the Font box.
 ,260
21

button
8 359 26 427
Ok

button
8 281 26 349
Cancel

staticText Disabled
4 4 18 194
Character Font & Attributes

checkBox
63 339 79 422
Bold

checkBox
79 339 95 422
Italic

checkBox
95 339 111 422
Underline

checkBox
111 339 127 422
Outline

checkBox
127 339 143 422
Shadow

staticText
45 339 61 375
Style

userItem Disabled
53 331 151 427 

radiobutton
95 235 111 318
Normal

radiobutton
111 235 127 318
Condense

radiobutton
127 235 143 318
Extend

staticText
77 235 93 288
Spacing

userItem Disabled
85 227 151 323 

staticText
34 4 48 81
Font Name:

userItem
54 5 150 126

staticText
34 151 48 218
Font Size:

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Tokkun Studio unveils alpha trailer for...
We are back on the MMORPG news train, and this time it comes from the sort of international developers Tokkun Studio. They are based in France and Japan, so it counts. Anyway, semantics aside, they have released an alpha trailer for the upcoming... | Read more »
Win a host of exclusive in-game Honor of...
To celebrate its latest Jujutsu Kaisen crossover event, Honor of Kings is offering a bounty of login and achievement rewards kicking off the holiday season early. [Read more] | Read more »
Miraibo GO comes out swinging hard as it...
Having just launched what feels like yesterday, Dreamcube Studio is wasting no time adding events to their open-world survival Miraibo GO. Abyssal Souls arrives relatively in time for the spooky season and brings with it horrifying new partners to... | Read more »
Ditch the heavy binders and high price t...
As fun as the real-world equivalent and the very old Game Boy version are, the Pokemon Trading Card games have historically been received poorly on mobile. It is a very strange and confusing trend, but one that The Pokemon Company is determined to... | Read more »
Peace amongst mobile gamers is now shatt...
Some of the crazy folk tales from gaming have undoubtedly come from the EVE universe. Stories of spying, betrayal, and epic battles have entered history, and now the franchise expands as CCP Games launches EVE Galaxy Conquest, a free-to-play 4x... | Read more »
Lord of Nazarick, the turn-based RPG bas...
Crunchyroll and A PLUS JAPAN have just confirmed that Lord of Nazarick, their turn-based RPG based on the popular OVERLORD anime, is now available for iOS and Android. Starting today at 2PM CET, fans can download the game from Google Play and the... | Read more »
Digital Extremes' recent Devstream...
If you are anything like me you are impatiently waiting for Warframe: 1999 whilst simultaneously cursing the fact Excalibur Prime is permanently Vault locked. To keep us fed during our wait, Digital Extremes hosted a Double Devstream to dish out a... | Read more »
The Frozen Canvas adds a splash of colou...
It is time to grab your gloves and layer up, as Torchlight: Infinite is diving into the frozen tundra in its sixth season. The Frozen Canvas is a colourful new update that brings a stylish flair to the Netherrealm and puts creativity in the... | Read more »
Back When AOL WAS the Internet – The Tou...
In Episode 606 of The TouchArcade Show we kick things off talking about my plans for this weekend, which has resulted in this week’s show being a bit shorter than normal. We also go over some more updates on our Patreon situation, which has been... | Read more »
Creative Assembly's latest mobile p...
The Total War series has been slowly trickling onto mobile, which is a fantastic thing because most, if not all, of them are incredibly great fun. Creative Assembly's latest to get the Feral Interactive treatment into portable form is Total War:... | Read more »

Price Scanner via MacPrices.net

Early Black Friday Deal: Apple’s newly upgrad...
Amazon has Apple 13″ MacBook Airs with M2 CPUs and 16GB of RAM on early Black Friday sale for $200 off MSRP, only $799. Their prices are the lowest currently available for these newly upgraded 13″ M2... Read more
13-inch 8GB M2 MacBook Airs for $749, $250 of...
Best Buy has Apple 13″ MacBook Airs with M2 CPUs and 8GB of RAM in stock and on sale on their online store for $250 off MSRP. Prices start at $749. Their prices are the lowest currently available for... Read more
Amazon is offering an early Black Friday $100...
Amazon is offering early Black Friday discounts on Apple’s new 2024 WiFi iPad minis ranging up to $100 off MSRP, each with free shipping. These are the lowest prices available for new minis anywhere... Read more
Price Drop! Clearance 14-inch M3 MacBook Pros...
Best Buy is offering a $500 discount on clearance 14″ M3 MacBook Pros on their online store this week with prices available starting at only $1099. Prices valid for online orders only, in-store... Read more
Apple AirPods Pro with USB-C on early Black F...
A couple of Apple retailers are offering $70 (28%) discounts on Apple’s AirPods Pro with USB-C (and hearing aid capabilities) this weekend. These are early AirPods Black Friday discounts if you’re... Read more
Price drop! 13-inch M3 MacBook Airs now avail...
With yesterday’s across-the-board MacBook Air upgrade to 16GB of RAM standard, Apple has dropped prices on clearance 13″ 8GB M3 MacBook Airs, Certified Refurbished, to a new low starting at only $829... Read more
Price drop! Apple 15-inch M3 MacBook Airs now...
With yesterday’s release of 15-inch M3 MacBook Airs with 16GB of RAM standard, Apple has dropped prices on clearance Certified Refurbished 15″ 8GB M3 MacBook Airs to a new low starting at only $999.... Read more
Apple has clearance 15-inch M2 MacBook Airs a...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs now available starting at $929 and ranging up to $410 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at... Read more
Apple drops prices on 13-inch M2 MacBook Airs...
Apple has dropped prices on 13″ M2 MacBook Airs to a new low of only $749 in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, now available for $679 for 8-Core CPU/7-Core GPU/256GB models. Apple’s one-year warranty is included, shipping is free, and each... Read more

Jobs Board

Seasonal Cashier - *Apple* Blossom Mall - J...
Seasonal Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Seasonal Fine Jewelry Commission Associate -...
…Fine Jewelry Commission Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) Read more
Seasonal Operations Associate - *Apple* Blo...
Seasonal Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.