mac-rom/Toolbox/StandardFile/StandardFilePACK.a

8399 lines
288 KiB
Plaintext
Raw Normal View History

;
; File: StandardFilePACK.a
;
; Contains: The Standard File package, PACK 3
;
; Written by: Steve Capps, Eric Ringewald, Ernst Beernink, John Meier, Nick Kledzik
;
; Copyright: <09> 1984-1992 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM6> 11/6/92 SWC Changed PackMacs.a->Packages.a.
; <SM5> 10/14/92 CSS Change some branch short instructions to branches. Also,
; check for .NewAge driver and display the proper icon if
; present.
; <11> 8/25/92 DTY Always use the popup CDEF. Get rid of usePopUpCDEF conditional.
; <10> 7/5/92 csd #1034877 <gbm>: Reversed some of change <9> because the code to
; rebuild the popup menu gets called multiple times. If it doesn<73>t
; _DeleteMenu the old menu, then it stays in the list and
; _InsertMenu fails. The first time _DeleteMenu is called, it<69>s
; being called for the CDEF<45>s menu which has already been removed
; from MenuList. This is okay, though; _DeleteMenu will do
; nothing.
; <9> 7/5/92 gbm #1034877,<csd>: Standard file was relying on some behavior of
; the pop-up CDEF, which has changed for Cube-E, so we must alter
; the handling of the pop-up menu. (We need to delete it from
; memory and the menu list when we<77>re through with it, because the
; CDEF no longer does that for us.
; <8> 5/26/92 FM Change the invisible check to special case remote volumes to
; never be invisible. That way if someone mounts a High Sierra or
; ISO format CD as an AppleShare volume it will show up in
; Standard File. (This is getting sick<63>)
; <7> 5/12/92 DTY #1028452: Make sure a volume is on line before seeing if it<69>s
; invisible or not.
; <6> 4/28/92 DTY Get rid of hasBalloonHelp conditional.
; <5> 4/21/92 FM Fix invisible check. I was using the wrong offset in the
; GetCatInfo reply. < duuhhhh<68>>
; <4> 4/3/92 gbm Change smKeyDisabState to a kinder, gentler spelling.
; (smKeyDisableState)
; <3> 4/3/92 DTY #1019375,<FM>: Check to see if the keyboard was already locked
; on entry to Standard File. If it was, don<6F>t lock it or unlock
; it.
; <2> 4/2/92 FM #1022940,<DTY>: #1022940 Make Standard file respect invisible
; volumes. Unfortunately High Sierra and ISO drivers that are
; currently shipping set the invisible bit by mistake. Therefore
; we have to special case them IF their FSTs are version 2.0.3 (We
; can check this by looking at the gestalt selector'hscd'. Also
; fixed #1011684 allowing recognition of user filters that change
; -1 (start hook) to an item in subdialogs
; <1> 10/1/91 JSM first checked in
; <0> 10/1/91 JSM Created from StandardFile3.PACK.a.
;
; Modification history from StandardFile3.PACK.a below:
;
; <68> 4/8/91 ngk KSM,#f2-ngk-001: remove dereferenced unlocked handle across
; DisposeMenu
; <67> 4/8/91 ngk KSM,#BS-047: fix wrong initial volume name when at desktop and
; curDirStore specifies non-boot volume.
; <66> 3/30/91 ngk DTY,#f1-ngk-002: FIx bug in which app's modalFilter proc was
; called twice with each key event.
; <65> 3/30/91 ngk DTY,#85960: don't intially activate TEbox if it is hidden
; (HideDItem). Fixes decompress dialog in AppleLink.
; <64> 3/29/91 ngk JDR,#f1-ngk-001: fix double paste in putfile for MPW and
; Hypercard
; <63> 3/25/91 ngk RLC,#b6-ngk-006: fix checking one too many file types
; <62> 3/20/91 ngk doh,#b6-ngk-004: fix abort register trashing bug
; <61> 3/18/91 ngk RLC, #85049: fix Cmd-N crash if no new folder button
; <60> 3/14/91 ngk kip,#b6-ngk-001: fix bug where pop up sometimes failed to change
; the folder.
; <59> 3/6/91 ngk RLC,#84250: fixed wrong balloon when upgrading old dialogs.
; <58> 2/26/91 ngk VL,#82594: Fix for Word 4.0, the open button was blank.
; <57> 2/21/91 ngk JDR, Fix bug introduced by fix 55.4,#82679.
; <56> 2/19/91 ngk KSM,#SLB102: now lock PACK3 before doing anything that could
; move memory. KSM,#BS-036: fix enabling of eject button after
; creating a new folder. KSM,#BS-040: check for Cmd-uppercase-V as
; well as Cmd-lowercase-v.
; <55> 2/11/91 ngk JDR,#82022: clr.w -(sp) instead of subq #2,sp before calling
; App's dialogfilter to fix bug in FileMaker. JDR,#79895: Force
; _PenNormal before drawing file list outline to fix bug in
; FileMaker. JDR,#82542: Fix out of bounds possibility in
; QuickSort. JDR,#82679: Volume name not updating on disk-insert
; and when following an alias to another volume. JDR,#82680: Fix
; saving at desktop for QuickMail. JDR,#82198: Fix disk insert
; check for UltraPaint by not relying on null events to check for
; insert event. JDR,#82541: Fix bug where InvalRect called before
; port set.
; <54> 1/26/91 PKE JSM,#79771: Ignore script codes in HFS info if the bit that
; enables scripted HFS items is off (as it is in System 7). Deals
; with problems caused by Finder setting these script codes to the
; wrong value. The real bug fix is in Finder.
; <53> 1/24/91 ngk VL, #77818: Fixed quicksort bug.
; <52> 1/17/91 ngk <KSM> fix for right-left script systems in putFile TE item.
; <51> 1/14/91 ngk <KSM> fix bug when filename field is full, now allow typing over
; selection to work.
; <50> 1/14/91 ngk <KSM> Fix bug if starting at desktop, lDisplyedVolRef not set
; up. Do better preflighting by preloading and marking nonpurgable
; all needed resources. Fix bug where you could put <Enter> into
; putfile filename box. When at desktop and nothing is selected,
; fix reply record to have vRefNum/dirID of last volume shown.
; <49> 1/9/91 ngk <kip> Fix bug in which save button had inconsistent hilight
; state if back window had update pending. Fix selectAndReveal to
; no longer scroll list so much that some blank spaced showed. Add
; support for custom SF2 dialogs to have help items. Fix clicking
; on volume when file list not active to draw list. Add support
; for page up/down keys. Optimized sorting in US case by checking
; if list is sorted before doing QuickSort. Changed drawing order
; to not clear list until new list is ready. Fix memory leak of
; items handle and dirID array.
; <48> 1/4/91 ngk <KSM> Fix bug that prevented you from opening an alias to a file.
; <47> 12/14/90 ngk <pp> Fix bug in which aliases to applications were always showing up.
; <46> 12/14/90 ngk <KSM> Try to use PopUpMenu CDEF. Fixed too many files bug - it
; now just displays as many as will fit (~600 but depends on name
; lengths). Fixed a bug for ResEdit - if app maps alias open to 1
; then return with alias in reply, not target. When at desktop and
; a MFS disk is choosen, now dim new folder button. Rework initial
; drawing so old and new calls get activate, update, then list
; built. Fix bug with initial active item not getting set up, if
; non-standard. Use bitsaving balloon for popupmenu. Don't warn on
; lock files for old calls. Don't warn about locked stationery.
; FIx saving to desktop bug, it sometimes choose wrong volume if
; desktop button was used. Fix Eject and Cmd-Right/LeftArrow to
; update volume icon. Use Record defintion for accessing PoupCDEF
; internal data.
; <45> 11/28/90 ngk <KSM> Fixed Pagemaker 4.0 bug - in their DITL, item one is a pict item
; intead of a button. Changed old calls to SF to draw in the old
; order so that apps that depend on activate as the first event
; are happy. Fixed sfHookChangeSelect in CustomPutFile to not show
; selection unless file list is active. If a file is not really an
; alias file, then return with it, instead of error alert. Force
; alias flag of folders to false. Fix type select to center select
; item in list, if the list had to be scrolled. Removed flicker of
; selected item if it is reselected. If app maps -1 hook to
; sfHookGotoDesktop then first volume on desktop is now selected.
; <44> 11/20/90 DC Fixed names of ID's of system icons
; <43> 10/30/90 ngk StandardGetFile was ignoring numTypes. In AddFolderContenst fix
; bug when numTypes is 0. Fix bug for apps that do folder
; selection and don't map to open instead of cancel. Disable Cmd
; right,left arrow when only 1 disk. Don't give tab key to old
; filter procs, MacWriteII tries to use it. Set low mem SFSaveDisk
; and CurDirStore when at desktop to reflect the desktop folder
; for the selected item. When in volume select compatability mode,
; do not map cmd-D. Fix GotoDesktop to not select first item in
; list, unless list is active. Fix set up of new folder button to
; dim if folder does not have search privileges. If app maps -1 to
; something, don't build list twice. Fix bug where filter proc was
; ignoring activate events. When at desktop and a disk is ejected,
; don't goto next drive. Use teSysJust to decide which side icons
; go on. Add flag after pack version that forces icons to be on
; left. Use new stationery icon. Fix bug in sorting use
; IUGetScriptItl instead of GetResource. Add SetUpDialogFlags to
; set up dialog flags for new std filter proc.
; <42> 9/27/90 ngk Pre-flighting Pack6 before calling _TypeSelectClear. Fill in
; reply record after click selecting a new item.
; <41> 9/17/90 ngk Disable new folder button on MFS disks.
; <40> 9/16/90 ngk Fixed bug that stopped type select from working in put file if
; TE item is disabled.
; <39> 8/31/90 ngk Restore check for command period and ESC, since
; standardFilterProc no longer does it for me. Restore lock state
; of PACK 0 and 6. Use resource based way to map file types to
; icons, now that special folders have seperate types. Use string
; resource to get command keys so that it is now localizable.
; <38> 8/21/90 ngk Don't allow word wrap and do allow horizontal scrolling in
; putfile TE.
; Beep if user tries to type more than 31 chars into filename TE.
; When pasting into filename TE, map <CR> and ':' to '-' and truncate
; to 31 chars. Add warning on opening locked files. Check for
; stationery and lockness (Nessie) after resolving aliases.
; Fixed bug in sorting, if list contained mixed scripts.
; Fixed bug where stationery warning dialog contained garbage.
; Fixed bug where if CurDirStore is set to trash, the system hangs.
; <37> 8/11/90 ngk Lots of bugs fixed: Auto-key tabbing in getfile selected a file.
; Finder flags not set to target when returning after resolving an
; alias. Selecting an alias to a volume, (incorrectly) set
; isFolder flag. sfHookOpenAlias on an alias file did not work.
; New folder at desktop put on wrong disk. Alias to volume on
; desktop did not resolve. In old reply records, wrong dirID was
; put in fType when selecting a volume. Set dir flag of alias file
; cat info when filtering thru CustomGetFile. Two files are
; selected, if app puts up its own window over sf. Now remember
; the folder in use for each volume. Stop using colorized icons in
; non-color grafports.
; <36> 8/7/90 PKE (first item is per NGK) Fix bug disposing of color table handle
; that doesn<73>t exist. (Now PKE changes) If setting of script tags
; is disabled, then lock keyboards when in Standard File, and - if
; sfPut - return smSystemScript as ScriptCode in reply record, and
; set Finder script tag byte to unused (=0) when creating folders.
; <35> 8/6/90 ngk Run folders through an apps filter in CustomGetFile when
; numTypes = -1.
; <34> 8/5/90 ngk When at desktop, update volume icon/name to reflect current
; selection. Preflight Pack-0 and Pack-6. Fixes so that during
; hook calls while at desktop, reply record has correct dirIDs.
; packed together fields in FileEntry. Fix filter to do nothing on
; subdialogs. Call activate proc even on known items. Save port
; around GetNextEvent. Use GetLabels call to get icon colors.
; <33> 7/26/90 ngk Fix use of editOpen to editField. Allow app to map -1 to
; sfHookGotoDesktop. Fix auto-key in list to not put chars into
; text field. Fix dialog hook to not be called on subdialogs for
; old routines.
; <32> 7/24/90 gbm Knock of a few assembler warnings
; <31> 7/19/90 EMT Layers.a -> LayerEqu.a
; <30> 7/15/90 ngk Now use ResolveAliasFile routine. Goto-Alias-Target when target
; is at the desktop level now works. Make aliases to folders and
; volumes show up in old filtered getfile and look like a folder
; for CustomGetFile.
; <29> 7/6/90 RLC Fix special case balloons to clear flag if mouse isn't in one of
; the special areas.
; <28> 7/3/90 ngk un-comment-out call to StdFilter.
; <27> 7/2/90 ngk Change _DisposDialog to _CloseDialog. Map 'drop' to 'APPL' for
; file filtering.
; <26> 7/2/90 ngk Use PictButton CDEF for NewFolderButton. Rework event loop for
; sub dialogs. Cached control handle for all buttons. Call dialog
; hook and filter for sub dialogs, too. Dim "Create" button in New
; folder dialog, if no name is entered. Changed Alerts to Dialogs.
; Use new server icon for file servers. Copy Finder color table
; into listRec.usrHandle for coloring of icons. Fix bug with
; activate lists and procs. Fix Cmd-DownArrow bug on aliases.
; Change gotoAliasTarget to option-open. Fix bug with volume
; sorting/selection. Use StdFilterProc to reduce code size.
; <25> 6/14/90 ngk Fix bug with SF2Compatibility.
; <24> 6/7/90 ngk Add compatability mode for volume selecting. Fix bug with
; locking ioNamePtr.
; <23> 6/6/90 ngk Use script manager alias style info. Always make sure handle
; that ioNamePtr points into for fileFilter is locked down. Moved
; stackframe definition into this file.
; <22> 6/1/90 ngk Add error message for new folder when name already exists. Fix
; bug in pop up going to desktop of locked volume. Added support
; for new edition file types. Now properly set sfIsVolume. Range
; check some strings better.
; <21> 5/23/90 ngk Conditionally use popup CDEF. Handle userCanceledErr in
; ResolveAlias. In PutFile, no longer select first item by
; default. Add Cmd-D to mean Desktop. Make sure apps get initial
; update event filter call. Fix redrawing of open outline. Removed
; patch to GetResource('SICN',x) by changing MDEF. Dialog storage
; now allocated in locals, so wRefCon not needed. For SF2
; compatability, move volume item right so doesn't hit halo.
; <20> 5/2/90 ngk Moved type select code into Pack6.
; <19> 4/30/90 ngk Factored out type select code. Changed allocation of local
; variables from the stack to a heap block - machines with only 8K
; of stack were running low, and QuickDraw was having problems.
; Deselected any items in list if user drags out of list. Disable
; open/save button if nothing is seleced and remove outline. Fix
; disk-insert and folder change via popup to select first item in
; target folder. Deselect list item if list is deactivated. Add
; Outline to default button in new folder sub-dialog. Make sure
; that NewFolder dialog is always on screen. Add standard keyboard
; equivalents for NewFolderDialog (Cmd-Period, ESC, <CR>, <Enter>)
; <18> 4/19/90 ngk Fix bug in initial file to select. Changed CompStyledString to
; test for case insensitive equality. Changed TypeSelect to handle
; case insensitive exact match.
; <17> 4/18/90 ngk hilite open button in converted dialogs
; <16> 4/10/90 ngk Added new folder button to PutFile. The button is actually a
; user item that simulates a button. Added concept of virtual and
; real items, to allow items id's to be moved around. Calls 5-8
; now require a different, simpler DITL. Command-arrow keys force
; the file list to be active.
; <15> 3/27/90 ngk Changed way file list is built to be faster - less memory calls
; and less sorting needed. Changed desktop level to have volumes
; at top of list, then desktop files, then grayed trash. Changed
; type select algorithm to not require sorted file entries.
; Changed initial drawing so that initial dialog is drawn before
; the file is being built.
; <14> 3/22/90 ngk Fixed test of stationery bit.
; <12+> 3/19/90 JRM warn when opening stationery from non stationery-aware apps
; <12> 3/19/90 ngk Now no longer possible to sneak into trash. Fixed bug in which
; opening files sometimes failed.
; <11> 3/17/90 ngk Fixed two bugs that showed up in applelink download of disk
; files. 1) UpdateEvents were sent incorrectly to modalFilters,
; 2) The prompt string past into putfile was being ignored. Now
; center window, if where = <-1,-1>. Now do sanity check that
; dialog if dialog is not fully visible, then autocenter it.
; <10> 3/13/90 ngk Check that volume supports AccessCntrl before using ioACuser
; field. Fixed bug where no access privs alert was blank. Fixed
; bug where modalFilterProc was not being used in SFPxFile.
; <9> 3/10/90 csd Changed three more word references to the byte-sized style field
; to byte moves.
; <8> 3/9/90 ngk Fix 68000 bug clr.w on an odd address in initialize of
; IDirName.style Fix bug where alias to app shows up with folder
; icon.
; <7> 3/9/90 ngk Updated to changes in StandardFile.a. Fixed another bug with
; QuickMail enclosures, they thought getCancel was 2 instead of 3.
; <6> 3/5/90 ngk Only call hookLastCall on new routines, 'cause it breaks
; QuickMail enclosure retrieval. Made keyboard equivalent for
; cancel flash the cancel button.
; <5> 3/5/90 PKE Added smTruncEnd as truncWhere parameter for TruncString call,
; since TruncString interface now matches former NTruncString
; interface.
; <4> 2/28/90 ngk Fix bug where hitting return key causes crash, 'cause a6 not set
; up.
; <3> 2/25/90 ngk Fixed bug in new calls, forgot to set reply.good. Use
; kWhereToEmptyTrashFolderType instead of kTrashFolderType. Fixed
; PopUpMenu item to only be redrawn on update events for it.
; Changed LDEF interface. Changed new reply record to return
; script and finder flags. Rearranged parameters on new calls to
; make simple calls simpler.
; <2> 2/18/90 ngk Always gray out trash when at desktop. Use special $1A menu item
; for better looking pop up menu. Changed CompStyledString to use
; _IUScriptOrder and _IUMagPString. Cleaned up UserItem draw
; procedure. Moved drawing of folder pop-up, file list halo, and
; open button outline to dialog filter.
; <1> 2/17/90 ngk Split 7.0 and 6.0 into separate files. System 7.0 has
; StandardFile3.<2E> and system 6.0 has StandardFile2.<2E>
; Split out PackMacs.a into StandardFile.a and added real record
; templates and symbolic constants for dummy hook calls.
; Massive de-spaghetti-zation (restructuring) of code.
; Transmorgified most code fragments into real procedures
; ending with rts and then MacsBug symbols. Split out incestuous
; LDEF into real stand-alone, separately-compiled LDEF.
; Fixed up button setting code. Defined and used more dummy
; hook items.
;
; split into StandardFile3.PACK.a and StandardFile2.a
;
; <8> 2/2/90 ngk Backspace and clear keys now flush type-ahead. Double clicking
; on ejected disks no longer crashes. Aliases now have their
; filenames written to the reply record before being resolved (for
; MPW set directory).
; <7> 1/25/90 JSM There is no Script Manager call to determine if truncation is
; needed, OK to use StringWidth. Remove unneeded TruncChar DC.W.
; <6> 1/22/90 JRM special case Letter folders so they get their own icon
; <5> 1/10/90 JSM Condense text, use _TruncString for long names. Based on an
; idea by Frank "Wanted His Name Here" Stanbach.
; <4> 1/6/90 JSM Change type of folder aliases in conjunction with Finder.
; <3> 1/6/90 ngk Fixed bug if NIL active list pointer was passed in. Fixed
; tabbing to file name TE in put file to select all.
; <2> 12/19/89 RC Fix odd addressing problem in lOpenState flag from TST.W to
; TST.B.
; <3.8> 12/11/89 BBM made the entry point <20>StandardFile<6C> a <20>MAIN<49> entry for 6.0.x
; systems
; <3.7> 12/7/89 dba improve type-select by using event.when instead of TickCount;
; fix bug that ignored all type-select characters when command key
; is not down; make Cmd-Left work; fix auto-scrolling and unify
; SingleSelect and SelectAndReveal; use new _LSetHilite to save
; code; get rid of bug where part of activate outline gets drawn
; in the GetFile case; activate earlier when clicking on the list
; <3.6> 11/30/89 RLC Added an 'include StandardFileHelp.a' and BSR ShowSFBalloons
; call.
; <3.5> 11/29/89 ngk Changed the border around the selected list to be 1-pix white
; then 2-pix black Fixed the activation of the TE item in Put file
; so you no longer get weird xor selection effects. Fixed a case
; where the Save/Open toggle is displayed wrong Now use edition
; mini-icon for edition files
; <3.4> 11/29/89 JRM Add reveal to command-open of aliases, open documents from trash
; or desktop
; <3.3> 11/20/89 ngk Fixed bug where you could not select the file if only one in
; folder.
; <3.2> 11/15/89 ngk Fixed missing semi-colon
; <3.1> 11/14/89 ngk Fixed type-select when key-repeat is turned off. Changed
; FileEntry to be a real record.
; <3.0> 11/14/89 JRM Use bootVol for desktop, trash, enumerate trash, open
; trash/desktop items still doesn't work
; <2.9> 11/14/89 JRM Fix eject of selected disk on desktop, stack off by 2 in
; GetFilenameScript
; <2.8> 11/7/89 csd With dba: change IDs of SICNs so they stay in the Standard File
; range
; <2.7> 10/31/89 JRM Add command-open of an alias which open the alias<61>s parent
; folder
; <2.6> 10/31/89 JRM Fix type-select by using new UpperStr
; <2.5> 10/30/89 JRM Use script byte for sorting, drawing Call RelString for sorting
; Fixed bugs opening alias documents and folders Draw aliases
; using italic, removed alias icon Use generic PACK3 icons when
; drawing and in popup
; <2.4> 10/13/89 ngk Now include 'Aliases.a'
; <2.3> 10/11/89 ngk Fixed bug with maxIndex that cause corrupted heap. Fixed
; trunction of foldername in popup with new PopUpSymbol. Fixed
; open/save toggle when nothing is selected. Fixed arrow keys to
; switch drives only with cmdkey down.
; <2.2> 10/4/89 ngk nothing
; <2.1> 10/4/89 ngk Added fancy autoscrolling so selection is always in view.
; Command-shift-uparrow now is same as desktop button. Put
; PopUpMenuSymbol on right side of directory menu. Changed height
; of directory menu back smaller. Command-UpArrow to desktop now
; selects right volume.
; <2.0> 10/1/89 ngk Removed outline from textbox when it is active item. Removed
; outline from getfile list if it is only active item. Fixed bug
; where you could double click on dimmed item.
; <1.9> 9/18/89 ngk Fixed bug of tst.w instead of tst.b
; <1.8> 9/13/89 ngk Added new selectors 5-8. Added concept of current keyboard
; target (called active DITL item), allows keyboard navigation in
; PutFile. Tabbing now moves between possible active items. Change
; open/save button to always be open when a folder is selected.
; Right arrow now moves between volumes. Command up arrow now
; selects the folder that came from. Added callBackPtr to
; selectors 7 & 8, allows them to be Pascal local procedures.
; Selectors 7 & 8's dialog filter is now called before mapping
; instead of after.
; <1.7> 8/29/89 JRM always tst.b lAtDesktop instead of tst.w
; <1.6> 8/29/89 JRM fixed all tst.w to tst.b for lNewReply
; <1.5> 8/28/89 SES removed references to nFiles.
; <1.4> 8/11/89 JRM add back in 604 conditionals that Darin said I could take out
; <1.3> 8/8/89 JRM use alias manager, folder manager
; <1.2> 6/8/89 JRM conditionals for 604 and bigbang
; <1.1> 6/5/89 JRM big bang standard file
; <v26> 4/21/89 JRM remove checks for ROM85 and FSFCBLen draw mark for aliases stub
; out code for opening aliases desktop is root of standard file
; drive button ==> desktop button add disks, trash, desktop items
; to desktop changed alerts to use string list (smaller) use list
; manager to save code use popup menu manager to save code
; <1.0> 11/16/88 CCH Added to EASE.
; <v25> 3/4/88 JRM quick fix so superdrive gets floppy icon
; <v24> 12/21/87 JRM check if sfSaveDisk or CurDirStore have been changed
; <6> 7/23/85 ELR Removed RESOURCE name for space considerations.
; 7/23/85 ELR Translated back to Workshop format again. 1 Aug 1985 ELR A
; TAB character is now a Drive Button.
; 7/18/85 ELR Moved lomem storage for current folder into Pat's 'RegSave'
; area. Removed reliance on 'folder depth' being saved. Only uses
; that space if TFS is around.
; 7/17/85 ELR Fix bug in path menu for more than six levels deep.
; 7/16/85 ELR Added check of Dialog origin. For dialogs from system file,
; checked for odd dialog size to verify that this is really the
; new dialog.
; 7/11/85 ELR Replaced vestigal (SetIText of item 10) to the string passed in
; "Prompt" on getfiles. Fixed Instant Pascal "X" bug.
; 7/10/85 ELR Added check in Modal Dialog filter to make sure Default Item is
; enabled if CR/Enter is hit. Should fix Microsoft bug.
; 7/2/85 ELR A Bunch of new stuff. Menu Selection of tree traversal. Saving
; last folder in low mem. Volume name is no longer hot.
; 5/1/85 ELR New Today. Cloned from the all new SF1, by Capps.
;
;
; The all new Standard File 2.
;
; 3 September 1985
;
; Written by Erich Ringewald.
;
; (C) Copyright Apple Computer Inc. 1984,1985
;
;
; 1 May 1985 ELR New Today. Cloned from the all new SF1,
; by Capps.
; 2 July 1985 ELR A Bunch of new stuff. Menu Selection of
; tree traversal. Saving last folder in low mem.
; Volume name is no longer hot.
; 10 July 1985 ELR Added check in Modal Dialog filter to make sure
; Default Item is enabled if CR/Enter is hit. Should
; fix Microsoft bug.
; 11 July 1985 ELR Replaced vestigal (SetIText of item 10) to the
; string passed in "Prompt" on getfiles. Fixed
; Instant Pascal "X" bug.
; 16 July 1985 ELR Added check of Dialog origin. For dialogs from
; system file, checked for odd dialog size to
; verify that this is really the new dialog.
; 17 July 1985 ELR Fix bug in path menu for more than six levels deep.
; 18 July 1985 ELR Moved lomem storage for current folder into Pat's
; 'RegSave' area. Removed reliance on 'folder depth'
; being saved. Only uses that space if TFS is around.
; Version
; 6 23 July 1985 ELR Removed RESOURCE name for space considerations.
; 23 July 1985 ELR Translated back to Workshop format again.
; 1 Aug 1985 ELR A TAB character is now a Drive Button.
;
; 7 15 Aug 1985 EHB Converted to use List Mini-ger
; Erase names and mini-icons if no disk inserted
; 19 Aug 1985 ELR On key events in putfile, ignore them. Fixes putfile scroll bug.
; 26 Aug 1985 ELR Only equate TAB with DRIVE if the button is lit. Fixes bugs with
; pressing the TAB key for DRIVE button functions.
; 28 Aug 1985 ELR Properly check if we are spitting out the boot disk, so that
; the formatter and other goodies are always around for the fun.
; Added conditional assembly flag PFFiles. If TRUE, Standard File
; will display files in the putfile mode.
; 3 Sep 1985 ELR Added conditional mode for TruncStr. Can put elipses in middle
; of string.
; 4 Sep 1985 EHB Deselect selection when drag to side of list.
; 5 Sep 1985 EHB Added dynamic sizing of pop-down menu.
; Added auto-scrolling of pop-down menu.
; Fixed position problem of pop-down menu.
; Used DrawName code for drawing from defProc.
; Added application mini-icon; tweaked other icons.
; 9 Sep 1985 EHB Reinstated Eject Notify to properly handle cmd-ejects.
; Fixed double-click and drag to different cell bug in SFList.
; 10 Sep 1985 EHB Fixed LDEF128 bug that put ellipses in file names.
; Made the cmd-eject stuff really work.
; If there are files in a list, select the first one.
; 8 13 Sep 1985 EHB Fixed update problem with volume and directory names.
; Eliminated double update on level switch.
; Fixed "New Button" problem (distinguish between open, double-click
; and other item coerced into Open).
; Don't select first item on putFile.
; Touched up icons and icon alignment a la Capps suggestions.
; Made PutFile list 2 cells higher so Jazz wouldn't break (looks better too).
; Rearranged PutFile Item list for same reason...
; 17 Sep 1985 EHB Make sure to set lDirName if no TFS
; 25 Sep 1985 EHB Fixed SFSaveFile logic so it's compatible.
; 04 Oct 1985 EHB Made pulldown menu's shadow smaller
; 9 06 Nov 1985 EHB Added event coersion after _ModalDialog and before call to
; user's filter proc. Double clicks -> open/save button, and
; open/save of folder not returned as button items.
; 07 Nov 1985 EHB Moved mini-icons out of resources into code. This avoids loading
; and purging and missing SICN problems.
; 07 Nov 1985 EHB rearranged ListClick for better drag selection
; 12 Nov 1985 EHB set feFile.dimmed boolean TRUE if non-folder in putFile, else FALSE
; 10 13-26 Nov 1985 EHB New button drawing; New button hiliting; fixed dlgFilter for tabbing
; to switch drives; exit treeMenu if button released before file list built;
; fixed for other DLOG's in system file; move DLOG up if too low; made things
; work pretty well with variable-sized system fonts.
; 27 Nov 1985 EHB Leave save button dimmed if disk is locked *** Is this OK???
; Made getFile list 16 pixels wider so same size as before
; 2 Dec 1985 EHB A folder open is passed through the dlgHook as "fake" item 103 (gOpenDir).
; Removed obsolete bitmap disposal code in Adios.
; 5 Dec 1985 EHB Fixed key scrolling bug introduced by fake item 103
; In treeMenu, do getVolInfo if no TFS
; Cmd-eject wasn't loading in pack2 etc. Fixed, cleaned up...
; Setup LTicks from event record in DlgFilter
; Call ListClick with LTicks from event record
; 9 Dec 1985 EHB Added code to handle up and down arrows.
; 12 Dec 1985 EHB Added command up/down arrows to traverse the path.
; 16 Dec 1985 EHB Fixed double click in folder in PutFile bug.
; 16 Dec 1985 EHB In FillReplyRecord, Put DirID into rType if a folder is selected.
; Call FillReplyRecord immediately before calling dialog hook.
; v12 17 Dec 1985 EHB Preserve lock state across calls to SF
; Fix update problem with tab-click in dirRect.
;
;-------------------- System File 3.0 ---------------------------
;
; v13 30 Jan 1986 EHB Fix another update problem with tab-click in dirRect.
; If sfSaveDisk not on-line, don't use it as default!
; 18 Feb 1986 EHB Resize list for funny sized fonts...
; Inval editText field when editText box moved.
; v14 Added TruncChar to header. If 0, no elipses.
; 26 Feb 1986 EHB Fixed hangup on App1Event (cleaned up DlfgFilter).
; 27 Feb 1986 EHB Restore passThrough of clicks in file list
;
;----------------------------------------------------------------
; ?? Aug 1986 DLD Fixed bug which was ignoring folders with privileges
; 03 Sep 1986 JRM access privilege changes
; getfile - not (search or read) grays folder icon
; putfile - not (search or write) grays folder icon
; alert prevents open dir of above
;v15 no write grays save button
;----------------------------------------------------------------
; 01 Oct 1986 JRM Fixed bug which was leaving garbage on long folder/volume names
; 01 Oct 1986 JRM Fixed bug which required an itemhit to recognize disk inserts
;v16
;----------------------------------------------------------------
; 12 Nov 1986 JRM changes to access privilege changes
; getfile - not (search or read) grays folder icon
; putfile - not search or not read/write grays folder icon
; alert prevents open dir of above
;v17 no read or no write grays save button
;----------------------------------------------------------------
;v18 03 Dec 1986 JRM don't use MPW fInvisible equate because they changed it
;----------------------------------------------------------------
;v19 12 Jan 1987 JRM don't trash $00000000 in stdExit if ListHandle is nil
; 12 Jan 1987 JRM fixed bug where a<ret> x<ret> didn't work because typeahead wasn't cleared
;----------------------------------------------------------------
;v20 26 Jan 1987 JRM use HGetState, HSetState except on old ROMs to keep UNIX people happy
; 17 Feb 1987 JRM exit file list loop only on fnfErr (someone else may have added files)
; 24 Feb 1987 JRM map command-. to cancel
; 24 Feb 1987 JRM (#6646) put up system error alert on OpenWD error
;----------------------------------------------------------------
;v21 02 Mar 1987 JRM more HGetState, HSetState, use _TickCount
;----------------------------------------------------------------
;v22 05 Mar 1987 JRM (#SD-KL029, #vr 073) fixed bugs with eject of unformatted disks
; 05 Mar 1987 JRM changes to invert by swapping foreground/background colors
;----------------------------------------------------------------
;v23 07 Jul 1987 JRM always set lPriv for MFS disks to all privileges
;----------------------------------------------------------------
;v24 <21dec87> JRM check if sfSaveDisk or CurDirStore have been changed
;(S347) when we get a gRedo command and if so, move to that
; new disk/directory.
;----------------------------------------------------------------
;v25 <04mar88> JRM quick fix so superdrive gets floppy icon
;(S420)
;----------------------------------------------------------------
;v26 <21apr89> JRM remove checks for ROM85 and FSFCBLen
; draw mark for aliases
; stub out code for opening aliases
; desktop is root of standard file
; drive button ==> desktop button
; add disks, trash, desktop items to desktop
; changed alerts to use string list (smaller)
; use list manager to save code
; use popup menu manager to save code
;(S???)
;----------------------------------------------------------------
; todo***:
; call disk driver for icon (new call that allows multiple sizes)
; show no write, no read, no search icons for current folder
; get two lomem locations
; one is a handle to the most recently used directories
; auto-sync list when changes occur (most important for desktop and appleshare folders)
; Rewrite the code that displays the volume icon and name. It might
; be smaller to use a menu and DrawItem. The code is currenly way
; too large because it used to be used by pop up and LDEF, too.
; The code for enabling/disabling the new folder button while at
; the desktop is wrong. The new folder button is enable on locked
; volumes and volumens where the user does not have permissions
; to create folders.
;------------------------------------------------------------------------
;
; Notes on starting the dialog.
;
; This is the chronological order of the call backs an app will
; get. This example use StandardGetFile with all call backs
; used. All simpler calls just skip some, but order is the same.
;
; HookProc(-1) ; chance for app to do any initialization
; DialogFilter(Deactivate) ; only if app has an active window when calling sf
; DialogFilter(Activate) ; activate event for sf main dialog
; ActivateProc(initialItem) ; tells app which item is initially the keyboard target
; DialogFilter(Update) ; update event for sf main dialog
; UserItemDrawProc(all) ; only if app has installed useritem (installed during hook -1)
; FileFilter(initial list) ; getfile only, called repeatedly to build list of files to display
;
;
PRINT PUSH,OFF
LOAD 'StandardEqu.d'
INCLUDE 'Packages.a'
MACRO
_LSetHilite ; secret List Manager interface
_PackCall #-4,_Pack0
ENDM
; secret PopUp CDEF internal structure (### should be in a private interface file someplace)
CDEFpopUpData RECORD 0
theMenu DS.L 1 ; MenuHandle
theMenuID DS.W 1 ; ID
popupResult DS.L 1 ; for MacApp & hierarchial popups (hiword == menuId)
myCtlRect DS.W 4 ; Rect, area where the control is drawn
; more fields
ENDR
INCLUDE 'Folders.a' ; for folder manager
INCLUDE 'Aliases.a' ; for alias resolving
INCLUDE 'LayerEqu.a' ; for window positioning
INCLUDE 'IntlUtilsPriv.a' ; for type select stuff
INCLUDE 'CTBUtilities.a' ; for pop up menu
INCLUDE 'Icons.a' ; for GetLabel
INCLUDE 'IconUtilsPriv.a' ; for generic icon ID's
INCLUDE 'Balloons.a' ; for help manager routines
INCLUDE 'BalloonsPriv.a' ; To get private _HMCountDITLHelpItems routine
INCLUDE 'FinderPriv.a' ; for rAliasTypeMapTable
INCLUDE 'DialogsPriv.a' ; for SetDefaultItem, etc
INCLUDE 'StandardFile.a' ; for standard file definitions
INCLUDE 'StandardFilePriv.a' ; my own equates
IF &TYPE('hasDebugSymbols') = 'UNDEFINED' THEN
hasDebugSymbols EQU 0
ENDIF
MACRO
DebuggerSymbol &name
IF hasDebugSymbols THEN
STRING ASIS
DC.B $80 + &LEN(&name)+3, 'sf_', '&name'
DC.W $0000
ENDIF
ENDM
PRINT POP
;___________________________________________________________________
;
; standard types.
;___________________________________________________________________
Point RECORD 0 ; Point = RECORD CASE INTEGER OF
v DS.W 1 ; 1: (v: INTEGER;
h DS.W 1 ; h: INTEGER);
ORG v
vh DS.W h ; 2: (vh: ARRAY[1..2] OF INTEGER)
ENDR ; END;
Rect RECORD 0 ; Rect = RECORD CASE INTEGER OF
top DS.W 1 ; 1: (top: INTEGER;
left DS.W 1 ; left: INTEGER;
bottom DS.W 1 ; bottom: INTEGER;
right DS.W 1 ; right: INTEGER);
ORG top ;
topLeft DS Point ; 2: (topLeft: Point;
botRight DS Point ; 3: (botRight: Point)
ENDR ; END;
BitMap RECORD 0 ; BitMap = RECORD
baseAddr DS.L 1 ; baseAddr: QDPtr;
rowBytes DS.W 1 ; rowBytes: INTEGER;
bounds DS Rect ; bounds: Rect
ENDR ; END;
FontInfo RECORD 0 ; FontInfo = RECORD
ascent DS.W 1 ; ascent: INTEGER;
descent DS.W 1 ; descent: INTEGER;
widMax DS.W 1 ; widMax: INTEGER;
leading DS.W 1 ; leading: INTEGER;
ENDR ; END;
EventRecord RECORD 0 ; EventRecord = RECORD
what DS.W 1 ; what: INTEGER;
message DS.L 1 ; message: LONGINT;
when DS.L 1 ; when: LONGINT;
where DS Point ; where: Point;
modifiers DS.W 1 ; modifiers: INTEGER
ENDR ; END;
VolumeParms RECORD 0 ; VolumeParms = RECORD
vMVersion DS.W 1 ; vMVersion: INTEGER;
vMAttrib DS.L 1 ; vMAttrib: LONGINT;
vMLocalHand DS.L 1 ; vMLocalHand: LONGINT;
vMServerAdr DS.L 1 ; vMServerAdr: LONGINT;
size EQU * ; END;
ENDR ;
;------------------------------------------------------
;
; parameter and local variable stack structures
;
Parameters5to8 RECORD {A6Link},DECR
GetParamSize EQU *-8 ; bytes of prameters to remove on return
fileFilter DS.L 1 ; ptr to function to weed out more files
numTypes DS.W 1 ; number of file types in typeList
typeList DS.L 1 ; ptr to file type list
ORG fileFilter+2
PutParamSize EQU *-8 ; bytes of prameters to remove on return
prompt DS.L 1 ; prompt
defaultName DS.L 1 ; default name in put file
reply DS.L 1 ; pointer to reply record
dlgID DS.W 1 ; DLOG ID to use
where DS.W 2 ; where the window goes
dlgHook DS.L 1 ; dlogHook ptr
filterProc DS.L 1 ; modal dialog filter or NIL
activeList DS.L 1 ; ptr to list of possible active items
activateProc DS.L 1 ; proc to handle activating items
callBackPtr DS.L 1 ; pass back parameter or NIL
return DS.L 1
A6Link DS.L 1
ENDR
Parameters1to4 RECORD {A6Link},DECR
GetParamSize EQU *-8 ; bytes of prameters to remove on return
GetWhere DS.W 2 ; where the window goes
GetPrompt DS.L 1 ; prompt
fileFilter DS.L 1 ; ptr to function to weed out more files
numTypes DS.W 1 ; number of file types in typeList
typeList DS.L 1 ; ptr to file type list
ORG GetPrompt+2
PutParamSize EQU *-8 ; bytes of prameters to remove on return
PutWhere DS.W 2 ; where the window goes
PutPrompt DS.L 1 ; prompt
defaultName DS.L 1 ; default name in put file
dlgHook DS.L 1 ; dlogHook ptr
reply DS.L 1 ; pointer to reply record
dlgID DS.W 1 ; DLOG ID to use
filterProc DS.L 1 ; modal dialog filter or NIL
activeList DS.L 1 ; ptr to list of possible active items
activateProc DS.L 1 ; proc to handle activating items
callBackPtr DS.L 1 ; pass back parameter or NIL
return DS.L 1
A6Link DS.L 1
ENDR
kMaxVolumes EQU 20
kPreFlightMax EQU 10 ; don't change this wihtout consulting NumPreFlightResources
PerVolumeInfo RECORD 0
desktopDir DS.L 1 ; dirID of desktop folder
lastDir DS.L 1 ; dirID of place to return to on this volume
size EQU *
ENDR
SFFrame RECORD 0
lTheDialogRec DS.B DWindLen ; window record for main dialog
lSubDialogRec DS.B DWindLen ; window record for any of the subdialogs
lA6Link DS.L 1 ; save off A6 from link
; unified parameters
lParamSize DS.W 1 ; bytes of prameters to remove on return
lWhere DS.W 2 ; where the window goes
lPrompt DS.L 1 ; prompt
lDefaultName DS.L 1 ; default file name
lFileFilter DS.L 1 ; ptr to function to weed out more files
lNumTypes DS.W 1 ; number of file types in lTypeList
lTypeList DS.L 1 ; ptr to file type list
lDlgHook DS.L 1 ; dlogHook ptr
lReply DS.L 1 ; pointer to reply record
lDlgID DS.W 1 ; DLOG ID to use
lFilterProc DS.L 1 ; modal dialog filter or NIL
lActiveList DS.L 1 ; ptr to list of possible active items
lActivateProc DS.L 1 ; proc to handle activating items
lCallBackPtr DS.L 1 ; pass back parameter or NIL
; local variables
lIOCmd DS.B ioHVQElSize ; space for any IO commands
lHit DS.W 1 ; item hit for dialog select
lItem DS.L 1 ; item handle from GetIItem
lBox DS Rect ; box for GetIItem
lKind DS.W 1 ; kind for GetIItem
lString DS.B 256 ; string temp
lPoint DS Point ; mouse point
lSavePort DS.L 1 ; the port saved
lSaveEject DS.L 1 ; the ejecthook saved
lSaveDisk DS.W 1 ; the saveDisk saved
lPack3State DS.W 1 ; the lock state of the pack
lPack0State DS.W 1 ; saved state of list pack - not used
lPack6State DS.W 1 ; saved state of international utils pack - not used
lDirName DS StyledString ; current directory name
lVolName DS StyledString ; current drive name
lVolIcon DS.W 1 ; mini-icon number for volume
lDisplyedVolRef DS.W 1 ; vRefNum of currently displayed volume
lVolRefNum DS.W 1 ; current volume refnum, calculated from drive number
lDriveNo DS.W 1 ; new drive number
lCurDir DS.L 1 ; new current directory
lNoEjects DS.W 1 ; ST if non-ejectable media
lVnFiles DS.W 1 ; # files on volume
lSigWord DS.W 1 ; sigword of current volume
lVolParms DS VolumeParms ; of current volume
lInset DS.W 1 ; Inset (pix) of folder center
lTop DS.W 1 ; Top of list
lNRect DS Rect ; name list rect
lVolRect DS Rect ; rect for volume name
lPopUpControl DS.L 1 ; control handle for pop up CDEF
lPopUpMaxRect DS Rect ; max width rect for pop up
lPopUpDirIDs DS.L 1 ; handle of array of dirIDs in pop up list
lPopUpDirCount DS.W 1 ; number of dirIDs in lPopUpDirIDs array
lFontInfoRec DS FontInfo
lHeight DS.W 1 ; ascent + descent + leading
lAlias DS FSSpec ; used when resolving alias
lOldDITL DS.B 1 ; true if old item list
lLocked DS.B 1 ; true if disk locked
lPriv DS.W 1 ; access privileges <11Sep86 jrm>
lDidEject DS.B 1 ; set TRUE if eject was done
lDidPack2 DS.B 1 ; ST if pack2 loaded
lScrollPurg DS.W 1 ; saved state of scroll bar
lLastSel DS.L 1 ; previous selected cell
lTypeSelect DS TypeSelectRecord ; buffer for type selecting
lSelector DS.W 1 ; selector number of SF call (1-8)
lDoingGetFile DS.B 1 ; Boolean, TRUE for get, FALSE for put
lUseOutlineOpen DS.B 1 ; Boolean, if true draw bold ring around open/save button
lNewReply DS.B 1 ; Boolean, Reply record is of new form
lUseCallBack DS.B 1 ; Boolean, use callBackPtr
lBalloonUp DS.B 1 ; <2.6 RLC 11/30/89> Help Mgr global use
lAtDesktop DS.B 1 ; 0=>normal, -1=>inTrash, 1=>atDeskTop
lStackFrameSize DS.W 1 ; amount of stack space to clean remove
lFileListHandle DS.L 1 ; List Manager Handle for files
lMainOpen DS.L 1 ; cache of control handle for open button in main dialog
lMainCancel DS.L 1 ; cache of control handle for cancel button in main dialog
lMainEject DS.L 1 ; cache of control handle for eject button in main dialog
lMainDesktop DS.L 1 ; cache of control handle for desktop button in main dialog
lMainNewFolder DS.L 1 ; cache of control handle for new folder button in main dialog
lNFCreate DS.L 1 ; cache of control handle for create button in new folder dialog
lEvent DS EventRecord ; an event record for disk insert events
lMeta DS.W 1 ; word for event manager<65>s modifiers
lTicks DS.L 1 ; long for event manager ticks
lMouseWhere DS Point ; Point for moused down in pop up <60>
lTrashDir DS.L 1 ; dirID of trash for volume
lDeskDir DS.L 1 ; dirID of desktop for volume
lActiveDITLitem DS.W 1 ; dialog item that responds to typing
lOpenRect DS Rect ; cache of boundry of open button
lOpenState DS.B 1 ; 0 for open shown, 1 for alt open shown
lOpenAltExists DS.B 1 ; 0 for no alt name, 1 for is alt name
lOpenName DS.B 32 ; title of open button when non-file selected
lOpenAltName DS.B 32 ; title of open button when file selected
lSystemScript DS.W 1 ; cached system script
lSystemFont DS.W 1 ; cached system script<70>s font
lSystemFontSize DS.W 1 ; cached system script<70>s font size
lBootVol DS.W 1 ; vrefnum of startup disk
lBootDrive DS.W 1 ; drive of startup disk
lTempDrive DS.W 1 ; temp drive (used during enumerate)
lMapFromVItems DS.L 1 ; pointer to table mapping virtual items to DITL items
lMapToVItems DS.L 1 ; pointer to table mapping DITL items to virtual items
lNewFolderErr DS.W 1 ; OSErr encountered by new folder create
lKnownRealItems DS.B 1 ; length of table mapping DITL items to virtual items
lQuitFlag DS.B 1 ; false until user hits open/cancel
lNewDialog DS.B 1 ; true iff using new dialog layout (i.e. newFolder button)
lVolumeSelect DS.B 1 ; true iff in volume select compatibility mode
lTemp DS.W 1 ; used for scratch
lIconColors DS.B (6*7) ; SizeOf(RGBColor)*7 label colors, color #0 is no color, 3-bits
lVolumes DS.B (kMaxVolumes*PerVolumeInfo.size)
lAliasTypeMapH DS.L 1 ; handle to table mapping alias file types to icon resource IDs
lFileTypeMapH DS.L 1 ; handle to table mapping file types to icon resource IDs
lCmdKeyOpen DS.B 1 ; command key equivalent for open button
lCmdKeyOptOpen DS.B 1 ; command key equivalent for option-open button
lCmdKeyDesktop DS.B 1 ; command key equivalent for desktop button
lCmdKeyNewFldr DS.B 1 ; command key equivalent for new folder button
lFilterFolders DS.B 1 ; In CustomGetFile folders are run through the app's filter
lSubDlgDone DS.B 1 ; dismisser button used in modal sub-dialog
lListIsActive DS.B 1 ; whether sf thinks file list is the active item
lATEIsActive DS.B 1 ; whether sf thinks a te field is the active item
lDontDrawList DS.B 1 ; flag to turn off file list drawing 'til after selection
lPopUpLooksGood DS.B 1 ; flag to not redraw popup after rebuilding its list
lInitialMapped DS.W 1 ; what the app mapped -1 hook to
lHelpTemplate DS.W 1 ; hdlg ID to call HMScanTemplate with, or zero
lActiveListBuf DS.W 6 ; for implict active list made for old calls that have added TE items
lCacheScrCode DS.W 1 ; script code of itl2 we have cached
lCacheScrHandle DS.L 1 ; itl2 handle we have cached
lTryShortSort DS.B 1 ; in US systems, file order is ususually display order, so may not need to sort
lPreFlightCount DS.B 1 ; number of resources loaded successfully
lPreFlightState DS.B kPreFlightMax ;
IAlwaysShowLocalCD DS.B 1 ; Boolean that is set when we need to special case High Sierra and ISO CD's <2> FM
IKeyboardState ds.l 1 ; <3> Current state of keyboard.
ALIGN
SFFrameSize EQU * ; size of link
ENDR
;------------------------------------------------------
;
; special key code and characters
;
chCR EQU $0D ; carriage return
chEnter EQU $03 ; Enter key (take default action)
chTab EQU $09
chLeftArrow EQU $1C
chRightArrow EQU $1D
chUpArrow EQU $1E
chDownArrow EQU $1F
chPeriod EQU $2E ; a period!
chEscape EQU $1B
chClear EQU $1B ; clear key on keypad happens to have same char code as ESC
chDelete EQU $08 ; aka backspace
kcEscape EQU $35 ; for escape we need a key code to be unambiguous
chPageUp EQU $0B
chPageDown EQU $0C
chEnd EQU $04
chHome EQU $01
StandardFile MAIN EXPORT
;-----------------------------------------------------------
;
; Pack3 - Standard File. Provides a standardized get/put file
; dialog for use by applications.
;
; #1 = putFile, #2 = GetFile
; #3 = Personal Dlg putFile, #4 = Personal Dlg getFile,
; #5 = improved PutFile, #6 = improved GetFile
; #6 = customizable improved PutFile, #7 = customizable improved GetFile
;
bra.s SkipHeader ; bra around std header
DC.W 0 ; flags
DC.L ('PACK')
DC.W 3 ; pack id
DC.W 28 ; version >= 8 = TFS Release!
; version >= 9 does events right
; version >= 14 supports truncChar
; <21dec87> version >= 24 supports changing sfSaveDisk
; <21dec87> and CurDirStore from dialogHook
; version >= 26 supports calls 5 to 8
forceIconsOnLeft DC.W 0 ; if non-zero, ignore teSysJust and force icon on left
pf2ActiveList DC.W $02,putName,putNmList ; activatable items in putfile
gf2ActiveList DC.W $01,getNmList ; activatable items in getfile
pf3ActiveList DC.W $02,sfItemFileNameTextEdit,sfItemFileListUser ; activatable items in putfile
gf3ActiveList DC.W $01,sfItemFileListUser ; activatable items in getfile
VirtualToSF2Put DC.B 0,1,2,0,4,5,6,8,0,0,7,3,0 ; mapping of virtual items to sf2Put
SF2PutToVirtual DC.B 0,1,2,11,4,5,6,10,7 ; mapping of sf2Put items to sf3
VirtualToSF2Get DC.B 0,1,3,0,4,5,6,7,0,0,0,0,0 ; mapping of virtual items to sf2Get
SF2GetToVirtual DC.B 0,1,2,2,4,5,6,7 ; mapping of sf2Get items to sf3
emptystring DC.B 1,' ' ; needed for building the pop up menu
ALIGN
SkipHeader
move.l (SP)+,A0 ; get rts
move.w (SP)+,D0 ; get flavor
cmp.w #1,d0
beq.s @SFPutFileEntry ; selector = 1
cmp.w #2,d0
beq.s @SFGetFileEntry ; selector = 2
cmp.w #3,d0
beq.s @SFPPutFileEntry ; selector = 3
cmp.w #4,d0
beq.s @SFPGetFileEntry ; selector = 4
cmp.w #5,d0
beq.s @StandardPutFileEntry ; selector = 5
cmp.w #6,d0
beq.s @StandardGetFileEntry ; selector = 6
cmp.w #7,d0
beq.s @CustomPutFileEntry ; selector = 7
cmp.w #8,d0
beq.s @CustomGetFileEntry ; selector = 8
MOVEQ #dsNoPk3,D0 ; passed bad parameter
_SysError ; and don<6F>t come back
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@SFPutFileEntry
move.w #putDlgID,-(SP) ; add parameter of DLOG ID
clr.l -(SP) ; add parameter of filter proc
bra.s @defaultActives
@SFGetFileEntry
move.w #getDlgID,-(SP) ; add parameter of DLOG ID
clr.l -(SP) ; add parameter of filter proc
bra.s @defaultActives
@SFPPutFileEntry
bra.s @defaultActives
@SFPGetFileEntry
bra.s @defaultActives
@StandardPutFileEntry
move.w #rStandardFilePutID,-(SP) ; add parameter of DLOG ID
bra.s @defaultProcs
@StandardGetFileEntry
move.w #rStandardFileGetID,-(SP) ; add parameter of DLOG ID
bra.s @defaultProcs
@CustomPutFileEntry
bra.s Main
@CustomGetFileEntry
bra.s Main
@defaultProcs move.l #-1,-(SP) ; add parameter of where
clr.l -(SP) ; add parameter of dialog hook
clr.l -(SP) ; add parameter of filter proc
@defaultActives clr.l -(SP) ; add parameter of active list
clr.l -(SP) ; add parameter of activateProc
clr.l -(SP) ; add parameter of callBackPtr
; bra.s Main
;-------------------------------------------------------------
;
; Main
;
; main loop for all standard file routines.
;
; Entry:
; A0 is return address
; D0.W is selector
;
Main
WITH SFFrame
move.l A0,-(SP) ; put return address back on stack
link A6,#0 ; allocate std. frame
movem.l D2-D7/A2-A4,-(SP) ; save regs
bsr Initialize
lea lTheDialogRec(a6),a3 ; use main dialog storage
move.w lDlgID(a6),d0 ; use the perscribed dialog ID
move.l #sfMainDialogRefCon,d3 ; mark the wRefCon as such
bsr StartDialog ; get dialog, do -1 hook, show window
bsr StartEventHandling ; handle initial activate and update events
bsr BuildInitialList ; build initial list of files
mainLoop
bsr ShowSFBalloons ; <3.6 RLC 11/30/89>
bsr FillReplyRecord ; be nice to dialog hooks
bsr SetUpButtons ; enable and disable appropriate buttons
bsr CheckDrives ; handle any inserts or ejects
bsr GetNextItemHit ; get hit
bsr DoAppsHook ; let app process hit
bsr DoMyHook ; let me process hit
tst.b lQuitFlag(a6)
beq.s mainLoop
lea lTheDialogRec(a6),a3 ; use main dialog storage
bsr EndDialog
abortExit bsr Finalize ; returns parameters to remove in d0
mainExit movem.l (SP)+,D2-D7/A2-A4 ; restore those regs
unlk A6
move.l (SP)+,A0 ; get rts
add.w D0,SP
jmp (A0)
DebuggerSymbol Main
PreFlightResources DC.W ('PA'),('CK'),0 ; list mgr
DC.W ('PA'),('CK'),6 ; international utils
DC.W ('CD'),('EF'),0 ; button CDEF
DC.W ('CD'),('EF'),1 ; scrollbar CDEF
DC.W ('CD'),('EF'),61 ; Pict button CDEF
DC.W ('CD'),('EF'),63 ; PopUp CDEF
DC.W ('fm'),('ap'),rAliasTypeMapTable ; mapping of alias to icons
DC.W ('fm'),('ap'),rGenericFileTypeMapTableID ; mapping of files to icons
DC.W ('LD'),('EF'),-4000 ; StandardFile LDEF
DC.W ('WD'),('EF'),0 ; Dialog WDEF
NumPreFlightResources EQU (*-PreFlightResources)/6
IF kPreFlightMax < NumPreFlightResources THEN
WRITELN 'kPreFlightMax is less than NumPreFlightResources'
ENDIF ; should error exit here
;-------------------------------------------------------------
;
; Initialize
;
; Initializes everything needed.
;
; assumes D0.W has selector and stack frame is set up
;
Initialize
move.w d0,d3 ; save selector
; lock and save current lock state <56, #SLB102>
move.l AppPacks+stdFile*4,a0; <56, #SLB102>
_HGetState ; get lock state <56, #SLB102>
move.b d0,d4 ; save lock state <56, #SLB102>
_HLock ; lock ourselves down <56, #SLB102>
; use a heap block for locals, cause it might use to much stack on a 68000 machine
move.l #SFFrameSize,d0
_NewPtr clear ; if this fails, abort
tst.w d0 ; d0 has MemErr
beq.s @allocOK
move.l AppPacks+stdFile*4,a0; <56, #SLB102>
move.b d4,d0 ; get saved lock state <56, #SLB102>
_HSetState ; restore lock state <56, #SLB102>
addq #4,sp ; remove return address
; mark reply record as "canceled"
move.l Parameters1to4.reply(a6),a0 ; assume old call <62, b6-ngk-004>
cmp.w #4,d3 ; test which selector <62, b6-ngk-004>
bls.s @grr ; if new call, assumption was wrong <62, b6-ngk-004>
move.l Parameters5to8.reply(a6),a0 ; new call <62, b6-ngk-004>
@grr clr.w StandardFileReply.sfGood(a0); note: works for both new and old reply records <62, b6-ngk-004>
bra.s mainExit ; quit
@allocOK move.l a6,a4 ; a4 has real stack frame for parameters
move.l a0,a6 ; a6 has the frame for locals
move.l a4,lA6Link(a6)
move.b d4,lPack3State(a6) ; and save lock state in locals <56, #SLB102>
; If setting of script tags is disabled, then lock keyboards so we can <36>
; only type in system script or Roman.
subq #4,sp ; space for GetEnvirons return
move.w #smGenFlags,-(sp) ; push GetEnvirons verb
_GetEnvirons
move.l (sp)+,d0
btst.l #smfNameTagEnab,d0 ; can we set script tags?
bne.s @doneKeybdLock ; if so, skip keyboard lock
subq #4,sp
move.w #smKeyDisableState,-(sp) ; <33> See if keyboard is already locked
_GetEnvirons
move.l (sp)+,IKeyboardState(a6) ; <33> Save it
tst.l IKeyboardState(a6) ; <33> If it<69>s already locked, don<6F>t bother locking it again.
bnz.s @doneKeybdLock ; <33>
move.w #smKeyDisableKybds,-(sp) ; disable keybds not in sys or Roman script
_KeyScript
@doneKeybdLock
; <2> FM
; Check for version 2.03 of the FSTs that handle CD's <2> FM
; They accidentally set the invisible bit <2> FM
move.b #0,IAlwaysShowLocalCD(a6) ; clear the special case flag.
move.l #kHighSierraCDFST,d0 ; check for 'hscd' <2> FM
_Gestalt ; get the response <2> FM
tst.w d0 ; if err no special case <2> FM
beq.s @noSpecialCaseCD ; <2> FM
move.b #1,IAlwaysShowLocalCD(a6) ; else set the special case flag.
@noSpecialCaseCD
; record the configuration
move.w d3,lSelector(a6) ; save the selector
@4 cmp.w #4,d3
shi.b lNewReply(a6) ; get whether it is new call
shi.b lUseOutlineOpen(a6) ; as well as calls 1 & 2
cmp.w #2,d3
bgt.s @0
st lUseOutlineOpen(a6) ; as well as calls 1 & 2
@0 cmp.w #6,d3
shi.b lUseCallBack(a6) ; only use callbackPtr on routine 7 & 8
btst #0,d3 ; is this a putfile or getfile ?
seq lDoingGetFile(a6)
beq @getFileSetUp
; set up for all put files
@putFileSetUp
tst.b lNewReply(a6)
bne.s @newPutSetUp
; set up for old put files only
move.w #Parameters1to4.PutParamSize,lStackFrameSize(a6)
move.l Parameters1to4.PutWhere(a4),lWhere(a6)
move.l Parameters1to4.PutPrompt(a4),lPrompt(a6)
move.l Parameters1to4.defaultName(a4),lDefaultName(a6)
move.w #rStandardFileOldPutID,lHelpTemplate(a6) ; old put does not have a help item
lea VirtualToSF2Put,a0
move.l a0,lMapFromVItems(a6)
lea SF2PutToVirtual,a0
move.l a0,lMapToVItems(a6)
move.b #8,lKnownRealItems(a6)
lea pf2ActiveList,a0
move.l a0,lActiveList(a6)
bra @oldSetUp
@newPutSetUp
; set up for new put files only
move.w #Parameters5to8.PutParamSize,lStackFrameSize(a6)
move.l Parameters5to8.prompt(a4),lPrompt(a6)
move.l Parameters5to8.defaultName(a4),lDefaultName(a6)
move.w Parameters5to8.dlgID(a4),d0 ; a zero for dialogID means use default
bne.s @newPutIDOK
move.w #sfPutDialogID,d0
@newPutIDOK move.w d0,lDlgID(a6)
move.b #11,lKnownRealItems(a6)
move.l Parameters5to8.activeList(a4),lActiveList(a6)
bne @newSetUp
lea pf3ActiveList,a0
move.l a0,lActiveList(a6)
bra @newSetUp
@getFileSetUp
; set up for all get files
tst.b lNewReply(a6)
bne.s @newGetSetUp
; set up for old get files only
move.w #Parameters1to4.GetParamSize,lStackFrameSize(a6)
move.l Parameters1to4.GetWhere(a4),lWhere(a6)
move.l Parameters1to4.GetPrompt(a4),lPrompt(a6)
move.l Parameters1to4.fileFilter(a4),lFileFilter(a6)
move.w Parameters1to4.numTypes(a4),lNumTypes(a6)
move.l Parameters1to4.typeList(a4),lTypeList(a6)
move.w #rStandardFileOldGetID,lHelpTemplate(a6) ; old get does not have a help item
lea VirtualToSF2Get,a0
move.l a0,lMapFromVItems(a6)
lea SF2GetToVirtual,a0
move.l a0,lMapToVItems(a6)
move.b #7,lKnownRealItems(a6)
lea gf2ActiveList,a0
move.l a0,lActiveList(a6)
bra.s @oldSetUp
@newGetSetUp
; set up for new get files only
move.w #Parameters5to8.GetParamSize,lStackFrameSize(a6)
clr.l lPrompt(a6)
move.l Parameters5to8.fileFilter(a4),lFileFilter(a6)
move.w Parameters5to8.numTypes(a4),d1
move.w d1,lNumTypes(a6)
move.w lSelector(a6),d0
cmp.w #8,d0 ; only CustomGetFile can filter folders
bne.s @getTypes
tst.l lFileFilter(a6)
sne lFilterFolders(a6) ; need a fileFIlter
cmp.w #-1,d1
seq d0 ; and numTypes = -1
and.b d0,lFilterFolders(a6) ; to filter folders
@getTypes move.l Parameters5to8.typeList(a4),lTypeList(a6)
move.w Parameters5to8.dlgID(a4),d0 ; a zero for dialogID means use default
bne.s @newGetIDOK
move.w #sfGetDialogID,d0
@newGetIDOK move.w d0,lDlgID(a6)
move.b #9,lKnownRealItems(a6)
move.l Parameters5to8.activeList(a4),lActiveList(a6)
bne.s @newSetUp
lea gf3ActiveList,a0
move.l a0,lActiveList(a6)
; bra.s @newSetUp
@newSetUp
; set up for all new routines
move.l Parameters5to8.reply(a4),lReply(a6)
move.l Parameters5to8.where(a4),lWhere(a6)
move.l Parameters5to8.dlgHook(a4),lDlgHook(a6)
move.l Parameters5to8.filterProc(a4),lFilterProc(a6)
st lNewDialog(a6)
bra.s @allSetUp
@oldSetUp
; set up for all old routines
move.l Parameters1to4.dlgHook(a4),lDlgHook(a6)
move.l Parameters1to4.reply(a4),lReply(a6)
move.w Parameters1to4.dlgID(a4),lDlgID(a6)
move.l Parameters1to4.filterProc(a4),lFilterProc(a6)
clr.b lNewDialog(a6)
; now check if no customization has been done. If so switch to new dialog
tst.l lFilterProc(a6)
bne.s @allSetUp ; can't change if there is a filter proc
tst.l lDlgHook(a6)
bne.s @allSetUp ; can't change if there is a dialog hook
tst.b lDoingGetFile(a6)
bne.s @testGetFile
cmp.w #rStandardFileOldPutID,lDlgID(a6)
bne.s @allSetUp ; can't change if there is a custom dialog
; looks like we get to pull a fast one and upgrade this to use new dialog
st lNewDialog(a6) ; say we are using new dialog
move.w #rStandardFilePutID,lDlgID(a6) ; switch ID
move.b #11,lKnownRealItems(a6) ; now have 11 items
lea pf3ActiveList,a0
move.l a0,lActiveList(a6) ; active list is different
shi.b lUseOutlineOpen(a6) ; force outlining of open button
bra.s @allSetUpUseTemplate ; going to use new dialog, so don't need to call scanTemplate <59,#84250>
@testGetFile
cmp.w #rStandardFileOldGetID,lDlgID(a6)
bne.s @allSetUp ; can't change if there is a custom dialog
; looks like we get to pull a fast one and upgrade this to use new dialog
st lNewDialog(a6) ; say we are using new dialog
move.w #rStandardFileGetID,lDlgID(a6) ; switch ID
move.b #9,lKnownRealItems(a6) ; now have 11 items
lea gf3ActiveList,a0
move.l a0,lActiveList(a6) ; active list is different
shi.b lUseOutlineOpen(a6) ; force outlining of open button
@allSetUpUseTemplate
clr.w lHelpTemplate(a6) ; going to use new dialog, so don't need to call scanTemplate <59,#84250>
; bra.s @allSetUp
@allSetUp
; set up for all routines
move.l Parameters1to4.activateProc(a4),lActivateProc(a6)
move.l Parameters1to4.callBackPtr(a4),lCallBackPtr(a6)
; <56, #SLB102> moved locking of PACK3 from here to beginning of Initialize
; save the current grafport
PEA lSavePort(A6)
_GetPort
; save off current eject hook
MOVE.L EjectNotify,lSaveEject(A6) ; save eject hook
LEA ejectHit,A1
MOVE.L A1,EjectNotify ; record ours
; mark canceled flag in reply record, in case loading of resources fails <62, b6-ngk-004>
move.l lReply(A6),a0 ; A0 = reply record <62, b6-ngk-004>
clr.w StandardFileReply.sfGood(a0) ; note: works for both new and old reply records <62, b6-ngk-004>
; load in all required resources
lea PreFlightResources,a2 ; a2 is table of resource types and IDs to load
lea lPreFlightState(a6),a4 ; a4 is array of Hstates to save for each resource
moveq #0,d3
@nextRes subq #4,sp ; loop through table
move.l (a2)+,-(sp)
move.w (a2)+,-(sp)
_GetResource
move.l (sp)+,d0
;;<62> beq abortExit
bne.s @gotRes ; <62, b6-ngk-004>
addq #4,sp ; remove return address <62, b6-ngk-004>
bra abortExit ; jump out and cleanup <62, b6-ngk-004>
@gotRes move.l d0,a0
_HGetState
move.b d0,(a4)+
_HNoPurge
addq #1,d3
move.b d3,lPreFlightCount(a6) ; after each success, mark it
cmp.b #NumPreFlightResources,d3 ; do each resource in table
blt.s @nextRes
; get handles to icon mapping resource
subq #4,sp
move.l #'fmap',-(sp)
move.w #rAliasTypeMapTable,-(sp)
_GetResource
move.l (sp)+,lAliasTypeMapH(a6)
subq #4,sp
move.l #'fmap',-(sp)
move.w #rGenericFileTypeMapTableID,-(sp)
_GetResource
move.l (sp)+,lFileTypeMapH(a6)
; set up A4 to point to reply record
MOVE.L lReply(A6),A4 ; A4 = reply record
TST.B lNewReply(a6)
BNE.S @2 ; only clear version field on old calls
CLR.W SFReply.version(A4) ; version always zero
@2
; mark the reply.good false, in case an error causes us to abort
clr.w StandardFileReply.sfGood(a4) ; note: works for both new and old reply records
; some defaults
clr.b lQuitFlag(a6)
moveq #1,d0
move.w d0,lLastSel(A6) ; no previous selection
moveq #fsRtDirID, d0
move.l d0,lCurDir(a6) ; start at the root
pea lTypeSelect(a6)
_TypeSelectClear ; clear type select buffer
; see if we should try short circuiting the quicksort by checking if list is already sorted
subq #4,sp ; space for GetEnvirons return
move.w #smRegionCode,-(sp) ; push GetEnvirons verb
_GetEnvirons
move.l (sp)+,d0
cmp.w #verUS,d0 ; ### we need to decide if verBritian, verCanada, etc should be checked
seq lTryShortSort(a6)
move.w #-666,lCacheScrCode(a6) ; use an obviously bad script code to note cache is empty
; save off low mem cur disk global
MOVE.W sfSaveDisk,lSaveDisk(A6) ; save next disk
CLR.W sfSaveDisk ; don't want to eject ???
; Get the volume of the startup disk
MOVE BootDrive, D1 ; get startup WD
LEA lIOCmd(A6),A0 ; do some I/O
MOVE D1,ioVRefNum(A0) ; ask for info about startup WD
CLR.L ioFilename(A0) ; no name
CLR ioWDIndex(A0) ; no index
_GetWDInfo
BMI.S @setBootVol ; if fails then assume it was a vRefNum
MOVE ioWDVRefNum(A0),D1 ; get volume of startup disk
@setBootVol MOVE D1,lBootVol(A6) ; save away real startup vrefnum
;LEA lIOCmd(A6),A0 ; do some I/O
CLR.W ioVolIndex(a0)
MOVE.W lBootVol(A6),ioDrvNum(A0) ; lookup by vrefnum
CLR.L ioVNPtr(A0) ; who cares about names
_HGetVInfo ; get info about this drive
MOVE.W ioVDrvInfo(A0),lBootDrive(A6); get drive of boot volume
; set up volume
bsr FindDisk ; go setup the first disk
bsr SniffDisk ; look at disk and folder
; make sure we are showing an arrow cursor
bsr SetCursorToArrow
; preprocess DITL
tst.b lNewDialog(a6)
beq.s @doneMunge
tst.b lDoingGetFile(a6)
bne.s @doneMunge
; only call this on sf3Put dialog layout
bsr.s MungeDITL ; change NewFolder user item into a rez-control
@doneMunge
rts
DebuggerSymbol Initialize
;-------------------------------------------------------------
; munges a DITL before GetNewDialog gets a hold of it.
; Converts NewFolderUseItem into a ResControl item.
;
; trashes scratch registers
;
MungeDITL
; get DLOG to get DITL ID
subq #4,sp
move.l #'DLOG',-(sp)
move.w lDlgID(a6),-(sp)
_GetResource
move.l (sp)+,a0
move.l (a0),a0
; get DITL and munge it
subq #4,sp
move.l #'DITL',-(sp)
move.w 18(a0),-(sp) ; offset in DLOG to DITL ID
_GetResource
move.l (sp)+,a0
move.l a0,a1 ; save for future use
moveq #sfItemNewFolderUser-2,d1 ; funky set up for FindItem2
bsr FindItem2 ; a0 now points to start of newfolder item
lea 12(a0),a0 ; fix up a0 to point to item type of new folder item
move.b (a0),d0 ; see if new folder item is a user item
and.b #$7F,d0 ; ignore enable bit
bne.s @exit ; if not user item then don't convert
moveq #ctrlItem+resCtrl,d0
move.b d0,(a0)+ ; convert item to a rez-control
move.b #2,(a0)+ ; rez-control has 2 bytes of parameters
; now munge in the resource ID parameter the rez-controls have
subq #4,sp ; result
move.l a1,-(sp) ; h
move.l (a1),a1
sub.l a1,a0 ; calc offset a0 is into handle
move.l a0,-(sp) ; offset
moveq #0,d0
move.l d0,-(sp) ; ptr1
move.l d0,-(sp) ; len1
move.w #rNewFolderControlID,lTemp(a6)
pea lTemp(a6) ; ptr2
moveq #2,d0
move.l d0,-(sp) ; len2 = SizeOf(word)
_Munger
addq #4,sp ; ignore result
@exit rts
DebuggerSymbol MungeDITL
;----------------------------------------------------------
; Finalize
;
; undoes all initialization, and cleans up real tidy.
;
Finalize
; clean up ghost volumes
BSR CleanVols ; unmount those guys
; dispose of handle of dirIDs used by popup
move.l lPopUpDirIDs(a6),a0
_DisposHandle
; get rid of the menu we stuck in the menu list (if it<69>s still there) <9>
; NOTE: This code is totally dependent on the current behavior of the pop-up CDEF. The latest <9>
; (as this code is written) version of the pop-up does NOT arbitrarily remove and dispose it<69>s <9>
; menu handle when the control is destroyed. Since the CDEF no longer cleans up after us, <9>
; we must delete the menu ourselves. Actually, I<>m being a LITTLE paranoid here and not trying <9>
; to delete the menu if I can<61>t find it in the list (even though I KNOW it will be there...) <9>
clr.l -(sp) ; make room for handle <9>
move.w #sfPopUpMenuID, -(sp) ; give it our special id <9>
_GetMHandle ; and ask for the handle <9>
move.l (sp)+, d0 ; clean stack and test return value <9>
beq.s @noMenuToKill ; NIL means no menu by this id is in the list<9>
move.l d0, -(sp) ; push for dispose the menu <9>
move.w #sfPopUpMenuID, -(sp) ; remove popup from menu list <9>
_DeleteMenu ; <9>
_DisposMenu ; d0 was pushed before delete <9>
@noMenuToKill ; <9>
; restore graf port
MOVE.L lSavePort(A6),-(SP) ; save the port
_SetPort
; restore old eject hook proc
MOVE.L lSaveEject(A6),ejectNotify ; restore the old notify rtn
; if we loaded stuff 'cause system disk was ejected, then make it purgable
TST.B lDidPack2(A6) ; did we call pack2?
BEQ.S @0 ; not free if no eject
_DIUnLoad
@0
; restore purge state of all required resources
; could make this loop faster by checking for purge bit before GetResource
lea PreFlightResources,a2 ; a2 is table of resource types and IDs to load
lea lPreFlightState(a6),a4 ; a4 is array of Hstates to restore for each resource
move.b lPreFlightCount(a6),d3
@nextRes subq.b #1,d3
blt.s @restoredState
subq #4,sp
move.l (a2)+,-(sp)
move.w (a2)+,-(sp)
_GetResource
move.l (sp)+,a0
move.b (a4)+,d0
btst #purge,d0 ; was purgable bit set before?
beq.s @nextRes
_HPurge ; if so mark it purgable again
bra.s @nextRes
@restoredState
; restore lock state of PACK3
move.l AppPacks+stdFile*4,a0
move.b lPack3State(a6),D0 ; get saved lock state
_HSetState ; restore lock state
; Re-enable keybds for all enabled scripts in case we disabled some of them. <36>
tst.l IKeyboardState(a6) ; <33> But if it was locked when we came in, don<6F>t unlock it.
bnz.s @keyboardWasLockedOnEntry ; <33>
move.w #smKeyEnableKybds,-(sp)
_KeyScript
@keyBoardWasLockedOnEntry
; free up space for locals and restore a6 to stack frame
move.w lStackFrameSize(a6),d3 ; get parameters to remove
move.l lA6Link(a6),a4
move.l a6,a0
_DisposPtr
move.l a4,a6
move.w d3,d0 ; return parameters to remove in d0
rts
DebuggerSymbol Finalize
;-------------------------------------------------------------
;
; An error in a getfile attempt.
;
SystemErrAlert
MOVE #sfErrSystemError,D1 ; tell user that something isn't right
BSR ErrorAlert ; show the alert.
RTS
DebuggerSymbol SystemErrAlert
;--------------------------------------------------------------------
;
; RealToVirtualItem
;
; in: D0.W - real DITL item number
; out: D0.W - virtual item number
; Z - set if no translation possible, d0 left unchanged
; trashes A0
;
RealToVirtualItem
tst.b lNewDialog(a6) ; new calls need no translation
bne.s @done
cmp.w #255,d0 ; only translate 0-255
bhi.s @noTrans
move.l lMapToVItems(a6),a0 ; get translation table
cmp.b lKnownRealItems(a6),d0
bls.s @doTrans ; if in range, do translation
@noTrans cmp.b d0,d0 ; set Z flag
bra.s @done
@doTrans move.b (a0,d0.w),d0 ; translate via lookup table
@done rts
DebuggerSymbol RealToVirtualItem
;--------------------------------------------------------------------
;
; VirtualToRealItem
;
; in: D0.W - virtual item number
; out: D0.W - real DITL item number
; Z - set if no translation possible, d0 left unchanged
;
; trashes A0
;
VirtualToRealItem
tst.b lNewDialog(a6) ; new calls need no translation
bne.s @done
move.l lMapFromVItems(a6),a0 ; get translation table
move.b (a0,d0.w),d0
@done rts
DebuggerSymbol VirtualToRealItem
;--------------------------------------------------------------------
;
; MainDialogHook
;
; in: lHit(a6) contains item hit
; a3 = dialog ptr
;
MainDialogHook
move.w lHit(a6),d0
cmp.w #sfHookFirstCall,d0
beq caseFirstHook ; sfHookFirstCall pseudo-item
cmp.w #sfHookLastCall,d0
beq caseLastHook ; sfHookLastCall pseudo-item
bsr.s RealToVirtualItem
subq #1,d0
beq caseOpen ; itemOpenButton
subq #1,d0
beq caseCancel ; itemCancelButton
subq #2,d0
beq caseOpenParent ; itemVolumeUser
subq #1,d0
beq caseEject ; itemEjectButton
subq #1,d0
beq caseNextDrive ; itemDesktopButton, but means next drive for compatability
subq #6,d0
beq caseNewFolder ; itemNewFolderUser
blt.s @doneProcess
SUB #89,D0 ; (101) rebuild file list
BLT.S @doneProcess
BEQ caseRebuildFileList
SUBQ #1,D0 ; (102) pop up a path list
BEQ casePopUpPathMenu
SUBQ #1,D0 ; (103) open a folder
BEQ caseOpenSelectedFolder
SUBQ #1,D0 ; (104) open an alias folder
BEQ caseOpenAlias
SUBQ #1,D0 ; (105) open the desktop
BEQ caseGotoDesktop
SUBQ #1,D0 ; (106) open the parent of an alias
BEQ caseGotoAliasTarget
SUBQ #1,D0 ; (107) open parent of current selection
BEQ caseOpenParent
SUBQ #1,D0 ; (108) command right arrow
BEQ caseNextDrive
SUBQ #1,D0 ; (109) command left arrow
BEQ casePrevDrive
SUBQ #1,D0 ; (110) hookChangeSelection
BEQ caseChangeSelection
SUB #sfHookSetActiveOffset-110,D0
BLT.S @doneProcess
CMP.W #50,D0 ; (200-250) set active item
BLT caseSetActiveItem
SUB #sfHookCharOffset-sfHookSetActiveOffset,D0 ; ($1000+) ?/character typed
BGT caseKeyDown
@doneProcess
RTS
DebuggerSymbol MainDialogHook
;-------------------------------------------------------------
;
; dialog is created but not shown, so do fixes
;
caseFirstHook
; cache away some font info
pea lFontInfoRec(a6) ; get the font info record
_GetFontInfo ; get the info
move.w lFontInfoRec.ascent(a6),d0
add.w lFontInfoRec.descent(a6),d0
add.w lFontInfoRec.leading(a6),d0
move.w d0,lHeight(a6)
; cache away the system script
moveq #smSysScript,d0
bsr GetScript
move.w D0,lSystemScript(A6) ; save system script (low word) in globals
MOVE.W SysFontFam,lSystemFont(A6) ; save system font in globals
CLR.W lSystemFontSize(A6) ; use default size
CLR.B lDirName.style(A6) ; the current directory is always unstyled
; cache of control handles for all buttons
moveq #sfItemOpenButton,d0
lea lMainOpen(a6),a0
bsr CacheButtonControl
move.l lBox.topLeft(a6),lOpenRect.topLeft(a6) ; save off button rect
move.l lBox.botRight(a6),lOpenRect.botRight(a6)
cmp.w #ctrlItem+btnCtrl,lKind(A6) ; this is a hack for PageMaker 4.0
beq.s @mainDone ; they change item 1 to a PICT item, instead of a button
clr.l lMainOpen(a6) ; I will mark this by a NIL controlhandle
@mainDone
moveq #sfItemCancelButton,d0
lea lMainCancel(a6),a0
bsr CacheButtonControl
moveq #sfItemEjectButton,d0
lea lMainEject(a6),a0
bsr CacheButtonControl
moveq #sfItemDesktopButton,d0
lea lMainDesktop(a6),a0
bsr CacheButtonControl
clr.l lMainNewFolder(a6) ; assume there is no new folder button
; see if the open name in the DITL is different than normal open
; if it is we will use the DITL open name when a file is selected
; and "open" when a folder or volume is selected.
LEA lOpenName(A6), A1
MOVEQ #sfOpenName, D1
BSR GetLocalString ; will return open string in lOpenName(A6)
move.l lMainOpen(A6),d0 ; get open control handle
beq.s @noOpenBut ; if it is NIL, then skip checking name
move.l d0,-(SP) ; pass in control handle
PEA lOpenAltName(A6) ; will return control title in lOpenAltName(A6)
_GetCTitle
moveq #0,d0
moveq #0,d1
tst.b lOpenAltName(A6) ; for Word 4.0, if DITL has no title <58, #82594>
beq.s @noOpenBut ; for open button, don't use alt. <58, #82594>
lea lOpenName(A6),a0
move.b (a0)+,D0 ; A0 is first char of string1
lea lOpenAltName(A6),a1
move.b (a1)+,D1 ; A1 is first char of string2
subq #2,sp ; room for result
move.l a0,-(sp)
move.l a1,-(sp)
move.w d0,-(sp)
move.w d1,-(sp)
_IUMagIDString
move.w (sp)+,d0 ; get result in d0
@noOpenBut move.b d0,lOpenAltExists(a6) ; D0 is 0 if equal, 1 if not equal
move.b d0,lOpenState(a6) ; remember we are now showing the altName
; set up command key equivalents from string resource
lea lString(A6), A1
moveq #sfCommandKeys, D1
bsr GetLocalString ; will return cmd keys string in lString(A6)
lea lString+1(A6), a0
lea lCmdKeyOpen(a6),a1 ; first command key in table
moveq #4,d0 ; number of command keyes in table
_BlockMove ; copy command keys into respective slots
; set appropriate default active item
; putFile has fileName TE active
; getFile has file list active
move.l lActiveList(a6),a0
move.w 2(a0),lActiveDITLitem(a6) ; get first item in list of activateable
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
cmp.w lActiveDITLitem(a6),d0
seq lListIsActive(a6) ; if it is file list, then remember
; set up user item for volume icon/name
moveq #sfItemVolumeUser,d0
bsr VirtualToRealItem
move.w d0,d3
bsr SetUserDraw ; install user draw proc
; set up user item for list of files
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
move.w d0,D3 ; user field ID for file box
bsr SetUserDraw ; install user draw proc
; this is here so lBox points to
; file list for SetUp List
; set up flags in dialog record. This is done before app gets first hook,
; in case app wants to change default item by changing aDefItem.
moveq #sfItemCancelButton,D0 ; get cancel button item
bsr VirtualToRealItem
move.w d0,d1 ; d1 = cancel button number
moveq #sfItemOpenButton,D0 ; get Open button item
bsr VirtualToRealItem ; d0 = default button number
move.b lNewDialog(a6),d2 ; d2 = whether to track cursor
bsr SetUpDialogFlags
tst.b lDoingGetFile(a6) ; special casing
bne.s @getFileMisc ; go to getfile
; NIL or zero length string prompt parameter => use string in DITL
MOVE.L lPrompt(A6),D0
BEQ.S @useDITL ; use DITL prompt if NIL
MOVE.L D0,A2 ; point to prompt
moveq #sfItemPromptStaticText,d0
bsr VirtualToRealItem
TST.B (A2) ; use DITL prompt if zero lenght string
BEQ.S @useDITL
BSR SetItsText
@useDITL
; set TextEdit to initially be the filename passed in
moveq #sfItemFileNameTextEdit,d0
bsr VirtualToRealItem
MOVE.L lDefaultName(A6),A2 ; point to file name
BSR SetItsText
; then select all of it
move.l A3,-(SP) ; pass the windowPtr
moveq #sfItemFileNameTextEdit,d0
bsr VirtualToRealItem
move.w d0,-(sp)
clr.w -(SP) ; select all
move.w #300,-(SP)
_SelIText ; set selection
; then enable autoscrolling of it
st -(sp) ; fAuto: BOOLEAN
move.l teHandle(a3),-(sp) ; hTE: TEHandle
_TEAutoView
; if there is a new folder button, then cache it off
tst.b lNewDialog(a6)
beq.s @continueSetUp
moveq #sfItemNewFolderUser,d0
lea lMainNewFolder(a6),a0
bsr.s CacheButtonControl
; bra.s @continueSetUp ; skip around getfile specials
@getFileMisc
@continueSetUp
; rearange MFS dialogs to work
tst.b lNewReply(a6)
bne.s @goodDITL
bsr SF1Compatability ; only call this on routines 1-4
@goodDITL
bsr GetFileListBoundary
bsr FixBoxes
bsr SetUpList
bsr FixBoxes
; Now position the window
MOVEQ #-1,D0
CMP.L lWhere(A6),D0 ; is where = <-1,-1> ?
BNE.S @moveWindow
MOVE.L A3,-(SP) ; pass the window
MOVE.B #lcMainScreen,-(SP) ; over main monitor
MOVE.B #hcCenter,-(SP) ; center horizontally
MOVE.B #vcAlertCenter,-(SP); center vertically like an alert
_AutoPositionWindow
BRA.S @windowMoved
@moveWindow
MOVE.L A3,-(SP) ; pass the window
MOVE.L lWhere(A6),-(SP) ; where it goes
ST -(SP) ; and select it
_MoveWindow
@windowMoved
rts
DebuggerSymbol caseFirstHook
;
; in d0 = virtual item code
; a0 = address to store control handle
CacheButtonControl
move.l a0,-(sp)
bsr VirtualToRealItem
bsr GetIt
move.l (sp)+,a0
move.l lItem(a6),(a0)
rts
; This is called after app get first hook call.
; It gives me a change to fix up after tweaking which app may have done.
;
MainHookAfterFirstHook
move.w lHit(a6),lInitialMapped(a6) ; save what app returned
bsr PositionSanityCheck ; make sure dialog is on screen
tst.b lNewDialog(a6) ; only do this for original four calls
bne.s @doneCompat ; that have not been upgraded to new dialogs
bsr SF2Compatability ; tweak HFS dialogs to work
@doneCompat
bsr FixBoxes ; update boxs now that we know where the window is
bsr GetFileListBoundary ; set up lNRect with file list boundary
tst.b lNewDialog(a6)
bne.s @boxFromDITL
@makeBox lea lPopUpMaxRect(a6),a0
move.w lNRect+Left(a6),Left(a0) ; Left of popup is same as left of file list
move.w lNRect+Right(a6),Right(a0) ; Right of popup is same as right of file list
move.w lNRect+top(a6),d1
subq.w #4,d1 ; need some padding
move.w d1,bottom(a0) ; bottom of popup is 3 pixels on top of file list
sub.w lHeight(a6),d1 ; system script height
subq.w #3,d1 ; more padding
move.w d1,top(a0) ; top of popup is script height + pad of 7 pixels for box
bra.s @haveMaxRect
@boxFromDITL
moveq #sfItemPopUpMenuUser,d0
bsr GetIt ; get bounding box
move.l lBox(a6),lPopUpMaxRect(a6)
move.l lBox+4(a6),lPopUpMaxRect+4(a6)
move.w lNRect+top(a6),d0 ; now check that it is at least 4 pixels above file list
sub.w lPopUpMaxRect+bottom(a6),d0
bmi.s @haveMaxRect ; if not above list, do nothing
sub.w #4,d0
bge.s @haveMaxRect ; if already 4 pixels above, do nothing
add.w d0,lPopUpMaxRect.top(a6) ; move control up to leave 4 pixels space
add.w d0,lPopUpMaxRect.bottom(a6)
@haveMaxRect
subq #4,sp ; :ControlHandle;
move.l a3,-(sp) ; theWindow: WindowPtr
pea lPopUpMaxRect(a6) ; boundsRect: Rect
clr.l -(sp) ; title: Str255 no title
sf -(sp) ; visible: BOOLEAN invisible til we build list
move.w #popupTitleCenterJust,-(sp) ; value: INTEGER centered, no styling
move.w #sfPopUpMenuID,-(sp) ; min: INTEGER menu ID for popup
clr.w -(sp) ; max: INTEGER title width
move.w #popupMenuCDEFproc,-(sp) ; procID: INTEGER no variant
clr.l -(sp) ; refCon: LONGINT no refCon
_NewControl
move.l (sp)+,lPopUpControl(a6) ; save control handle
rts
DebuggerSymbol MainHookAfterFirstHook
;-------------------------------------------------------------------------------------
;
; This gets the event off to a good start. We want the activate then update.
; If we let the dialog mgr do this, we might get key or mouse downs before the
; update.
;
StartEventHandling
; keep calling GetNextEvent 'til we get the activate event for the main dialog
@getAgain subq #2,sp ; room for Boolean result
move.w #256,-(sp) ; only want activate events
pea lEvent(a6) ; VAR eventRecord
_GetNextEvent
tst.b (sp)+
beq.s @getAgain ; if no event, try again
cmp.w #activateEvt,lEvent.what(a6)
bne.s @getAgain ; if not activate event, try again
; process the activate event by calling my dialog filter (which completely overrides dialog mgr)
bsr.s HandleEvent ; handle activate event (this is called for both deact and act)
cmp.l lEvent.message(a6),a3
bne.s @getAgain ; if not for main sf dialog, try agin
btst #0,lEvent.modifiers+1(a6)
beq.s @getAgain ; if not activating, try again (is this necessary?)
; fake an update event and handle it in my dialog filter
move.w #updatEvt,lEvent.what(a6)
move.l a3,lEvent.message(a6)
bsr.s HandleEvent
rts
DebuggerSymbol StartEventHandling
;---------------------------------
; send event to TheDialogFilter
;
HandleEvent subq #2,sp ; room for boolean result
move.l a3,-(sp) ; dialog
pea lEvent(a6) ; VAR event record
pea lHit(a6) ; VAR itemHit
bsr TheDialogFilter
addq #2,sp ; ignore result
rts
DebuggerSymbol HandleEvent
;--------------------------------------------------
;
; This is called after initial activate and update event
;
BuildInitialList
tst.b lNewDialog(a6)
beq.s @normalList ; old calls to sf don't get fancy -1 mapping
; if app mapped -1 to 110 then auto-select first file
move.w lInitialMapped(a6),d0
cmp.w #sfHookChangeSelection,d0 ; if app returned sfHookChangeSelection
bne.s @chkDesktop
st d0 ; force rebuild
bsr caseChangeSelection ; then rebuild list before showing dialog
bra.s @done
; if app mapped -1 to 103 then goto to desktop
@chkDesktop
cmp.w #sfHookGotoDesktop,d0
bne.s @normalList
bsr caseGotoDesktop2 ; switch to desktop and redraw
bra.s @done
; otherwise select first file in list if file list is initial active item
@normalList bsr ReListDisk ; enumerate folder, build file list, and draw it
tst.b lListIsActive(a6) ; see if file list is keyboard target
beq.s @done ; if not, don't select first
tst.b lAtDesktop(a6) ; if at desktop <67, #BS-047>
ble.s @first ; <67, #BS-047>
move.w lBootVol(a6),lVolRefNum(A6) ; switch to boot volume <67, #BS-047>
bsr SelectBootVolume ; select boot volume <67, #BS-047>
bra.s @done
@first move.w #chDownArrow,D0 ; else get first non-dimmed by simulating a down arrow
bsr ArrowKey
; make sure volume icon is up to date
@done move.w lVolRefNum(A6),d0 ; set up volume icon to current disk <55.7, #82680>
bsr SetVolumeIcon ; <55.7, #82680>
rts
DebuggerSymbol BuildInitialList
;-------------------------------------------------------------
; release list manager stuff
;
caseLastHook
move.l lFileListHandle(a6),a1 ; get file list handle
move.l a1,-(sp) ; dispose file list handle
_LDispose
rts
DebuggerSymbol caseLastHook
;-------------------------------------------------------------
;
; User hit cancel, escape, or command-period
;
caseCancel
st lQuitFlag(a6) ; want to fall out of event loop
rts
DebuggerSymbol caseCancel
;-------------------------------------------------------------
;
; User hit open/save, return, enter, or doubled-clicked on item in list
;
caseOpen
move.l lCurDir(A6), d7 ; default directory
move.w lVolRefNum(a6),d6 ; default vrefnum
tst.b lDoingGetFile(a6)
bne GetFileEnd
PutFileEnd tst.b lAtDesktop(a6) ; at desktop we have many possible place to save
ble.s @haveDir
move.w lDisplyedVolRef(a6),d6 ; get the volume to save on
move.w d6,d0 ; get desktop for this vRefNum
bsr GetVolumeInfoPtr ; a0 (out) pointer to info
move.l PerVolumeInfo.desktopDir(a0),d7 ; desktop dirID
@haveDir
; get info on name choosen to see if it already exists
bsr GetReplysFilenametoA0 ; get name in filename box
move.l a0,a1
LEA lIOCmd(A6), A0 ; Point to IO command block
MOVE.W d6,ioVRefNum(A0) ; use volume from globals
MOVE.L A1,ioFileName(A0) ; Set pointer to volume name
CLR.W ioFileType(A0) ; no variations, please
CLR.W ioFDirIndex(A0) ; And use given name.
move.l d7,ioDirID(a0) ; use current directory
_GetCatInfo
BEQ.S @chkOver ; if no error, may overwrite?
CMP.W #fnfErr,D0 ; not found
BEQ FinishReplyRecord ; doesn't exist, plow ahead
; CMP #-5000,D0 ; access denied <JRM 09Sep86>
; BEQ.S goodPut ; write only folders will always give this <JRM 09Sep86>
; we're not supporting write only folders yet
CMP.W #NSVErr,D0 ; see if bad volume
BNE SystemErrAlert
MOVE.W #sfErrBadFilename,D1; tell user the name or volume was bad
bra ErrorAlert
; ask the user if the existing file should be overwritten
@chkOver btst #ioDirFlg,ioFLAttrib(a0) ; is it a folder?
beq.s @chkReplaceExisting ; if not go on
move #sfErrSaveOnFolder,D1 ; warn user that that is a folder
bsr ErrorAlert
@exit bra ExitCaseOpen
@chkReplaceExisting
move.l lIOCmd+ioFileName(A6),a1 ; pass the file name
move.w #rSFReplaceExistingDialogID,d4 ; d4 is dialog to use
move.l #sfReplaceDialogRefCon,d3 ; d3 is dialog refcon
bsr ErrorAlert2 ; raise a file alert
subq #1,D0 ; look at result
bne.s @exit ; only 1 is "yes", all others mean cancel
tst.b lNewReply(A6) ; can caller handle replace flag?
beq.s @1 ; br around if not
addq.b #1,StandardFileReply.sfReplacing(A4) ; yes, it is a replace
@1 bra FinishReplyRecord
GetFileEnd bsr FillReplyRecord ; fill the return record
bsr GetSel ; get selection into A0
bmi FinishReplyRecord ; should never happen, (means nothing is selected)
; but if it does then fill out vol/dir only
btst #isAliasBit,FileEntry.feFndrFlags(a0) ; if this is an alias, then app did some slimy
; hook stuff to get this to happen
bne FinishReplyRecord ; if so, return with alias (not target) in reply
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; if this is a directory, then app did some slimy
; hook stuff to get this to happen
bne DoneGood ; if so, just return with current reply record
move.l FileEntry.feParID(A0),d7 ; remember dirID
move.w FileEntry.feVRefNum(A0),d6 ; remember vRefNum
; On opens, check if it is stationery and warn if this is a
; non stationery-aware application.
move.w FileEntry.feFndrFlags(A0),d5
swap d5 ; put finder flags in high word
move.b FileEntry.feFLAttr(A0),d5 ; and file attributes in low word
StatAndLockCheck ; needed flags are in d5
btst #isStationeryBit+16,d5 ; is this stationery? (testing high word)
beq.s @CheckLock ; br if not, no need for warning
subq #4, sp ; reserve space for handle
move.l #'SIZE', -(sp) ; look for app's size resource
move #-1, -(sp)
_GetResource ; ### maybe we should call process manager to get this
move.l (sp)+, d0 ; got the size?
beq.s @doneStatWarning ; br if no size, always do warning
move.l d0, a0
move.l (a0), a0 ; deref size resource
btst #isStatAwareBit, 1(a0) ; is app stationery aware?
bne.s @doneStatWarning ; br if so, doesn't need a warning
@warning bsr GetReplysFilenametoA0
move.l a0,a1 ; a1 is for paramtext
move.w #rSFStationeryWrnDialogID,d4 ; d4 is dialog to use
move.l #sfStatWarnDialogRefCon,d3 ; d3 is dialog refcon
bsr ErrorAlert2 ; raise a file alert
subq #1,D0 ; look at result
bne.s ExitCaseOpen ; <20>1 -> it was cancelled
@doneStatWarning
@CheckLock tst.b lNewReply(a6) ; don't give lock warning to old calls
beq.s @noLockWarning
btst #isLockedFile,d5 ; is the file locked
beq.s @noLockWarning ; br if not, no need for warning
btst #isStationeryBit+16,d5 ; is this locked stationery? (testing high word)
bne.s @noLockWarning ; if so, no need for warning
bsr GetReplysFilenametoA0
move.l a0,a1 ; a1 is for paramtext
move.w #rSFLockedWrnDialogID,d4 ; d4 is dialog to use
move.l #sfLockWarnDialogRefCon,d3 ; d3 is dialog refcon
bsr ErrorAlert2 ; raise a file alert
subq #1,D0 ; look at result
bne.s ExitCaseOpen ; <20>1 -> it was cancelled
@noLockWarning
FinishReplyRecord
; Fill out the dirID/vrefnum or WDRefnum part of the reply record
tst.b lNewReply(A6) ; can caller handle dirIDs?
beq.s @makeWD ; br if not, make a WD
move.l d7, StandardFileReply.sfFile+FSSpec.parID(A4) ; return back chosen directory
move.w d6,StandardFileReply.sfFile+FSSpec.vRefNum(A4) ; return real vrefnum
bra.s DoneGood
@makeWD cmp.w #sigWord,lSigWord(a6) ; is this an MFS disk? (lSigWord set up by SetVolumeIcon)
beq.s @returnVolume ; br if so, don't make WD on MFS Volumes
lea lIOCmd(a6),a0 ; get our IO Block back
move.w d6,ioVRefNum(a0) ; make a WD for this volume
clr.l ioFileName(a0)
move.l d7,ioDirID(a0) ; with this dirID
move.l #'ERIK',ioWDProcID(a0) ; historical reasons
_OpenWD
bmi SystemErrAlert ; too many WDs open (*** separate alert?) 24feb87
move.w ioVRefNum(a0),d6 ; returns working directory refnum in ioVRefNum
@returnVolume
move d6,SFReply.vRefNum(a4)
DoneGood addq.b #1,SFReply.good(A4) ; true, a good name (this works for both reply records)
st lQuitFlag(a6) ; want to fall out of event loop
ExitCaseOpen
rts
DebuggerSymbol caseOpen
;-------------------------------------------------------------
;
; User hit NewFolder Button
;
caseNewFolder
tst.b lNewDialog(a6) ; on do this is there is a new folder button
beq.s @exit
tst.b lDoingGetFile(a6)
bne.s @exit
; only do this if button is enabled
move.w #sfItemNewFolderUser,d0
bsr VirtualToRealItem
bsr CanDo ; is the new folder control active ?
bmi.s @exit ; exit if it is dimmed
; center over new folder button
moveq #sfItemNewFolderUser,d0
bsr VirtualToRealItem
bsr GetIt
lea lBox(a6),a0
move.w Rect.bottom(a0),d0
add.w Rect.top(a0),d0
lsr.w #1,d0 ; center.v = (top+bottom)/2
swap d0
move.w Rect.right(a0),d0
add.w Rect.left(a0),d0
lsr.w #1,d0 ; center.h = (left+right)/2
move.l d0,lPoint(a6)
pea lPoint(a6)
_LocalToGlobal ; lPoint now contains center of button in global coordinates
; get dialog for new folder name
move.w #rSFNewFolderDialogID,d0 ; id for dialog
move.l #sfNewFolderDialogRefCon,d3 ; refcon for new folder dialog
bsr DoSubDialog ; return button hit in d0
cmp.w #1,d0
bne.s @exit ; if not action button, then skip out
move.w lNewFolderErr(a6),d0 ; see if there was an error during folder create
bne.s @handleErr
bsr NewDir ; if not switch to new folder
bra.s @exit
@handleErr moveq #sfFolderNameExists,d1 ; special case error of name already exists
cmp.w #dupFNerr,d0
beq.s @doError
moveq #sfErrSystemError,d1 ; otherwise, use generic error message
@doError bsr ErrorAlert
@exit rts
DebuggerSymbol caseNewFolder
;-------------------------------------------------------------
;
;
NewFolderDialogHook
move.w lHit(a6),d0
cmp.w #sfHookFirstCall,d0
bne.s @tryNull
; set up dialog flags
moveq #1,d0 ; d0 = default button number
moveq #2,d1 ; d1 = cancel button number
st d2 ; d2 = track cursor
bsr SetUpDialogFlags
; center over new folder button
; lPoint contains center of button in global coordinates
move.w portRect+Rect.bottom(a3),d0
add.w portRect+Rect.top(a3),d0
lsr.w #1,d0 ; center.v = (top+bottom)/2
swap d0
move.w portRect+Rect.right(a3),d0
add.w portRect+Rect.left(a3),d0
lsr.w #1,d0 ; center.h = (top+bottom)/2
sub.l d0,lPoint(a6) ; lPoint now contains where to move window to
move.l a3,-(sp)
move.l lPoint(a6),-(sp)
clr.w -(sp) ; don't bring to front
_MoveWindow
bsr MyCheckWindow
bne.s @windowOK
; uh, oh. centering over newfolder button will put it off screen
; so center over main dialog, which we know is on screen.
move.l a3,-(sp) ; whichWindow: WindowPtr
move.b #lcParentWindow,-(sp) ; where: LocationControlValues
move.b #hcCenter,-(sp) ; horizontalControl: HorizontalControlValues
move.b #vcDocumentCenter,-(sp) ; verticalControl: VerticalControlValues
_AutoPositionWindow
@windowOK
; remember control handle of create button
moveq #1,d0 ; create button is item 1
bsr GetIt
move.l lItem(a6),lNFCreate(a6)
; select all of text by default
move.l a3,-(SP) ; pass the windowPtr
move.w #3,-(sp) ; TE is item 3
clr.w -(SP) ; select all
move.w #300,-(SP)
_SelIText ; set selection
bra @exit
@tryNull cmp.w #sfHookNullEvent,d0
bne.s @tryCancel
; if TE has 0 chars in it then dim "Create" button
moveq #3,d0 ; TE is item 3
bsr GetIt
move.l lItem(a6),a0
_GetHandleSize ; get length of text typed
moveq #0,d1
tst.w d0 ; >0 length -> $0000
sle d1 ; 0 length -> $00ff
move.l lNFCreate(a6),-(sp)
move.w d1,-(sp)
_HiliteControl ; properly enable button
bra @exit
@tryCancel cmp.w #2,d0 ; if cancel then dismiss dialog
beq @dismisser
cmp.w #1,d0 ; if not "New" button then go on
bne @exit
; get text out of TE box
moveq #3,d0 ; TE is item 3
bsr GetIt
move.l lItem(A6),-(sp)
pea lString(a6)
_GetIText
; get current keyboard script
bsr GetKeyScript
move.w d0,lItem(a6) ; get script out of low word
; create a folder
lea lIOCmd(a6),a0
lea lString(a6),a1
move.b (a1),d0 ; truncate entered string to 31 chars
cmp.b #31,d0
bls.s @nameOK
moveq #31,d0
move.b d0,(a1)
@nameOK move.l a1,ioNamePtr(a0)
move.w lVolRefNum(a6),ioVRefNum(a0)
move.l lCurDir(a6),ioDirID(a0)
tst.b lAtDesktop(a6) ; if we are not at desktop then vol/dir is OK
ble.s @dirOK
move.w lDisplyedVolRef(a6),d0 ; d0 (in) vrefnum of disk
move.w d0,lIOCmd+ioVRefNum(a6) ; better vRefNum
bsr GetVolumeInfoPtr ; a0 (out) pointer to info
move.l PerVolumeInfo.desktopDir(a0),lIOCmd+ioDirID(a6) ; better dirID
lea lIOCmd(a6),a0 ; restore trashed a0
@dirOK _DirCreate
move.w d0,lNewFolderErr(a6)
bne.s @dismisser
; set script byte in finder info
moveq #-1,d0
move.w d0,ioFDirIndex(a0) ; get info by dirID
_GetCatInfo
bmi.s @goto ; skip script set if error
move.w lItem(a6),d0
bmi.s @goto ; skip script set if smSystemScript <36>
bset #7,d0 ; high bit means use script
move.b d0,ioFlxFndrInfo+sfFndrScript(a0) ; set the folder's script byte
_SetCatInfo
; now go into new folder and rebuild list
@goto move.l ioDirID(a0),lCurDir(a6)
move.w ioVRefNum(a0),d0 ; need Drive number, but <56, #BS-036>
bsr VRefNumToDriveNo ; have a vRefNum ,so convert <56, #BS-036>
move.w d1,lDriveNo(A6) ; <56, #BS-036>
@dismisser st lSubDlgDone(a6)
@exit rts
DebuggerSymbol NewFolderDialogHook
;-------------------------------------------------------------
;
; User typed command-up-arrow, back up in the directory
;
caseOpenParent
tst.b lAtDesktop(a6) ; at desktop already?
bgt.s @exit ; br if so, exit early
lea lIOCmd(a6),a0 ; get our param block
move #-1,ioFDirIndex(a0) ; lookup by dirID mode
move.l lCurDir(A6),ioDirID(a0) ; lookup current folder
clr.l ioFileName(a0) ; no names
_GetCatInfo
bmi.s @exit
move.l ioDrDirID(a0),-(sp) ; remember dir where we were (so we can select it)
move.w ioVRefNum(a0),-(sp) ; remember vol where we were
move.l ioDrParID(a0), d1 ; get the parent directory
move.l d1,lCurDir(a6) ; make parent the current dir
moveq #fsRtParID, d0 ; = 1
cmp.l d0, d1 ; at root of root?
bne.s @select ; br if not, leave dir alone
bsr GotoDesktop ; change to special desktop
@select st lDontDrawList(a6) ; turn off drawing to reduce flick, cause about to change selection
bsr NewDir ; rebuild list at new location
move.w (sp)+,d4 ; retrieve previous volume
move.l (sp)+,d2 ; retrieve previous dir
; now find the folder we were in in this list and select it
moveq #-1,d3 ; start at start
@nextcell
addq.l #1,d3
move.l d3,d0
swap D0 ; need D0 high word be index, low word be zero
bsr GetCellPtr ; D0=cell in ==> A0=dataPtr out
bpl.s @next ; minus -> out of cells
sf lDontDrawList(a6) ; turn drawing back on
bsr DrawFileList ; could not find parent, won't call SelectAndReveal so need to draw
bra.s @exit
@next moveq #fsRtDirID,d0 ; = 2
cmp.l d0,d2 ; were we at root before?
bne.s @notRoot
moveq #fsRtParID,d0 ; = 1
cmp.l FileEntry.feParID(a0),d0 ; then we need to find a volume to select
beq.s @dirOK ; (feTypeOrDirID contains desktop folder ID)
bra.s @nextcell
@notRoot cmp.l FileEntry.feTypeOrDirID(a0),d2 ; is this the right folder?
bne.s @nextcell
@dirOK cmp.w FileEntry.feVRefNum(a0),d4 ; is this the right drive?
bne.s @nextcell
st d2 ; try to center parent in file list
bsr SelectAndReveal ; now select that folder, will turn drawing back on
@exit rts
DebuggerSymbol caseOpenParent
;----------------------------------------------------------------
;
; When the user hits the eject button, we eject the disk, erase
; any current file list, and then fall into the code to skip to
; the next disk.
;
caseEject
bsr SmartEjectDisk ; eject either the selected disk, or the current disk
bne SystemErrAlert ; any problem doing so?
Eject2 tst.b lAtDesktop(a6) ; are we are desktop?
ble.s @nextDisk ; if not goto next disk (cause this one is history)
bra caseGotoDesktop2
@nextDisk bsr NextDisk ; go figure out next disk, sets lDriveNo(a6)
bsr.s GotoVolumesPreferedFolder ; find the folder to goto for the new volume
@done rts
DebuggerSymbol caseEject
;-------------------------------------------------------------------
; changes to prefered folder for lDriveNo(A6)
;
GotoVolumesPreferedFolder
move.w lDriveNo(A6),d0 ; get the new drive number
bsr GetVinfo
; if we have a preferred folder then goto it
move.w ioVRefNum(a0),d0
move.w d0,d1 ; save vRefnum, cause GetVolumeInfoPtr trashes a0 & d0
bsr GetVolumeInfoPtr
move.l PerVolumeInfo.lastDir(a0),d0
beq.s @doit ; if no preference, defaults to root
move.l d0,lCurDir(a6)
@doit move.w d1,d0
bsr SetVolumeIcon
bsr SuckDisk ; and rebuild the file list
rts
DebuggerSymbol GotoVolumesPreferedFolder
;-------------------------------------------------------------------
; saves prefered folder associated with lVolRefNum(a6)
;
SaveVolumesPreferedFolder
tst.b lAtDesktop(a6) ; if we are at desktop
bgt.s @done ; don't save current location
; save off folder at in current volume
move.w lVolRefNum(a6),d0
bsr GetVolumeInfoPtr ; return info for the volume by a0
move.l lCurDir(a6),PerVolumeInfo.lastDir(a0)
@done rts
DebuggerSymbol SaveVolumesPreferedFolder
;-------------------------------------------------------------------
;
; caseNextDrive - When the user hits the right arrow, this hops to the next disk.
;
caseNextDrive
bsr CountDIPs
cmp.w #1,d3 ; want to do nothing if only one disk
beq.s @done
bsr.s SaveVolumesPreferedFolder ; save off folder at in current volume
bsr NextDisk ; go figure out next disk, sets lDriveNo(a6)
bsr GotoVolumesPreferedFolder ; find the folder to goto for the new volume
@done rts
DebuggerSymbol caseNextDrive
;-------------------------------------------------------------------
;
; casePrevDrive - When the user hits the left arrow, this hops to the previous disk.
;
casePrevDrive
bsr CountDIPs
cmp.w #1,d3 ; want to do nothing if only one disk
beq.s @done
bsr.s SaveVolumesPreferedFolder ; save off folder at in current volume
bsr PrevDisk ; go figure out prev disk, sets lDriveNo(a6)
bsr GotoVolumesPreferedFolder ; find the folder to goto for the new volume
@done rts
DebuggerSymbol casePrevDrive
;----------------------------------------------------------------
;
; The application, on its dlg hook, can request a "rebuilding" of
; the file list based on new selection criteria. This is handled here.
;
caseRebuildFileList
bsr DumpList ; get rid of old list
move.w lVolRefNum(A6), d0 ; <21dec87> get volume being displayed
neg.w d0 ; <21dec87> turn into a drive number
cmp.w sfSaveDisk, d0 ; <21dec87> has app requested a change?
bne.s @changeDir ; <21dec87> br if so, switch to that volume
move.l lCurDir(A6), d0 ; <21dec87> get dir being displayed
cmp.l CurDirStore, d0 ; <21dec87> has app requested a change?
bne.s @changeDir ; <21dec87> br if so, switch to that dir
bsr ReListDisk ; set up new list
rts ; get on with the show
@changeDir move.w sfSaveDisk,lSaveDisk(A6) ; <21dec87> pass default volume to FindDisk
bsr FindDisk ; <21dec87> go figure out saveDisk and CurDir
bsr SuckDisk
rts
DebuggerSymbol caseRebuildFileList
;----------------------------------------------------------------
;
; The application, on its dlg hook, can request a change of selected item.
; This can also cause the file list to be rebuilt if the volume or folder changed
;
; in: d0 ==0 ->smart rebuild, only rebuild list if it will be different
; <>0 ->force rebuild, even if folder is same
;
caseChangeSelection
tst.b lNewReply(a6) ; this only works with the new reply record
beq.s @exit
move.w d0,d1 ; remember if d0 was non-zero
move.w StandardFileReply.sfFile+FSSpec.vRefNum(a4),d0
move.l StandardFileReply.sfFile+FSSpec.parID(a4),d7
tst.w d1
bne.s @redoList ; if d0 was non-zero then force rebuild
cmp.w lVolRefNum(A6),d0
bne.s @redoList
cmp.l lCurDir(A6),d7
beq.s @changeSelection
@redoList bsr GoFindDisk ; d7=dirID, d0=vRefNum
bsr SuckDisk
@changeSelection
lea StandardFileReply.sfFile+FSSpec.name(A4), A0 ; get address of default name
move.b (a0),d0 ; was a name supplied?
beq.s @exit ; br if not, skip default select
cmp.b #31,d0 ; sanity check the name
bgt.s @exit
move.w StandardFileReply.sfScript(A4),D0 ; get script
bsr RevealByName
@exit rts
DebuggerSymbol caseChangeSelection
;---------------------------------------------------------------
; User moused down in the pop up menu rect.
casePopUpPathMenu
; tst.b lAtDesktop(a6) ; don't do pup up when already at top
; bgt.s @done
subq #2,sp ; :INTEGER
move.l lPopUpControl(a6),-(sp) ; theControl: ControlHandle
move.l lMouseWhere(a6),-(sp) ; startPt: Point, use position saved in TheDialogFilter <60>
;<60> subq #4,sp
;<60> move.l sp,-(sp)
;<60> _GetMouse ; startPt: Point
moveq #-1,d0
move.l d0,-(sp) ; actionProc: ProcPtr
_TrackControl
tst.w (sp)+
beq.s @done
bsr PopUpNewItem
@done rts
DebuggerSymbol casePopUpPathMenu
;--------------------------------------------------
; user wants to open a folder
;
caseOpenSelectedFolder
pea lTypeSelect(a6)
_TypeSelectClear ; clear type select buffer
bsr GetSel ; get selection in A0
bmi.s @done ; can do anything without selection
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; a directory?
beq.s @done ; br if not, do nothing
; don't allow opendir if missing access privileges <jrm 04Sep86>
move.b FileEntry.feFLPriv(a0),d0 ; get access privileges <jrm 04Sep86>
tst.b lDoingGetFile(a6) ; <jrm 04Sep86>
bne.s @getFile ; branch if getfile <jrm 04Sep86>
btst #bNoSearch, d0 ; do open if has search
beq.s @doOpen ; br if has search
and.b #mNoRead+mNoWrite,d0 ; also open if R and W <jrm 04Sep86>
beq.s @doOpen ; br if R and W <jrm 04Sep86>
@openErr move #sfErrNoPrivileges,D1 ; not enough access privileges <jrm 04Sep86>
bsr ErrorAlert ; explain to user <jrm 04Sep86>
bra.s @done
@getFile
and.b #mNoSearch+mNoRead,d0 ; getfile folder needs R or S <jrm 04Sep86>
cmp.b #mNoSearch+mNoRead,d0 ; missing both? <jrm 04Sep86>
beq.s @openErr ; no, branch to normal open dir <jrm 04Sep86>
@doOpen move.l FileEntry.feTypeOrDirID(a0),d1 ; get dirID to go into
moveq #fsRtParID,d0
cmp.l FileEntry.feParID(a0),d0 ; check if this is really a volume's desktop folder
bne.s @storeDir
moveq #fsRtDirID,d1 ; if so, switch to open root folder
@storeDir move.l d1,lCurDir(a6)
move.w FileEntry.feDrive(a0),lDriveNo(a6)
bsr NewDirSelectFirstIfGetFile ; enumerate new directory
@done rts
DebuggerSymbol caseOpenSelectedFolder
;-------------------------------------------------------------
; OpenAliasCommon
; in: current selection is alias
;
; out: lAlias(a6) = target FSSpec
; D0 = result OSErr
; d1 = dialog err to use if error
;
OpenAliasCommon
; set up FSSpec of alias file
bsr GetSel ; get selection in A0
move.w FileEntry.feVRefNum(a0),lAlias.vRefNum(A6)
move.l FileEntry.feParID(a0),lAlias.parID(A6)
lea FileEntry.feFile.text(A0), A0
lea lAlias.name(A6), A1
moveq #32, D0
_BlockMove
; call _ResolveAliasFile
subq #2,sp ; room for result
pea lAlias(a6) ; theSpec: FSSpec
st -(sp) ; resolveAliasChains: Boolean
pea lTemp(a6) ; VAR targetIsFolder: Boolean
pea lTemp(a6) ; VAR wasAliased: Boolean
_ResolveAliasFile
move.w (sp)+,d0
move.w #sfErrBadAlias,D1 ; assume it was a bad alias
tst.w D0 ; did resolve alias fail?
bne.s @done ; if so, just return that error
movem.l d2-d3,-(sp) ; be safe and save registers
move.w lAlias.vRefNum(A6),d2
move.l lAlias.parID(A6),d3
bsr TrashCheck ; returns with Z flag set, if in trash (saves all registers)
movem.l (sp)+,d2-d3 ; restore d2,d3
bne.s @done ; if not in trash, return noErr
moveq #-1,d0 ; return an error code to force alert
move.w #sfErrTrashAlias,D1 ; else suggest alias in trash alert
@done rts
DebuggerSymbol OpenAliasCommon
;-------------------------------------------------------
;
; user wants to warp via folder/volume alias to new location
;
caseOpenAlias
pea lTypeSelect(a6)
_TypeSelectClear ; clear type select buffer
bsr.s OpenAliasCommon
cmp.w #userCanceledErr,d0 ; if user cancel mount then just go on
beq @done
cmp.w #resNotFound,d0 ; resNotFound => file was really not a alias file
beq caseOpen ; so goto to normal open case
tst.w d0
bne ErrorAlert ; any other error, tell user
lea lIOCmd(a6),a0 ; get our param block
clr.w ioFDirIndex(a0) ; lookup by name mode
move.l lAlias.parID(A6),ioDirID(a0); lookup new folder
move.w lAlias.vRefNum(A6),ioVRefnum(a0); alias vrefnum
lea lAlias.name(A6),a1 ; get alias name
move.l a1,ioFileName(a0) ; use alias name
move.w #sfErrBadAlias,D1 ; assume it is a bad alias
_GetCatInfo ; get dirID of aliased directory
bne ErrorAlert ; br on error, tell user
btst #ioDirFlg,ioFlAttrib(a0) ; alias to folder or file?
bne.s @doFolder
; this is an alias to a file,
; so we need to fill out the reply record and return
@doFile move.w lAlias.vRefNum(A6), d6 ; set these and then rejoin code
move.l lAlias.parID(A6), d7 ; that handle's WDrefNums and such nonsense
bsr GetReplysFilenametoA0 ; get ptr into reply record
move.l a0, a1 ; and copy into result name
lea lAlias.name(A6), A0 ; copy from alias name
MOVEQ #32, D0 ; size is fileName max
_BlockMove ; fill out filename field of reply record
; fill out file type
lea lIOCmd(a6),a0
move.l ioFlUsrWds+fdType(A0),d0 ; get file type (this is usually the same as alias type)
cmp.l #kApplicationAliasType,d0 ; except for aliases to applications
bne.s @setType
move.l #'APPL',d0 ; if the type was 'adrp' then change it to 'APPL'
@setType move.l d0,StandardFileReply.sfType(A4) ; note: this works for both kinds of reply records
tst.b lNewReply(a6)
beq.s @joinRest
; fill out more stuff in new reply record
move.w ioFlUsrWds+fdFlags(a0),StandardFileReply.sfFlags(A4) ; stuff in finder flags
bsr GetFilenameFont ; returns script code in d0
move.w d0,StandardFileReply.sfScript(A4) ; stuff in script code
clr.b StandardFileReply.sfIsFolder(A4) ; stuff in is not a folder
clr.b StandardFileReply.sfIsVolume(A4) ; stuff in is not a volume
@joinRest ; now we jump back into code the concludes sf. It expects:
; d5 = flags
; d6 = vRefNum
; d7 = dirID
move.w ioFlUsrWds+fdFlags(a0),d5
swap d5 ; put finder flags in high word
move.b ioFlAttrib(a0),d5 ; and file attributes in low word
bra StatAndLockCheck
@doFolder LEA lIOCmd(a6),a0 ; get our param block
MOVE.L ioDirID(A0), D7 ; pass new directory
MOVE.W ioVRefnum(A0), D0 ; get vrefnum
bsr SetVolumeIcon ; update volume icon/name <55.4, #82679>
move.w lIOCmd+ioVRefNum(A6),d0 ; get vRefNum of new disk <57>
bsr GoFindDisk ; requires volume to find in d0.w
bsr SuckDisk
@done rts
DebuggerSymbol caseOpenAlias
;-------------------------------------------------------------
;
; user hit command-shift-uparrow or desktop button
;
caseGotoDesktop
bsr SaveVolumesPreferedFolder ; remember this location
caseGotoDesktop2
bsr GotoDesktop ; set up to goto boot volume's desktop folder
bsr NewDir ; build and display desktop list
SelectBootVolume
; make sure volume icon shows boot disk
move.w lBootVol(a6),d0
bsr SetVolumeIcon
; find boot volume in list (volumes are always first, so find first matching vRefNum)
moveq #-1,d3 ; start at start
@nextcell addq.l #1,d3
move.l d3,d0
swap d0 ; need D0 high word be index, low word be zero
bsr GetCellPtr ; D0=cell in ==> A0=dataPtr out
bmi.s @done ; minus -> out of cells, should never happen
move.w lBootVol(a6),d0 ; usually -1
cmp.w FileEntry.feVRefNum(a0),d0 ; is this the boot volume?
bne.s @nextcell ; if not try next
moveq #0,d0 ; if we want to select item $1234 in list (zero base)
move.w d3,d0 ;
swap d0 ; then save off $12340000 (row 1234, column 0 )
move.l d0,lLastSel(a6) ; save off default item to select
tst.b lListIsActive(a6)
beq.s @done ; if file list inactive, don't select
st d2 ; try to center selection in file list
bsr SelectAndReveal ; now select that volume
@done rts
DebuggerSymbol caseGotoDesktop
;-------------------------------------------------------------
;
; user did Command-Open of an alias
;
caseGotoAliasTarget
bsr OpenAliasCommon
cmp.w #userCanceledErr,d0 ; if user cancel mount then just go on
beq.s @done
tst.w d0
bne ErrorAlert ; br if so, tell user
st lDontDrawList(a6) ; turn off drawing until we find target
move.l lAlias.parID(A6),D7 ; lookup parent of file
moveq #1,d0
cmp.l d0,d7 ; if parentID = 1 then need to goto desktop
bne.s @notVolume
bsr GotoDesktop
bsr NewDir
bra.s @selectIt
@notVolume move.w lAlias.vRefNum(A6), D0 ; file's vrefnum
bsr GoFindDisk ; lookup up the disk
bsr NewDir ; and switch filelist to it
bne SystemErrAlert
@selectIt lea lAlias.name(A6), a0 ; get alias name
move.w lSystemScript(a6),d0 ; get alias script ### really should get script of file
bsr RevealByName ; and select it in list, will turn drawing back on
move.w lAlias.vRefNum(A6), D0 ; get vrefnum <55.4, #82679>
bsr SetVolumeIcon ; update volume icon/name <55.4, #82679>
@done rts
DebuggerSymbol caseGotoAliasTarget
;----------------------------------------------------------------
;
; new dummy hits that force new active item.
;
caseSetActiveItem
bsr SetActiveNow
rts
DebuggerSymbol caseSetActiveItem
;----------------------------------------------------------------
;
; When the user types a character, we must scroll the list display
; to that position. Call ArrowKey to handle arrow keys.
; --> D0 character typed
;
caseKeyDown
move.w D0,D6 ; save the char <9Dec85>
bsr ArrowKey ; handle arrow key <9Dec85>
bne.s @done ; => handled arrow key <9Dec85>
; build an event record
lea lEvent(a6),a0
move.w #keyDwnEvt,EventRecord.what(a0) ; what = keyDown
move.l lTicks(a6),EventRecord.when(a0) ; when = saved by filter
moveq #0,d0
move.w d0,EventRecord.modifiers(a0) ; modifiers = 0
move.b d6,d0
move.l d0,EventRecord.message(a0) ; message = key pressed (keyCode missing)
; call TypeSelectNewKey
subq #2,sp ; room for boolean result
move.l a0,-(sp) ; event record
pea lTypeSelect(a6) ; tsr
_TypeSelectNewKey
tst.b (sp)+
beq.s @done
bsr SelectTyped
@done rts
DebuggerSymbol caseKeyDown
;-------------------------------------------------------------
;
; GetKeyScript - d0 out: keyboard script
; GetScript - d0 in: GetEnvirons code, out: d0 result
;
GetKeyScript
; If setting of script tags is disabled, always return keybd script = smSystemScript <36>
subq #4,sp ; space for GetEnvirons return
move.w #smGenFlags,-(sp) ; push GetEnvirons verb
_GetEnvirons
move.l (sp)+,d0
btst.l #smfNameTagEnab,d0 ; can we set script tags?
bne.s @getRealKeyScript ; if so, get real keybd script
move.l #smSystemScript,d0
rts
@getRealKeyScript
moveq #smKeyScript,d0
GetScript
subq #4,sp ; space for long
move.w d0,-(sp) ; ask for current keyboard script
_GetEnvirons ; from script manager
move.l (sp)+,d0 ; get long result, script in low word
rts
DebuggerSymbol GetKeyScript
;-------------------------------------------------------------
; CheckDrives
; handle any ejects
;
CheckDrives
move.w sfSaveDisk,d0 ; was a disk ejected?
bpl.s @2 ; yes if negative driveNo in d0
bsr.s cmdEject ; if yes then remove it from list
@2 rts
DebuggerSymbol CheckDrives
;----------------------------------------------------------------
;
; When the user hits cmd-shift 1 or 2, we first turn the drive number
; into a refNum so that EjectDisk can compare it to the Boot volume.
; Next we call EjectDisk to eject the specified disk. This destroys a
; bunch of our state, but not LDriveNo. If we ejected the current drive
; call NextDisk to get the next one; otherwise, call SniffDisk to set up the
; state.
CmdEject
neg.w d0 ; make d0 a real drive number
MOVE.L VCBQHdr+QHead,A1 ; Point to the VCB queue <5Dec85>
@0
CMP.W VCBDrvNum(A1),D0 ; is it the right drive #? <5Dec85>
BEQ.S @1 ; if so, skip out <5Dec85>
MOVE.L QLink(A1),A1 ; Get the link to the next vol <5Dec85>
MOVE.L A1,D1 ; is it NIL? <5Dec85>
BNE.S @0 ; if not, go back. <5Dec85>
BRA.S @2 ; if we fall out, just exit <5Dec85>
@1
move.w VCBVRefNum(A1),lVolRefNum(A6) ; set up volume to eject
bsr EjectDisk ; eject it
tst.b lAtDesktop(a6) ; if at desktop, need to rebuild list <2Feb90>
bgt caseGotoDesktop ; this time, without the ejected volume <2Feb90>
@2
move.w sfSaveDisk,d0 ; get disk we ejected
neg.w d0 ; make it a real drive number
clr.w sfSaveDisk ; flag eject done
cmp.w lDriveNo(A6),d0 ; did we just eject it?
beq Eject2 ; => yes, now find a new disk etc...
bsr SniffDisk ; else reset all our info <5Dec85>
rts
DebuggerSymbol CmdEject
;----------------------------------------------------------------
;
;
; SetActiveNow
;
; d0 = dialog item to make active
; a6 = main stack frame
; a3 = dialog ptr
SetActiveNow
cmp.w lActiveDITLitem(a6),d0 ; is selected already active?
beq.s @done ; if so skip the change
; deactive current
move.l a3,-(sp) ; dialog ptr
move.w lActiveDITLitem(a6),-(sp) ; which item
clr.w -(sp) ; deactivate
move.w d0,lActiveDITLitem(a6) ; remember the new active one
bsr CallActivate
; active the next
move.l a3,-(sp) ; dialog ptr
move.w lActiveDITLitem(a6),-(sp) ; which item
st -(sp) ; activate
bsr CallActivate
@done rts
DebuggerSymbol SetActiveNow
;-----------------------------------------------------------------
;
; Setup the filelist to match the new disk
;
SuckDisk bsr DumpList ; kill the current file list
bsr.s SuckCommon ; rebuild the file list
bne SystemErrAlert ; error? br if so and exit
rts
DebuggerSymbol SuckDisk
;
; just like NewDisk, but in PutFile warns if locked disk
SuckCommon tst.b lDoingGetFile(a6) ; write lock is not a concern
bne.s @okDisk ; for getfile
bsr SniffDisk ; check out disk...
bne.s @exit
tst.b d7 ; see if locked
bpl.s @okDisk
move #sfErrDiskLocked,D1 ; warn user that the disk is locked
bsr ErrorAlert
move.w #sfHookNullEvent,lHit(a6) ; clr button hit, so dialog does not return
@okDisk bsr NewDisk ; set up new disk
@exit rts
DebuggerSymbol SuckCommon
;-------------------------------------------------------------
;
GetReplysFilenametoA0
lea SFReply.fName(a4),a0 ; assume old name
tst.b lNewReply(a6) ; new call ?
beq.s @exit ; br if not, use old name
lea StandardFileReply.sfFile+FSSpec.name(a4),a0 ; use new name
@exit rts
DebuggerSymbol GetReplysFilenametoA0
;----------------------------------------------------------------
;
; GetNextItemHit
;
GetNextItemHit
sf lDontDrawList(a6) ; this should be false, but error handling could have messed up
PEA TheDialogFilter ; filter proc
PEA lHit(A6) ; pass the item var
_ModalDialog ; be modal
cmp.l #sfMainDialogRefCon,wRefCon(a3) ; only pre-process the hits in the main dialog
bne.s @doReturn_1
; Remap the returned item so that the hook gets a different view of reality.
; Double clicks become presses of the Open/Save button, and Open/Save of a
; folder is returned as a separate item.
moveq #sfItemDesktopButton,d0
bsr VirtualToRealItem
cmp.w lHit(A6),d0
bne.s @notDrive
tst.b lVolumeSelect(a6) ; in compatibility mode, we don't map to hookGotoDesktop
bne.s @doReturn_1
move.w #sfHookGotoDesktop,lHit(A6) ; coerce old Drive button into Desktop button
@doReturn_1 bra @doReturn ; and return back our special command
@notDrive moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
cmp.w lHit(A6),d0 ; was hit in the File list?
bne.s @chkOpen ; if so do mousedown in list
moveq #-1,d1 ; erase what was selected last, so it won't flash
move.l d1,lLastSel(a6)
bsr SetActiveNow ; make the list item active now
subq #2, sp ; boolean result for ListClick
clr.l -(sp) ; space for a point
move.l sp,-(sp) ; point at it
_GetMouse ; where art thou fairest mouse?
move lMeta(a6),-(sp) ; event modifiers saved from DlgFltr
move.l lFileListHandle(a6),-(sp)
_LClick
bsr FillReplyRecord ; _LClick could have changed selection, so update reply record <42> ngk 27Sept90
move.b (sp)+,d2 ; get double click result
bsr GetSel ; get selection into A0
bmi.s @nullItem ; => no selection
tst.b d2
bne.s @doubleClk ; => no dublclik, pass file list item through to user
tst.b lAtDesktop(a6) ; if we are at desktop
ble.s @1
move.w FileEntry.feVRefNum(a0),d0 ; then update volume icon
bsr SetVolumeIcon
@1 bra.s @doReturn_1
@doubleClk tst.b FileEntry.feFile.dimmed(a0) ; is it dimmed?
bne.s @nullItem ; can<61>t double click on a dimmed selection
moveq #sfItemOpenButton,d0 ; coerce item into open button
bsr VirtualToRealItem
move.w d0,lHit(A6) ; coerce original item into open button
bra.s @gotOpen ; => coerce to open directory, if necessary <16Dec85>
; if open or save (or double click) on a folder, don't return button item
@chkOpen moveq #sfItemOpenButton,d0 ; coerce item into open button
bsr VirtualToRealItem
cmp.w lHit(a6),d0
bne.s @chkNull
tst.b lDoingGetFile(a6) ; is this getFile,
bne.s @gotOpen ; if so go on with open
tst.b lOpenState(a6) ; does button say save
bne.s @doReturn ; if so, don't change it to hookOpenFolder
@gotOpen bsr GetSel ; get selection into A0
bmi.s @doReturn ; => no selection, exit
btst #isAliasBit,FileEntry.feFndrFlags(a0) ; is it an alias?
beq.s @openNonAlias ; br if so
@openAlias move.w #sfHookOpenAlias, lHit(a6) ; assume opening alias normally
btst #optionKey,lMeta(A6) ; was option key pressed?
beq.s @doReturn ; br if so, return open alias
move.w #sfHookGotoAliasTarget,lHit(A6) ; return open of alias's parent
bra.s @doReturn
@nullItem move.w #sfHookNullEvent,lHit(a6)
bra.s @doReturn
@openNonAlias
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; a directory?
beq.s @doReturn ; br if not, return regular open
move.w #sfHookOpenFolder,lHit(A6) ; coerce item to open directory
bra.s @doReturn
@chkNull tst.b lNewReply(a6) ; some apps (UltraPaint 1.0) eat null events <55.6, #82198>
beq.s @doCheck ; need to check disk inserts for them too. <55.6, #82198>
; on new calls, if disk was inserted then map null event to a change selection
; so don't check for disk insert unless we have a null event we can map
cmp.w #sfHookNullEvent,lHit(a6)
bne.s @doReturn ; during null events
@doCheck bsr.s CheckForDiskInsert ; check for disk inserts
@doReturn
rts
DebuggerSymbol GetNextItemHit
;----------------------------------------------------------------
;
; CheckForDiskInsert
;
; Checks for disk insert event (ModalDialog masks these out)
; If mount failed, tries format dialog
; If mounted OK, then switches display to that disk
;
CheckForDiskInsert
SUBQ #2,SP ; get the disk inserted event
MOVE #$0080,-(SP) ; both inserted and app1evts
PEA lEvent(A6)
_GetNextEvent
move.l a3,-(sp) ; GetNextEvent may change port so reset it
_SetPort
TST.B (SP)+ ; did we get the disk inserted
BEQ.S @done
; See if the mount suceeded
TST.W lEvent.message(A6) ; did it succeed?
BEQ.S @showThisDisk ; br if not, try formatting it
; if not then do DIBadMount
ST lDidPack2(A6) ; record that pack2's been here
BSR SetCursorToArrow ; cursor to arrow
SUBQ #2,SP ; room for result
MOVE.L lWhere(A6),-(SP) ; pass where to put it
MOVE.L lEvent.message(A6),-(SP) ; pass the message
_DIBadMount
TST (SP)+ ; 0 - success set cc's
BNE.S @done
@showThisDisk
; save off folder at in current volume
move.w lVolRefNum(a6),d0
bsr GetVolumeInfoPtr ; return info for the volume by a0
move.l lCurDir(a6),PerVolumeInfo.lastDir(a0)
; get info for new disk
move.w lEvent.message+2(A6),d0
bsr.s GetVinfo
; if we have a preferred folder then goto it
move.w lIOCmd+ioVRefNum(A6),d0 ; get vRefNum of new disk <55.4, #82679>
bsr SetVolumeIcon ; update displayed volume icon and name <55.4, #82679>
move.w lIOCmd+ioVRefNum(A6),d0 ; <55.4, #82679>
bsr GetVolumeInfoPtr
move.l PerVolumeInfo.lastDir(a0),d1
bne.s @gotDir
moveq #fsRtDirID,d1 ; if no preference, defaults to root
@gotDir
tst.b lNewReply(a6)
beq.s @oldWay
; the new way is to map null event into a sfHookChangeSelection to the root of the new disk
; this gives apps a chance to stop the disk change (nice for volume select)
@newWay move.w lIOCmd+ioVRefNum(a6),StandardFileReply.sfFile+FSSpec.vRefNum(a4) ; set vRefnum of reply
move.l d1,StandardFileReply.sfFile+FSSpec.parID(a4) ; set parID of reply
clr.b StandardFileReply.sfFile+FSSpec.name(a4) ; select nothing
move.w #sfHookChangeSelection,lHit(a6)
bra.s @done
@oldWay move.w lEvent.message+2(A6),lDriveNo(A6) ; set up driveNum for SuckDisk
move.l d1,lCurDir(a6) ; set up dir for SuckDisk
bsr SuckDisk ; switch to it
@done rts
DebuggerSymbol CheckForDiskInsert
;---------------------------------------------------------------------
;
; A Common get volume info call.
;
; in d0 = driveNo
;
GetVinfo
lea lIOCmd(A6),A0 ; do some I/O
clr.w ioVolIndex(a0)
move.w d0,ioDrvNum(A0) ; lookup by drive number
clr.l ioVNPtr(A0)
_HGetVInfo ; get info about this drive
rts
DebuggerSymbol GetVinfo
;---------------------------------------------------------------------
;
; The common eject code. First check to see if the disk to be removed
; is Boot disk. If so, we'd better load up the bare necessities...
;
SmartEjectDisk
TST.B lAtDesktop(A6) ; at the desktop?
BLE.S EjectDisk ; br if not, use current disk
bsr GetSel ; get selection in A0
move.w FileEntry.feVRefNum(A0), D7 ; eject selected disk
bra.s EjectCommon
EjectDisk MOVE.W lVolRefNum(A6), D7 ; eject current disk
EjectCommon TST.B lDidEject(A6) ; was eject already called?
BNE.S @doEject ; yes, just eject the disk
CMP.W lBootVol(A6),D7 ; is this the startup disk?
BNE.S @doEject ; br if not, skip preloading
ST lDidEject(A6) ; record eject for freeAlert
ST lDidPack2(A6) ; record that pack2's been here
_DILoad ; Tell the formatter to nest down
@doEject
CLR.B lVolName+StyledString.text(A6) ; no volume name
LEA lIOCmd(A6),A0 ; do some I/O
CLR.L ioVNPtr(A0) ; and set it up
MOVE D7,ioVRefNum(A0) ; eject the only drive
_Eject
RTS ; return with error
; The following is a bunch of incestuous code for munging about in the VCB queue.
;----------------------------------------------
GoFindDisk NEG.W D0 ; make it a drive num
MOVE.W D0,lSaveDisk(A6) ; pass new disk to FindDisk
BSR.S FindD7Disk ; setup lDriveNo amd lCurDir
RTS
DebuggerSymbol GoFindDisk
; FindDisk takes the drive number in lSaveDisk(A6) and dirID in CurDirStore and
; sets up D1 & lDriveNo(A6) to be the drive number and D7 & lCurDir(a6) do
; be the dirID, after some sanity checks.
FindDisk
MOVE.L CurDirStore,D7 ; get the DIR ID
FindD7Disk
MOVE.W lSaveDisk(A6),D2 ; get negated refnum
BMI findError ; skip if uninitialized
NEG.W D2 ; flip it to get volrefnum (HACK)
; see if the specified volume is both in the drive queue and on-line
MOVE.L vcbQHdr+QHead,A1 ; first VCB start over
@fdLoop
CMP.W vcbVRefNum(A1),D2 ; get this refnum
BEQ.S @found ; => found the default refnum <30Jan86>
MOVE.L QLink(A1),A1 ; point to next VCB
MOVE.L A1,D0 ; are we done??
BNE.S @fdLoop ; if not try again
BRA.W findError ; => didn't find the refnum <30Jan86>
@found MOVE.W vcbDRefNum(A1),D1 ; is the volume on line? <30Jan86>
BPL.W findError ; => no, go find one <30Jan86>
lea lIOCmd(a6),a0 ; point at io block
move #-1,ioFDirIndex(a0) ; special getinfo
clr.l ioFileName(a0) ; no names
move d2,ioVRefNum(a0) ; look at given volume
move.l d7,ioDirID(a0) ; at the given folder
_GetCatInfo
beq.s @dirOK ; br if dir ok, exit
moveq #fsRtDirID,d7 ; use root if folder doesn't exist
@dirOK
moveq #0,d3 ; flag that we are going forward in the list
bra.s tryDrive ; => try this drive
; This routine cycles through the VCB queue and finds the "next" disk that isn't
; the current refnum. It makes that local set to the new one.
; Also, this is two routines in one. We use D3 as a flag and do either
; <20>next<78> disk, or <20>previous<75> disk.
PrevDisk
moveq #-1,d3 ; flag that we are going backward
bra.s JoinNextDisk
NextDisk
moveq #0,d3 ; flag that we are going forward
JoinNextDisk
; first skip to the current vRefNum we know of; it might not exist
moveq #fsRtDirID,d7 ; to the root
MOVE.L vcbQHdr+QHead,A1 ; first VCB start over
MOVE.W lVolRefNum(A6),D2 ; get current refnum
BEQ.W findError
@cdLoop CMP.W vcbVRefNum(A1),D2 ; get this refnum
BEQ.S inSearch ; start with next one
MOVE.L QLink(A1),D0
BEQ.S findError
MOVE.L D0,A1 ; point to next VCB
BRA.S @cdLoop ; will this ever end??
; now search for a non zero drive
tryDrive ; <2> FM
MOVE.W vcbDrvNum(A1),D1 ; get drive #
BNE.S @found
MOVE.W vcbDRefNum(A1),D1 ; see if hiding..
BPL.S inSearch
NEG.W D1 ; drive really is there
@found
BSR VolumeIsInvisible ; If the drive is invisible, <2> <7>
TST.W D0 ; don<6F>t show it in the list. <2> <7>
BNE.S inSearch ; <2> <7>
tst.w d3 ; are we looking for the previous?
bz.s foundDrive ; no, go report that we found the next
move.w d1,d3 ; keep track of the last one we found
inSearch
MOVE.L QLink(A1),D0 ; point to next VCB
BNE.S @ndLoop ; if at end, start over
MOVE.L vcbQHdr+QHead,D0 ; first VCB start over
@ndLoop MOVE.L D0,A1 ; get vcb ptr
CMP.W vcbVRefNum(A1),D2 ; see if repeated
BNE.S tryDrive
tst.w d3 ; we looped once all the way around
bgt.s foundPrevious ; if +, we were looking for previous and found something
move.w d2,d1 ; stay with the same disk as before
bra.s foundDrive
foundPrevious
move.w d3,d1 ; the last drive we stashed is it!
bra.s foundDrive
findError MOVE.L lDeskDir(A6),D7 ; default is desktop dir.
MOVE.W lBootDrive(A6),D1 ; on startup volume
foundDrive MOVE.W D1,lDriveNo(A6) ; save for new disk
MOVE.L D7,lCurDir(a6)
RTS
DebuggerSymbol FindDisk
;------------------------------------------------------------------ <2> FM
; <2> FM
; This routine checks if a volume is invisible because <2> FM
; we don't want to show invisible volumes. <2> FM
; (20/20 is a little strange sometimes) <2> FM
; <2> FM
; in: A1.w = VCB ptr <2> FM
; out: d0.w = true - volume is invisible; false - visible <2> FM
; trashes: a0,d0 <2> FM
; <2> FM
; If this disk is invisible then we want to skip it, because <2> FM
; we don't display invisible disks. A disk is invisible if the <2> FM
; invisible bit is set on its root folder. <2> FM
;
; We special case High Sierra and ISO CD Roms to always be visible because they
; accidentally have that bit set. We also special case remote volumes
; because they could be CD roms mounted remotely. At this point it
; seems like we should be special casing 20/20 hidden volumes because
; it would be easier<65> oh well.
VolumeIsInvisible
movem.l a0-a1/d1,-(sp)
; Is this a remote volume? (We always show remote volumes<65>)
move.w vcbDRefNum(a1),d0 ; get driver RefNum
addq #1,d0
neg.w d0 ; massage index
lsl.w #2,d0
move.l uTableBase,a0
move.l (a0,d0.w),a0 ; index into table
move.l (a0),a0 ; dereference handle
btst #6,dCtlFlags+1(a0) ; see if it is in RAM
move.l dCtlDriver(a0),a0 ; get driver start pointer
beq.s @havePtr ; check result of tst.w
move.l (a0),a0 ; RAM drivers need an extra dereference
@havePtr lea drvrName+2(a0),a0 ; skip length byte and initial period
cmp.l #'AFPT',(a0) ; .AFPTranslator means fileserver
beq.s @skipInvisibleCheck ; Don't ever hide remote volumes<65>
; else are we looking at a local cd that we need to special case?
tst.b SFFrame.IAlwaysShowLocalCD(A6) ; do we special case CD's? <2> FM
beq.s @noSpecialCaseCD ; no<6E> go check for invis. <2> FM
cmp.w #$4147,vcbFSID(A1) ; Is this a ISO volume? <2> FM
beq.s @skipInvisibleCheck ; yes<65> skip check <2> FM
cmp.w #$4242,vcbFSID(A1) ; well, is it High Sierra? <2> FM
beq.s @skipInvisibleCheck ; yes<65> skip check <2> FM
@noSpecialCaseCD ; <2> FM
lea lIOCmd(A6),A0 ; do some I/O
move.w vcbVRefNum(A1),d0 ; get volume refnum <09> <2> FM
move.w d0,ioVRefNum(a0) ; <2> FM
move #-1,ioFDirIndex(a0) ; special case entry count <2> FM
move.l #fsRtDirID,ioDirID(a0) ; Get the root info <2> FM
clr.l ioFileName(a0) ; no name of directory. <2> FM
_GetCatInfo ; get the info <2> FM
bne.s @skipInvisibleCheck ; if err then I'm confused<65> <2> FM
btst #isInvisible,ioFlUsrWds+fdFlags(a0) ;is this volume invisible? <3> FM
beq.s @skipInvisibleCheck ; yes so skip <2> FM
moveq #1,d0 ; yes it was invisible! <2> FM
bra.s @exit ; <2> FM
@skipInvisibleCheck ; <2> FM
moveq #0,d0 ; <2> FM
@exit movem.l (sp)+,a0-a1/d1
rts ; <2> FM
;------------------------------------------------------------------
;
; This routine converts a vRefNum to its Drive Number
;
; in: d0.w = vRefNum
; out: d1.w = Drive Number (or 0, if no such vRefNum)
; trashes: a0
;
VRefNumToDriveNo ; <56, #BS-036>
move.l vcbQHdr+QHead,d1 ; first VCB <56, #BS-036>
@vcbLoop beq.s @done ; exit at end of list <56, #BS-036>
move.l d1,a0 ; <56, #BS-036>
cmp.w vcbVRefNum(a0),d0 ; found volume? <56, #BS-036>
beq.s @getDrive ; if so, get drive no. <56, #BS-036>
move.l qLink(a0),d1 ; point to next VCB <56, #BS-036>
bra.s @vcbLoop ; <56, #BS-036>
@getDrive move.w vcbDrvNum(a0),d1 ; get drive # <56, #BS-036>
@done rts ; <56, #BS-036>
DebuggerSymbol VRefNumToDriveNo
;------------------------------------------------------------------
;
; This routine counts the number of disks in place and returns the number in D3.W
;
CountDIPs
MOVEQ #0,D3 ; zero drive counter
MOVE.L vcbQHdr+QHead,D0 ; first VCB
@vcbLoop
BEQ.S @done ; exit at finish
MOVE.L D0,A1
MOVE vcbDrvNum(A1),D0 ; get drive #
BNE.S @1 ; if <> then count it
MOVE vcbDRefNum(A1),D1 ; see if hiding..
BPL.S @0 ; not hiding, ignore it
@1
ADDQ #1,D3 ; increment # drives w/DIP
@0
MOVE.L QLink(A1),D0 ; point to next VCB
BRA.S @vcbLoop
@done RTS
DebuggerSymbol CountDIPs
;------------------------------------------------------------------
;
; This routine cycles through the VCB queue and unmounts any disks
; who are clean and offline
;
CleanVols LEA lIOCmd(A6),A0 ; get iocmd ready
CLR.L ioVNPtr(A0) ; not by name
MOVE.L vcbQHdr+QHead,A1 ; first VCB start over
@0
TST vcbDrvNum(A1) ; is it offline
BNE.S @1 ; if not go to next
TST vcbDRefNum(A1) ; see if hiding..
BMI.S @1 ; it's really online
TST.B qType+1(A1) ; files ever opened?
BMI.S @1
MOVE.W vcbVRefNum(A1),ioVRefNum(A0) ; in case we do something
_UnmountVol
@1
MOVE.L QLink(A1),A1 ; point to next VCB
MOVE.L A1,D0 ; any more?
BNE.S @0 ; if at end, start over
RTS
DebuggerSymbol CleanVols
;--------------------------------------------------------------------
;
; This gets called when a new disk is inserted. RelistDisk called when disk
; names should be recalc'ed.
;
NewDisk
tst.w lDriveNo(A6) ; is there a disk???
bne.s NewDirSelectFirst ; => yes
bsr EraseFileList ; else erase file list
bsr InvalVol ; inval names for redraw
bsr InvalPopUp ; inval names for redraw
move.l lFileListHandle(a6),-(sp) ; get the list handle
_LSetHilite ; and unhilite the scroller
moveq #0,d0
rts
DebuggerSymbol NewDisk
NewDirSelectFirstIfListActive
tst.b lListIsActive(a6) ; if list active
bne.s NewDirSelectFirst ; then select first
;bra.s NewDir ; else select nothing
NewDir bsr DumpList ; clear displayed list
bsr.s SniffDisk ; get ready for next dir/disk
beq.s ReListDisk ; no error
rts
DebuggerSymbol NewDir
NewDirSelectFirstIfGetFile
tst.b lDoingGetFile(a6) ; switch directory, but only select first
beq.s NewDir ; if doing getfile
NewDirSelectFirst
bsr.s NewDir
bne.s @1
move.w #chDownArrow,D0 ; get first non-dimmed by simulating a down arrow
bsr ArrowKey
moveq #0,d0 ; clear condition codes
@1 rts
DebuggerSymbol NewDirSelectFirst
; recalculate the position of the dirRect in case we get a mouseDown in the dirRect before
; the update to redraw (and hence recalculate) the new dirRect has come through.
ReListDisk
BSR ReBuildMenu
BSR DrawPopUpMenu ; draw pop up showing new folder we are in
BSR AddFileListItems ; go set up the file list
BSR EraseFileList ; erase current list
BSR DrawFileList ; then draw new
BSR SetCursorToArrow ; arrow again
moveq #0,d0
rts
DebuggerSymbol ReListDisk
;------------------------------------------------------------------
;
; This looks at the disk from lDriveNo(A6) and gets its refnum into
; lVolRefNum(A6) exits with A0 pointing to VolInfo
;
SniffDisk
MOVE lDriveNo(A6), D0 ; is there a disk?
BEQ @exit ; br if not, exit
; Get lots of interesting info about this drive
CLR.B lAtDesktop(A6) ; assume we're not at the desktop
LEA lIOCmd(A6),A0 ; do some I/O
CLR.W ioVolIndex(a0)
MOVE lDriveNo(A6),ioDrvNum(A0) ; lookup by drive number
LEA lVolName+StyledString.text(A6),A1 ; point to volume name
MOVE.L A1,ioVNPtr(A0) ; and set it up
_HGetVInfo ; get info about this drive
BNE @exit
move.w ioVSigWord(a0),lSigWord(a6) ; save sigword
move.w ioVAtrb(a0),d7 ; save the lock state
tst.b d7 ; save lock state in lLocked(a6) <27-Nov-85>
smi lLocked(a6) ; true = locked <27-Nov-85>
move.w ioVRefNum(a0),d0 ; pass vRefNum
bsr getVolIcon ; set up the icon
move.w d0,lVolIcon(a6) ; save icon away for this disk
LEA lIOCmd(A6),A0 ; do some I/O
MOVE.W ioVRefNum(A0),D0 ; get volume refnum
MOVE.W D0,lVolRefNum(A6) ; save default volume refnum
MOVE.W D0,sfSaveDisk ; fix it up
NEG.W sfSaveDisk ; really fix it up
MOVE.W lDriveNo(A6),D1 ; get target drive #
BSR NotEjectable ; not ejectable?
MOVE.B D0,lNoEjects(A6) ; record if it can't be ejected
; get volume paramters
LEA lIOCmd(A6),A0 ; do some I/O
CLR.L ioNamePtr(A0) ; don't care about name
MOVE.W lVolRefNum(A6),ioVRefNum(A0) ; lookup by vRefNum
LEA lVolParms(A6),A1
MOVE.L A1,ioBuffer(A0) ; volParms to be filled
MOVEQ #VolumeParms.size,D0
MOVE.L D0,ioReqCount(A0) ; size of volParms
_GetVolParms ; get parameters about this volume
BNE @exit
; get dirIDs of special folders for this volume
MOVE.W lVolRefNum(A6), D0 ; look on current disk
MOVE.L #kWhereToEmptyTrashFolderType,D1 ; get special trash folder
BSR FindFolder
MOVE.L D0,lTrashDir(A6) ; save away trash dirID
MOVE.W lVolRefNum(A6), D0 ; look on current disk
MOVE.L #kDesktopFolderType,D1 ; get special desktop folder
BSR FindFolder
MOVE.L D0,lDeskDir(A6) ; save away current desktop dirID
; Check to see if the new dir requested is actually trash or desktop folder
LEA lDirName.text(A6), A1 ; get handy directory name
MOVE.L lCurDir(A6),D0 ; get new directory
CMP.L lTrashDir(A6),D0 ; dirID same as trash?
BNE.S @checkDesk ; br if not
@gotoRoot moveq #fsRtDirID,d0
move.l d0,lCurDir(a6)
move.l d0,CurDirStore
bra SniffDisk ; try again, "from the top"
@checkDesk CMP.L lDeskDir(A6), D0 ; dirID same as desktop?
BNE.S @checkDir ; br if not
MOVE.B #1,lAtDesktop(A6) ; mark that we're at desktop
MOVEQ #sfDesktopName,D1 ; name of desktop
BSR GetLocalString ; set current dirName to desktop
MOVE.W lSystemFont(A6),lDirName.font(A6) ; desktop/trash are always in system font
MOVE.L lCurDir(A6), CurDirStore ; store dirID away in lomem
ST lNoEjects(A6) ; can't eject desktop
CLR lVnFiles(A6) ; don't know how many files there are
CLR lPriv(A6) ; all privileges
;<55.5><55.7, #82680> don't update volume icon here because, this is called by Initialize before
;<55.5><55.7, #82680> dialog (port) is created and desktop dirIDs are computed.
;<55.5><55.7, #82680> move.w lVolRefNum(A6),d0 ; set up volume icon to current disk
;<55.5><55.7, #82680> bsr SetVolumeIcon ;
bra.s @okExit
; Get info about a particular folder on this disk (and fall back to root on error)
@checkDir move.l lCurDir(a6), d1 ; get directory
@checkD1Dir lea lIOCmd(A6),A0 ; do some I/O
move #-1,ioFDirIndex(a0) ; special case entry count
move.l d1,ioDirID(a0)
lea lDirName.text(A6),a1
move.l a1,ioFileName(a0) ; get name of directory.
_GetCatInfo
beq.s @cont
@tryRoot moveq #fsRtDirID,d1
cmp.l lCurDir(a6), d1 ; at the root?
beq.s @exit
bra.s @checkD1Dir ; br if not, try root
@cont move ioDrNmFls(a0),lVnFiles(a6) ; save # files
clr.b lPriv(a6) ; assume all privleges
move.l lVolParms.vMAttrib(a6),D0 ; get volumes parms
btst #bAccessCntl,D0 ; does it support access control?
beq.s @havePrivs ; if not, don't get permissions byte
move.b ioACUser(a0),lPriv(a6) ; stuff in the permissions
@havePrivs tst.b lLocked(a6) ; is disk also locked?
beq.s @setDir
bset #bNoWrite,lPriv(A6) ; if locked, flip on noWrite perm bit
@setDir move.l d1,CurDirStore
move.l d1,lCurDir(a6)
; see if folder is buried in the trash
@trashCheck
move.l ioDrParID(a0),d1
cmp.l lTrashDir(A6),d1 ; is parent folder the trash folder?
beq @gotoRoot ; if so, goto to root level
move #-1,ioFDirIndex(a0) ; look up by dirID only
move.l d1,ioDrDirID(a0)
clr.l ioFileName(a0)
_GetCatInfo
beq.s @trashCheck
@okExit moveq #0, d0 ; exit with no error
@exit rts
DebuggerSymbol SniffDisk
;----------------------------------------------
; in: d3.L = dirID
; d2.w = vRefNum
;
; out: Z flag set if in trash
TrashCheck movem.l d0-d3/a0,-(sp)
move.w d2,d0
move.l #kWhereToEmptyTrashFolderType, D1; get special trash folder
bsr.s FindFolder
bne.s @doCheck ; if no trash folder, then can't be in trash
moveq #1,d0
bra.s @done ; return with Z flag clear
@doCheck move.l d0,d1 ; save dirID of trash in d1
lea lIOCmd(A6),a0 ; do some I/O
@checkNext move.l d3,ioDrDirID(a0) ; start at given folder
cmp.l d3,d1 ; is it the trash?
beq.s @done ; if so, we are in the trash
move #-1,ioFDirIndex(a0) ; look up by dirID only
clr.l ioFileName(a0)
_GetCatInfo
move.l ioDrParID(a0),d3 ; move up to parent folder
tst.w d0
beq.s @checkNext
@done movem.l (sp)+,d0-d3/a0
rts
DebuggerSymbol TrashCheck
;--------------------------------------------------------
; FindFolder - find the dirid of a special folder
; d0 (in) vrefnum of disk
; d1 (in) which special folder
; d0 (out) dirid of folder, or 0 if there was an error
FindFolder SUBQ #2, SP ; error result
MOVE D0, -(SP) ; look on this disk
MOVE.L D1, -(SP) ; look for this folder
ST -(SP) ; create folder if it doesn't exist
PEA lKind(A6) ; unused destination vrefnum
CLR.L lItem(A6) ; assume error getting dirID
PEA lItem(A6) ; dirID result
_FindFolder
ADDQ #2, SP ; ignore error
MOVE.L lItem(A6), D0 ; return dirID (0 if an error occurred)
RTS
DebuggerSymbol FindFolder
GotoDesktop MOVE.L #kDesktopFolderType, D1; get special desktop folder
BRA.S GotoCommon
GotoTrash MOVE.L #kWhereToEmptyTrashFolderType, D1; get special trash folder
GotoCommon MOVE lBootVol(A6), D0 ; look on startup disk
BSR.S FindFolder
MOVE.L D0, lCurDir(A6) ; change to this directory
MOVE lBootDrive(A6), lDriveNo(A6) ; change to startup disk
RTS
DebuggerSymbol GotoDesktop
;--------------------------------------------------------------------
;
; d1 (in) drive number
; d0 (out) ST if not ejectable
;
; trash a0
NotEjectable
move.l a0,-(sp)
MOVE.L DrvQHdr+QHead, A0 ; Point to the drive queue
@nextDrive
CMP.W DQDrive(A0), D1 ; is it the right drive #?
BEQ.S @foundDrive ; if so, skip out
MOVE.L QLink(A0), A0 ; Get the link to the next vol
MOVE.L A0, D0 ; is it NIL?
BNE.S @nextDrive ; br if not, try next drive
BRA.S @exit
@foundDrive CMP.B #8,-3(A0) ; ejectable value?? I.M. IV-181
SGE D0 ; ST if not ejectable
@exit move.l (sp)+,a0
RTS
DebuggerSymbol NotEjectable
;--------------------------------------------------------------------
;
SetCursorToArrow
MOVE.L (A5),A0 ; hack entry point for set cursor
PEA arrow(A0)
_SetCursor
RTS
DebuggerSymbol SetCursorToArrow
;--------------------------------------------------------------------
;
; Called TheDialogFilter(dialog,event,VAR item): BOOLEAN
; This is the filter proc for Modal dialog. It first does the normal
; force <CR> <Enter> to adefitem. Then it tries to return a bogus button
; for null events(100). And...for key events, it returns yet another bogus
; button (1000+char) for key scrolling.
; Finally it calls the caller's filter proc before returning.
FilterFrame RECORD {A4Link},DECR
result DS.W 1 ; returned BOOLEAN
paramSize EQU *-8 ; prameters to remove on return
theDialog DS.L 1 ; DialogPtr
theEvent DS.L 1 ; VAR EventRecord
itemHit DS.L 1 ; VAR INTEGER
ReturnAddr DS.L 1
A4Link DS.L 1
; locals go here
localWhere DS Point
whichWindow DS.L 1
mouseState DS.W 1
calledFilter DS.W 1 ; whether apps dialog filter has been called for this event <66, #f1-ngk-002>
ALIGN
frameSize EQU * ; size of link
ENDR
TheDialogFilter
link A4,#FilterFrame.frameSize
movem.l D3/D4/A2/A3/A6,-(SP) ; save work regs
clr.w FilterFrame.result(A4) ; assume failure return
clr.w FilterFrame.calledFilter(A4) ; initialize <66, #f1-ngk-002>
move.l FilterFrame.theEvent(A4),A2 ; A2 = pointer to the event
move.l FilterFrame.theDialog(A4),A3 ; A3 = Dialog pointer
; ### This should do the same thing as the ROM code ClaimEvent.
; For update and Activate events, A3 should come from the event
; record, instead of the parameters.
lea -lTheDialogRec(A3),A6 ; assume main dialog
cmp.l #sfMainDialogRefCon,wRefCon(a3) ; back solve for A6
beq.s @haveA6
lea -lSubDialogRec(A3),A6 ; in sub dialog, so A6 is different
@haveA6
; call apps dialog filter
tst.b lNewReply(a6)
beq.s @callStdFilter ; in BigBang we call app's DlgFilter first, not last
bsr CallUserDlgFilter
bne @done ; if returned true, then no need to do my filter
@callStdFilter
; call standard dialog filter
bsr CallStdDlgFilter
or.b d0,FilterFrame.result(A4) ; return with z-flag set if someone handled event
bne @done ; if returned true, then no need to do my filter
; case off of event.what field
move.w EventRecord.what(A2),d0
beq @ReturnNullEvent ; handle null event for all dialogs
cmp.w #activateEvt,d0
beq @filterActivateEvent ; handle activate event for all dialogs
; don't do anymore filtering on subdialogs
cmp.l #sfMainDialogRefCon,wRefCon(a3)
beq.s @mainCase
cmp.l #sfNewFolderDialogRefCon,wRefCon(a3)
bne.s @NoFiltering_2
; filter key-downs and auto-keys for new folder dialog
@newFolderCase
subq.w #3,d0
beq @filterAutoKey ; key down
subq.w #2,d0
beq @filterAutoKey ; auto-key, both needed to limit TE to 31 chars
subq.w #1,d0
beq @filterUpdateEvent
bra.s @NoFiltering_2
; filter lots of stuff for main dialog
@mainCase subq #1,d0
beq.s @filterMouseDown
subq.w #2,d0
beq @filterKeyDown
subq.w #2,d0
beq @filterAutoKey
subq.w #1,d0
beq @filterUpdateEvent
@NoFiltering_2
bra @NoFilter_1
;
; filtering of mouse down events
;
@filterMouseDown
subq.w #2,sp ; room for integer return value
move.l EventRecord.where(a2),-(sp)
pea FilterFrame.whichWindow(a4) ; space for windowptr
_FindWindow
move.w (sp)+,d0 ; result code
cmp.l FilterFrame.whichWindow(a4),a3 ; in my window?
bne.s @NoFiltering_2
cmp.w #inContent,d0 ; inside ?
bne.s @NoFiltering_2
move.l EventRecord.where(a2),FilterFrame.localWhere(a4)
pea FilterFrame.localWhere(a4)
_GlobalToLocal ; convert to local coordinates
; see if moused in my dummy popUpMenu item
move.l FilterFrame.localWhere(a4),lMouseWhere(a6) ; save off last mouse down position <60>
subq.w #2,sp ; room for Boolean return value
move.l FilterFrame.localWhere(a4),-(sp)
; ### seems like I should be able to use MaxRect and CDEF should do nothing if outside current size
move.l lPopUpControl(a6),a0 ; get popup control
move.l (a0),a0
move.l contrlData(a0),a0 ; get control data handle
move.l (a0),a0
pea CDEFpopUpData.myCtlRect(a0) ; current size rect is 6 bytes into control data
_PtInRect
moveq #sfHookFolderPopUp,d0
tst.b (sp)+ ; in pop up menu ?
bne @ChangeHitTo ; yes => map to hookFolderPopUp pseduo item
; see if it is a hit in an activatable item
@checkActive
subq.w #2,sp ; room for integer return value
move.l FilterFrame.theDialog(a4),-(sp)
move.l FilterFrame.localWhere(a4),-(sp)
_FindDItem
move.w (sp)+,d1
bmi.s @checkVersion ; if returns -1 then no item found
addq #1,d1 ; FindDItem returns item number minus one
move.l lActiveList(a6),a0
move.w (a0),d0 ; list length in D0
cmp.w #1,d0 ; is there only one activatable item?
beq.s @NoFilter_1 ; if so, do nothing
cmp.w lActiveDITLitem(a6),d1 ; is item already active?
beq.s @NoFilter_1 ; if so, do nothing
; need to find if item hit is an activatable item
@findNext2 addq #2,a0 ; walk list
subq.w #1,d0
bmi.s @NoFilter_1 ; item hit not in list
cmp.w (a0),d1
bne.s @findNext2
; activate the moused-on item
move.w d1,d0 ; item to enable in d0
bsr SetActiveNow ; a3 already set up
@NoFilter_1 bra @NoFiltering ; go on as if no filtering happened
@versionData
dc.l $03444549
@checkVersion
tst.b lDoingGetfile(a6)
bne.s @NoFilter_1
tst.l FilterFrame.localWhere(a4)
bne.s @NoFilter_1
btst #cmdKey,EventRecord.modifiers(a2)
beq.s @NoFilter_1
move.l a4,-(sp)
; get current text and selection range
moveq #sfItemFileNameTextEdit,d0
bsr VIrtualToRealItem
move.w d0,d3 ; d3 is now real item number
bsr GetIt
move.l lItem(a6),a4 ; a4 is now item handle
move.l teHandle(a3),a0
move.l (a0),a0
move.l teSelStart(a0),d4
swap d4 ; d4 is now old selection range
move.l a4,-(sp)
pea lString(A6)
_GetIText
; change to new text and no selection range
move.l a4,-(sp)
pea @versionData
_SetIText
move.l a3,-(sp)
move.w d3,-(sp)
clr.l -(sp)
_SelIText
@versionWait
subq #2,sp
_StillDown
tst.b (sp)+
bne.s @versionWait
; restore old string and selection
move.l a4,-(sp)
pea lString(A6)
_SetIText
move.l a3,-(sp)
move.w d3,-(sp)
move.l d4,-(sp)
_SelIText
move.l (sp)+,a4
bra @NoFiltering
;
; filtering of key down events
;
@filterKeyDown
move.w EventRecord.modifiers(A2),d1 ; save the modifiers
moveq #0,D2 ; clear out character
move.b EventRecord.message+3(A2),D2 ; get character into D2
; check for default item keyboard equivalent
; cmp.b #chEnter,D2 ; is it Enter key?
; beq @DefaultItem
; cmp.b #chCR,D2 ; is it Return key?
; beq @DefaultItem
; check for command keys
btst #cmdKey, d1 ; is command key down
beq @notCmdKey ; br if not
; now check for Cmd-O
moveq #sfItemOpenButton,d0
bsr VirtualToRealItem
cmp.b lCmdKeyOpen(a6),d2 ; was it an Oh
beq @ReturnButton ; yes, lets go<67>
cmp.b lCmdKeyOptOpen(a6),d2 ; was it an option-Oh
beq @ReturnButton ; yes, lets go<67>
; now check for Cmd-D
tst.b lVolumeSelect(a6) ; don't do cmd-D when in volumeselect mode (button is drive)
bne.s @checkArrows
moveq #sfItemDesktopButton,d0
bsr VirtualToRealItem
cmp.b lCmdKeyDesktop(a6),d2 ; was it an Dee
beq @ReturnButton ; yes, lets go<67>
; check for Cmd-N, only in putFile
tst.b lDoingGetFile(a6)
bne.s @checkArrows
moveq #sfItemNewFolderUser,d0
tst.b lNewDialog(a6) ; <61 #85049>
beq.s @checkArrows ; <61 #85049>
;<61 #85049>bsr VirtualToRealItem
cmp.b lCmdKeyNewFldr(a6),d2 ; was it an ehNa
beq @ReturnButton ; yes, lets go<67>
; now check for command arrow keys
@checkArrows
cmp.b #chDownArrow,d2 ; was it down arrow?
bne.s @chkRightArrow ; no, try next
bsr GetSel ; get selection in A0
bmi.s @NoFIltering_ ; can do anything without selection
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; a folder or alias to a folder?
beq.s @NoFIltering_ ; if not, do nothing
move.w #sfHookOpenFolder,d0
btst #isAliasBit,FileEntry.feFndrFlags(a0) ; is it a real folder (not an alias)?
beq.s @ActivateList ; if so, change it to sfHookOpenFolder
move.w #sfHookGotoAliasTarget,d0
btst #optionKey,EventRecord.modifiers(a2); is option key down?
bne.s @ActivateList ; if so, change to sfHookGotoAliasTarget
move.w #sfHookOpenAlias,d0 ; else change to sfHookOpenAlias
bra.s @ActivateList
@chkRightArrow
move.w #sfHookGotoNextDrive,d0
cmp.b #chRightArrow,d2 ; was it right arrow?
beq.s @ActivateList ; yes, lets go<67>
move.w #sfHookGotoPrevDrive,d0
cmp.b #chLeftArrow,d2 ; was it left arrow?
beq.s @ActivateList ; yes, lets go<67>
cmp.b #chUpArrow,d2 ; was it up arrow?
bne.s @notCmdKey ; no, try other keys
move.w #sfHookGotoParent,d0 ; assume shift not down
btst #shiftKey, d1 ; is shift key down
beq.s @ActivateList ; no, lets go<67>
move.w #sfItemDesktopButton,d0
bsr VirtualToRealItem ; command-shift-upArrow means goto desktop
bsr CanDo ; is the desktop control active
bmi @ReturnNullEvent ; exit if it is dimmed
bsr FlashItem ; flash item to give feedback
; a command arrow key was used. make sure file list is now target
@ActivateList
move.w d0,-(sp) ; save off
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
cmp.w lActiveDITLitem(a6),d0 ; is list already active ?
beq.s @listNowActive
bsr SetActiveNow
@listNowActive
move.w (sp)+,d0 ; restore
bra @ChangeHitTo
@NoFiltering_
bra @NoFiltering
@notCmdKey
; Tab -> need to switch to next possible active item
cmp.b #chTab,D2 ; is it a TAB?
bne.s @notTab
move.w lActiveDITLitem(a6),d1
move.l lActiveList(a6),a0
cmp.w #1,(a0) ; is there only one activatable item?
beq.s @hideEvent ; so do nothing
; need to find next activatable item
move.w (a0),d0 ; list length in D0
move.w lActiveDITLitem(a6),d1 ; current item in D1
@findnext addq #2,a0 ; walk list
subq.w #1,d0
bmi.s @wrap ; if can't find current, then just use first
cmp.w (a0),d1
bne.s @findnext
tst.w d0 ; is this last item
bne.s @haveNext
@wrap move.l lActiveList(a6),a0 ; if so wrap around
@haveNext move.w 2(a0),d0 ; get next item into d0
; activate next item
bsr SetActiveNow ; d0 and a3 already set up
@hideEvent clr.w EventRecord.what(A2) ; make sure apps filter does not see tab key
bra @ReturnNullEvent ; map TAB to a null event
@notTab ; fall into same code as @filterAutoKey
;
; filtering of auto repeat key down events and common keys for new folder sub dialog
;
@filterAutoKey
; for compatibility, old calls to sf get a chance to see keydown event
; new calls, already got a chance at beginning of TheDialogFilter
tst.b lNewReply(a6)
bne.s @doneUserKey ; for compatibility, old apps need filter to get key events
bsr CallUserDlgFilter
bne @done ; if returned true, then app handle event
; jump to done and avoid repeat call to CallUserDlgFilter
move.w EventRecord.what(A2),d0 ; check if app changed event.what <64, #f1-ngk-001>
cmp.w #keyDwnEvt,d0 ; still key down? <64, #f1-ngk-001>
beq.s @doneUserKey ; <64, #f1-ngk-001>
cmp.w #AutoKeyEvt,d0 ; or autokey? <64, #f1-ngk-001>
bne @done ; if not, app changed, so not key <64, #f1-ngk-001>
@doneUserKey
move.w EventRecord.modifiers(A2),d1 ; save the modifiers
moveq #0,D2 ; clear out character
move.b EventRecord.message+3(A2),D2 ; get character into D2
; check for ESC key, which means hit the Cancel button
; moveq #2,d0 ; cancel is always button 2
; cmp.b #chEscape,d2 ; was it an escape?
; bne.s @1
; cmp.b #kcEscape,EventRecord.message+2(a2) ; need the key code to tell escape from clear
; beq @ReturnButton ; yes, lets go<67>
;@1
; auto-key tab does nothing
cmp.b #chTab,D2 ; is it a TAB?
beq @ReturnNullEvent ; if so, eat the key
btst #cmdKey,d1 ; is command key pressed?
beq.s @TEchk ; if not, then key could be for TE
; now check for Cmd-period, which means hit the Cancel button
; moveq #2,d0 ; cancel is always button 2
; cmp.b lCmdKeyCancel(a6),d2 ; was it a period?
; beq @ReturnButton ; yes, lets go<67>
; check for Cmd-V in putfile for filename, or in newfolder for folder name
@PasteChk tst.b lDoingGetFile(a6)
bne @NoFiltering
cmp.b #'V',d2 ; was it a V? (generated by menu) <56, #BS-040>
beq.s @haveCmdV ; <56, #BS-040>
cmp.b #'v',d2 ; was it a v? (generated by keyboard) ### not localizable
bne @NoFiltering
@haveCmdV cmp.l #sfNewFolderDialogRefCon,wRefCon(a3)
beq.s @doPaste
cmp.l #sfMainDialogRefCon,wRefCon(a3)
bne @NoFiltering
moveq #sfItemFileNameTextEdit,d0
bsr VirtualToRealItem
subq #1,d0
cmp.w editField(a3),d0 ; is this the fileName TE item?
bne @NoFiltering ; if not, let dialog manager handle it
@doPaste bsr PasteFileName ; if so, do my special paste
bra @ReturnNullEvent
; now check and see if TextEdit deserves the key
; note that the auto-key events rejoin the keyDown events here, since arrow keys repeat
@TEchk tst.b lListIsActive(a6) ; if list active
bne.s @notForTE
; move.l teHandle(a3),a0 ; get TE record for this dialog
; cmp.l #0,a0
; beq.s @notForTE ; no TE, so don't give it to Dialog manager
move.w editField(a3),d3
addq.w #1,d3 ; see if any TE items are active (-1 => no active field)
; beq.s @notForTE ; if not, then don't give it to Dialog manager
; move.l (a0),a0
; tst.b teActive(a0) ; is TE item active?
; beq.s @notForTE ; if not, then don't give it to Dialog manager
cmp.l #sfMainDialogRefCon,wRefCon(a3)
bne.s @isFileName ; if not main, must be new folder subdialog
moveq #sfItemFileNameTextEdit,d0
bsr VirtualToRealItem
cmp.w d3,d0 ; is it filename TE item?
bne.s @NotMyKey ; if not, must be an app te item
@isFileName cmp.b #chCR,D2 ; is it a CR?
beq.s @ReturnNullEvent_1 ; if so, eat CR
cmp.b #chEnter,D2 ; is it an Enter?
beq.s @ReturnNullEvent_1 ; if so, eat Enter
cmp.b #':',D2 ; is it a colon?
beq.s @ReturnNullEvent_1 ; if so, eat colon
move.l teHandle(a3),a0 ; get TE record for this dialog
move.l (a0),a0
move.w teLength(a0),d0
cmp.w #31,d0 ; is filename already full?
blt.s @NoFiltering_3 ; if not, let Dialog manager handle it
cmp.b #chLeftArrow,D2 ; is it a left arrow?
beq.s @NoFiltering_3 ; if so, let Dialog manager handle it
cmp.b #chRightArrow,D2 ; is it a right arrow?
beq.s @NoFiltering_3 ; if so, let Dialog manager handle it
cmp.b #chDelete,D2 ; is it the delete?
beq.s @NoFiltering_3 ; if so, let Dialog manager handle it
move.w teSelEnd(a0),d0
sub.w teSelStart(A0),d0 ; get size of selection
bgt.s @NoFiltering_3 ; if 1 or more chars, allow typing to overwrite
move.w #1,-(sp)
_SysBeep ; eat char, don't let it get put into filename
@ReturnNullEvent_1
bra @ReturnNullEvent
@NotMyKey tst.b lATEIsActive(a6)
beq.s @ReturnNullEvent_1
@NoFiltering_3
bra @NoFiltering
; the key was not for TE, if it is not a cmd-key, then map it to 1000+char only
@notForTE btst #cmdKey,d1 ; is command key pressed?
bne.s @NoFiltering_1 ; if so, then don't map it
move.w D2, D0
add.w #sfHookCharOffset,D0 ; Return as itemHit = $1000+character
bra @ChangeHitTo
;
; filtering of update events
;
@filterUpdateEvent
; is this the main sf dialog?
move.l a3,-(sp) ; save a3
lea lTheDialogRec(a6),a3 ; in here a3=main dialog
cmp.l EventRecord.message(A2),a3 ; is update for main dialog?
bne.s @doneUpdate
; switch to port update event is for
subq #4,sp
pea (sp)
_GetPort ; save port for later restore
move.l a3,-(sp)
_SetPort ; switch to main dialog port to draw stuff
; if update event for me, be paranoid and draw all
; non-userItem things
; force drawing of active item halo
move.b lListIsActive(a6),d0
bsr DrawFileListHalo ; be sure to draw extra box around the active control
; for compatibility, old calls to sf get a chance to see update event
; new calls, already got a change at beginning of TheDialogFilter
tst.b lNewReply(a6)
bne.s @doneUserUpt ; in BigBang we call app's DlgFilter first, not last
bsr CallUserDlgFilter
bne.s @doneDrawing ; if returned true, then app did update
@doneUserUpt
; now do what dialog mgr would do and
move.l a3,-(sp)
_BeginUpdate
move.l a3,-(sp)
_DrawDialog ; draw dialog items
move.l a3,-(sp)
_EndUpdate
; tell dialog mgr to not handle this update event
move.l FilterFrame.itemHit(A4),A0 ; return null pseudo-item
move.w #sfHookNullEvent,(A0)
move.b #1,FilterFrame.result(A4)
@doneDrawing
_SetPort ; restore port
@doneUpdate move.l (sp)+,a3 ; restore a3
bra @checkUpdateFlood
@NoFiltering_1
bra.s @NoFiltering
;
; filtering of activate events
;
@filterActivateEvent
move.l EventRecord.message(A2),a0 ; be sure it is activate for main dialog
cmp.l #sfMainDialogRefCon,wRefCon(a0)
bne.s @NoFiltering_1
move.l a3,-(sp) ; save current a3
subq #4,sp
pea (sp)
_GetPort ; save port on stack
lea lTheDialogRec(a6),a3 ; switch to main dialog
move.l a3,-(sp)
_SetPort ; and port
move.w EventRecord.modifiers(A2),d0
btst #activeFlag,d0 ; is it an activate or deactivate
sne d0 ; make d0 a boolean
move.b d0,-(sp) ; save d0
move.l a3,-(sp)
move.w lActiveDITLitem(a6),-(sp)
move.b d0,-(sp) ; activate or deactivate
bsr CallActivate ; make sure item is properly active
move.b (sp)+,d0 ; restore d0
bne.s @ActivateEvent
@DeactivateEvent
; this is now done by StdFilterProc
; move.l lMainOpen(a6),d0
; beq.s @doCancel ; if no open button, don't try to dim
; move.l d0,a0
; bsr.s @dimIt ; dim open button
;@doCancel move.l lMainCancel(a6),a0
; bsr.s @dimIt ; dim cancel button
move.l lMainEject(a6),a0
bsr.s @dimIt ; dim eject button
move.l lMainDesktop(a6),a0
bsr.s @dimIt ; dim desktop button
move.l lMainNewFolder(a6),d0
beq.s @doneActivate
move.l d0,a0 ; if it exists,
bsr.s @dimIt ; dim newfolder button
bra.s @doneActivate
@dimIt move.l a0,-(sp) ; pass the button
move.w #255,-(sp)
_HiliteControl
rts
@ActivateEvent
; cancel is not set up in main loop because it is always enabled
; this is now done by StdFilterProc
; move.l lMainCancel(a6),-(sp) ; pass the button
; move.w #0,-(sp)
; _HiliteControl
@doneActivate
_SetPort ; restore port
move.l (sp)+,a3 ; restore a3
;bra @ReturnNullEvent ; don't let dialog manager try to activeate TE item
@ReturnNullEvent
moveq #sfHookNullEvent,D0 ; return fake button
bra.s @ChangeHitTo
@DefaultItem
move.w aDefItem(a3),D0 ; default item number from dialog record
@ReturnButton
bsr CanDo ; is the control active??
bmi.s @returnNullEvent ; exit if it is dimmed
bsr FlashItem ; flash item to give feedback
@ChangeHitTo
move.l FilterFrame.itemHit(A4),A0 ; point to item result
move.w D0,(A0)
move.b #1,FilterFrame.result(A4) ; turn false into true
@NoFiltering
move.w EventRecord.modifiers(A2),lMeta(A6) ; save the modifiers
move.l EventRecord.when(A2),lTicks(A6) ; and the ticks
tst.b lNewReply(a6)
bne.s @checkUpdateFlood ; in new calls we call user DlgFilter first, not last
tst.w FilterFrame.calledFilter(A4); already called? (keydown events are handled earlier) <66, #f1-ngk-002>
bne.s @checkUpdateFlood ; if so, don't call again <66, #f1-ngk-002>
bsr.s CallUserDlgFilter
@checkUpdateFlood
; if an update event is pending for a behind window and no one
; handles it then, ModalDialog won't return. So at the last moment
; we check for update events that no one has handled and map them
; to hookNullEvents
tst.b FilterFrame.result(A4) ; has event been handled?
bne.s @done ; if so, we're done
cmp.w #updatEvt,EventRecord.what(a2) ; is it an update event?
bne.s @done ; if not, we're done
cmp.l EventRecord.message(A2),a3 ; is it update for another?
beq.s @done ; if so, map to hookNullEvent
move.w #nullEvt,EventRecord.what(a2) ; but first, give StdFilter proc
bsr.s CallStdDlgFilter ; a chance to do null event processing
bra.s @ReturnNullEvent
@done movem.l (SP)+,D3/D4/A2/A3/A6 ; restore work registers
unlk A4
move.l (SP)+,A0 ; get rts
add.w #FilterFrame.paramSize,SP
jmp (A0)
DebuggerSymbol TheDialogFilter
;-------------------------------
;
; called by TheDialogFilter
;
; a3 = dialog
; a2 = eventrecord
;
CallStdDlgFilter
subq.l #6,sp ; Make a proc ptr var and result
pea 2(sp) ; Push the proc addr
_GetStdFilterProc ; Get the standard filter proc address (macro)
tst.w (sp)+ ; Everything OK
beq.s @gotIt ; branch if have proc
addq #4,sp ; remove space for proc ptr
moveq #0,d0 ; return with z-flag set
bra.s @done
@gotIt move.l (sp)+,a0 ; Get the filter proc address
subq #2,sp ; BOOLEAN
move.l a3,-(sp) ; theDialog: DialogPtr
move.l a2,-(sp) ; VAR theEvent: EventRecord
move.l FilterFrame.itemHit(a4),-(sp) ; VAR itemHit: INTEGER
jsr (a0)
move.b (sp)+,d0
@done rts
DebuggerSymbol CallStdDlgFilter
;-------------------------------
;
; called by TheDialogFilter, assumes A6 and A4 are setup
;
CallUserDlgFilter
st FilterFrame.calledFilter(A4) ; mark that have called filter <66, #f1-ngk-002>
move.l lFilterProc(A6),D0 ; is there a dialog filter
beq.s @noFilter
lea lTheDialogRec(a6),a0
cmp.l a0,a3
beq.s @doFilter ; if this is a sub dialog
tst.b lNewReply(a6) ; and not a new reply then done
beq.s @noFilter
@doFilter MOVE.L D0,A0 ; point to proc
clr.w -(sp) ; make room for returned boolean <55.1, #82022>
MOVE.L A3,-(SP) ; pass dialog
MOVE.L A2,-(SP) ; pass the event
MOVE.L FilterFrame.itemHit(A4),-(SP) ; point to item result
TST.B lUseCallBack(A6) ; does routine want callback?
BEQ.S @noCallBackPtr
MOVE.L lCallBackPtr(A6),-(SP)
@noCallBackPtr
JSR (A0) ; call the hook
MOVE.B (SP)+,D0 ; OR in their result
OR.B D0,FilterFrame.result(A4)
@noFilter
RTS
DebuggerSymbol CallUserDlgFilter
;--------------------------------------------------------------------
;
; Does a paste in which <CR> and ':' are changed to '-'
;
PasteFileName
subq #4,sp
move.l TEScrpHandle,-(sp) ; hDext: Handle
move.l #'TEXT',-(sp) ; theType: ResType
pea lPoint(a6) ; VAR offset {not used}
_GetScrap
move.l (sp)+,d0 ; if < 0 then error
bpl.s @haveText
clr.w TEScrpLength ; so mark nothing is TE scrap
bra.s @done ; and do nothing
@haveText move.w d0,TEScrpLength ; success, update TE scrap length
; now remove <CR> and ':' from TE scrap
; note that this way is OK, because second byte of
; a double byte char is never < $40 (which includes CR and ':')
move.l TEScrpHandle,a0
move.l (a0),a0 ; walk through scrap
@nextChar cmp.b #chCR,(a0) ; if <CR>
beq.s @change
cmp.b #':',(a0) ; or if ':'
bne.s @loop
@change move.b #'-',(a0) ; then change to '-'
@loop addq #1,a0
subq #1,d0 ; until no more scrap
bgt.s @nextChar
; next paste in processed stuff
move.l teHandle(a3),-(sp)
_TEPaste
; lastly, truncate to 31 chars
move.l teHandle(a3),a1
move.l (a1),a1
move.w teLength(a1),d0
cmp.w #31,d0 ; is currently text length <= 31 ?
ble.s @done ; if so then done
move.l teTextH(a1),a0 ; else trucate whole TE to its first 31 chars
moveq #31,d0
move.w d0,teLength(a1)
_SetHandleSize ; a0 = handle, d0 = new size
move.l teHandle(a3),-(sp) ; recalc TE stuff
_TECalText
@done rts
DebuggerSymbol PasteFileName
;-----------------
; In: d0.w
; returns with N flag set it control is dimmed
;
CanDo move.w d0,-(sp) ; save control #
bsr.s GetIt ; item passed in d0
move.l lItem(a6),a0 ; get control handle
move.l (a0),a0 ; control pointer
move.w (sp)+,d0 ; restore control #
tst.b ContrlHilite(a0) ; is control dimmed?
@done rts
DebuggerSymbol CanDo
;--------------------------------------------------------------------
;
; GetIt
; Gets the item given in D0. Puts result in std frame
GetIt MOVE.L A3,-(SP) ; pass the window
MOVE D0,-(SP) ; user field ID
PEA lKind(A6)
PEA lItem(A6)
PEA lBox(A6)
_GetDItem ; get current settings
RTS
DebuggerSymbol GetIt
;--------------------------------------------------------------------
;
; SetIt
; Sets the item given in D0. From results in std frame
SetIt move.l A3,-(SP) ; pass the window
move.w D0,-(SP) ; user field ID
move.w lKind(A6),-(sp)
move.l lItem(A6),-(sp)
PEA lBox(A6)
_SetDItem ; get current settings
RTS
DebuggerSymbol SetIt
;--------------------------------------------------------------------
; flash button, item number in D0
;
FlashItem move.w d0, -(SP) ; save item number
bsr.s GetIt ; get item handle
move.l lItem(A6), -(SP) ; hilite the control
move.w #1, -(SP)
_HiliteControl
move.w #8, A0 ; let the user see the hilite
_Delay
move.l lItem(A6), -(SP) ; restore control to normal
clr.w -(SP)
_HiliteControl
@done move.w (SP)+, D0 ; restore item number
rts
DebuggerSymbol FlashItem
;--------------------------------------------------------------------
;
; draws or undraws the extra border around the file list
; in: a3 -> dialog ptr
; a6 -> main stack frame
; d0 -> draw black if not zero
; penPat is white or black, as needed
;
DrawFileListHalo
move.l lActiveList(a6),a0
cmp.w #1,(a0) ; how many activatable items are there?
ble.s @exit ; if one or less then no border
move.b d0,-(sp)
_PenNormal
tst.b (sp)+ ; was d0 true ?
bne.s @1 ; if so draw dark border
move.w #notPatCopy,-(sp) ; else, switch to draw in white
_PenMode
@1 move.l lNRect.topLeft(a6),lBox.topLeft(a6) ; copy lNRect into temp rect
move.l lNRect.botRight(a6),lBox.botRight(a6)
pea lBox(a6)
move.l #$fffdfffd,-(sp) ; outset box by three
_InsetRect
move.l #$00020002,-(SP)
_PenSize
pea lBox(a6)
_FrameRect ; frame it
_PenNormal ; don't mess up anyone else
@exit rts
DebuggerSymbol DrawFileListHalo
bEditText equ 4
;--------------------------------------------------------------------
;
; PROCEDURE CallActivate(theDialog: DialogPtr; itemNo: INTEGER; activating: BOOLEAN);
;
; if the item is not one of the standard ones, calls user's proc
; to tell it it is activating or deactivating
; in: a3 -> dialog ptr
; a6 -> main stack frame
; 4(sp) -> boolean, activting or not
; 6(sp) -> word, which item
; 8(sp) -> long, dialog ptr (same as a3)
CallActivate
move.w 6(sp),d0 ; see if item is a text edit
bsr GetIt
move.w lKind(A6),d0
btst #bEditText,d0 ; is this a TE item? <40 ngk 16sept90 >
beq @checkFileList ; if so I can de/activate it for app
move.w lBox+left(a6),d0 ; is the TE item hidden (HideDItem) ? <65, #85960>
cmp.w #$2000,D0 ; unsigned compare, < $2000 means not hidden <65, #85960>
bgt @TEdone ; if hidden, don't try to activate (fixes AppleLink 6.0) <65, #85960>
tst.b 4(sp)
sne lATEIsActive(a6) ; remember that a TE item is active (or not)
bne.s @TEActivate
@TEDeActivate
; deactive the TE item
move.l teHandle(a3),-(sp) ; if deactivating then
_TEDeactivate ; deactivate the TE
; mark the dialog as not having active TE field
move.w #-1,editField(a3)
bra @checkFileList ;<SM5> CSS
@TEActivate
; switch to new item's text handle
move.l teHandle(a3),a0
move.l (a0),a1
move.l lItem(a6),teTextH(a1)
; switch TE's rects to new items's rect
lea teDestRect(a1),A0
move.l lBox(A6),(A0)+ ; set dest rect
move.l lBox+4(A6),(A0)+
tst.w TeSysJust
bmi.s @normBox ; don't make box wider in right-left scripts
add.w #100,teDestRect+Rect.right(a1) ; make dest rect wider to allow scrolling
@normBox move.l lBox(A6),(A0)+ ; set view rect
move.l lBox+4(A6),(A0)+
st teClikLoc(A1) ; remove double click possibility
; select all and TEActivate it, unless mouse is down (user is dragging)
clr.l -(sp) ; select from 0
move.w teLength(a1),d0
ext.l d0 ; d0 = length
move.l d0,-(sp)
subq #2,sp
_Button
tst.b (sp)+
beq.s @setIt
clr.l (sp) ; don't select, 'cause it would make a flicker
@setIt move.l teHandle(a3),-(sp) ; this TE
_TESetSelect
move.l teHandle(a3),-(sp)
_TECalText ; recalc stuff
move.l teHandle(a3),-(sp)
_TEActivate ; active the TE item
; mark dialog with which field is active
move.w 6(sp),d0
subq.w #1,d0
move.w d0,editField(a3)
; if this is putfile filename, then set <CR> mode
tst.b lDoingGetFile(a6) ; is it put file?
bne.s @TEdone
moveq #sfItemFileNameTextEdit,d0
bsr VirtualToRealItem
cmp.w 6(sp),d0 ; is it filename TE item?
bne.s @TEdone
move.l teHandle(a3),a0
move.l (a0),a0
moveq #-1,d0
move.w d0,teCROnly(a0) ; set TERec so that no implicit word wrap
@TEdone bra.s @doneMyStuff
@checkFileList
; see if the item being activated/deactivated is a list then do halo
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
cmp.w 6(sp),d0
bne.s @doneMyStuff
move.b 4(sp),d0 ; be paranoid (possible to miss activate events)
cmp.b lListIsActive(a6),d0 ; if I think it is already in this activate state
beq.s @doneMyStuff ; then do nothing
move.b d0,lListIsActive(a6) ; now remember new state
; draw the right halo
bsr DrawFileListHalo ; state to draw in d0
; select-deselect the selected item
tst.b 4(sp)
beq.s @deActList
; we are now activating the list, if there was an item selected, reselect it
move.l lLastSel(a6),d0
bmi.s @doneMyStuff
st -(sp)
bra.s @setSelect
; now know we are deactiving, so see if there is a selected item
@deActList bsr GetSel
move.l d0,lLastSel(a6)
bmi.s @doneMyStuff
; is a selected item, so save it off and deselect it
clr.b -(sp) ; set selected false
@setSelect move.l d0,-(sp) ; push the cell to deselect
move.l lFileListHandle(a6),-(sp)
_LSetSelect ; deselect the chosen cell
@doneMyStuff
; jump to apps proc to tell it what is happening
move.l lActivateProc(a6),A0 ; get ActivateProc Ptr in A0
move.l a0,d0
beq.s @noActvProc ; if NIL then don<6F>t call
move.l (sp),-(sp) ; move return address down to make room
move.l lCallBackPtr(a6),4(SP) ; for the extra parameter
jmp (a0) ; note: does not return here
@noActvProc move.l (SP)+,(SP) ; remove parameters
move.l (SP)+,(SP)
rts
DebuggerSymbol CallActivate
;--------------------------------------------------------------------
;
; This is the start of a hack to support apps (like quickmail enclosures)
; dialog that disable the filename field. If we could notice that, then
; we could change the active field to be the file list
;
;SyncActiveItem
; move.l teHandle(a3),a0 ; get TE record for this dialog
; cmp.l #0,a0
; beq.s @notTE ; no TE, so don't give it to Dialog manager
; move.w editField(a3),d3
; addq.w #1,d3 ; see if any TE items are active (-1 => no active field)
; beq.s @notTE ; if not, then don't give it to Dialog manager
; move.l (a0),a0
; tst.b teActive(a0) ; is TE item active?
; beq.s @notTE ; if not, then don't give it to Dialog manager
;###
;@notTE
;
; rts
; DebuggerSymbol SyncActiveItem
;--------------------------------------------------------------------
;
; Given an item in D3, this assumes its a user item and sets the draw proc to
; our common drawproc
SetUserDraw
MOVE D3,D0 ; user field ID for disk name
BSR GetIt ; get current settings
MOVE.L A3,-(SP) ; pass the window
MOVE D3,-(SP) ; button ID
MOVE lKind(A6),-(SP)
PEA UserDraw ; install the draw proc
PEA lBox(A6)
_SetDItem
RTS
DebuggerSymbol SetUserDraw
;--------------------------------------------------------------------
;
; Given a item # in D0 and a string in A2 this sets its text
SetItsText
BSR GetIt ; get current settings
MOVE.L lItem(A6),-(SP) ; set the prompt
MOVE.L A2,-(SP)
_SetIText
RTS
DebuggerSymbol SetItsText
;--------------------------------------------------------------------
;
; TruncString( VAR theStyle: Style; indent: INTEGER; VAR str: STR255; r: Rect );
; 18 16 12 8
; This truncates the string to fit in the given rectangle, condensing
; the text and appending ellipses if needed.
TruncString
LINK A6,#0 ; set up the std world
MOVEM.L D2-D7/A2-A4,-(SP) ; save those regs
; calculate the width of the rectangle
MOVE.L 8(A6),A0 ; get the rectangle
MOVE.L (A0)+,D0 ; get the topleft
MOVE.L (A0)+,D3 ; get the botright
SUB.W D0,D3 ; find extent
SUB.W 16(A6),D3 ; slop for indent
; calculate the width of the text to avoid unecessary calls to _TruncString
MOVE.L 12(A6),A3 ; get the string pointer
SUBQ #2,SP ; get the width
MOVE.L A3,-(SP)
_StringWidth
CMP.W (SP)+,D3 ; see if it fits first time
BGT.S @exit ; escape if so
; text doesn't fit, so let's try using condensed mode
MOVE.L 18(A6),A0 ; get current style
BSET #condenseBit,1(A0) ; add condensed to current style
MOVE.W (A0),-(SP) ; and set it
_TextFace
; let _TruncString truncate the string if needed
SUBQ #2,SP ; returns whether string truncated
MOVE.W D3,-(SP) ; width
MOVE.L 12(A6),-(SP) ; theString
MOVE.W #smTruncEnd,-(SP) ; truncate at end <5>
_TruncString
ADDQ #2,SP ; ignore result
@exit
MOVEM.L (SP)+,D2-D7/A2-A4 ; restore those regs
UNLK A6
MOVE.L (SP)+,A0 ; get rts
ADD #14,SP
JMP (A0)
DebuggerSymbol TruncString
;--------------------------------------------------------------------
;
; UserDraw handles the draw requests for the user fields in the dialog box
; The global storage pointer is in the refcon of the window
; PROCEDURE UserDraw(wind: WindowPtr; item: Integer);
udregs EQU 44+4 ; 11 regs + RTS
udItem EQU udRegs ; item passed
udWind EQU udItem+2 ; window passed
UserDraw
MOVEM.L D2-D7/A2-A6,-(SP) ; save magic regs(44 bytes)
MOVE.W udItem(SP),D7 ; save the item number
MOVE.L udWind(SP),A3 ; get the window
lea -lTheDialogRec(A3),A6 ; get the stdFile stack
moveq #sfItemVolumeUser,d0
bsr VirtualToRealItem
cmp.w d0,d7 ; is it volume title?
bne.s @notVol
bsr.s DrawVolume
bra.s @exit
@notVol moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
cmp.w d0,d7 ; is it file list?
bne.s @notFileList
bsr DrawFileList
bra.s @exit
@notFileList
cmp.w #getGrayBar,d7 ; is it getGrayBar?
bne.s @exit
bsr.s DrawGrayBar
@exit MOVEM.L (SP)+,D2-D7/A2-A6 ; save magic regs(44 bytes)
MOVE.L (SP)+,A0 ; get rts
ADDQ.L #6,SP
JMP (A0)
DebuggerSymbol UserDraw
;------------------------------------------
; Draw Volume Icon and Name
;
;
DrawVolume
move.l a3,-(sp)
; erase what's currently there
lea lVolRect(a6),a2
move.l a2,-(sp)
_EraseRect
; draw the icon and name for the current volume
lea lVolName(a6),a3
move.w lVolIcon(a6),d7 ; disk icon selector
moveq #0,d3 ; pass in indent
bsr DrawName ; draw volume icon and name in a2 rect
move.l (sp)+,a3
rts
DebuggerSymbol DrawVolume
;------------------------------------------
; Draw gray dividing line in get file
;
;
DrawGrayBar
moveq #getGrayBar,D0 ; user field ID
bsr GetIt ; get current settings
pea lBox(a6)
_PenNormal
_FrameRect ; frame the box
rts
DebuggerSymbol DrawGrayBar
;----------------------------------------------------------
; Draw PopUpMenu with icon, current folder, and drop shadow
;
; assumes a3 = dialogPtr
; a6 = main stack frame
;
DrawPopUpMenu
tst.b lPopUpLooksGood(a6) ; when user goes up in pop up, the CDEF has already drawn it correctly
bne.s @looksGood ; lPopUpLooksGood is used to flag that state.
; with the popup CDEF we need to force the control to redraw
; but then we don't want the later redraw on update, so remove
; the controls bounds from the update rgn
move.l lPopUpControl(a6),-(sp)
_Draw1Control
move.l lPopUpControl(a6),a0
move.l (a0),a0
pea contrlRect(a0)
_ValidRect
@looksGood sf lPopUpLooksGood(a6)
rts
DebuggerSymbol DrawPopUpMenu
;-----------------------------------
; GetInset centers specified string in specified rect.
;
; Entry: A0 = rect
; A1 = string
; D3 = inset from frame
; Exit: D4 = inset from edge of rect
;
; It centers the string in the rect, leaving room for an icon on the left,
getInset move Right(a0),d4 ; New routine as of <17Dec85>
sub Left(a0),d4
sub #iconWidth+iconPad,d4 ; width of icon+white space
sub d3,d4 ; + indent
sub d3,d4 ; twice for centering
subq.l #2,sp
move.l a1,-(sp) ; string pointer
_StringWidth
sub (sp)+,d4
bge.s @1 ; will fit
clr d4 ; won't, don't center
@1 lsr #1,d4 ; div 2
rts
DebuggerSymbol getInset
;-----------------------------------------------------
;
; Draw name centers the name and draws it with the appropriate
; mini icon, passed in d7.
; The indent is in d3
; The centering inset is returned in d4.
; DrawInPlace should be called with d4 set up and the list handle in A0.
DrawName
move.l a2,a0 ; pass bounds rect
lea StyledString.text(a3),a1 ; pass string ptr <17Dec85>
bsr.s getInset ; get inset into D4 <17Dec85>
move.w lFontInfoRec.ascent(a6),d5 ; get ascent
swap d5
move.w lHeight(A6),d5 ; get height
move.l lFileListHandle(a6),a0 ; list handle for plotmini
DrawInPlace
; A0 = listHandle, A2 = Rect, A3 = StyledString
; D3 = indent, D4 = position, D5 = ascent,
; D7 = icon
sub.w #70,sp ; string buffer and point
move.l sp,a1
move.l (a2),(a1)
add.w d4,Left(a1) ; position it
add.w d3,Left(a1) ; add indent
move.l (a1),d1 ; pass topLeft in d1
move.w d5,d0 ; get vertical offset
sub.w #16,d0 ; get difference from standard
bmi.s @1 ; => ignore neg
asr.w #1,d0 ; split the difference
swap d1 ; get top
add.w d0,d1 ; add in difference
swap d1 ; and make it a topLeft
@1 move.l a0, -(sp) ; save a0/d1 across plotmini
move.l d1, -(sp)
move.l 4(sp), a0
move.l (sp), d1
move.w d7,d0 ; icon selector
bsr PlotMini ; list handle in a0
addq #8, sp ; strip saved a0/d1
move.l (sp)+,d0 ; get start point
add.w #iconwidth+iconpad,d0 ; pad to left
move.l d0,-(sp) ; save for stuffing tempRect
move.l d0,-(sp) ; push for moveto
swap d5 ; get ascent
add.w d5,(sp) ; add ascent to vertical
_MoveTo ; position the pen
lea TempRect,a0 ; build rect for truncating string
move.l (sp)+,(a0)
move.l 4(a2),4(a0)
; make a copy of the string so we don't destroy it
move.l sp,a1 ; destination string
lea styledString.text(a3), a0 ; get ptr to source string
moveq #0,d0 ; get a long count
move.b (a0),d0 ; get the count
addq.b #1,d0 ; add in the length byte
_BlockMove ; get name to be trunc'd
move StyledString.font(a3), d0 ; get font
cmp.w lSystemFont(a3), d0 ; same as port's font?
beq.s @systemFont ; br if so, skip set
move d0, -(sp)
_TextFont ; set string for font
bra.s @fontSet
; *** why is this set every time we draw a string?!
; make sure we have system face and size
@systemFont
clr.w -(sp)
_TextFont
clr.w -(sp)
_TextSize
@fontSet
move.b StyledString.style(a3), d0 ; style normal?
beq.s @faceSet ; br if so, style already set
move.b d0, -(sp) ; set string's style
_TextFace
@faceSet
move.b StyledString.style(a3),-(sp) ; make a copy of the current style
move.l sp,-(sp) ; pea pointer to current style
move.w #2,-(sp) ; 2 pixel indent
pea 8(sp) ; pea lXName
pea TempRect
bsr TruncString
pea 2(sp) ; pea lXName
_DrawString
move.w (sp)+, d0 ; was face different?
beq.s @faceRestored ; br if not
clr.w -(SP) ; restore face to normal
_TextFace
@faceRestored
add.w #66,sp ; strip string buffer
move StyledString.font(a3), d0 ; get font
cmp.w lSystemFont(a3), d0 ; was it same as system font?
beq.s @fontRestored ; br if so, don't need restore
clr.w -(sp) ; restore font to normal
_TextFont
@fontRestored
rts
DebuggerSymbol DrawName
;---------------------------------------------------
;
; Plot one of the mini icons. d0 = offset frrom genericIconBase
; d1 = topleft for icon
; a0 = list handle
; Trashes: a0,a1,d0,d1
PlotMini
lea IconBitMap,a1 ; use lowmem for bitmap
move #2,BitMap.rowBytes(a1) ; QD Rowbytes for 16x16
clr.l BitMap.bounds.topLeft(a1) ; boundsrect 0,0,16,16
move.l #$00100010,BitMap.bounds.botRight(a1) ;
subq #4, sp ; space for handle
move.l #'SICN', -(sp) ; get a small icon
move d0, -(sp) ; pass SICN id
_GetResource
move.l (sp)+, d0 ; got an icon?
beq.s @exit ; br if not, exit
move.l d0, a0
move.l (a0),BitMap.baseAddr(a1) ; replace in bitmap
move.l a1,-(sp) ; src bitmap
move.l GrafGlobals(a5),a0 ; get qd globals
move.l ThePort(a0),a0 ; point at the current port
pea portBits(a0) ; pass window bitmap as dest bitmap
pea BitMap.bounds.topLeft(a1) ; use bounds as src rect
lea Scratch20,a0
move.l a0,-(sp) ; save the address
move.l d1,(a0)+ ; point to topleft
move -4(a0),(a0) ; copy top
add #16,(a0)+ ; bottom = top+size
move -4(a0),(a0) ; copy left
add #16,(a0) ; right = left+size
move #srcCopy,-(sp) ; copy mode
clr.l -(sp) ; NIL MaskRgn
_CopyBits ; finally
@exit
rts
DebuggerSymbol PlotMini
;-------------------------------------------------------------
;
;
AllOthersDialogHook
move.w lHit(a6),d0
cmp.w #sfHookFirstCall,d0
bne.s @notFirstCall
; so center over main dialog, which we know is on screen.
move.l a3,-(sp) ; whichWindow: WindowPtr
move.b #lcParentWindow,-(sp) ; where: LocationControlValues
move.b #hcCenter,-(sp) ; horizontalControl: HorizontalControlValues
move.b #vcDocumentCenter,-(sp) ; verticalControl: VerticalControlValues
_AutoPositionWindow
; change default button on replace and stationery dialog to second button
moveq #1,d0 ; assume default is button 1
cmp.l #sfReplaceDialogRefCon,wRefCon(a3)
beq.s @default2
cmp.l #sfStatWarnDialogRefCon,wRefCon(a3)
bne.s @haveDefault
@default2 moveq #2,d0
@haveDefault
; change cancel button on general error dialog to first button
moveq #2,d1 ; assume cancel is button 2
cmp.l #sfErrorDialogRefCon,wRefCon(a3); this dialog has no button #2
bne.s @haveCancel
moveq #1,d1
@haveCancel st d2 ; d2 = track cursor
bsr SetUpDialogFlags ; requires d0,d1,d2 and a3
@notFirstCall
cmp.w #1,d0
beq.s @dismisser
cmp.w #2,d0
bne.s @exit
@dismisser st lSubDlgDone(a6)
@exit rts
DebuggerSymbol AllOthersDialogHook
;--------------------------------------------------------------------
;
; Get STR# D1 into A1
;
GetLocalString
CLR.B (A1) ; assume failure
SUBQ #4, SP ; Save space for handle
MOVE.L #'STR#', -(SP) ; Push STR#
MOVE.W #rStandardFileStringsID, -(SP) ; Push ID
_GetResource ; Get the string list
MOVE.L (SP)+, D0 ; and copy to A0
BEQ.S @exit
MOVE.L D0, A0
MOVE.L (A0), A0 ; Dereference stringlist.
MOVE.W (A0)+, D0 ; Get count
MOVEQ #0, D0 ; zero high order
@nextString
SUBQ #1, D1 ; Decrement index
BEQ.S @gotString ; if zero, have right string
MOVE.B (A0)+, D0 ; Get string length
ADD.W D0, A0 ; Skip over
BRA.S @nextString ; and loop back
@gotString
MOVEQ #1, D0 ; include length byte
ADD.B (A0), D0 ; Get string length
_BlockMove ; Copy the string
@exit
RTS
DebuggerSymbol GetLocalString
;--------------------------------------------------------------------
; ErrorAlert(errorStringIndex)
; This routine raises an alert AFTER moving it to center
; D1 (in) string index
; D0 (out) alert result
;
; ErrorAlert2(namePtr)
; Raise the replace alert using the filename passed in in A1
; A1 (in) ptr to string for citation ^0
; D4 (in) dialog ID
; d3 (in) dialog refcon
; D0 (out) alert result
;
ErrorAlert move.w #rSFOKDialogID,d4
move.l #sfErrorDialogRefCon,d3
lea lString(A6),a1
bsr.s GetLocalString
ErrorAlert2 move.l a1,-(SP)
clr.l -(SP)
clr.l -(SP)
clr.l -(SP)
_ParamText
move.w d4,d0 ; d0 = dialog ID
bsr.s DoSubDialog
rts
DebuggerSymbol ErrorAlert
;---------------------------------------------
; d0 = dialog res ID
; d3 = refcon
;
DoSubDialog
clr.b lSubDlgDone(a6)
lea lSubDialogRec(a6),a3 ; a3 = dialog storage
bsr.s StartDialog ; d3 = refcon
; loop until lSubDlgDone is true
@next tst.b lSubDlgDone(a6)
bne.s @done
bsr GetNextItemHit ; get hit
bsr DoAppsHook ; let app process hit
bsr DoMyHook ; let me process hit
bra.s @next
@done
; take down dialog
move.w lHit(a6),-(sp) ; save hit that cause dismiss around EndDialog
bsr.s EndDialog
move.w (sp)+, lHit(a6)
lea lTheDialogRec(a6),a3 ; restore main dialog
move.l a3,-(sp)
_SetPort
move.w lHit(a6),d0
rts
DebuggerSymbol DoSubDialog
;--------------------------------------------
; StartDialog
; in: a3 = dialog storage
; d0.w = dialog ID
; d3.l = refcon
StartDialog
; load the dialog
subq #4,SP ; room for window
move.w d0,-(sp) ; id for dialog
move.l a3,-(sp) ; use my window stroage
moveq #-1,D0 ; get -1
move.l D0,-(SP) ; behind = -1
_GetNewDialog ; allocate a new dialog
tst.l (sp)+
bne.s @gotDialog
addq #4,sp ; pop return address
bra abortExit ; jump to abort code, note: this is only helpful on main dialog
@gotDialog move.l d3,wRefCon(a3) ; mark which dialog this is
move.l a3,-(sp) ; make it current grafport
_SetPort
; do first hook
move.w #sfHookFirstCall,lHit(a6)
bsr.s DoMyHook ; let me process hit first !!!!!
bsr DoAppsHook ; let app process hit
cmp.l #sfMainDialogRefCon,wRefCon(a3) ; the main dialog need some
beq.s @specialMainExit ; special casing (MainHookAfterFirstHook)
cmp.w #sfHookFirstCall,lHit(a6) ; Check if the users filter changed item <2> FM
beq.s @showWindow ; hit. If they did they must want to surpress the dialog <2> FM
bsr DoMyHook ; Run through DoMyhook again so we can surpress the dialog <2> FM
tst.b lSubDlgDone(a6) ; did they repress the dialog?? <2>
bne.s @exitNoShowWindow ; out of sight out of mind<6E> <2>
bra.s @showWindow
@specialMainExit
bsr MainHookAfterFirstHook
; show dialog
@showWindow move.l A3,-(sp)
_ShowWindow ; show it
@exitNoShowWindow
rts
DebuggerSymbol StartDialog
;--------------------------------------------
; EndDialog
;
; in: a3 = dialog storage
;
EndDialog
; hide window
move.l a3,-(sp)
_HideWindow
; last hook
move.w #sfHookLastCall,lHit(a6)
tst.b lNewReply(a6) ; don't call last hook on calls 1-4
beq.s @doMyHook
bsr.s DoAppsHook ; let app process hit
@doMyHook bsr.s DoMyHook ; let me process hit first
; dispose dialog
move.l a3,-(sp)
_CloseDialog ; take down the dialog
move.l items(a3),a0 ; dispose of the item list
_DisposeHandle
rts
DebuggerSymbol EndDialog
;--------------------------------------------------------------------
;
;
DoMyHook move.l wRefCon(a3),d1
lea MainDialogHook,a0 ; use MainDialogHook for main dialog
cmp.l #sfMainDialogRefCon,d1
beq.s @doit
lea NewFolderDialogHook,a0 ; use NewFolderDialogHook for new folder dialog
cmp.l #sfNewFolderDialogRefCon,d1
beq.s @doit
lea AllOthersDialogHook,a0 ; otherwise use AllOthersDialogHook
@doit jsr (a0)
rts
DebuggerSymbol DoMyHook
;--------------------------------------------------------------------
;
;
;
DoAppsHook move.l lDlgHook(a6),d0 ; get the hook
beq.s @doneHook ; if none, then we're done
lea lTheDialogRec(a6),a0
cmp.l a0,a3
beq.s @dialogOK ; if this is a sub dialog
tst.b lNewReply(a6) ; and not a new reply then done
beq.s @doneHook
@dialogOK subq #2,sp ; room for result
move.w lHit(a6),-(SP) ; pass the item hit
move.l A3,-(SP) ; pass the dialog
tst.b lUseCallBack(a6) ; does routine want callback?
beq.s @noCallBackPtr
move.l lCallBackPtr(a6),-(sp)
@noCallBackPtr
move.l D0,A0
jsr (A0) ; call the hook
move.w (SP)+,lHit(a6) ; get result item
@doneHook rts
DebuggerSymbol DoAppsHook
;---------------------------------------------------------
;
; in: d0.w = default button number
; d1.w = cancel button number
; d2.b = whether to track cursor (boolean)
; a3.l = dialog ptr
SetUpDialogFlags
move.b d2,-(sp) ; save for future use
move.w d1,-(sp) ; save for future use
; system handles default button
tst.l lMainOpen(a6) ; hack for PageMaker
beq.s @doneMain
subq #2,sp ; room for OSErr result
move.l a3,-(sp) ; dialogPtr
move.w d0,-(sp) ; default item
_SetDialogDefaultItem
addq #2,sp ; ignore result code
@doneMain
; system handles cancel button
move.w (sp)+,d1 ; retreive cancel button number
subq #2,sp ; room for OSErr result
move.l a3,-(sp) ; dialogPtr
move.w d1,-(sp) ; cancel item number
_SetDialogCancelItem
addq #2,sp ; ignore result code
; system (in new dialog) the cursor
move.b (sp)+,d2 ; retreive saved d2
subq #2,sp ; room for OSErr result
move.l a3,-(sp) ; dialogPtr
move.b d2,-(sp) ; whether to track
_SetDialogTracksCursor
addq #2,sp ; ignore result code
rts
DebuggerSymbol SetUpDialogFlags
;--------------------------------------------------------------------
;
; PROCEDURE AddFileListItems;
;
; Entry
; A6 = stdfile frame
; disk = lVolRefNum(A6)
;
; Builds up the file list which consists of the header followed
; by a concatenation of file entries.
; (header)(file entry 1)...(file entry n)
;
; Register usage
; D6 offset of next record
; D5 current dirID
; D4 current file index
; D3 used by ForDiskDo
; A4 list cell data handle
; A3 list handle
; A2 used by ForDiskDo as vcb ptr
AddFileListItems
MOVEM.L D2-D6/A2-A4,-(SP)
MOVEQ #1, D0
MOVE.L D0,lLastSel(A6) ; no previous selection
CMP.W #40,lVnFiles(A6) ; a lot of files?
BLS.S @skipWatch ; br if not, skip watch
SUBQ #4,SP ; get the hour glass
MOVE #4,-(SP)
_GetCursor
MOVE.L (SP)+,A0
MOVE.L (A0),-(SP)
_SetCursor
@skipWatch
MOVE.L lFileListHandle(A6),A3 ; A3 = handle to list rec
MOVE.L (A3),A4 ; get pointer to data record
MOVE.L cells(A4),A4 ; A4 = handle to cell data
MOVE.L A3,A0 ; set to starting size
MOVE.L #sizeList+64,D0 ; start with room for 30 files
_SetHandleSize
MOVE.L A4,A0 ; set to starting size
MOVE.L #1023,D0 ; start with a good size chunk ~30 files
; note, we grow it by 1024 each time, use 1023 now so we max at $7fff
_SetHandleSize
MOVEQ #0,D6 ; D6 = offset into data handle
TST.B lAtDesktop(A6) ; at trash?
BLE @notDesktop ; br if regular folder
; fall through to desktop case
; Add an entry for each disk which is mounted
LEA AddDiskItem, A0
BSR ForDiskDo
; Sort the volume names at top of list
moveq #0,d0 ; sort from start
move.l (A3),A0
move.w dataBounds+Rect.bottom(A0),d1 ; number of volumes
move.w d1,-(sp) ; save off for next sort
subq.w #1,d1 ; sort is zero based
bsr SortSome
; Add entries for desktop folder of each disk which is mounted
MOVE.L #kDesktopFolderType,D5 ; add contents of desktop for all disks
LEA AddSpecialFolder,A0
BSR ForDiskDo
; Sort the desktop files
move.w (sp)+,d0 ; sort from start of desktop files
move.l (A3),A0
move.w dataBounds+Rect.bottom(A0),d1 ; get number of files
subq.w #1,d1 ; sort is zero based
bsr SortSome
; Always add the trash to the desktop
MOVE.L (A4),A1 ; dereference the list
LEA (A1,D6.W),A1
WITH FileEntry
MOVEQ #fsRtDirID,D0
MOVE.L D0,feTypeOrDirID(A1) ; stuff in 2 for dirID of trash
MOVE.L D0,feParID(A1) ; stuff in 2 for parID of trash
MOVE.W lBootVol(a6),feVRefNum(A1) ; trash's volume is startup
MOVE.W lBootDrive(A6),feDrive(A1) ; trash's drive is startup
CLR.B feFLAttr(A1) ;
BSET #ioDirFlg,feFLAttr(A1) ; set isFolder attribute
MOVE.B #mNoEject+bOpenable+bNoWrite+bNoRead+bNoSearch,feFLPriv(A1) ; give it no permissions
MOVE.W #trashIconResource,feIcon(A1) ; set trash icon
bsr GetIconSide ; gets iconLeft and Just into d0.w
move.w d0,FileEntry.feIconLeft(A1)
;ST feIconLeft(A1) ; icon on left
;MOVE.B #teJustLeft,feJust(A1) ; left justify text
CLR.W feIconColor(A1) ; trash is always black
MOVE.W lSystemScript(A6),feFile.script(A1) ; trash uses system script
MOVE.W lSystemFont(A6),feFile.font(A1) ; trash uses system font
MOVE.W lSystemFontSize(A6),feFile.size(A1) ; trash uses system size
ST feFile.dimmed(A1) ; trash is always dimmed
CLR.B feFile.style(A1) ; normal style
ENDWITH
lea FileEntry.feFile.text(A1),A1
moveq #sfTrashName, D1
bsr GetLocalString ; load trash name into a1
bsr AddNewRecord
bra.s @doneBuilding
@notDesktop move.l lCurDir(a6), D5 ; add contents of current directory
move lDriveNo(a6),lTempDrive(a6) ; setup drive for enumerate
bsr AddFolderContents
moveq #0,d0 ; sort from start
move.l (A3),A0
move.w dataBounds+Rect.bottom(A0),d1 ; get number of files
beq.s @doneBuilding ; don't sort if no files
subq.w #1,d1 ; sort is zero based
bsr.s SortSome
@doneBuilding
move.l (A3),A0
move.w dataBounds+Rect.bottom(A0),d3 ; get # files
move.w d3,d0
bsr SetBounds ; calc new visible files
move.w d3,d0 ; get # files
beq.s @setMaxIndex
subq.w #1,D0 ; zero based
add.w D0,D0 ; *2
@setMaxIndex
move.w D0,maxIndex(A0) ; set number of entries
movem.l (SP)+,D2-D6/A2-A4
rts
DebuggerSymbol AddFileListItems
;---------------------------------------------------
; in: d0.w,d1.w = sort range
; a3 = list handle
; a4 = list cells data
;
; trashes: all data registers and A0,A1
;
SortSome movem.l a2-a4,-(sp)
add.w d0,d0 ; sorting indexes which are two bytes wide
move.w d0,-(sp) ; sort from
add.w d1,d1 ; sorting indexes which are two bytes wide
move.w d1,-(sp) ; sort to
move.l a4,a0
_HLock ; lock cells data
move.l (a4),a2 ; get ptr to cell data into a2
move.l a3,a0
_HLock ; lock list record
move.l (a3),a0
lea cellArray(a0),a4 ; get ptr to offsets into a4
bsr OptQuickSort
movem.l (sp)+,a2-a4
move.l a3,a0
_HUnLock ; unlock list record
move.l a4,a0
_HUnLock ; unlock cells data
rts
DebuggerSymbol SortSome
;---------------------------------------------------
;
; in: D1.L = file type
; out: D0.W = resource ID of icon to use
; D2.B = file is alias to container
FileTypeToIconResourceID
move.l a0,-(sp)
move.l lAliasTypeMapH(a6),a0 ; try alias table
st d2 ; asssume is alias to container
bsr.s FileTypeLookUp ; returns with Z not set if it found match
bne.s @done
sf d2
move.l lFileTypeMapH(a6),a0 ; try generic stuff table
bsr.s FileTypeLookUp ; returns with Z not set if it found match
bne.s @done
move.w #genericDocumentIconResource,d0 ; not in any table so default to document icon
@done move.l (sp)+,a0
rts
DebuggerSymbol FileTypeToIconResourceID
;---------------------------------------------------
;
; in: D1.L = file type
; A0 = handle to mapping table
; out: D0.W = resource ID of icon to use
; trashed: A0
;
FileTypeLookUp
move.l (a0),a0 ; dereference handle
@next move.l (a0)+,d0
beq.s @done ; zero signals end of table, return with Z set
cmp.l d0,d1
beq.s @found
addq #4,a0 ; skip past wrong resource ID
bra.s @next
@found move.l (a0)+,d0 ; return correct resource ID, with Z not set
swap d0 ; want high word
@done rts
DebuggerSymbol FileTypeLookUp
;---------------------------------------------------
; AddFolderContents
; add the contents of the folder to the file list
;
; D6 offset of next record
; D5 current dirID
; D4 current file index
; D3 ForDiskDo ProcPtr
; A4 list cell data handle
; A3 list handle
; A2 ForDiskDo vcb ptr
;
; lIOCmd(a6).ioVRefNum needs to be set up
;
; trashes A0, A1, D0, D1
AddFolderContents
moveq #1, d4 ; index beginning at first file
@nextFile move.l a4,a0 ; lock down cell data cause ioNamePtr points into it
_HLock
lea lIOCmd(a6),a0 ; point to I/O command
move.w d4,ioFDirIndex(a0) ; And use the given index.
move.l (a4),a1 ; dereference the list
lea FileEntry.feFile.text(A1,D6.W),A1 ; Point to name entry
move.l a1,ioFileName(a0)
move.l d5,ioDirID(a0)
_GetCatInfo ; another file?
bmi @exit ; br if not, we're done with this folder
addq.w #1,d4 ; and bump index to get next file
move.l ioDirID(a0), d0 ; get dirID of the folder
cmp.l lTrashDir(a6), d0 ; is this the trash folder?
beq.s @nextFile ; br if so, don't show it
cmp.l lDeskDir(a6), d0 ; is this the desk folder?
beq.s @nextFile ; br if so, don't show it
move.l (a4),a1 ; dereference the list
lea (a1,d6.w), a1 ; point at record in a1
clr.b FileEntry.feFile.dimmed(a1) ; default all entries to not dim
move.w lTempDrive(a6),FileEntry.feDrive(a1) ; stuff in drive number
move.w ioVRefNum(a0),FileEntry.feVRefNum(a1) ; stuff in vRefNum
move.b ioFlAttrib(a0),FileEntry.feFLAttr(a1) ; stuff in the attribute
clr.b FileEntry.feFLPriv(A1) ; assume can't get permissions
move.w ioFlUsrWds+fdFlags(a0),FileEntry.feFndrFlags(a1) ; stuff in finder flags
; set up icon color for the file/folder
bsr GetColorFromCatInfo
move.w d0,FileEntry.feIconColor(a1)
btst #ioDirFlg,ioFlAttrib(a0) ; is it a folder?
bne.s @isFolder ; br if so, go do folder stuff
@isFile move.l ioFlParID(a0),FileEntry.feParID(a1) ; stuff dirID
move.l ioFlUsrWds+fdType(A0),d1
move.l d1,FileEntry.feTypeOrDirID(a1) ; stuff file type
; get icon for this file
bsr FileTypeToIconResourceID ; d1 in, d0 out
cmp.w #trashIconResource,d0
seq.b FileEntry.feFile.dimmed(a1) ; dim out aliases to trash
cmp.w #genericDocumentIconResource,d0 ; is the a document?
bne.s @doneStatChk
btst #isStationeryBit,FileEntry.feFndrFlags(a1) ; and is stationery bit set?
beq.s @doneStatChk
move.w #genericStationeryIconResource,d0 ; if so, use stationery icon
@doneStatChk
tst.b d2 ; is this alias?
beq @setIcon
cmp.l #kApplicationAliasType,d1 ; 'adrp', if not an alias to an application
beq.s @setIcon
cmp.l #kContainerAliasType,d1 ; 'drop', if not an old alias to an application (or unknown container)
beq.s @setIcon
; must be an alias to a folder/volume
bset #ioDirFlg,FileEntry.feFLAttr(a1) ; pretend this is a folder
bset #ioDirFlg,ioFlAttrib(a0) ; pretend this is a folder
bra.s @setIcon
; folders may look different if lacking privileges
@isFolder bclr #isAliasBit,FileEntry.feFndrFlags(a1) ; force alias flag of folders to false
move.l ioDirID(a0),FileEntry.feTypeOrDirID(a1) ; stuff dirID of this folder
move.l ioDrParID(a0),FileEntry.feParID(a1) ; stuff in the dirID of this folder's parent
move.l lVolParms.vMAttrib(a6),D1 ; get volumes parms
btst #bAccessCntl,D1 ; does it support access control?
beq.s @getFolderIcon ; if not, don't get permissions byte
move.b ioACUser(a0),FileEntry.feFLPriv(A1) ; stuff in the permissions
tst.b lLocked(a6) ; is disk also locked?
beq.s @getFolderIcon
bset #bNoWrite,FileEntry.feFLPriv(A1) ; is locked, flip on noWrite perm bit
; set up mini-icon for folder
@getFolderIcon
move.w #genericLetterIconResource, d0
btst #isLetter,FileEntry.feFndrFlags(a1) ; is it letter?
bne.s @setIcon ; br if so, got icon
move.w #genericFolderIconResource,d0 ; assume it is a public folder
move.b FileEntry.feFLPriv(A1),d1 ; get access privileges
tst.b lDoingGetFile(a6) ; <jrm 04Sep86>
bne.s @getFile ; branch if getfile <jrm 04Sep86>
btst #bNoSearch, d1 ; normal folder if has search
beq.s @setIcon ; br if has search
and.b #mNoRead+mNoWrite,d1 ; also normal if R and W <jrm 04Sep86>
beq.s @setIcon ; br if R and W <jrm 04Sep86>
bra.s @grayFolder ; else, can't open this
@getFile and.b #mNoSearch+mNoRead,d1 ; getfile folder needs R or S <jrm 04Sep86>
cmp.b #mNoSearch+mNoRead,d1 ; missing both? <jrm 04Sep86>
bne.s @setIcon ; no, branch to normal open dir <jrm 04Sep86>
@grayFolder move.w #privateFolderIconResource,d0 ; use different folder
bset #bOpenable,FileEntry.feFLPriv(a1) ; mark unopenable
@setIcon move.w d0,FileEntry.feIcon(a1) ; save mini-icon id
tst.b lNoEjects(a6)
beq.s @ejectIsSet
bset #bNoEject,FileEntry.feFLPriv(A1) ; set this file can be eject if its volume can
@ejectIsSet
bsr GetIconSide ; gets iconLeft and Just into d0.w
move.w d0,FileEntry.feIconLeft(A1)
;st FileEntry.feIconLeft(A1) ; icon on left
;move.b #teJustLeft,FileEntry.feJust(A1) ; left justify text
btst #ioDirFlg,ioFlAttrib(a0) ; never dimmed for folders
bne.s @doneDim
tst.b lDoingGetFile(a6) ; dimmed files in putfile files
bne.s @doneDim
st FileEntry.feFile.dimmed(a1)
@doneDim
; Set the font for the file's name from Finder Info
bsr GetFilenameFont ; get filename's font
move.w d0,FileEntry.feFile.script(a1) ; stuff script into record
move.w d1,FileEntry.feFile.font(a1) ; stuff font into record
move.w lSystemFontSize(A6),FileEntry.feFile.size(a1) ; stuff system size
moveq #0, d0 ; assume no styling
btst #isAliasBit,FileEntry.feFndrFlags(a1) ; see if it is an alias
beq.s @setStyle
; get style to draw alias in from script manager
subq #4, sp ; longint result
move.w FileEntry.feFile.script(a1),-(sp) ; pass script
move.w #smScriptAliasStyle,-(sp) ; get alias styling for this script
_GetScript
move.l (sp)+, d1 ; returns a long
move.b d1,d0 ; put style byte in d0
lea lIOCmd(a6),a0 ; a0 could have been trashed by GetScript
move.l (a4),a1 ; a1 could have been trashed by GetScript
lea (a1,d6.w), a1 ; point at record in a1
@setStyle move.b d0,FileEntry.feFile.style(a1); stuff style into record
btst #isInvisible,FileEntry.feFndrFlags(a1) ; is it invisible?
beq.s @visible ; br if not, keep checking
tst.b lDoingGetFile(a6) ; is this putfile?
beq.s @goNextFile ; br if so, never show invisibles
tst.w lNumTypes(A6) ; accepting everything?
bge.s @goNextFile ; br if not, don't show invisibles
@visible tst.b lDoingGetFile(a6) ; is this putfile?
beq.s @addRecord ; br if so, always match (but dimmed)
btst #ioDirFlg,ioFlAttrib(a0) ; is it a folder?
bne.s @matched ; br if so, always add to list
; for get file, check list of file types and possible filter proc
move.l ioFlUsrWds(A0),D0 ; get this file's type
move.l lTypeList(A6),A1 ; get type list
move.w lNumTypes(A6),D1 ; get # types in list
bmi.s @matched ; skip if promiscuous match (-1 => match all)
@nextType cmp.l (A1)+,D0 ; see if matches
beq.s @matched ; it does, go on...
subq #1,D1 ; try next type
bne.s @nextType ; until exhausted the list of types <63 #b6-ngk-006>
;<63> bpl.s @nextType
@goNextFile bra @nextFile ; no match in whole list
@matched btst #ioDirFlg,ioFlAttrib(a0) ; is it a folder?
beq.s @filter ; br if not, add to list
tst.b lFilterFolders(a6) ; for custom get file, we call filter on folders
beq.s @addRecord
@filter bsr.s CallAppsFileFilter
bne.s @goNextFile ; if returned true then don't add this record
; Passed through the filter, extend for the next entry
@addRecord bsr AddNewRecord
bpl.s @goNextFile ; and try the next file
@exit rts
DebuggerSymbol AddFolderContents
;------------------------------------
;
;
CallAppsFileFilter
tst.l lFileFilter(A6) ; see if filter there
beq.s @exit ; if not, then return as if filter returned false
subq #2,SP ; room for boolean
pea lIOCmd(A6) ; pass info
tst.b lUseCallBack(a6)
beq.s @noCallBackPtr
move.l lCallBackPtr(a6),-(sp)
@noCallBackPtr
move.l lFileFilter(a6),A0
jsr (A0) ; call the file filter
move.b (SP)+,d0 ; skip this file if true
@exit rts
DebuggerSymbol CallAppsFileFilter
;------------------------------------
;
; in: a0 = catinforec
; out: d0 = color index
GetColorFromCatInfo
moveq #0,d0
move.b ioFlUsrWds+fdFlags+1(a0),d0 ; get Finder flags, color is bits 1-3
asr.w #1,d0 ; color bits are in bits 0-2
and.w #$07,d0 ; color offset
rts
DebuggerSymbol GetColorFromCatInfo
;------------------------------------
;
; out: d0.w.low = text justification
; d0.w.high = icon on left boolean
;
GetIconSide
move.b forceIconsOnLeft,d0 ; check if PACK has been localized
bne.s @default ; if not used default
tst.w teSysJust ; if so, check sysJust
beq.s @default ; if left-to-right, use default
move.w #$00FF,d0 ; else icon on right, right justified
bra.s @done
@default move.w #$FF00,d0 ; default: icon on left, left justified
@done rts
;-----------------------------------------------------------------
; GetFilenameFont - lookup the filename's font given a param block
; a0 (in) getcatinfo param block
; d1 (out) font id
; d0 (out) script id
; trashes d2, preserves a1 (added this comment, but no change in reg use <54>)
GetFilenameFont
movem.l a0-a1, -(sp) ; save regs; leaves a0 on top of stack
; If use of script tags is disabled, always set filename script = SystemScript <54>
subq #4,sp ; space for GetEnvirons return <54>
move.w #smGenFlags,-(sp) ; push GetEnvirons verb <54>
_GetEnvirons ; <54>
move.l (sp)+,d0 ; get Script Mgr flags <54>
btst.l #smfNameTagEnab,d0 ; are script tags in use? <54>
beq.s @setSysScript ; if not, assume system script <54>
move.l (sp),a0 ; restore from stack <54>
moveq #0, d0 ; clear out script
move.b ioFlxFndrInfo+sfFndrScript(a0), d0 ; get the filename's script word
bclr #7, d0 ; is script byte valid?
bne.s @gotScript ; br if so, got script
@setSysScript ; <54>
move.w lSystemScript(a6), d0 ; default to system script
@gotScript move d0, -(sp) ; save script so we can return it
move lSystemFont(a6), d1 ; assume it is the system font
cmp.w lSystemScript(a6), d0 ; same script as system?
beq.s @exit ; br if so, got font
subq #4, sp ; longint result
move d0, -(sp) ; pass script
move #smScriptSysFond, -(sp) ; get system font for this script
_GetScript
move.l (sp)+, d1 ; return font id
@exit move (sp)+, d0 ; return script id
movem.l (sp)+, a0-a1 ; restore regs
rts
DebuggerSymbol GetFilenameFont
;-----------------------------------------------------------------
; ForDiskDo - iterator to call a procedure for all online disks
;
; Register usage
;
; in: A0 = procedure to do for each disk
;
; trashes d3,a2
;
ForDiskDo MOVEM.L A1/D0,-(sp) ; save so we can use in invisible check <2> FM
MOVE.L vcbQHdr+QHead,A2 ; first VCB start over <2> FM
MOVE.L A0, D3 ; save procPtr
@NextDisk MOVE.L A2, D0
BEQ.S @exit
TST.W vcbDrvNum(A2) ; is it offline
BNE.S @online ; br if not, use disk
TST.W vcbDRefNum(A2) ; is it really online
BPL.S @skipDisk ; br if now, skip this disk
@online
MOVE.L A2,A1 ; <2> <7>
BSR VolumeIsInvisible ; <2> <7> See if this volume is invisible
TST.W D0 ; <2> <7> If it is, don<6F>t call the procedure
BNE.S @skipDisk ; <2> <7> for it
MOVE vcbDrvNum(A2),lTempDrive(A6); setup drive for enumerate
move.l a2,-(sp)
MOVE.L D3, A0 ; get the proc ptr
JSR (A0) ; and call the interator function
move.l (sp)+,a2
BMI.S @exit
@skipDisk MOVE.L QLink(A2), A2 ; get next disk
BRA.S @NextDisk
@exit MOVEM.L (sp)+,A1/D0 ; restore <2> FM
rts
DebuggerSymbol ForDiskDo
;-----------------------------------------------------------------
; AddSpecialFolder
;
; adds contents of trash or desktop folder to current list
;
; in: D5 = folder type
; A2 = VCB pointer
;
; D6 offset of next record
;
; A4 list data ptr
; A3 list handle
;
; trashes a0,
AddSpecialFolder
MOVE.W vcbVRefNum(A2), D0
LEA lIOCmd(a6),A0 ; point to I/O command
MOVE.W D0,ioVRefNum(A0) ; remember we're listing this volume
MOVE.L D5,-(SP) ; save folder type
MOVE.L D5, D1 ; pass type in D1
BSR FindFolder ; lookup special folder in D0
MOVE.L D0, D5 ; got the folder?
BEQ.S @exit ; br if not, skip enumeration
move.w lTempDrive(A6),d1 ; get target drive #
bsr NotEjectable ; not ejectable?
move.b D0,lNoEjects(A6) ; record if it can't be ejected
bsr AddFolderContents ; add contents of this special folder to list
@exit MOVE.L (SP)+, D5 ; restore folder type
moveq #0,d0 ; return no error
rts
DebuggerSymbol AddSpecialFolder
; AddDiskItem - Add a disk into the list
;
; Register usage
; D6 offset of next record
; D5 current dirID
; D4 current file index
; D3 ForDiskDo ProcPtr
; A4 list data ptr
; A3 alternate RTS stack
; A2 ForDiskDo vcb ptr
; trashes A1, D0, D1, A0, D2
AddDiskItem
LEA lIOCmd(A6),A0 ; point to I/O command
MOVE vcbVRefNum(A2),ioVRefNum(A0) ; lookup this volume
MOVE #-1, ioFDirIndex(A0) ;lookup by dirID
MOVEQ #fsRtDirID, D0
MOVE.L D0,ioDirID(A0) ; get root of volume
MOVE.L (A4), A1
LEA FileEntry.feFile.text(A1,D6.W), A1
MOVE.L A1,ioFileName(A0) ; fill in name while we're at it
_GetCatInfo ; find about this volume
BMI @exit ; exit if volume gone already
MOVE.L (A4),A1 ; dereference the list
LEA (A1,D6.W), A1
move.w vcbVRefNum(a2),d0 ; d0 (in) vrefnum of disk
move.l #kDesktopFolderType,d1 ; d1 (in) which special folder
movem.l a0-a2,-(sp)
bsr FindFolder ; d0 (out) dirID of folder, or 0 if there was an error
move.l d0,d1 ; save in d1
move.w vcbVRefNum(a2),d0 ; d0 (in) vrefnum of disk
bsr GetVolumeInfoPtr ; a0 (out) pointer to info
tst.l d1
bne.s @gotDesk
moveq #fsRtDirID,d1 ; if no desktop folder, use root = 2
@gotDesk move.l d1,PerVolumeInfo.desktopDir(a0) ; save off desktop dirID for this volume
movem.l (sp)+,a0-a2
WITH FileEntry
MOVE.L D1,feTypeOrDirID(A1) ; stuff in the dirID of desktop of volume
MOVEQ #fsRtParID, D0 ; = 1
MOVE.L D0,feParID(A1) ; stuff in the dirID of the parent of root
MOVE.W vcbDrvNum(A2),feDrive(A1) ; save drive number
MOVE.W vcbVRefNum(a2),FileEntry.feVRefNum(a1) ; stuff in vRefNum
MOVE.B ioFlAttrib(a0),feFLAttr(A1) ; stuff in the attribute
CLR.B feFLPriv(A1) ; assume can't get permissions
MOVE.W vcbDrvNum(A2), D1 ; get drive number
BSR NotEjectable ; returns with d0=0 if ejectable
TST.B d0
BEQ.S @1
BSET #bNoEject,FileEntry.feFLPriv(a1) ; remember if ejectable
@1 MOVE.W ioFlUsrWds+fdFlags(a0),feFndrFlags(A1) ; stuff in finder flags
MOVE.W ioVRefNum(a0),d0 ; pass vRefNum to GetVolIcon
BSR GetVolIcon ; icon depends on volume type
MOVE.W D0,feIcon(A1) ; stuff icon
BSR GetColorFromCatInfo
MOVE.W d0,feIconColor(A1) ; save icon color
bsr GetIconSide ; gets iconLeft and Just into d0.w
move.w d0,FileEntry.feIconLeft(A1)
;ST feIconLeft(A1) ; icon on left
;MOVE.B #teJustLeft,feJust(A1) ; left justify text
BSR GetFilenameFont ; lookup filename's font
MOVE.W D0,feFile.script(A1) ; save name's script
MOVE.W D1,feFile.font(A1) ; save name's font
MOVE.W lSystemFontSize(A6),feFile.size(A1) ; volumes use system size
CLR.B feFile.dimmed(A1) ; volumes are never dimmed
CLR.B feFile.style(A1) ; normal style
ENDWITH
BSR.S AddNewRecord ; add the new record onto list and indices
@exit rts
DebuggerSymbol AddDiskItem
;-----------------------------------------------------------------
;
; Extend the data and indices handle and update the offset to the current record
;
; Register usage
; A3 list record handle
; A4 list cell handle
; D6 offset into cell data of current record
; trashes: D0, D1, A0
AddNewRecord
; stuff index into index array
moveq #0,d1
move.l (a3),a0
move.w dataBounds+Rect.bottom(a0),d1 ; current items in list
;subq #1,d1
add.l d1,d1 ; each is two bytes
move.l A3,A0 ; get the list record size
_GetHandleSize
sub.l #sizeList,D0 ; get indices size
cmp.l d0,d1
blt.s @stuffIndex
add.l #sizeList+64,d0 ; grow index by 32 entries
_SetHandleSize ; make more room
bne.s @errExit
@stuffIndex move.l (a3),a0
move.w d6,cellArray(a0,d1.w) ; insert new index
addq.w #1,dataBounds+Rect.bottom(a0)
; advance offset (d6) into cell data
moveq #FileEntry.feFile.text+1+2, D1 ; static size + length byte + round up
move.l (A4), A0 ; deref data handle
add.b FileEntry.feFile.text(A0,D6.w),D1; add in name length
bclr #0, D1 ; evenize
add.w d1,d6 ; size of current record into D1
; make sure is room for next record
move.l A4,A0 ; get the list cell data size
_GetHandleSize
move.l d0,d1
sub.l d6,d1 ; compute room left in cell data
cmp.l #FileEntry.size,d1 ; is there room for next record?
bge.s @okExit ; if so, go on
move.l d0,d1
_HUnLock ; it might have been locked
move.w #1024,d0
add.l d1,d0 ; do long add for SetHandleSize
tst.w d0 ; test as if word, high bit of index is flag for selection
bmi.s @errExit ; so can only go up to $7FFF
_SetHandleSize ; add 1K chunk
beq.s @okExit
@errExit moveq #-1, D0
@okExit rts
DebuggerSymbol AddNewRecord
;--------------------------------------------------------------------
;
; QuickSort( l, r: INTEGER );
;
;
;
; A4 dereferenced offsets array into FileEntry list
; A2 dereferenced FileEntry list
;
; trashes all data regs and A0-A1 except D6 and D7
;
LeftIndex Equ 6+4
RightIndex Equ 4+4
QuickSort move.w D6,-(SP) ; save reg, only word, to save recursed stack space
move.w D7,-(SP) ; save reg
move.w LeftIndex(SP),D6 ; D6 is left pointer
move.w RightIndex(SP),D7 ; D7 is right pointer
move.w d7,d5
sub.w d6,d5
ble.s @done ; nothing to sort
cmp.w #2,d5
bne.s @normalCase
; special case only two items in list to sort
move.w 0(A4,D6.W),D3 ; get index of left
lea FileEntry.feFile(A2,D3.W),A0 ; point to left string
move.w 0(A4,D7.W),D4 ; get index of right
lea FileEntry.feFile(A2,D4.W),A1 ; point to right string
bsr CompStyledString ; cc's set CMP left,right
blt.s @done ; if already sorted then done
move.w D4,(A4,D6.W) ; else swap entries
move.w D3,(A4,D7.W)
bra.s @done
@normalCase
; do normal QuickSort
bsr.s Partition ; takes d6,d7 returns d5
; sort left partition (l, i-1)
move.w d5,-(sp) ; save d5
move.w d6,-(sp)
subq.w #2,d5
move.w d5,-(sp)
bsr.s QuickSort
move.w (sp)+,d5 ; restore d5
; sort right partition (i+1, r)
addq.w #2,d5
move.w d5,-(sp)
move.w d7,-(sp)
bsr.s QuickSort
@done move.w (SP)+,D7 ; restore reg
move.w (SP)+,D6 ; restore reg
move.l (SP)+,(SP) ; pop parameters
rts
DebuggerSymbol QuickSort
;
;
; This partition uses the middle element as the pivot point.
; This could be improved by spending some cycles to find a
; better pivot, such as "median of three"
;
Partition movem.l D6-D7,-(SP) ; save regs
; c := (r+l)/2
move.w d7,d5
add.w d6,d5
lsr.w #1,d5
and.w #$FFFE,d5 ; pick midpoint as pivot
; exchange A[c] <-> A[r]
move.w 0(A4,D5.W),D3 ; move pivot to end
move.w (A4,D7.W),(A4,D5.W) ; so we can use traditionaly QS
move.w D3,(A4,D7.W)
; x := A[r]
lea FileEntry.feFile(A2,D3.W),A0 ; point to pivot entry
; i := l - 1;
subq.w #2,d6
; repeat
; repeat i:= i+1 until A[j] <20> x
@nextLeft addq.w #2,d6
move.w 0(A4,D6.W),D3 ; get testee offset = left
lea FileEntry.feFile(A2,D3.W),A1 ; point to testee name
bsr.s CompStyledString ; cc's set CMP testee,pivot
bgt.s @nextLeft ; continue if still less than or equal to pivot
; repeat j:= j-1 until A[j] <20> x
@nextRight subq.w #2,d7
ble.s @exitRepeat ; bounds check on j <55.3, #82542>
move.w 0(A4,D7.W),D3 ; get testee offset = left
lea FileEntry.feFile(A2,D3.W),A1 ; point to testee name
bsr.s CompStyledString ; cc's set CMP testee,pivot
blt.s @nextRight ; continue if still greater than pivot
; if i <20> j then leave
cmp.w d6,d7
ble.s @exitRepeat
; exchange A[i] <-> A[j]
move.w 0(A4,D6.W),D3 ; do swap of indices
move.w (A4,D7.W),(A4,D6.W)
move.w D3,(A4,D7.W)
; until false
bra.s @nextLeft
@exitRepeat
; return i
move.w d6,d5
movem.l (SP)+,D6-D7 ; restore regs
; exchange A[r] <-> A[i]
move.w 0(A4,D5.W),D3 ; this swap pivot value into partition split
move.w (A4,D7.W),(A4,D5.W) ; it partitions the range into 3 parts
move.w D3,(A4,D7.W) ; (l,i-1),(i,i),(i+1,r)
rts
DebuggerSymbol Partition
;--------------------------------------------------------------------
;
; CompStyledString
;
; input: A0 - Styled string,
; A1 - Styled string,
; ouptut: flags set as if CMP (A1),(A0)
;
; trashes d0
;
CompStyledString
; first check if two strings are even in the same script
cmp.l a0,a1 ; optimize when strings are obviously the same
beq.s @done
movem.l a0-a1,-(sp) ; save off a0, a1
move.w StyledString.script(a0),d0 ; get first script id
cmp.w StyledString.script(a1),d0 ; compare script numbers first
beq.s @testString ; same script so compare the text
; they are not in same script, so just use script order
subq #2,sp ; room for result
move.w d0,-(sp)
move.w StyledString.script(a1),-(sp)
_IUScriptOrder ; get order for scripts
tst.w (sp)+ ; set CC's and we are done
bra.s @restore
; check if strings are byte for byte the same
@testString lea StyledString.text(a0),a0 ; aPtr
lea StyledString.text(a1),a1 ; bPtr
move.b (a0),d0 ; length
@nextByte cmp.b (a0)+,(a1)+
dbne d0,@nextByte
beq.s @restore ; strings are exactly the same bytes, so done
movem.l (sp),a0-a1 ; retrieve a0,a1 from stack
; since they are not exactly the same, MagPString can return an ordering
@inequal subq #2,sp ; room for result
pea StyledString.text+1(a0) ; aPtr
pea StyledString.text+1(a1) ; bPtr
moveq #0,d0
move.b StyledString.text(a0),d0
move.w d0,-(sp) ; aLen
move.b StyledString.text(a1),d0
move.w d0,-(sp) ; bLen
move.w StyledString.script(a0),d0 ; for what script do we want itl2?
cmp.w lCacheScrCode(a6),d0 ; have we already cached that?
beq.s @gotItl
move.w d0,lCacheScrCode(a6) ; change cache to this script
subq #4,sp
move.w #2,-(sp) ; specify type of 'itlx' resource
move.w d0,-(sp) ; specify the script code
move.w #-1,-(sp) ; specify system, not app, sorting
_IUGetScriptItl ; get itl2 handle into cache
move.l (sp)+,lCacheScrHandle(a6)
@gotItl move.l lCacheScrHandle(a6),-(sp) ; itl2 handle
_IUMagPString ; sorting comparison
tst.w (sp)+ ; set CC's and we are done
@restore movem.l (sp)+,a0-a1 ; restore a0, a1
@done rts
DebuggerSymbol CompStyledString
;--------------------------------------------------------------------
; OptQuickSort(l, r: INTEGER);
;
; Walks list and checks if list is already sorted
; before calling QuickSort
;
; trashes all data regs and A0-A1 except D6 and D7
;
OptQuickSort
tst.b lTryShortSort(a6) ; should we check if already sorted before calling QS?
beq.s @doQS ; if not, just QuickSort it
movem.l D6-D7,-(SP) ; save regs
move.w 6+8(SP),D6 ; D6 is left pointer
move.w 4+8(SP),D7 ; D7 is right pointer
@next cmp.w d7,d6
bhs.s @sorted
move.w 0(A4,D6.W),D3 ; get index of left
lea FileEntry.feFile(A2,D3.W),A0 ; point to left string
addq.w #2,d6
move.w 0(A4,D6.W),D4 ; get index of right
lea FileEntry.feFile(A2,D4.W),A1 ; point to right string
bsr CompStyledString ; cc's set CMP left,right
ble.s @next
movem.l (SP)+,D6-D7 ; restore regs
@doQS bra QuickSort
@sorted movem.l (SP)+,D6-D7 ; restore regs
move.l (SP)+,(SP) ; pop parameters
@done rts
DebuggerSymbol OptQuickSort
;--------------------------------------------------------------------
;
; PROCEDURE RevealByName;
; A0 name of item to be selected and scrolled to
; D0 script of name
RevealByName
cmp.w #smSystemScript,d0
bne.s @realScript
move.w lSystemScript(a6),d0
@realScript move.w D0, lTypeSelect.tsrScript(A6) ; uses script
lea lTypeSelect.tsrKeyStrokes(A6),A1; point to the typeahead buffer
moveq #1, D0 ; string size is 1 for length byte
add.b (A0),D0 ; plus length of string
_BlockMove ; copy default name into typeahead buffer
SelectTyped
move.l lFileListHandle(a6),a0
move.l (a0),a0
move.w dataBounds+Rect.bottom(a0),d0
sub.w dataBounds+Rect.top(a0),d0
beq.s @done
subq #2,sp ; result
pea lTypeSelect(a6) ; tsr
move.w d0,-(sp) ; listSize
move.w #tsNormalSelectMode,-(sp) ; selectMode
pea MyGetStringProc ; getStringProc
move.l lFileListHandle(a6),-(sp) ; yourDataPtr is listrec handle
_TypeSelectFindItem
move.w (sp)+,d3
subq #1,d3 ; convert to zero based
st d2 ; OK to center name in file list
bsr.s SelectAndReveal ; select cell in d3
@done rts
DebuggerSymbol RevealByName
;--------------------------------------------------------------------
;
; FUNCTION MyGetStringProc(item: INTEGER;
; VAR itemsScript: ScriptCode;
; VAR itemsStringPtr: StringPtr;
; yourDataPtr: Ptr): BOOLEAN;
;
MyGetStringProc
; get list handle
move.l 4(sp),a0 ; 4 = yourDataPtr is listrec handle
move.l (a0),a0
; get offset of 'item' in cells handle
move.w 16(sp),d0 ; 16 = item
subq.w #1,d0 ; convert first from 1
add.w dataBounds+Rect.top(a0),d0 ; to top
add.w d0,d0 ; each index is two bytes wide
move.w cellArray(a0,d0.w),d0 ; get offset into cell data
and.w #$7FFF,d0 ; strip off selected bit
; get address of 'item' FileEntry
move.l cells(a0),a0
move.l (a0),a0
lea (a0,d0.w),a1
; retrieve itemsScript
move.l 12(sp),a0 ; 12 = itemsScript
move.w FileEntry.feFile.script(a1),(a0)
; retrieve itemsStringPtr
move.l 8(sp),a0 ; 8 = itemsStringPtr
clr.l (a0) ; return NIL by default
tst.b FileEntry.feFile.dimmed(a1) ; is it dimmed
bne.s @1 ; if so return NIL
lea FileEntry.feFile.text(a1),a1
move.l a1,(a0) ; else return pointer
@1 move.l (sp)+,a0 ; return
add #14,sp
move.b #1,(sp) ; always return true
jmp (a0)
DebuggerSymbol MyGetStringProc
;--------------------------------------------------------------------
;
; SelectAndReveal - select a new cell and scroll it into view
; in: d3.w cell index
; d2.b boolean, OK to center selection if scrolling is needed.
;
; trashed: d0,d1,d2,d3,a0,a1,a2
SelectAndReveal
move.w d4,-(sp) ; save d4
move.b d2,d4 ; d4 now contains center boolean
tst.b lListIsActive(a6) ; is the list the active item?
bne.s @canShow ; if not, just remember the index for when list becomes active
moveq #0,d0 ; if we want to select item $1234 in list (zero base)
move.w d3,d0 ;
swap d0 ; then save off $12340000 (row 1234, column 0 )
move.l d0,lLastSel(a6) ;
bra @doneScroll
@canShow move.l lFileListHandle(a6),a2 ; a2 = list handle
bsr GetSel ; get selected cell into d0
bmi.s @noDeselect ; nothing currently selected, so nothing to deselect
swap d0 ; get row number in low word
cmp.w d3,d0 ; are we trying to change to the current selection?
beq.s @doneSelect ; if so, don't deselect and select, to avoid a flash
swap d0 ; restore d0
sf -(sp) ; un selected cell
move.l d0,-(sp) ; push the cell to deselect
move.l a2,-(sp)
_LSetSelect ; select the chosen cell
@noDeselect
move.w d3,d0 ; get cell number
swap d0 ; put it up in vertical
clr.w d0 ; horizontal is always 0
move.l d0,lLastSel(a6) ; remember last selected cell
st -(sp) ; selected cell
move.l d0,-(sp) ; push the cell to select
move.l a2,-(sp)
_LSetSelect ; select the chosen cell
@doneSelect move.l (a2),a1 ; list ptr
move.w visible+top(a1),d1 ; the top visible
move.w visible+bottom(a1),d2 ; below the bottom visible
move.w d3,d0 ; check and see how far we should scroll
sub.w d1,d0 ; do we need to scroll down (above the top)?
blt.s @scroll ; => not visible, scroll
move.w d3,d0 ; check and see how far we should scroll
addq.w #1,d0 ; remember, we probably scroll one less than you think
sub.w d2,d0 ; do we need to scroll up (below the bottom)?
ble.s @doneScroll ; => visible, no need to scroll
@scroll ; now we have decided that we need to scroll, we must decide whether
; to scroll the minimum necessary distance or whether to attempt to center
; the selection in the visible area by checking the parameter on the stack
tst.b d4 ; can we center?
beq.s @doScroll ; if not, then just scroll minimal amout
move.w d3,d0 ; check and see how far we should scroll
add.w d2,d1 ; find the center cell by averaging top and bottom
subq.w #1,d1 ; round so more items in list are below than above
asr.w #1,d1 ; we now have the center of the visible cells
sub.w d1,d0 ; calculate the amount to scroll
add.w d0,d2 ; do a bounds check to see if we will scroll too far
sub.w dataBounds+bottom(a1),d2; will new bottom be out of bounds? and how much
ble.s @doScroll ; if in bounds, go on
sub.w d2,d0 ; don't scroll so much, to stay in bounds
@doScroll tst.b lDontDrawList(a6)
beq.s @scrollit
; display is blank, LScroll would only draw some cells, instead change visible rect
add.w d0,visible+top(a1) ; change visible rect
add.w d0,visible+bottom(a1)
bra.s @doneScroll ; then draw whole list at once
@scrollit clr.w -(sp) ; no horizontal scrolling
move.w d0,-(sp) ; scroll this far vertically
move.l a2,-(sp) ; list handle
_LScroll
@doneScroll tst.b lDontDrawList(a6)
beq.s @checkVolume
; display is blank, need to draw whole list
sf lDontDrawList(a6) ; turn drawing back on
bsr.s DrawFileList ; draw whole list
@checkVolume
; now see if we are at desktop and need to change volume icon
tst.b lAtDesktop(a6)
ble.s @done ; only do check if at desktop
bsr GetSel
bmi.s @done ; safety check
; we need to switch "current volume"
move.w FileEntry.feVRefNum(a0),d0
bsr SetVolumeIcon
@done move.w (sp)+,d4
rts
DebuggerSymbol SelectAndReveal
;--------------------------------------------------------------------
;
; PROCEDURE EraseFileList;
;
EraseFileList
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
bsr GetIt ; get list box into lBox(A6)
move.l lFileListHandle(a6),a0 ; get the list handle
move.l (a0),a0 ; get pointer
pea rView(a0) ; push the viewrect
_EraseRect ; erase old list
rts
DebuggerSymbol EraseFileList
;--------------------------------------------------------------------
;
; PROCEDURE DrawFileList;
;
; Draws the file list.
;
DrawFileList
_PenNormal ; want pen that is 1,1 <55.2, #79895>
pea lNRect(a6)
_FrameRect
tst.b lDontDrawList(a6)
bne.s @done
move.l visRgn(a3), -(sp) ; pass visible region
move.l lFileListHandle(a6),-(sp) ; point at the list
_LUpdate
; validate the list and scrollbars since we've just drawn 'em
move.l lFileListHandle(a6),a0 ; get the list handle
move.l (a0),a0 ; get pointer
pea rView(a0) ; push the viewrect
_ValidRect ; get rid of list update from treemenu
@done rts
DebuggerSymbol DrawFileList
;--------------------------------------------------------------------
;
; This gets called through the eject notify hook
; Notify( drive, caller: INTEGER ): BOOLEAN;
;
ejectHit
MOVE.L (SP)+,A1
MOVE (SP)+,D0 ; see who called
MOVE (SP)+,D1 ; get drive
ST (SP) ; return true (don't ever eject disk)
SUBQ #1,D0
BNE.S @0 ; => disk switch called us
MOVE.W D1,sfSaveDisk ; save disk to eject
NEG.W sfSaveDisk ; make negative (is normally positive)
SF (SP) ; return false
@0 JMP (A1) ; adios
DebuggerSymbol ejectHit
;------------------------------------------------------------
;
; SetUpButtons
;
; Sets the state of all buttons
;
SetUpButtons
bsr.s SetUpDeskTopButton
bsr.s SetUpEjectButton
bsr SetUpNewFolderButton
bsr SetUpOpenButton
@done rts
DebuggerSymbol SetUpButtons
;------------------------------------------------------------
;
; SetUpDeskTopButton
;
; disable desktop button if at desktop
;
SetUpDeskTopButton
tst.b lAtDesktop(A6) ; at the desktop?
sgt D3 ; set if so, dim it
move.l lMainDesktop(a6),a0
bsr DimButton ; set dim state
rts
DebuggerSymbol SetUpDeskTopButton
;------------------------------------------------------------
;
; SetUpEjectButton
;
; enable eject if current disk ejectable
; or desktop chosen and ejectable disk selected
;
SetUpEjectButton
TST.B lAtDesktop(A6) ; at the desktop?
BLE.S @notDesk ; br if not
ST D3 ; assume dimmed
BSR GetSel ; get selection in A0
BMI.S @dimEject ; br if no selection
btst #bNoEject,FileEntry.feFLPriv(a0)
sne d3
BRA.S @dimEject
@notDesk BSR CountDIPs ; find # disks
TST.W D3
SEQ D3
OR.B lNoEjects(A6),D3 ; if media says no, don't allow
@dimEject move.l lMainEject(a6),a0
bsr DimButton
rts
DebuggerSymbol SetUpEjectButton
;------------------------------------------------------------
;
; SetUpNewFolderButton
;
; disable desktop button if at desktop
;
SetUpNewFolderButton
tst.b lDoingGetFile(a6)
bne.s @done
move.b lPriv(A6),d0 ; get privs
and.b #mNoSearch+mNoWrite,d0 ; need write and search
sne d3 ; d3 = FF iff do not have (write and search)
cmp.w #sigWord,lSigWord(a6) ; is this an MFS disk? <41 ngk 17Sept90>
bne.s @1 ; <41 ngk 17Sept90>
st d3 ; if so, disable new folder button <41 ngk 17Sept90>
@1
move.l lMainNewFolder(a6),d0 ; see if there is a new folder button
beq.s @done
move.l d0,a0
bsr DimButton ; dim/enable based on d3
@done rts
DebuggerSymbol SetUpNewFolderButton
;------------------------------------------------------------------------------
;
; SetUpOpenButton
;
; The following table tries to organize the possible states of the system
; and how to set up the open button
;
;
;
; Put/Get ActiveItem Select CurPriv SelPriv TEempty DiskIn Title Enabled
; ------- ---------- ------ ------- ------- ------- ------ |---- -------
;
; Get FileList file xxx n.a. n.a. yes |alt yes
; Get FileList volume n.a. xxx n.a. yes |open yes
; Get FileList folder n.a. rd/src n.a. yes |open yes
; Get FileList folder n.a. ~rd~src n.a. yes |open no
; Get FileList none n.a. n.a. n.a. yes |alt no
; Get FileList dimmed n.a. n.a. n.a. yes |alt no
;
; Put FileList vl/fldr n.a. wr/src n.a. yes |open yes
; Put FileList vl/fldr n.a. ~wr~src n.a. yes |open no
; Put FileList file n.a. n.a. n.a. yes |??? ???
; Put FileList none wr/src n.a. no yes |alt yes
; Put FileList none wr/src n.a. yes yes |alt no
; Put FileList none ~wr~src n.a. n.a. yes |alt no
; Put FileList dimmed wr/src n.a. no yes |alt yes
; Put FileList dimmed wr/src n.a. yes yes |alt no
; Put FileList dimmed ~wr~src n.a. n.a. yes |alt no
; Put TE name n.a. wr/src n.a. no yes |alt yes
; Put TE name n.a. wr/src n.a. yes yes |alt no
;
;
; This boils down to the following equations:
;
; title is open := (FileList is target)
; & (volume or folder is selected)
; & (selection is not dimmed)
;
; button is enabled := (title = open) &
; ( (selection has search priv)
; & ( (putFile & (selection has write priv))
; | (getFile & (selection has read priv)) ) ) |
; ( (title = alt) &
; ( (getFile & (is selection) & (is not dimmed) )
; | (putFile & (~TEempty) & (cur priv has write and search) )) )
;
SetUpOpenButton
; first figure out whether the open button should say "open" or "save"
bsr GetSel ; get file entry into A0
move.l a0,a2 ; save in a2 for later use
bmi.s @notOpen ; branch if no selection
tst.b lListIsActive(a6) ; is File List the active item?
beq.s @notOpen ; branch if not
; moveq #sfItemFileListUser,d0
; bsr VirtualToRealItem
; cmp.w lActiveDITLitem(a6),d0 ; is File List the active item?
; bne.s @notOpen ; branch if not
btst #ioDirFlg,FileEntry.feFlAttr(a2) ; is it a folder or volume?
beq.s @notOpen ; branch if not
tst.b FileEntry.feFile.dimmed(a2) ; is it dimmed?
bne.s @notOpen ; branch if not
@isOpen tst.b lOpenState(a6)
beq.s @doneTitle ; button already correct
lea lOpenName(a6),a0
clr.b lOpenState(a6)
moveq #2,d0 ; control max for open button for balloon help
bra.s @changeTitle
@notOpen tst.b lOpenState(a6)
bne.s @doneTitle ; button already correct
lea lOpenAltName(a6),a0
st lOpenState(a6)
moveq #1,d0 ; control max for alt-open button for balloon help
@changeTitle
tst.b lOpenAltExists(a6) ; is there really an alternate name?
beq.s @doneTitle
move.l lMainOpen(a6),a1 ; lMainOpen can not be NIL if lOpenAltExists is true
move.l a1,-(sp) ; the open button control
move.l (a1),a1
move.w d0,contrlMax(a1) ; change control max value
move.l a0,-(sp) ; string to set title to
_SetCTitle
pea lOpenRect(a6) ; SetCTitle has side effect of inval'ing control rect
_ValidRect ; so undo that side effect
@doneTitle
; now figure out whether to dim or enable the open button
tst.b lOpenState(a6)
bne.s @altShown
@openShown move.l a2,a0 ; at this point we know there is a selection
btst #bOpenable,FileEntry.feFLPriv(a0) ; can selection be opened?
bne.s @disable ; branch if not
bra.s @enable
@altShown tst.b lDoingGetFile(a6) ; getFile always has altopen enabled
bne.s @altGet ; branch if it is
; test if TE is empty
tst.b lNewReply(a6) ; new call ?
beq.s @2 ; branch around if not
tst.b StandardFileReply.sfFile+FSSpec.name(a4) ; test length of typed name
beq.s @disable
bra.s @3
@2 tst.b SFReply.fName(a4) ; test length of typed name
beq.s @disable
; test privledges in current folder
@3 move.b lPriv(A6),d0 ; get privs
btst #bNoWrite,d0 ; need read and write to save
bne.s @disable
btst #bNoRead,d0
bne.s @disable
bra.s @enable
@altGet moveq #-1,d0
cmp.l d0,a2 ; see if there is a selection
beq.s @disable ; dim alt if no selection
tst.b FileEntry.feFile.dimmed(a2) ; see if selection is dimmed
bne.s @disable ; dim alt if selection is dimmed
@enable moveq #0,d3
bra.s @setOpen
@disable moveq #-1,d3
@setOpen move.l lMainOpen(a6),d0
beq.s @doneSetUp ; if control handle is NIL, then don't try to dim
move.l d0,a0
bsr.s DimButton ; set highlight state
@doneSetUp rts
DebuggerSymbol SetUpOpenButton
;------------------------------------------------------------
; a0 = handle to button control record
; if D3 is 0 then enable button in D0
; if D3 is FF then disable button in D0
;
DimButton move.l a0,-(sp) ; pass the button
move.w d3,-(sp)
clr.b (sp) ; clear high part
_HiliteControl
@done rts
DebuggerSymbol DimButton
;-------------------------------------------------------------------
;
; FillReplyRecord. Fill the return record.
;
; original reply records:
; getFile
; If no selections fName = 0 and fType = 0.
; If a file is selected, fName <> 0, and contains the file name.
; If a folder is selected, fName = 0 and fType <> 0, and contains the DirID.
; putFIle
; fName = whatever is in TE box
;
; new reply records:
; getFile:
; If no selection, sfFile.fileName = 0 and sfType = 0.
; If a file is selected, sfFile is correct FileSpec, sfType is file type
; If a folder or volume is selected, sfFile is correct FileSpec
; putFile:
; sfFile.vRefnum, sfFile+FSSpec.parID is current volume/folder in view
; sfFile.fileName = whatever is in TE box
; sfType = 0
;
; in: a4 = reply record
; trashes: d0,d1,d2,a0,a1
;
FillReplyRecord
tst.b lNewReply(a6) ; new call ?
beq @oldReply ; branch around if not
@newRply moveq #0,d0
move.w d0,StandardFileReply.sfGood(a4) ; clear good and replacing
move.b d0,StandardFileReply.sfFile+FSSpec.name(a4) ; remains 0 if no file selected
move.l d0,StandardFileReply.sfType(a4) ; default to 0
move.w d0,StandardFileReply.sfFlags(a4) ; zero out flags
move.b d0,StandardFileReply.sfIsFolder(a4) ; assume not a folder
move.b d0,StandardFileReply.sfIsVolume(a4) ; assume not a volume
move.l d0,StandardFileReply.sfReserved1(a4) ; always 0
move.w d0,StandardFileReply.sfReserved2(a4) ; always 0
move.w lVolRefNum(a6),StandardFileReply.sfFile+FSSpec.vRefNum(a4) ; default vRefNum
move.l lCurDir(a6),StandardFileReply.sfFile+FSSpec.parID(a4) ; default parID
tst.b lAtDesktop(a6) ; if at desktop, lCurDir is not a reliable default
ble.s @notDesk
move.w lDisplyedVolRef(a6),d0 ; get the volume to save on
move.w d0,StandardFileReply.sfFile+FSSpec.vRefNum(a4) ; get desktop for this vRefNum
bsr GetVolumeInfoPtr ; a0 (out) pointer to info
move.l PerVolumeInfo.desktopDir(a0),StandardFileReply.sfFile+FSSpec.parID(a4) ; desktop dirID
@notDesk
bsr GetSel ; get selection into A0
bmi.s @noSelection ; if none then done
move.w FileEntry.feVRefNum(a0),StandardFileReply.sfFile+FSSpec.vRefNum(a4) ; better vRefNum
move.l FileEntry.feParID(a0),StandardFileReply.sfFile+FSSpec.parID(a4) ; better parID
@noSelection
tst.b lDoingGetFile(a6)
beq.s @putFill
@getFill move.l a0,d0 ; if a0=-1 then no selection
bmi @done
tst.b FileEntry.feFile.dimmed(a0) ; don't fill out rest if item is dimmed (trash)
bne @done
move.w FileEntry.feFile.script(a0),StandardFileReply.sfScript(a4) ; get script
move.w FileEntry.feFndrFlags(a0),StandardFileReply.sfFlags(a4) ; get flags
btst #isAliasBit,FileEntry.feFndrFlags(a0) ; is it an alias?
bne.s @isFile ; then it must be a file (even though folder bit may be set)
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; is it a folder?
beq.s @isFile
@isFolder moveq #fsRtParID,d1 ; = 1
cmp.l FileEntry.feParID(a0),d1 ; is it a volume?
sne StandardFileReply.sfIsFolder(a4) ;
seq StandardFileReply.sfIsVolume(a4) ;
bra.s @getFillName
@isFile move.l FileEntry.feTypeOrDirID(a0),StandardFileReply.sfType(A4) ; get file type
@getFillName
lea FileEntry.feFile.text(a0),a0 ; a0 is source for blockmove
lea StandardFileReply.sfFile+FSSpec.name(a4),a1 ; a1 is destination for blockmove
bra @fillName
@putFill tst.b lAtDesktop(a6) ; if we are not at desktop then vol/dir is OK
ble.s @dirOK
move.w lDisplyedVolRef(a6),d0 ; d0 (in) vrefnum of disk
move.w d0,StandardFileReply.sfFile+FSSpec.vRefNum(a4) ; better vRefNum
bsr GetVolumeInfoPtr ; a0 (out) pointer to info
move.l PerVolumeInfo.desktopDir(a0),StandardFileReply.sfFile+FSSpec.parID(a4) ; better dirID
@dirOK bsr GetKeyScript
move.w d0,StandardFileReply.sfScript(a4) ; get script out of low word
; ### is this right? can keyboard script change after typing but before save hit?
moveq #sfItemFileNameTextEdit,d0 ; get the edit text item
bsr VirtualToRealItem
bsr GetIt
move.l lItem(a6),-(sp) ; push item handle
pea lString(a6) ; place to put name
_GetIText
lea lString(a6),a0 ; a0 is source for blockmove
lea StandardFileReply.sfFile+FSSpec.name(a4),a1 ; a1 is destination for blockmove
bra.s @fillName
@oldReply clr.w SFReply.good(a4) ; clear good and replacing
clr.b SFReply.fName(a4) ; remains 0 if no file selected
clr.l SFReply.fType(a4) ; remains 0 if no selection
tst.b lDoingGetFile(a6)
beq.s @oldPutFill
@oldGetFill bsr GetSel ; get selection into A0
bmi.s @done ; if none then done
move.w FileEntry.feVRefNum(a0),SFReply.vRefNum(a4) ; return volume (new for 7.0)
move.l FileEntry.feTypeOrDirID(a0),SFReply.fType(A4) ; return type or DirID
btst #isAliasBit,FileEntry.feFndrFlags(a0) ; is it an alias?
bne.s @oldName ; => yes, so just get name
btst #ioDirFlg,FileEntry.feFlAttr(a0) ; is it a folder?
beq.s @oldName ; => no, so fill in file name
moveq #fsRtParID,d0 ; = 1
cmp.l FileEntry.feParID(a0),d0 ; is it a volume?
bne.s @done ; if not, we're done
moveq #fsRtDirID,d0 ; = 2
move.l d0,SFReply.fType(A4) ; it is a volume use 2, instead of desktop folder
bra.s @done
@oldName lea FileEntry.feFile.text(a0),a0 ; point to name
lea SFReply.fName(a4),a1 ; a1 is destination for blockmove
bra.s @fillName
@oldPutFill moveq #sfItemFileNameTextEdit,d0 ; get the edit text item
bsr VirtualToRealItem
bsr GetIt
move.l lItem(a6),-(sp) ; push item handle
pea lString(a6) ; place to put name
_GetIText
lea lString(a6),a0 ; a0 is source for blockmove
lea SFReply.fName(a4),a1; a1 is destination for blockmove
@fillName moveq #31,d1 ; be conservative with make filename length
moveq #0,d0
move.b (a0),d0 ; get string length
cmp.l d1,d0 ; less than max?
ble.s @3
move.b d1,d0 ; no, trim to 31
move.b d0,(a0) ; stuff length
@3 addq.b #1,d0 ; allow for length byte itself
_BlockMove ; fill filename of reply
@done rts
DebuggerSymbol FillReplyRecord
;-------------------------------------------------------------------
;
; Set up the list. lBox(a6) is the bounding rect for the list.
;
SetUpList sub.l #16,sp ; a temporary rectangle
lea lNRect(a6),a0
move.l (a0),(sp)
move.l 4(a0),4(sp) ; copy the original file rect
sub.w #15,6(sp) ; lose 15 pixels for scroll bar
move.l sp,-(sp) ; point at temprect
move.l OneOne,-(sp) ; shrink 1, 1 for listmgr
_InsetRect
lea 8(sp), a0
clr.l (a0)+
clr.l (a0)+
move.l sp,a0 ; a0 points at temprect for lmgr
subq.l #4,sp ; space for list handle
move.l a0,-(sp) ; pass at rView
addq #8, a0
move.l a0, -(sp) ; pass data bounds
clr.l -(sp) ; empty size
move.w #-4000,-(sp) ; use default proc
move.l a3,-(sp) ; pass window pointer to ernie
st -(sp) ; draw it
sf -(sp) ; no grow
sf -(sp) ; no horizontal scroll
st -(sp) ; has vertscroll
_LNew
move.l (sp)+, a1 ; get ListHandle
move.l a1, lFileListHandle(a6) ; save away ListHandle
move.l (a1), a1
lea ClickHack, a0
move.l a0, lClikLoop(a1) ; set up our custom click proc
move.b #$FC,selFlags(a1) ; want single selection, but OK to select "empty" cells <ngk 20Nov89>
; This is because our "lengths" are bogus, so "empty" is bogus <ngk 20Nov89>
add.l #16,sp ; throw away rest of temprect
; initialize the indent to be h=iconPad,v=Font ascent
move.w lFontInfoRec.ascent(a6),indent+Point.v(a1)
move.w #iconPad-1,indent+Point.h(a1)
; if on a color machine with color graph port
; then put a ptr to an array of RGBColor's in usrHandle
btst #6,ROM85 ; do we have Color QD?
bne.s @doneColor
move.w portVersion(A3),d0
and.w #$C000,d0 ; are we using a color grafport?
beq.s @doneColor
moveq #1,d3
lea lIconColors(a6),a2
@nextColor subq #2,sp ; : OSErr
move.w d3,-(sp) ; labelNumber: INTEGER
move.l a2,-(sp) ; VAR labelColor: RGBColor
clr.l -(sp) ; VAR Str255: labelString
_GetLabel
tst.w (sp)+
bne.s @doneColor
addq #6,a2 ; SizeOf(RGBRec)
addq #1,d3
cmp.w #7,d3 ; only do colors 1 thru 7
ble.s @nextColor
move.l lFileListHandle(a6),a0
move.l (a0), a0
lea lIconColors(a6),a1
move.l a1,userHandle(a0) ; save ptr to color table in userHandle for LDEF to get to
bsr DumpList ; initialize bounds and visible
@doneColor
rts
DebuggerSymbol SetUpList
;-----------------------------------------------------------------------
; The hack allows user to deselect by dragging out of list
;
ClickHack movem.l a6/a3,-(sp)
move.l GrafGlobals(A5),A0
move.l thePort(A0),A0 ; get our stack frame
lea -lTheDialogRec(a0),a6
bsr.s GetSel ; get selection in A0, cell in d0
move.l d0,lLastSel(a6)
bmi.s @exit ; can do anything without selection
move.l lFileListHandle(a6), A3 ; get the list handle
move.l (A3), A3
move.l mouseLoc(a3),lPoint(a6)
subq #2,sp ; room for boolean result
move.l lPoint(a6),-(sp)
pea lNRect(a6)
_PtInRect ; is cursor still in file list box?
tst.b (sp)+
bne.s @exit
; cursor moved out of list rect
move.w visible+Rect.top(a3),d0
cmp.w dataBounds+Rect.top(a3),d0
beq.s @doneAutoscroll
move.w visible+Rect.bottom(a3),d0
cmp.w dataBounds+Rect.bottom(a3),d0
bne.s @exit
@doneAutoscroll
; cursor is out of list rec and done autoscrolling, so deselect
clr.w -(SP) ; deselect
move.l lLastSel(a6),-(SP) ; pass the last selected cell
move.l lFileListHandle(a6), -(sp) ; pass the list
_LSetSelect
moveq #-1,d0
move.l d0,lLastSel(a6) ; remember nothing is selected
@exit
movem.l (sp)+,a6/a3
MOVEQ #1, D0 ; never abort the click
RTS
DebuggerSymbol ClickHack
;------------------------------------------------------
; note: GetCellPtr and GetSel must be kept in sync
;
; GetCellPtr - get a pointer to the cell data
;
; d0 -> cell
; a0 <- ptr to cell data
;
GetCellPtr movem.l a3/a4,-(sp)
move.l d0,-(sp) ; fill tempcell with data
move.l lFileListHandle(a6),a4 ; pass list handle in a4
move.l sp,a3 ; pass ptr to cell in a3
bra.s GetData
;------------------------------------------------------
; GetSel -- get the current selection
;
; CCs - set minus if no selection
; a0 - points at selected item
; d0 - cell for selected item
GetSel movem.l a3/a4,-(sp)
move.l lFileListHandle(a6),a4 ; get list handle
clr.l -(sp) ; fill tempcell with data
move.l sp,a3 ; and save ptr to cell
subq #2, sp ; boolean result
st -(sp) ; find first selected cell
move.l a3,-(sp) ; VAR cell
move.l a4,-(sp) ; list handle
_LGetSelect
tst.b (sp)+ ; did we find somethings selected?
beq.s GSErrExit ; br if not, exit
; get a pointer to the cell data given a pointer to a cell in a3
GetData subq.l #4,sp ; 2 VAR INTs
move.l sp,-(sp) ; point at INT1
move.l (sp),-(sp)
addq.l #2,(sp) ; point at INT2
move.l (a3),-(sp) ; the cell from above
move.l a4,-(sp) ; list handle
_LFind
move.l (sp)+,d0 ; hi offset, lo length, kill 2 VARINTs
bmi.s GSErrExit ; skip out if couldn't find selected cell
swap d0 ; get offset for cell
move.l (a4),a0 ; list ptr deref
move.l Cells(a0),a0 ; cell handle
move.l (a0),a0 ; point at cellblock
add.w d0,a0 ; a0 points to data of cell
move.l (a3), d0 ; return cell found
bra.s GSExit
GSErrExit moveq #-1,d0 ; return failure with CCs set MINUS
move.l d0,a0
GSExit addq.l #4,sp ; remove cell from stack
movem.l (sp)+,a3/a4 ; restore regs
rts
DebuggerSymbol GetCellPtr
;-------------------------------------------------------------
;
; FixBoxes.
; A3 must contain window ptr for call to GetIt.
; The VolRect is the rect that contains the volume name
; The DirRect is the rect that contains the directory name and that gets
; mouse clicks for the pulldown menu.
; The ButRect contains the button frame and shadow for draw, inval, and erase
FixBoxes moveq #0,d0 ; default indent = 0
FixEdges move.w d0,-(sp) ; save indent
moveq #sfItemVolumeUser,d0; get the volume name/icon useritem
bsr VirtualToRealItem
bsr GetIt ; set up this item
move.w (sp)+,d0 ; get indent
move.l lBox+topLeft(a6),lVolRect+topLeft(a6)
move.l lBox+botRight(a6),lVolRect+botRight(a6) ; copy the item's rect
rts
DebuggerSymbol FixBoxes
;---------------------------------
;
; Inval volume icon and name.
;
InvalVol
pea lVolRect(a6)
_InvalRect
rts
DebuggerSymbol InvalVol
;---------------------------------
;
; Inval pop up menu area
;
InvalPopUp
pea lPopUpMaxRect(a6)
_InvalRect
rts
DebuggerSymbol InvalPopUp
;---------------------------------
;
; This is called after hookFirstCall but before the window is shown.
;
SF2Compatability
clr.b lVolumeSelect(a6)
tst.b lDoingGetFile(a6)
beq.s @setDrive
; set up user item for gray line between buttons
moveq #getGrayBar,D3 ; user field ID for grey line
bsr SetUserDraw ; install user draw proc
; ? this must be here for historical reasons ?
moveq #10,d0 ; set up the "ignored" prompt
move.l lPrompt(a6),a2 ; pointer to string
bsr SetItsText
; see if file list is off screen, in which case we go into volume select compatibility mode
moveq #getNmList,d3
bsr FindItem ; get file list boundary into -8(a0)
subq #2,sp ; room for result
move.l 4+Rect.topLeft(a0),-(sp) ; push top left of file list rect
pea portRect(a3) ; push boundary of dialog
_PtInRect
tst.b (sp)+
bne.s @setDrive ; if it is inside dialog then go on normally
st lVolumeSelect(a6) ; we are in that mode
bra @done
; Change drive button title to "desktop"
@setDrive MOVEQ #putDrive,D0 ; get drive button item
BSR GetIt
LEA lString(A6), A1
MOVEQ #sfDesktopName, D1
BSR GetLocalString
MOVE.L lItem(A6),-(SP) ; get the control
PEA lString(A6)
_SetCTitle
; make sure filelist and volume user items are enabled
moveq #putVolume,d3
bsr EnblItem ; enable volume Item
addq #4,Rect.left-8(a0) ; shrink the volume rect a bit to it does not overlap the file list halo
moveq #sfItemFileListUser,d0
bsr VIrtualToRealItem
move.w d0,d3
bsr EnblItem ; enable file list
; some apps have customized SF2 dialogs with added TE items. We need to
; add these to the standard list of activatble items, or they would be
; unacessable.
move.l lActiveList(a6),a0 ; copy standard list to buffer that can be append to
lea lActiveListBuf(a6),a1
move.l (a0)+,(a1) ; copy 6 bytes (getfile only needs 4, but whose counting)
move.w (a0)+,4(a1)
move.l a1,lActiveList(a6) ; switch pointer to point to buffer
move.b lKnownRealItems(a6),d3 ; start at end of standard items
move.l items(a3),a0 ; item list handle
move.l (a0),a0 ; ptr
move.w (a0),d2 ; get number of items-1
addq.w #1,d2 ; get number of items
@nextItem addq.w #1,d3 ; go to next item
cmp.w d3,d2 ; are we at end of items?
blt.s @doneExtraTEs
bsr FindItem ; in:d3, out: a0
btst #bEditText,12(a0) ; see if it is a TE item
beq.s @nextItem ; loop
addq.w #1,(a1) ; now have one more item
move.w (a1),d0 ; get how many count
add.w d0,d0 ; each element is a word (2 bytes)
move.w d3,(a1,d0.w) ; go to end and add this new one
bra.s @nextItem ; loop
@doneExtraTEs
; check if SF2 custom dialog has a help item in it. If so, force scan
; this way an app can continue to use SF2 and get help in 7.0 and run in 6.0
subq #2,sp ; room for integer result
move.l a3,-(sp) ; dialog ptr
_HMCountDITLHelpItems
tst.w (sp)+ ; get how many help items are in
ble.s @doneHelpCheck ; if error of no help items, go on
clr.w lHelpTemplate(a6) ; mark that have no template to force scan
@doneHelpCheck
@done rts
DebuggerSymbol SF2Compatability
;----------------------------------------------------------
;
; The dialog hack. This routine shuffles around items in the
; dialog, and the dialog itself, to make this StdFile behave
; nicely when being called by guys thinking they are calling
; the old StdFile.
;
SF1Compatability
; get list box boundary into lNRect(A6)
bsr GetFileListBoundary
; get change in size into d4, and default rect into temprect
moveq #0,d4
clr.l tempRect ; temprect topleft = 0,0
move.l #$0088015C,tempRect+4 ; temprect botRight = 136,348 (old getFile)
move.w lHeight(a6),d4 ; get height of button
add.w #6,d4 ; 3 for shadow, frame; 3 for spacing
tst.b lDoingGetFile(a6)
bne.s @ItemHack ; is get file...
add #88,d4 ; add room for file list (putfile)
move.l #$00680130,tempRect+4 ; temprect botright = 104,304 (old putFile)
; adjust the item list if necessary. Item list needs to be moved down if
; width of item 8 <> 1 (for putfile) or width of item 8 <> 16 (for getfile).
@ItemHack moveq #1,d5 ; get width of gray line for putfile
tst.b lDoingGetFile(a6) ; is putfile?
beq.s @0 ; => yes
moveq #16,d5 ; else get width of scrollbar
@0 moveq #8,d3 ; go get item 8 for width check
bsr FindItem ; get item into A0
move.w ItmRect+right(a0),d0 ; get the right
sub.w ItmRect+left(a0),d0 ; sub the left
moveq #0,d3 ; set default for PlaceIt
cmp.w d5,d0 ; is it an old ditl??
seq lOldDITL(a6) ; set flag for below
beq.s @1 ; => yes, go adjust things
move.w lHeight(a6),d4 ; else check for bigger font
sub.w #16,d4 ; what we expected? (get size difference in d4)
beq @doneMoving ; => yes, no need to move items around
@1 move.w lNRect+top(a6),d6 ; this is the top of file rect
move.l Items(a3),a0 ; handle to item list
move.l (a0),a0 ; deref
move.w (a0),d5 ; # items -1
moveq #1,d3 ; start with item 1
@2 bsr FindItem ; get pointer to item
tst.b lDoingGetFile(a6) ; context check?
beq.s @3 ; => it's putfile
cmp.w ItmRect+bottom(a0),d6 ; see if he's above me
bge.s @4 ; skip move if he's above me
@3 add d4,ItmRect+top(a0) ; add to top
add d4,ItmRect+bottom(a0) ; to offset the item
btst #2,ItmType(a0) ; is this a control?
beq.s @4 ; nope...
move.l ItmHndl(a0),-(sp) ; save the control handle
move.l ItmRect+topleft(a0),-(sp) ; move to new location
_MoveControl ; Move it
@4 addq #1,d3 ; next item
dbra d5,@2 ; shuffle them all
; tweak the list's rectangle. If an old dialog, make the list 16 pixels wider
; (because scrollbar internal to list now).
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
move.w d0,d3
bsr FindItem ; get the item
addq #ItmRect,a0 ; point to the rect for below
move.w lHeight(a6),d1 ; get height of cell for below
tst.b lOldDITL(a6) ; new item list?
beq.s @6 ; => yes, just adjust for fontsize
tst.b lDoingGetFile(a6) ; is putfile?
beq.s @5 ; => yes, don't need to grow list
add.w #16,right(a0) ; add 16 to the fileListItem.right
bra.s @6 ; => and resize the list, DLOG
; putFile: jam standard list at $18,$F,$6A,$E7
; the cell height is in d1. The standard cell height is d1-16, so make top,bottom 16 less in constants
@5 move.l #$0008000F,top(a0) ; top - 16, left
add.w d1,top(a0) ; bump top for button
move.l #$005A00E7,bottom(a0) ; bottom - 16, right
add.w d1,bottom(a0) ; bump bottom for button
; if the cells won't fit evenly into list, shrink the list
@6 move.w bottom(a0),d0 ; get bottom
sub.w top(a0),d0 ; get height
subq #2,d0 ; skip top, bottom lines
divu d1,d0 ; divide by cell height
swap d0 ; get remainder
sub.w d0,bottom(a0) ; shrink to next cell boundary
tst.b lOldDITL(a6) ; new item list?
beq.s @BumpDLOG ; => yes, just make DLOG bigger
; now we must resize the DLOG. If it is in app, or if in sys with new
; DLOG ID, use DLOG from DWindow. Else use the DLOG rect already in tempRect.
subq.l #6,sp ; make room for handle and resFile
move.l #'DLOG',-(sp) ; push the type
move.w lDlgID(a6),d3 ; get the dialog ID
move.w d3,-(sp) ; push the dialog ID
_GetResource ; get res handle onto stack
_HomeResFile ; where does it live?
move.w (sp)+,d0 ; get it
bne.s @BumpDLOG ; => not from sys file
cmp.w #putDlgID,d3 ; was it std putFile? <EHB 20-Oct-85>
beq.s @BDLOG ; => yes, it's ok <EHB 20-Oct-85>
cmp.w #getDlgID,d3 ; was it std getfile? <EHB 20-Oct-85>
beq.s @BDLOG ; => yes, it's ok <EHB 20-Oct-85>
@BumpDLOG move.l DWindow+PortRect+4(a3),TempRect+4 ; else use DLOG size
@BDLOG move.l d4,d3 ; make a copy for dialog rect delta
; Now temprect contains a rect that the caller thought he was putting
; up. This rect will be grown by d3, and the box needs to be re-centered
; on the screen after this operation.
move.l d3,d5
swap d5
add.l TempRect+4,d5
move.l a3,-(sp) ; first grow the window
move.l d5,-(sp) ; by this amount
st -(sp) ; updating necessary
_SizeWindow
; invalidate current edit field cause it was moved
move.w #-1,DWindow+editField(A3)
; get list box boundary into lNRect(A6) again, incase it moved.
bsr.s GetFileListBoundary
@doneMoving
rts
DebuggerSymbol SF1Compatability
GetFileListBoundary
moveq #sfItemFileListUser,d0
bsr VirtualToRealItem
bsr GetIt
lea lBox(a6),a0 ; point to box
move.l (a0)+,lNRect+topLeft(a6) ; stuff away the rectangle
move.l (a0)+,lNRect+botRight(a6) ; of the file list
rts
DebuggerSymbol GetFileListBoundary
; If we branched here from above, then there was a new DITL. We must assume that
; there is also a new DLOG. Users who specify new DITLs (as opposed to the system's
; new DITL) must also supply a new DLOG. At this point, the window will have that size.
;
; check is window (a3) is entirely on screen
; returns with CC set
;
MyCheckWindow
subq #2,sp ; room for boolean result
move.l a3,-(sp) ; whichWindow = theDialog
move.b #ccFrame,-(sp) ; checkControl = ccFrame
st -(sp) ; entirelyOnScreen = TRUE
_CheckWindow
tst.b (sp)+ ; is dialog entirely on screen?
rts
DebuggerSymbol MyCheckWindow
;
; make sure the dialog is entirely on screen
;
PositionSanityCheck
bsr.s MyCheckWindow
bne.s @done ; if so, then we are done
move.l A3,-(SP) ; pass the window
move.b #lcMainScreen,-(SP) ; over main monitor
move.b #hcCenter,-(SP) ; center horizontally
move.b #vcAlertCenter,-(SP); center vertically like an alert
_AutoPositionWindow
@done rts
DebuggerSymbol PositionSanityCheck
;-------------------------------------------------------------------
;
; Enable an item. Assumes a3 -> dialog record. d3 contains item #
; to enable. returns ptr to item in a0.
;
; FindItem2 assumes a0 is handle to items, d1 contains item# - 2
EnblItem
bsr.s FindItem
add.w #12,a0 ; right to the type
bclr #7,(a0) ; enable the item
rts
DebuggerSymbol EnblItem
FindItem move d3,d1
subq.w #2,d1 ; minor adjustment
move.l items(a3),a0 ; item list handle
FindItem2 move.l (a0),a0 ; ptr
addq.l #2,a0 ; skip item count
moveq #0,d0
tst.w d1
bmi.s @1
@0 add.w #13,a0 ; skip handle(4), rect(8), type(1)
move.b (a0)+,d0 ; get length of data
addq.b #1,d0
bclr #0,d0 ; round up length
add.w d0,a0 ; skip data
dbra d1,@0
@1 rts
DebuggerSymbol FindItem
;--------------------------------------------------------------------
;
; in: d0.w = vRefNum
;
; trashes d0-d2,a0-a1
;
SetVolumeIcon
; get volume name
lea lIOCmd(A6),A0 ; do some I/O
clr.w ioVolIndex(a0) ; lookup by vRefNum
move.w D0,ioVRefNum(A0) ; look on item's drive
pea lVolName+StyledString.text(A6) ; point to volume name
move.l (sp)+,ioVNPtr(A0) ; and set it up
_HGetVInfo ; get info about this drive
bne.s @exit
; see if it has changed
move.w ioVRefNum(a0),d0 ; pass vRefNum
cmp.w lDisplyedVolRef(a6),d0
beq.s @exit
move.w d0,lDisplyedVolRef(a6)
move.w ioVSigWord(a0),lSigWord(a6) ; update signature so we can tell we're on an MFS disk
; get volume icon
bsr.s getVolIcon ; set up the icon
move.w d0,lVolIcon(a6) ; save icon away for this disk
; set low mem globals to reflect new directory
move.w lDisplyedVolRef(a6),d0
move.w d0,SFSaveDisk ; update low-mem volume
neg.w SFSaveDisk ; want drive number, not vrefnum
tst.b lAtDesktop(a6) ; special case when at desktop, since there <55.5>
ble.s @inval ; are merged folders for each volume <55.5>
bsr.s GetVolumeInfoPtr ; a0 (out) pointer to info
move.l PerVolumeInfo.desktopDir(a0),d0
beq.s @inval ; just in case dirID not known yet <55.5>
move.l d0,CurDirStore ; update low-mem dirID <55.5>
; inval display
@inval bsr InvalVol
@exit rts
DebuggerSymbol SetVolumeIcon
;--------------------------------------------------------------------
; in: d0.w = vRefNum
; out: a0 = ^VolumeInfo, trashed d0
;
GetVolumeInfoPtr
neg.w d0 ; -1 -> 1
subq #1,d0 ; zero based
asl.w #3,d0 ; * SizeOf(PerVolumeInfo)
lea lVolumes(a6),a0
lea (a0,d0.w),a0
rts
DebuggerSymbol GetVolumeInfoPtr
;--------------------------------------------------------------------
; in: d0.w = vRefNum
; out: d0.w = iconID
;
GetVolIcon move.l a0,-(sp) ; don't trash a0
move.l VCBQHdr+2,a0 ; walk vcb queue
@nextVcb cmp.w vcbVRefNum(a0),d0
beq.s @gotVCB ; get driver refnum
move.l qLink(a0),d1
move.l d1,a0
bne.s @nextVcb
bra.s @default ; should never get here
@gotVCB move.w vcbDRefNum(a0),d0 ; get driver RefNum
addq #1,d0
neg.w d0 ; massage index
lsl.w #2,d0
move.l uTableBase,a0
move.l (a0,d0.w),a0 ; index into table
move.l (a0),a0 ; dereference handle
btst #6,dCtlFlags+1(a0) ; see if it is in RAM
move.l dCtlDriver(a0),a0 ; get driver start pointer
beq.s @havePtr ; check result of tst.w
move.l (a0),a0 ; RAM drivers need an extra dereference
@havePtr lea drvrName+2(a0),a0 ; skip length byte and initial period
move.w #floppyIconResource,d0
cmp.l #'Sony',(a0) ; .Sony means use floppy icon
beq.s @done
cmp.l #'NewA',(a0) ; .NewAge means use floppy icon <SM5> CSS
beq.s @done
move.w #genericFileServerIconResource,d0
cmp.l #'AFPT',(a0) ; .AFPTranslator means use fileserver icon
beq.s @done
@default move.w #genericHardDiskIconResource,d0 ; else use Hard disk icon
@done move.l (sp)+,a0
rts
DebuggerSymbol GetVolIcon
;---------------------------------------------------------------
;
; GetPopupIcon
; in: d1 = dirID of folder
; out: d0 = icon ID to use
GetPopupIcon
move.w #desktopIconResource, d0 ; assume it is the desktop icon
cmp.l lDeskDir(a6),d1 ; is this the desktop?
beq.s @exit ; br if so, got icon
move.w #trashIconResource, d0 ; assume it is the trash icon
cmp.l lTrashDir(a6),d1 ; is this the trash?
beq.s @exit ; br if so, got icon
move.w lVolIcon(a6),d0 ; use disk's icon
cmp.l #2,d1 ; is this root level?
beq.s @exit ; br if so, got icon
; otherwise it must be a folder
move.w #openFolderIconResource,d0; anything else is an open folde
@exit rts
DebuggerSymbol GetPopupIcon
;
;
ReBuildMenu
movem.l a2-a4,-(sp) ; save some regs
; a2 hold handle to array of dirIDs
; a3 holds pointer to IO param block
; a4 hold menu handle
; d5 is item index
; d6 is dirID
moveq #0, d6 ; assume no movement
subq #4, sp
move #sfPopUpMenuID, -(sp)
pea emptyString
_NewMenu
move.l (sp)+, d0
beq @noMenuExit
move.l d0, a4 ; keep menu in a4
moveq #0, d0
_NewHandle
bmi @noMenuExit
moveq #1,d5 ; keep menu item in d5
move.l lCurDir(a6),d6 ; keep current directory in d6
move.l a0, a2 ; keep dirID handle in a2
lea lIOCmd(a6), a3 ; keep param block in a3
move.w lVolRefNum(a6),ioVRefnum(a3) ; setup volume in param block
lea lString(a6),a1 ; setup name in param block
move.l a1,ioFileName(a3)
@nextDirectory
moveq #1, d0
cmp.l d0, d6 ; at root of root?
bne.s @dirOK
@atDesktop move.l lDeskDir(a6), d6 ; root of root is desktop
@dirOK cmp.l lDeskDir(a6), d6 ; is this the desktop?
bne.s @notDesktop ; br if not, check trash
moveq #sfDesktopName, D1 ; get desktop's name
bra.s @fillName ; fill item using name
@notDesktop cmp.l lTrashDir(a6), d6 ; is this the trash?
bne.s @notTrash ; br if not, it's a folder
moveq #sfTrashName, D1 ; get trash's name
@fillName lea lString(a6),a1 ; handy place to put name
bsr GetLocalString ; load string resource
bra.s @fillEntry ; fill entry using this name
@notTrash move.l d6,ioDirID(a3) ; for this directory
move #-1,ioFDirIndex(a3) ; lookup by dirID
move.l a3, a0
_GetCatInfo
bne.s @noDrawExit ; skip out on file system error jrm 01oct86
@fillEntry move d5, d0
asl #2, d0
move.l a2, a0
_SetHandleSize
bmi.s @noDrawExit
move.l (a2), a0
move d5, d0
asl #2, d0
move.l d6, -4(a0, d0.w) ; save away dirid for this item
move.l a4, -(sp)
pea emptyString
_AppendMenu ; add a menu item
@setMenuItem
move.l a4, -(sp)
move d5, -(sp)
pea lString(a6)
_SetItem
move.l d6, d1
bsr GetPopupIcon
@gotIcon
move.l a4, -(sp)
move d5, -(sp)
sub.w #genericIconBase,d0 ; start SF icons at 0 instead of genericIconBase
move.w d0,-(sp)
_SetItmIcon
move.l a4, -(sp)
move d5, -(sp)
move #$1A, -(sp) ; magic value for small icons
_SetItemCmd
cmp.l lDeskDir(a6),d6 ; is this the desktop?
beq.s @disposeExit ; br if so, we're done
addq #1, d5 ; add 1 to number of names
cmp.l lTrashDir(a6),d6 ; is this the trash?
beq @atDesktop ; br if so, next is desktop
move.l ioDrParID(a3),d6 ; next is parent folder
bra @nextDirectory
@noDrawExit
; ### I really don't know if inval is appropriate here
bsr InvalPopUp ; need to redraw PopUpMenuSymbol (this error handling needs to be looked at)
moveq #0, d6 ; no movement
@disposeExit
; swap in the new array of dirIDs
move.l lPopUpDirIDs(a6),d0
beq.s @storeNewDirs
move.l d0,a0
_DisposHandle
@storeNewDirs
move.l a2,lPopUpDirIDs(a6)
move.w d5,lPopUpDirCount(a6)
; swap the new menu into the menuHandle
move.l lPopUpControl(a6),a0
move.l (a0),a0
move.w #1,contrlValue(a0) ; we always want the top item "selected"
st contrlVis(a0) ; force it visible (it was initially hidden)
move.l contrlData(a0),a0
; <10> The following code was removed for change <9>, but shouldn<64>t have been. Since this code path is taken
; <10> every time the path popup changes, it needs to delete the old version of the menu from MenuList before
; <10> inserting the updated version. Otherwise, the _InsertMenu fails.
; <10>
; <10) So, this is exactly the same as the pre-<9> code. The first time this code is run, the popup CDEF will
; <10> already have called _DeleteMenu, removing its menu from the MenuList. Our _DeleteMenu is harmless and
; <10> does nothing in that case. However, since we, and not the CDEF, are now inserting the menu, the CDEF will
; <10> assume we own it and will never _DeleteMenu or _DisposMenu it. Because of this, we _DeleteMenu and _DisposMenu
; <10> every subsequent time through this code and once when we<77>re all done (see change <9>).
move.l a0,d5 ; save data handle <10> <68, #f2-ngk-001>
move.l (a0),a0 ; <10>
move.l CDEFpopUpData.theMenu(a0),d0 ; menuHandle is first long in control data <10>
beq.s @storeNewMenu ; <10>
move.l d0, -(sp) ; push for dispose the menu <10>
move.w #sfPopUpMenuID, -(sp) ; remove popup from menu list <10>
_DeleteMenu ; <10> harmless if not in the menu list
_DisposMenu ; d0 was pushed before delete <10>
@storeNewMenu ; <10>
move.l d5,a0 ; retrieve data handle <10>
move.l (a0),a0 ; dereference <68, #f2-ngk-001>
move.l a4,CDEFpopUpData.theMenu(a0) ; menuHandle is first long in control data
move.l a4, -(sp)
move #-1, -(sp) ; add a popup menu
_InsertMenu
@noMenuExit
movem.l (sp)+, a2-a4 ; restore regs
rts
DebuggerSymbol ReBuildMenu
;---------------------------------------------------------------
;
PopUpNewItem
move.l lPopUpControl(a6),a0
move.l (a0),a0
move.w contrlValue(a0),d0 ; get newly selected item # in pop up
cmp.w lPopUpDirCount(a6),d0 ; are we going to desktop?
beq.s @desktop
subq #1,d0 ; list is zero-based, menu is one-based
move.l lPopUpDirIDs(a6),a0
move.l (a0),a0
asl.w #2,d0 ; array of longs
move.l (a0,d0.w),d0 ; get dirID of newly selected item
bne.s @haveDir ; if zero then a volume with no desktop folder
@desktop tst.b lAtDesktop(a6) ; are we already at desktop?
bgt.s @done
bra caseGotoDesktop2 ; do same as pressing Desktop button
@haveDir cmp.l lCurDir(a6), d0 ; did the user change directories?
beq.s @done ; if not, don't recalc
move.l d0, lCurDir(a6) ; stuff new directory
st lPopUpLooksGood(a6)
bsr NewDirSelectFirstIfGetFile ; build and draw a new dir
@done rts
DebuggerSymbol PopUpNewItem
;-------------------------------------------------------------------
;
; DumpList empties our current list.
;
DumpList
move.l lFileListHandle(a6),D0
beq.s @done ; do nothing if no file list
move.l d0,A0 ; file list handle
move.l (A0),A0 ; data record pointer
lea databounds(A0),A1 ; say there's no data
clr.l (A1)+ ; topLeft = 0
clr.w (A1)+ ; bottom = 0
move.w #1,(A1) ; right = 1
lea visible(A0),A1 ; say there's no visible
clr.l (a1)+ ;
clr.l (a1)+
; the size of the data and array are reset by setHandleSize to new size
@done rts
DebuggerSymbol DumpList
;------------
; SetBounds -- use rView to determine the list's data and visible bounds.
; set visible top,left,bottom,right to 0,0,x,1
; x := (rview.bottom-rview.top)/cellsize.v
; Entry: D0 = # of cells in list
; A0 = pointer to data record
; Trashes: A1,D0,D1
SetBounds
LEA dataBounds(A0),A1 ; get bounds pointer
CLR.L (A1)+ ; top = left = 0
MOVE.W D0,(A1)+ ; bottom = # of cells
MOVE.W #1,(A1)+ ; bounds.right = 1
LEA visible(A0),A1 ; get visible pointer
CLR.L (A1)+ ; set vis top,left = 0
MOVE.W cellsize+v(A0),D1 ; get cellsize
MOVEQ #0,D0 ; division needs a long
ADD.W rView+bottom(A0),D0 ; add bottom
SUB.W rView+top(A0),D0 ; subtract top
ADD.W D1,D0 ; add cellsize.v
SUBQ #1,D0 ; and subtract 1
DIVU D1,D0 ; divide by cellsize.v
MOVE.W D0,(A1)+ ; and update visible bottom
MOVE.W #1,(A1) ; vis.right = 1
; set control max of scroll bar, don't use SetCtlMax because it will change display
; thumb. We will let LUpdate do that. This way scrollbar jumps once to new location
move.w dataBounds+bottom(A0),d0
sub.w visible+bottom(A0),d0
move.l vScroll(a0),a1
move.l (a1),a1
move.w d0,contrlMax(a1)
clr.w contrlValue(a1)
RTS
DebuggerSymbol SetBounds
;-------------------------------------------------------------------------------
; in: D0.W = key out: D0.W = BOOLEAN
;
; Given a keyCode, it handles arrow keys and returns true if it was one.
; Uses up and down arrow to move selection. If it is not visible, scroll to it.
; If there is no selection, get one (up arrow = bottom; dn arrow = top) and
; make it visible. Dimmed items are skipped over. If there are no selections,
; nothing happens. If there is only one selectable item, it remains selected.
;
;-------------------------------------------------------------------------------
ArrowKey MOVEM.L A4/D3-D5,-(SP) ; save regs
MOVE.L lFileListHandle(A6), A4 ; A4 = list handle
; handle arrow keys
MOVEQ #-1,D4 ; D4 = up direction offset
CMP.B #chUpArrow,D0 ; is it up arrow?
BEQ.S @gotArrow ; br if so, handle up arrow
MOVEQ #1,D4 ; D4 = down direction offset
CMP.B #chDownArrow,D0 ; is it down arrow?
BEQ.S @gotArrow ; br if so, handle down
CMP.B #chRightArrow,D0 ; is it right arrow?
BEQ.S @arrowExit ; br if so, eat key
CMP.B #chLeftArrow,D0 ; is it left arrow?
BEQ.S @arrowExit ; br if so, eat key
; handle paging keys
move.l lFileListHandle(a6),a1
move.l (a1),a0
move.w visible+top(a0),d3
sub.w visible+bottom(a0),d3 ; calculate the size of a page
cmp.b #chPageUp,d0
beq.s @scrollList
neg.w d3 ; page down by negative of pugUp value
cmp.b #chPageDown,d0
beq.s @scrollList
move.w #-2000,d3 ; scroll a very large amout to goto top
cmp.b #chHome,d0
beq.s @scrollList
neg.w d3 ; negate Home to goto end
cmp.b #chEnd,d0
bne.s @noArrowExit
@scrollList clr.w -(sp) ; col
move.w d3,-(sp) ; row
move.l a1,-(sp) ; list record
_LScroll
bra.s @arrowExit
@gotArrow MOVE.L (A4), A0
MOVE.W dataBounds+bottom(A0),D5; D5 = bounds.bottom
SUBQ #1,D5 ; D5 = last cell number
BSR GetSel ; get current selection
BMI.S @noSelection ; br if no selection
MOVE.L D0, D3 ; D3 = save current cell
SWAP D3 ; get column in low word
BRA.S @NextCell
; if no selections, move selection to top for down arrow, end for up arrow. If top/bottom
; not selected, search starting at end.
@NoSelection
MOVEQ #0,D3 ; assume go to top of list
TST.W D4 ; go to top of list?
BPL.S @DoSelect ; br if so, select top
MOVE.W D5,D3 ; else select bottom
BRA.S @DoSelect
; Scan the list, selecting the first non-dimmed cell in the right direction
@NextCell ADD.W D4,D3 ; at top?
BMI.S @arrowExit ; br is so, exit
CMP.W D3,D5 ; at bottom?
BLT.S @arrowExit ; br if so, exit
@DoSelect MOVE.L D3, D0
SWAP D0
BSR GetCellPtr
TST.B FileEntry.feFile.dimmed(A0) ; is it dimmed?
BNE.S @NextCell ; br if so, try next cell
sf d2 ; don't center selection with scrolling, just scroll by one
BSR SelectAndReveal ; select the cell in D3
@arrowExit
pea lTypeSelect(a6)
_TypeSelectClear ; clear type select buffer
MOVEQ #1, D0
BRA.S @exit
@noArrowExit
MOVEQ #0, D0
@exit
MOVEM.L (SP)+,A4/D3-D5 ; restore regs
RTS
DebuggerSymbol ArrowKey
;--------------------------------------------------------------
; PROCEDURE ShowSFBalloons; {Shows balloons that are specified by 'PACK' resources}
;
; Enter: A2 = pointer to any event (including NULL)
; A3 = Dialog ptr
; A6 = main stack frame
;
;
; local variables off of A4
sdrHelpMsg EQU -hmmHMSize
sdrHotRect EQU sdrHelpMsg-8
sdrTip EQU sdrHotRect-4
sdrMouse EQU sdrTip-4
sdrSize EQU sdrMouse
;
;
ShowSFBalloons
LINK A4,#sdrSize ; make a stack frame
MOVEM.L D0-D2/A0-A3,-(SP) ; save regs just in case some body cares
SUBQ #2,SP
_HMGetBalloons ; we're safe as this is 7.0 only
TST.B (SP)+
BEQ.S @exitSFBalloons ; ok, help wasn't on so let's exit
PEA sdrMouse(A4) ; a place to put the mouse point
_GetMouse ; go and get it
move.l lPopUpControl(a6),a0 ; get popup control
move.l (a0),a0
move.l contrlData(a0),a0 ; get control data handle
move.l (a0),a0
lea CDEFpopUpData.myCtlRect(a0),a2 ; current size rect is 6 bytes into control data
SUBQ.L #2,SP ; room for boolean
MOVE.L sdrMouse(A4),-(SP) ; push that mouse point
pea (a2) ; current size of menu
_PtInRect
TST.B (SP)+ ; was the mouse in dir Rect?
BEQ.S @WasntDirRect ; go now and check the Save button
MOVE.W #hsiPopUpMenu,D0 ; get the directory popup message
move.l a2,a0
BSR.S ShowSpecialBalloon ; go and show the balloon
BRA.S @exitSFBalloons ; time to exit
@WasntDirRect
move.w lHelpTemplate(a6),d0 ; new calls, and old ones with help items don't need scan
beq.s @exitClearly
SUBQ #2,SP
MOVE.W D0,-(SP) ; push the resource id of the dialog
MOVE.W #-1,-(SP) ; don't look in another resource ref num
; 'cuz we want resources to come from here (i.e. System)
MOVE.L #'hdlg',-(SP) ; scan our 'hdlg' resource for msgs
_HMScanTemplateItems
TST (SP)+ ; use result as flag
; BEQ.S ; *** someday
@exitClearly
CLR.B lBalloonUp(A6) ; so we get our special case balloons
@exitSFBalloons
MOVEM.L (SP)+,D0-D2/A0-A3 ; go restore the regs
UNLK A4
@dontCallHelp
RTS ; return to the bulk
DebuggerSymbol ShowSFBalloons
;
; ShowSpecialBalloon -
;
; Enter: A0 = -> to Hot Rect
; A4 = local stack frame
; A6 = standard file stack frame
; D0 = message number index (in STR#, res ID = rStandardFileHelpStringsID)
;
;
ShowSpecialBalloon
CMP.B lBalloonUp(A6),D0
BEQ.S @exitsdr
MOVE.B D0,lBalloonUp(A6) ; set our global saying we
; showed the help balloon
; A0 -> Hot Rect
MOVE.L topLeft(A0),sdrHotRect+topLeft(A4) ; copy the Hot Rect
MOVE.L botRight(A0),sdrHotRect+botRight(A4)
LEA sdrHelpMsg(A4),A0
MOVE #khmmStringRes,hmmHelpType(A0) ; we want to show a 'STR#' resource
MOVE #rStandardFileHelpStringsID,hmmHelpMessage(A0) ; of this res ID
MOVE D0,hmmHelpMessage+2(A0) ; and this index
MOVE.L sdrHotRect+botRight(A4),D0 ; make the tip the bottom right for now
MOVE.L D0,sdrTip(A4)
SUBQ.W #5,V+sdrTip(A4)
SUBQ.W #8,H+sdrTip(A4) ; move it up and left a bit
PEA sdrTip(A4) ; convert tip to global
_LocalToGlobal
PEA sdrHotRect+topLeft(A4) ; and the altrect to left
_LocalToGlobal
PEA sdrHotRect+botRight(A4) ; and the altrect bottom right
_LocalToGlobal
SUBQ #2,SP ; room for pack call result
PEA sdrHelpMsg(A4) ; push the help message
MOVE.L sdrTip(A4),-(SP) ; push the tip
PEA sdrHotRect(A4) ; push the altRect (also the hot rect)
CLR.L -(SP) ; no tipProc
CLR.L -(SP) ; 0 for proc and variant IDs
MOVE.W #kHMSaveBitsWindow,-(SP) ; save bits behind, AND generate update event
_HMShowBalloon ; call the package
MOVE (SP)+,D0 ; did we get a noErr result?
BEQ.S @exitsdr ; yes, just exit
@sdrUnsuccess
CLR.B lBalloonUp(A6) ; no, so clear the flag
@exitsdr
RTS
DebuggerSymbol ShowSpecialBalloon
ENDWITH
END ; of file