mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-11-19 06:30:59 +00:00
8405 lines
288 KiB
Plaintext
8405 lines
288 KiB
Plaintext
;
|
||
; Hacks to match MacOS (most recent first):
|
||
;
|
||
; <Sys7.1> 8/3/92 Reverted <SM5>
|
||
; 9/2/94 SuperMario ROM source dump (header preserved below)
|
||
;
|
||
|
||
;
|
||
; File: StandardFilePACK.a
|
||
;
|
||
; Contains: The Standard File package, PACK 3
|
||
;
|
||
; Written by: Steve Capps, Eric Ringewald, Ernst Beernink, John Meier, Nick Kledzik
|
||
;
|
||
; Copyright: © 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’t
|
||
; _DeleteMenu the old menu, then it stays in the list and
|
||
; _InsertMenu fails. The first time _DeleteMenu is called, it’s
|
||
; being called for the CDEF’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’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…)
|
||
; <7> 5/12/92 DTY #1028452: Make sure a volume is on line before seeing if it’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…>
|
||
; <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’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’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.≈ and system 6.0 has StandardFile2.≈
|
||
; 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 ‘StandardFile’ a ‘MAIN’ 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’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’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’s font
|
||
lSystemFontSize DS.W 1 ; cached system script’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’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’s already locked, don’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’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’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’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’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 ; ≠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 ; ≠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’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
|
||
; “next” disk, or “previous” 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’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… oh well.
|
||
|
||
VolumeIsInvisible
|
||
|
||
movem.l a0-a1/d1,-(sp)
|
||
|
||
; Is this a remote volume? (We always show remote volumes…)
|
||
|
||
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…
|
||
|
||
; 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… go check for invis. <2> FM
|
||
cmp.w #$4147,vcbFSID(A1) ; Is this a ISO volume? <2> FM
|
||
beq.s @skipInvisibleCheck ; yes… skip check <2> FM
|
||
cmp.w #$4242,vcbFSID(A1) ; well, is it High Sierra? <2> FM
|
||
beq.s @skipInvisibleCheck ; yes… skip check <2> FM
|
||
|
||
@noSpecialCaseCD ; <2> FM
|
||
lea lIOCmd(A6),A0 ; do some I/O
|
||
move.w vcbVRefNum(A1),d0 ; get volume refnum … <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… <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…
|
||
cmp.b lCmdKeyOptOpen(a6),d2 ; was it an option-Oh
|
||
beq @ReturnButton ; yes, lets go…
|
||
|
||
; 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…
|
||
|
||
; 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…
|
||
|
||
; 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…
|
||
|
||
move.w #sfHookGotoPrevDrive,d0
|
||
cmp.b #chLeftArrow,d2 ; was it left arrow?
|
||
beq.s @ActivateList ; yes, lets go…
|
||
|
||
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…
|
||
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…
|
||
;@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…
|
||
|
||
; 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.s @checkFileList ;<SM5> CSS <Sys7.1>
|
||
@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’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… <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’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] ≥ 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] ≤ 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 ≥ 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
|
||
; ex<SM5> <Sys7.1> Don't treat 'NewA' same as 'Sony'
|
||
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’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’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
|
||
|