mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-22 23:29:27 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
8399 lines
288 KiB
Plaintext
8399 lines
288 KiB
Plaintext
;
|
||
; 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 @checkFileList ;<SM5> CSS
|
||
@TEActivate
|
||
; switch to new item's text handle
|
||
move.l teHandle(a3),a0
|
||
move.l (a0),a1
|
||
move.l lItem(a6),teTextH(a1)
|
||
|
||
; switch TE's rects to new items's rect
|
||
lea teDestRect(a1),A0
|
||
move.l lBox(A6),(A0)+ ; set dest rect
|
||
move.l lBox+4(A6),(A0)+
|
||
tst.w TeSysJust
|
||
bmi.s @normBox ; don't make box wider in right-left scripts
|
||
add.w #100,teDestRect+Rect.right(a1) ; make dest rect wider to allow scrolling
|
||
@normBox move.l lBox(A6),(A0)+ ; set view rect
|
||
move.l lBox+4(A6),(A0)+
|
||
st teClikLoc(A1) ; remove double click possibility
|
||
|
||
; select all and TEActivate it, unless mouse is down (user is dragging)
|
||
clr.l -(sp) ; select from 0
|
||
move.w teLength(a1),d0
|
||
ext.l d0 ; d0 = length
|
||
move.l d0,-(sp)
|
||
subq #2,sp
|
||
_Button
|
||
tst.b (sp)+
|
||
beq.s @setIt
|
||
clr.l (sp) ; don't select, 'cause it would make a flicker
|
||
@setIt move.l teHandle(a3),-(sp) ; this TE
|
||
_TESetSelect
|
||
|
||
move.l teHandle(a3),-(sp)
|
||
_TECalText ; recalc stuff
|
||
|
||
move.l teHandle(a3),-(sp)
|
||
_TEActivate ; active the TE item
|
||
|
||
; mark dialog with which field is active
|
||
move.w 6(sp),d0
|
||
subq.w #1,d0
|
||
move.w d0,editField(a3)
|
||
|
||
; if this is putfile filename, then set <CR> mode
|
||
tst.b lDoingGetFile(a6) ; is it put file?
|
||
bne.s @TEdone
|
||
moveq #sfItemFileNameTextEdit,d0
|
||
bsr VirtualToRealItem
|
||
cmp.w 6(sp),d0 ; is it filename TE item?
|
||
bne.s @TEdone
|
||
move.l teHandle(a3),a0
|
||
move.l (a0),a0
|
||
moveq #-1,d0
|
||
move.w d0,teCROnly(a0) ; set TERec so that no implicit word wrap
|
||
@TEdone bra.s @doneMyStuff
|
||
|
||
@checkFileList
|
||
; see if the item being activated/deactivated is a list then do halo
|
||
moveq #sfItemFileListUser,d0
|
||
bsr VirtualToRealItem
|
||
cmp.w 6(sp),d0
|
||
bne.s @doneMyStuff
|
||
|
||
move.b 4(sp),d0 ; be paranoid (possible to miss activate events)
|
||
cmp.b lListIsActive(a6),d0 ; if I think it is already in this activate state
|
||
beq.s @doneMyStuff ; then do nothing
|
||
move.b d0,lListIsActive(a6) ; now remember new state
|
||
|
||
; draw the right halo
|
||
bsr DrawFileListHalo ; state to draw in d0
|
||
; select-deselect the selected item
|
||
tst.b 4(sp)
|
||
beq.s @deActList
|
||
; we are now activating the list, if there was an item selected, reselect it
|
||
move.l lLastSel(a6),d0
|
||
bmi.s @doneMyStuff
|
||
st -(sp)
|
||
bra.s @setSelect
|
||
|
||
; now know we are deactiving, so see if there is a selected item
|
||
@deActList bsr GetSel
|
||
move.l d0,lLastSel(a6)
|
||
bmi.s @doneMyStuff
|
||
; is a selected item, so save it off and deselect it
|
||
clr.b -(sp) ; set selected false
|
||
@setSelect move.l d0,-(sp) ; push the cell to deselect
|
||
move.l lFileListHandle(a6),-(sp)
|
||
_LSetSelect ; deselect the chosen cell
|
||
|
||
@doneMyStuff
|
||
; jump to apps proc to tell it what is happening
|
||
move.l lActivateProc(a6),A0 ; get ActivateProc Ptr in A0
|
||
move.l a0,d0
|
||
beq.s @noActvProc ; if NIL then donÕ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
|
||
cmp.l #'NewA',(a0) ; .NewAge means use floppy icon <SM5> CSS
|
||
beq.s @done
|
||
move.w #genericFileServerIconResource,d0
|
||
cmp.l #'AFPT',(a0) ; .AFPTranslator means use fileserver icon
|
||
beq.s @done
|
||
@default move.w #genericHardDiskIconResource,d0 ; else use Hard disk icon
|
||
@done move.l (sp)+,a0
|
||
rts
|
||
DebuggerSymbol GetVolIcon
|
||
|
||
|
||
;---------------------------------------------------------------
|
||
;
|
||
; GetPopupIcon
|
||
; in: d1 = dirID of folder
|
||
; out: d0 = icon ID to use
|
||
GetPopupIcon
|
||
move.w #desktopIconResource, d0 ; assume it is the desktop icon
|
||
cmp.l lDeskDir(a6),d1 ; is this the desktop?
|
||
beq.s @exit ; br if so, got icon
|
||
|
||
move.w #trashIconResource, d0 ; assume it is the trash icon
|
||
cmp.l lTrashDir(a6),d1 ; is this the trash?
|
||
beq.s @exit ; br if so, got icon
|
||
|
||
move.w lVolIcon(a6),d0 ; use disk's icon
|
||
cmp.l #2,d1 ; is this root level?
|
||
beq.s @exit ; br if so, got icon
|
||
|
||
; otherwise it must be a folder
|
||
move.w #openFolderIconResource,d0; anything else is an open folde
|
||
@exit rts
|
||
DebuggerSymbol GetPopupIcon
|
||
|
||
|
||
|
||
|
||
;
|
||
;
|
||
ReBuildMenu
|
||
movem.l a2-a4,-(sp) ; save some regs
|
||
; a2 hold handle to array of dirIDs
|
||
; a3 holds pointer to IO param block
|
||
; a4 hold menu handle
|
||
; d5 is item index
|
||
; d6 is dirID
|
||
moveq #0, d6 ; assume no movement
|
||
|
||
subq #4, sp
|
||
move #sfPopUpMenuID, -(sp)
|
||
pea emptyString
|
||
_NewMenu
|
||
move.l (sp)+, d0
|
||
beq @noMenuExit
|
||
move.l d0, a4 ; keep menu in a4
|
||
|
||
moveq #0, d0
|
||
_NewHandle
|
||
bmi @noMenuExit
|
||
|
||
moveq #1,d5 ; keep menu item in d5
|
||
move.l lCurDir(a6),d6 ; keep current directory in d6
|
||
|
||
move.l a0, a2 ; keep dirID handle in a2
|
||
lea lIOCmd(a6), a3 ; keep param block in a3
|
||
|
||
move.w lVolRefNum(a6),ioVRefnum(a3) ; setup volume in param block
|
||
lea lString(a6),a1 ; setup name in param block
|
||
move.l a1,ioFileName(a3)
|
||
|
||
@nextDirectory
|
||
moveq #1, d0
|
||
cmp.l d0, d6 ; at root of root?
|
||
bne.s @dirOK
|
||
@atDesktop move.l lDeskDir(a6), d6 ; root of root is desktop
|
||
|
||
@dirOK cmp.l lDeskDir(a6), d6 ; is this the desktop?
|
||
bne.s @notDesktop ; br if not, check trash
|
||
|
||
moveq #sfDesktopName, D1 ; get desktop's name
|
||
bra.s @fillName ; fill item using name
|
||
|
||
@notDesktop cmp.l lTrashDir(a6), d6 ; is this the trash?
|
||
bne.s @notTrash ; br if not, it's a folder
|
||
|
||
moveq #sfTrashName, D1 ; get trash's name
|
||
|
||
@fillName lea lString(a6),a1 ; handy place to put name
|
||
bsr GetLocalString ; load string resource
|
||
bra.s @fillEntry ; fill entry using this name
|
||
|
||
@notTrash move.l d6,ioDirID(a3) ; for this directory
|
||
move #-1,ioFDirIndex(a3) ; lookup by dirID
|
||
move.l a3, a0
|
||
_GetCatInfo
|
||
bne.s @noDrawExit ; skip out on file system error jrm 01oct86
|
||
|
||
@fillEntry move d5, d0
|
||
asl #2, d0
|
||
move.l a2, a0
|
||
_SetHandleSize
|
||
bmi.s @noDrawExit
|
||
|
||
move.l (a2), a0
|
||
move d5, d0
|
||
asl #2, d0
|
||
move.l d6, -4(a0, d0.w) ; save away dirid for this item
|
||
|
||
move.l a4, -(sp)
|
||
pea emptyString
|
||
_AppendMenu ; add a menu item
|
||
|
||
@setMenuItem
|
||
move.l a4, -(sp)
|
||
move d5, -(sp)
|
||
pea lString(a6)
|
||
_SetItem
|
||
|
||
move.l d6, d1
|
||
bsr GetPopupIcon
|
||
|
||
@gotIcon
|
||
move.l a4, -(sp)
|
||
move d5, -(sp)
|
||
sub.w #genericIconBase,d0 ; start SF icons at 0 instead of genericIconBase
|
||
move.w d0,-(sp)
|
||
_SetItmIcon
|
||
|
||
move.l a4, -(sp)
|
||
move d5, -(sp)
|
||
move #$1A, -(sp) ; magic value for small icons
|
||
_SetItemCmd
|
||
|
||
cmp.l lDeskDir(a6),d6 ; is this the desktop?
|
||
beq.s @disposeExit ; br if so, we're done
|
||
|
||
addq #1, d5 ; add 1 to number of names
|
||
|
||
cmp.l lTrashDir(a6),d6 ; is this the trash?
|
||
beq @atDesktop ; br if so, next is desktop
|
||
|
||
move.l ioDrParID(a3),d6 ; next is parent folder
|
||
bra @nextDirectory
|
||
|
||
@noDrawExit
|
||
; ### I really don't know if inval is appropriate here
|
||
bsr InvalPopUp ; need to redraw PopUpMenuSymbol (this error handling needs to be looked at)
|
||
moveq #0, d6 ; no movement
|
||
|
||
@disposeExit
|
||
; swap in the new array of dirIDs
|
||
move.l lPopUpDirIDs(a6),d0
|
||
beq.s @storeNewDirs
|
||
move.l d0,a0
|
||
_DisposHandle
|
||
@storeNewDirs
|
||
move.l a2,lPopUpDirIDs(a6)
|
||
move.w d5,lPopUpDirCount(a6)
|
||
|
||
; swap the new menu into the menuHandle
|
||
move.l lPopUpControl(a6),a0
|
||
move.l (a0),a0
|
||
move.w #1,contrlValue(a0) ; we always want the top item "selected"
|
||
st contrlVis(a0) ; force it visible (it was initially hidden)
|
||
move.l contrlData(a0),a0
|
||
|
||
; <10> The following code was removed for change <9>, but shouldnÕ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
|
||
|