mirror of
https://github.com/ctm/executor.git
synced 2024-06-10 10:29:31 +00:00
2762 lines
70 KiB
C
2762 lines
70 KiB
C
/*
|
|
* NOTE: currently we only do an automount when crossing a filesystem.
|
|
* This is might be bad: currently we're seeing an error when
|
|
* we try to open "/tmp" on roland, because 4 has already been
|
|
* specified as "/Net" from iclone. I'm really not convinced
|
|
* that the proper solution is to do an automount, though.
|
|
*/
|
|
|
|
/* Copyright 1987 - 1997 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_stdfile[] =
|
|
"$Id: stdfile.c 120 2005-07-14 21:20:19Z ctm $";
|
|
#endif
|
|
|
|
/* Forward declarations in StdFilePkg.h (DO NOT DELETE THIS LINE) */
|
|
|
|
#include "rsys/common.h"
|
|
|
|
#if defined (LINUX)
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/cdrom.h>
|
|
#endif
|
|
|
|
#include "DialogMgr.h"
|
|
#include "FileMgr.h"
|
|
#include "EventMgr.h"
|
|
#include "StdFilePkg.h"
|
|
#include "ControlMgr.h"
|
|
#include "MenuMgr.h"
|
|
#include "ResourceMgr.h"
|
|
#include "ToolboxEvent.h"
|
|
#include "ToolboxUtil.h"
|
|
#include "MemoryMgr.h"
|
|
#include "OSUtil.h"
|
|
#include "ScriptMgr.h"
|
|
|
|
#include "rsys/cquick.h"
|
|
#include "rsys/wind.h"
|
|
#include "rsys/hfs.h"
|
|
#include "rsys/file.h"
|
|
#include "rsys/stdfile.h"
|
|
#include "rsys/arrowkeys.h"
|
|
#include "rsys/glue.h"
|
|
#include "rsys/resource.h"
|
|
#include "rsys/pstuff.h"
|
|
#include "rsys/hfs.h"
|
|
#include "rsys/time.h"
|
|
#include "rsys/flags.h"
|
|
#include "rsys/tempalloc.h"
|
|
#include "rsys/hook.h"
|
|
#include "rsys/toolevent.h"
|
|
#include "rsys/string.h"
|
|
#include "rsys/dcache.h"
|
|
#include "rsys/menu.h"
|
|
|
|
#include "rsys/executor.h"
|
|
|
|
#include "rsys/osevent.h"
|
|
|
|
PUBLIC int nodrivesearch_p = FALSE;
|
|
|
|
#if defined (MSDOS) || defined (CYGWIN32)
|
|
#include "dosdisk.h"
|
|
#include "aspi.h"
|
|
#include "rsys/checkpoint.h"
|
|
#endif
|
|
|
|
#include "rsys/print.h"
|
|
#include "rsys/system_error.h"
|
|
|
|
typedef union
|
|
{
|
|
SFReply *oreplyp;
|
|
StandardFileReply *nreplyp;
|
|
}
|
|
reply_u;
|
|
|
|
typedef union
|
|
{
|
|
ProcPtr oflfilef;
|
|
FileFilterYDProcPtr cflfilef;
|
|
}
|
|
file_filter_u;
|
|
|
|
typedef union
|
|
{
|
|
ProcPtr ofilterp;
|
|
ModalFilterYDProcPtr cfilterp;
|
|
}
|
|
filter_u;
|
|
|
|
typedef union
|
|
{
|
|
ProcPtr odh;
|
|
DlgHookYDProcPtr cdh;
|
|
}
|
|
dialog_hook_u;
|
|
|
|
typedef struct {
|
|
sf_flavor_t flavor;
|
|
reply_u flreplyp;
|
|
ControlHandle flsh;
|
|
INTEGER flnmfil;
|
|
INTEGER flnmlin;
|
|
INTEGER fllinht;
|
|
INTEGER flascent;
|
|
INTEGER flsel;
|
|
Rect flrect;
|
|
Rect flcurdirrect;
|
|
struct flinfostr {
|
|
INTEGER floffs;
|
|
INTEGER flicns;
|
|
} **flinfo;
|
|
char **flstrs;
|
|
file_filter_u flfilef;
|
|
INTEGER flnumt;
|
|
OSType * fltl;
|
|
ControlHandle flch;
|
|
INTEGER flgraynondirs;
|
|
Str255 flcurdirname;
|
|
filter_u magicfp;
|
|
INTEGER fl_cancel_item;
|
|
UNIV Ptr mydata;
|
|
} fltype;
|
|
|
|
A1(PRIVATE, INTEGER, movealert, INTEGER, id)
|
|
{
|
|
Handle h;
|
|
INTEGER dh, dv;
|
|
Rect *rp;
|
|
|
|
h = GetResource(TICK("ALRT"), id);
|
|
if (!(*h).p)
|
|
LoadResource(h);
|
|
rp = (Rect *) STARH(h);
|
|
dh = CW(rp->right) - CW(rp->left);
|
|
dv = CW(rp->bottom) - CW(rp->top);
|
|
rp->left = CWC(150);
|
|
rp->top = CWC(30);
|
|
rp->right = CW(150 + dh);
|
|
rp->bottom = CW(30 + dv);
|
|
return(Alert(id, (ProcPtr)0));
|
|
}
|
|
|
|
#define SICONS -15744
|
|
|
|
A1(PRIVATE, void, drawminiicon, INTEGER, icon)
|
|
{
|
|
Handle h;
|
|
BitMap bm;
|
|
Rect r;
|
|
|
|
h = ROMlib_getrestid(TICK("SICN"), SICONS);
|
|
if (!h)
|
|
/*-->*/ return; /* badness */
|
|
HLock(h);
|
|
bm.baseAddr = RM((Ptr) STARH(h) + icon * 16 * 16 / 8);
|
|
bm.rowBytes = CWC(2);
|
|
bm.bounds.left = bm.bounds.top = CWC(0);
|
|
bm.bounds.right = bm.bounds.bottom = CWC(16);
|
|
r.top = PORT_PEN_LOC (thePort).v;
|
|
r.left = PORT_PEN_LOC (thePort).h;
|
|
r.bottom = CW(CW(r.top) + 16);
|
|
r.right = CW(CW(r.left) + 16);
|
|
CopyBits(&bm, PORT_BITS_FOR_COPY (thePort),
|
|
&bm.bounds, &r, srcCopy, NULL);
|
|
HUnlock(h);
|
|
}
|
|
|
|
/*
|
|
* NOTE: the Rect pointed to below has a normal top, left and right,
|
|
* BUT the bottom is the amount to add to the top for drawing
|
|
* text, not the real bottom.
|
|
*/
|
|
|
|
A3(PRIVATE, void, drawinboxwithicon, StringPtr, str, Rect *, rp, INTEGER, icon)
|
|
{
|
|
Rect r;
|
|
INTEGER width, strlen, strwidths[255], lengthavail, *widp;
|
|
static char *ellipsis = "\003...";
|
|
|
|
/*
|
|
* Note: the ellipsis code is a bit shabby, not truncating at a character
|
|
* boundary, nor leaving space on either side, but for now, it's
|
|
* ok.
|
|
*/
|
|
|
|
MoveTo(CW(rp->left) + 2, CW(rp->top));
|
|
drawminiicon(icon);
|
|
MoveTo(CW(rp->left) + 2 + 16 + 3 , CW(rp->top) + CW(rp->bottom)-1); /* see note above */
|
|
r.left = rp->left;
|
|
r.right = rp->right;
|
|
r.top = rp->top;
|
|
r.bottom = CWC(32766);
|
|
ClipRect(&r);
|
|
strlen = *str;
|
|
MeasureText(strlen, (Ptr) (str + 1), (Ptr) strwidths);
|
|
lengthavail = CW(rp->right) - (CW(rp->left) + 2 + 16 + 3);
|
|
if (CW(strwidths[strlen]) > lengthavail) {
|
|
width = StringWidth((StringPtr) ellipsis);
|
|
/* 4 might be the space on the right of the ellipsis. */
|
|
/* TODO: figure out exactly what the number is. */
|
|
lengthavail -= (width + 4);
|
|
widp = strwidths;
|
|
while (CW(*++widp) < lengthavail)
|
|
DrawChar(*++str);
|
|
DrawString((StringPtr) ellipsis);
|
|
} else
|
|
DrawString(str);
|
|
r.top = CWC(-32767);
|
|
r.left = CWC(-32767);
|
|
r.right = CWC(32766);
|
|
ClipRect(&r);
|
|
}
|
|
|
|
A2(PRIVATE, void, safeflflip, fltype *, f, INTEGER, sel)
|
|
{
|
|
Rect r;
|
|
INTEGER fltop = GetCtlValue(f->flsh);
|
|
|
|
if (sel >= fltop && sel < fltop + f->flnmlin) {
|
|
r.left = f->flrect.left;
|
|
r.right = f->flrect.right;
|
|
r.top = CW(CW(f->flrect.top) + (sel - fltop) * f->fllinht);
|
|
r.bottom = CW(CW(r.top) + f->fllinht);
|
|
if (EmptyRgn(MR(((WindowPeek)thePort)->updateRgn))) /* stuff to draw? */
|
|
InvertRect(&r); /* no: we can flip */
|
|
else
|
|
InvalRect(&r); /* yes: flip later */
|
|
}
|
|
}
|
|
|
|
#define GRAYBIT (1 << 5 )
|
|
#define ICONMASK (~GRAYBIT)
|
|
|
|
A3(PRIVATE, void, flupdate, fltype *, f, INTEGER, st, INTEGER, n)
|
|
{
|
|
INTEGER i;
|
|
struct flinfostr *ip;
|
|
INTEGER sel = f->flsel;
|
|
INTEGER fltop;
|
|
Rect r;
|
|
|
|
fltop = GetCtlValue(f->flsh);
|
|
r.top = CW(CW(f->flrect.top) + (st - fltop) * f->fllinht);
|
|
r.bottom = CW(f->flascent);
|
|
r.left = f->flrect.left;
|
|
r.right = f->flrect.right;
|
|
|
|
ip = MR(*f->flinfo) + st;
|
|
HLock((Handle) f->flstrs);
|
|
for (i = st; i < st + n && i < fltop + f->flnmlin && i < f->flnmfil; i++) {
|
|
drawinboxwithicon((StringPtr) (MR(*f->flstrs) + ip->floffs), &r,
|
|
ip->flicns & ICONMASK);
|
|
if (ip->flicns & GRAYBIT) {
|
|
r.bottom = CW(CW(r.top) + f->fllinht);
|
|
PenMode(notPatBic);
|
|
PenPat(gray);
|
|
PaintRect(&r);
|
|
PenPat(black);
|
|
PenMode(patCopy);
|
|
r.bottom = CW(f->flascent);
|
|
}
|
|
ip++;
|
|
r.top = CW(CW(r.top) + (f->fllinht));
|
|
}
|
|
HUnlock((Handle) f->flstrs);
|
|
if (sel >= st && sel < st + n)
|
|
safeflflip(f, sel);
|
|
}
|
|
|
|
A3(PRIVATE, void, flscroll, fltype *, f, INTEGER, from, INTEGER, to)
|
|
{
|
|
RgnHandle rh;
|
|
INTEGER toscroll;
|
|
|
|
if (from != to) {
|
|
rh = NewRgn();
|
|
ScrollRect(&f->flrect, 0, (from - to) * f->fllinht, rh);
|
|
if (to > from) {
|
|
toscroll = to - from;
|
|
if (toscroll >= f->flnmlin)
|
|
flupdate(f, to, f->flnmlin);
|
|
else
|
|
flupdate(f, from+f->flnmlin, toscroll);
|
|
} else {
|
|
toscroll = from - to;
|
|
if (toscroll > f->flnmlin)
|
|
toscroll = f->flnmlin;
|
|
flupdate(f, to, toscroll);
|
|
}
|
|
DisposeRgn(rh);
|
|
}
|
|
}
|
|
|
|
#define CTLFL(sh) \
|
|
((fltype *)(long) MR(MR((WindowPeek)STARH((sh))->contrlOwner)->refCon))
|
|
|
|
/*
|
|
* this hack is necessary because Excel 4 can bring up a dialog on top of
|
|
* stdfile at a time when the refcon has been set to 'stdf'.
|
|
*/
|
|
|
|
static LONGINT emergency_save_ref_con;
|
|
|
|
PRIVATE fltype *
|
|
WINDFL (void *dp)
|
|
{
|
|
fltype *retval;
|
|
|
|
retval = (fltype *) (long) ((WindowPeek)dp)->refCon;
|
|
if ((long) retval == CLC ((long) TICK("stdf")))
|
|
retval = (fltype *) SYN68K_TO_US (emergency_save_ref_con);
|
|
else
|
|
retval = MR (retval);
|
|
return retval;
|
|
}
|
|
|
|
#if 0
|
|
#define WINDFL(dp) \
|
|
((fltype *)(long) MR(((WindowPeek)dp)->refCon))
|
|
#endif
|
|
|
|
P2 (PUBLIC, pascal void, ROMlib_stdftrack, ControlHandle, sh, INTEGER, part)
|
|
{
|
|
const uint32 min_between_scroll_msecs = 100;
|
|
static uint32 last_scroll_msecs;
|
|
uint32 current_msecs;
|
|
int16 from, pg;
|
|
|
|
current_msecs = msecs_elapsed ();
|
|
|
|
if (current_msecs - min_between_scroll_msecs < last_scroll_msecs)
|
|
return;
|
|
else
|
|
last_scroll_msecs = current_msecs;
|
|
|
|
from = GetCtlValue (sh);
|
|
pg = CTLFL(sh)->flnmlin - 1;
|
|
switch (part)
|
|
{
|
|
case inUpButton:
|
|
SetCtlValue(sh, from-1);
|
|
break;
|
|
case inDownButton:
|
|
SetCtlValue(sh, from+1);
|
|
break;
|
|
case inPageUp:
|
|
SetCtlValue(sh, from-pg);
|
|
break;
|
|
case inPageDown:
|
|
SetCtlValue(sh, from+pg);
|
|
break;
|
|
}
|
|
flscroll (CTLFL (sh), from, GetCtlValue (sh));
|
|
}
|
|
|
|
PRIVATE INTEGER cachedvrn = 32767;
|
|
PRIVATE INTEGER savesel = -1;
|
|
PRIVATE LONGINT oldticks = -1000;
|
|
PRIVATE LONGINT lastkeydowntime = 0;
|
|
PRIVATE Str255 prefix = { 0 };
|
|
PRIVATE char **holdstr;
|
|
|
|
PUBLIC void ROMlib_init_stdfile(void)
|
|
{
|
|
cachedvrn = 32767;
|
|
savesel = -1;
|
|
oldticks = -1000;
|
|
lastkeydowntime = 0;
|
|
prefix[0] = 0;
|
|
holdstr = 0;
|
|
}
|
|
|
|
A2(PRIVATE, StringPtr, getdiskname, BOOLEAN *, ejectablep,
|
|
boolean_t *, writablep)
|
|
{
|
|
static BOOLEAN ejectable;
|
|
static boolean_t writable;
|
|
static Str255 retval;
|
|
ParamBlockRec pbr;
|
|
|
|
if (SFSaveDisk != cachedvrn) {
|
|
OSErr err;
|
|
|
|
pbr.volumeParam.ioNamePtr = RM(&retval[0]);
|
|
pbr.volumeParam.ioVolIndex = 0;
|
|
pbr.volumeParam.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
err = PBGetVInfo(&pbr, FALSE);
|
|
cachedvrn = SFSaveDisk;
|
|
if (err == noErr)
|
|
{
|
|
ejectable = !(pbr.volumeParam.ioVAtrb & CWC(VNONEJECTABLEBIT));
|
|
writable = !(pbr.volumeParam.ioVAtrb &
|
|
CWC(VHARDLOCKBIT|VSOFTLOCKBIT));
|
|
if (writable && pbr.volumeParam.ioVFrBlk == 0)
|
|
writable = FALSE;
|
|
}
|
|
else
|
|
{
|
|
warning_unexpected ("surprising PBGetVInfo retval = %d\n", err);
|
|
ejectable = FALSE;
|
|
writable = TRUE;
|
|
}
|
|
}
|
|
if (ejectablep)
|
|
*ejectablep = ejectable;
|
|
if (writablep)
|
|
*writablep = writable;
|
|
return retval;
|
|
}
|
|
|
|
A1(PRIVATE, void, drawjobberattop, DialogPeek, dp)
|
|
{
|
|
INTEGER icon;
|
|
Rect *rp;
|
|
fltype *flp;
|
|
INTEGER savebottom;
|
|
BOOLEAN ejectable;
|
|
PenState ps;
|
|
|
|
GetPenState(&ps);
|
|
PenNormal();
|
|
if (CL(CurDirStore) == 2) {
|
|
#if 1
|
|
/* TODO: ask cliff about a better way to do this */
|
|
/* unused = */ getdiskname( &ejectable, NULL );
|
|
icon = ejectable ? MICONFLOPPY : MICONDISK;
|
|
#else /* 0 */
|
|
icon = MICONDISK;
|
|
#endif /* 0 */
|
|
} else
|
|
icon = MICONOFOLDER;
|
|
flp = WINDFL(dp);
|
|
rp = &flp->flcurdirrect;
|
|
savebottom = rp->bottom;
|
|
rp->bottom = CW(flp->flascent);
|
|
rp->left = CW(CW(rp->left) + (2));
|
|
drawinboxwithicon(flp->flcurdirname, rp, icon);
|
|
rp->left = CW(CW(rp->left) - (2));
|
|
rp->bottom = savebottom;
|
|
FrameRect(rp);
|
|
MoveTo(CW(rp->left)+1, CW(rp->bottom));
|
|
LineTo(CW(rp->right), CW(rp->bottom));
|
|
LineTo(CW(rp->right), CW(rp->top)+1);
|
|
SetPenState(&ps);
|
|
}
|
|
|
|
A1(PRIVATE, LONGINT, getdirid, StringPtr, fname)
|
|
{
|
|
CInfoPBRec hpb;
|
|
LONGINT retval;
|
|
OSErr err;
|
|
|
|
hpb.dirInfo.ioCompletion = 0;
|
|
hpb.dirInfo.ioNamePtr = RM(fname);
|
|
hpb.dirInfo.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
hpb.dirInfo.ioFDirIndex = CWC (0);
|
|
hpb.dirInfo.ioDrDirID = CurDirStore;
|
|
err = PBGetCatInfo(&hpb, FALSE);
|
|
if (err == noErr)
|
|
retval = CL (hpb.dirInfo.ioDrDirID);
|
|
else
|
|
{
|
|
warning_unexpected ("PBGetCatInfo return value err = %d\n", err);
|
|
retval = 2; /* known good id ... an error might be better here */
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
#define MAXPREFIX 64
|
|
|
|
PRIVATE void
|
|
set_type_and_name (fltype *f, OSType type, Str255 name)
|
|
{
|
|
switch (f->flavor)
|
|
{
|
|
case original_sf:
|
|
f->flreplyp.oreplyp->fType = CL (type);
|
|
str31assign (f->flreplyp.oreplyp->fName, name);
|
|
break;
|
|
case new_sf:
|
|
case new_custom_sf:
|
|
f->flreplyp.nreplyp->sfType = CL (type);
|
|
str31assign (f->flreplyp.nreplyp->sfFile.name, name);
|
|
f->flreplyp.nreplyp->sfIsFolder = !!type;
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", f->flavor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
A2(PRIVATE, void, settype, fltype *, f, INTEGER, newsel)
|
|
{
|
|
StringPtr ip;
|
|
|
|
ip = (StringPtr) MR(*f->flstrs) + MR(*f->flinfo)[newsel].floffs;
|
|
if (MR(*f->flinfo)[newsel].flicns == MICONCFOLDER)
|
|
set_type_and_name (f, getdirid (ip), (StringPtr) "");
|
|
else
|
|
set_type_and_name (f, 0, ip);
|
|
}
|
|
|
|
A2(PRIVATE, INTEGER, flwhich, fltype *, f, Point, p)
|
|
{
|
|
INTEGER retval;
|
|
INTEGER bump, from;
|
|
|
|
if (!PtInRect(p, &f->flrect)) {
|
|
bump = 0;
|
|
if (p.v < CW(f->flrect.top))
|
|
bump = -1;
|
|
else if (p.v >= CW(f->flrect.bottom))
|
|
bump = 1;
|
|
if (bump) {
|
|
from = GetCtlValue(f->flsh);
|
|
SetCtlValue(f->flsh, from+bump);
|
|
flscroll(f, from, GetCtlValue(f->flsh));
|
|
}
|
|
/*-->*/ return(-1);
|
|
}
|
|
retval = (p.v - CW(f->flrect.top)) / f->fllinht + GetCtlValue(f->flsh);
|
|
if (retval >= f->flnmfil || MR(*f->flinfo)[retval].flicns & GRAYBIT)
|
|
/*-->*/ retval = -1;
|
|
return(retval);
|
|
}
|
|
|
|
A3(PRIVATE, void, flmouse, fltype *, f, Point, p, ControlHandle, ch)
|
|
{
|
|
INTEGER newsel;
|
|
EventRecord evt;
|
|
|
|
evt.where = p;
|
|
do {
|
|
GlobalToLocal(&evt.where);
|
|
p.h = CW(evt.where.h);
|
|
p.v = CW(evt.where.v);
|
|
if ((newsel = flwhich(f, p)) != f->flsel) {
|
|
if (f->flsel != -1) {
|
|
safeflflip(f, f->flsel);
|
|
if (newsel == -1) {
|
|
if (!f->flgraynondirs)
|
|
HiliteControl(ch, 255);
|
|
set_type_and_name (f, 0, (StringPtr) "");
|
|
}
|
|
}
|
|
if (newsel != -1) {
|
|
safeflflip(f, newsel);
|
|
if (f->flsel == -1)
|
|
HiliteControl(ch, 0);
|
|
settype(f, newsel);
|
|
}
|
|
f->flsel = newsel;
|
|
}
|
|
} while (!GetNextEvent(mUpMask, &evt));
|
|
}
|
|
|
|
typedef pascal BOOLEAN (*filtp)(DialogPtr dp, EventRecord *evp, INTEGER *ith);
|
|
|
|
#define CALLFILTERPROC(dp, evt, ith, fp) \
|
|
ROMlib_CALLFILTERPROC((dp), (evt), (ith), (filtp) (fp))
|
|
|
|
A4(static inline, BOOLEAN, ROMlib_CALLFILTERPROC, DialogPtr, dp,
|
|
EventRecord *, evtp, INTEGER, *ith, filtp, fp)
|
|
{
|
|
BOOLEAN retval;
|
|
LONGINT save_ref_con;
|
|
|
|
save_ref_con = GetWRefCon (dp);
|
|
SetWRefCon (dp, TICK("stdf"));
|
|
ROMlib_hook(stdfile_filtnumber);
|
|
HOOKSAVEREGS();
|
|
retval = CToPascalCall(fp, CTOP_SectRect, dp, evtp, ith);
|
|
HOOKRESTOREREGS();
|
|
SetWRefCon (dp, save_ref_con);
|
|
return retval;
|
|
}
|
|
|
|
#if 0 /* Needed to generate a CTOP value */
|
|
P4 (PUBLIC pascal trap, BOOLEAN, unused_stdfile, DialogPtr, dp, EventRecord *,
|
|
evp, INTEGER *, ith, UNIV Ptr, data)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
typedef pascal BOOLEAN (*custom_filtp)(DialogPtr dp, EventRecord *evp,
|
|
INTEGER *ith, UNIV Ptr data);
|
|
|
|
#define CALL_NEW_FILTER_PROC(dp, evt, ith, data, fp) \
|
|
ROMlib_CALL_NEW_FILTER_PROC((dp), (evt), (ith), (data), \
|
|
(custom_filtp) (fp))
|
|
|
|
PRIVATE BOOLEAN
|
|
ROMlib_CALL_NEW_FILTER_PROC (DialogPtr dp, EventRecord *evtp, INTEGER *ith,
|
|
UNIV Ptr data, custom_filtp fp)
|
|
{
|
|
BOOLEAN retval;
|
|
LONGINT save_ref_con;
|
|
|
|
save_ref_con = GetWRefCon (dp);
|
|
SetWRefCon (dp, TICK("stdf"));
|
|
ROMlib_hook(stdfile_filtnumber);
|
|
HOOKSAVEREGS();
|
|
retval = CToPascalCall(fp, CTOP_unused_stdfile, dp, evtp, ith, data);
|
|
HOOKRESTOREREGS();
|
|
SetWRefCon (dp, save_ref_con);
|
|
return retval;
|
|
}
|
|
|
|
A1(PRIVATE, void, getcurname, fltype *, f)
|
|
{
|
|
int w;
|
|
CInfoPBRec hpb;
|
|
Rect *r;
|
|
OSErr err;
|
|
|
|
hpb.dirInfo.ioCompletion = 0;
|
|
hpb.dirInfo.ioNamePtr = RM(&f->flcurdirname[0]);
|
|
f->flcurdirname[0] = 0;
|
|
hpb.dirInfo.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
hpb.dirInfo.ioFDirIndex = CWC(-1);
|
|
hpb.dirInfo.ioDrDirID = CurDirStore;
|
|
err = PBGetCatInfo(&hpb, FALSE);
|
|
if (err != noErr)
|
|
{
|
|
warning_unexpected ("PBGetCatInfo err = %d\n", err);
|
|
str255_from_c_string (f->flcurdirname, "?error?");
|
|
}
|
|
r = &f->flrect;
|
|
w = StringWidth(f->flcurdirname) + 2 + 16 + 3 + 2 + 2 + 4;
|
|
#if 1
|
|
if (w > CW(r->right) - CW(r->left) + 17) {
|
|
f->flcurdirrect.left = r->left;
|
|
f->flcurdirrect.right = CW(CW(r->right) + 17);
|
|
} else {
|
|
f->flcurdirrect.left = CW((CW(r->left) + CW(r->right) + 17 - w) / 2 - 2);
|
|
f->flcurdirrect.right = CW(CW(f->flcurdirrect.left) + w);
|
|
}
|
|
#else /* 1 */
|
|
f->flcurdirrect.left = (CW(r->left) + CW(r->right) + 17 - w) / 2 - 2;
|
|
f->flcurdirrect.right = CW(CW(f->flcurdirrect.left) + w);
|
|
#endif /* 1 */
|
|
}
|
|
|
|
A1(PRIVATE, void, flfinit, fltype *, fp)
|
|
{
|
|
DisposeControl(fp->flsh);
|
|
DisposHandle((Handle) fp->flinfo);
|
|
DisposHandle((Handle) fp->flstrs);
|
|
}
|
|
|
|
A3(PRIVATE, void, flinsert, fltype *, f, StringPtr, p, INTEGER, micon)
|
|
{
|
|
struct flinfostr finfo;
|
|
|
|
finfo.floffs = GetHandleSize((Handle) f->flstrs);
|
|
finfo.flicns = micon;
|
|
PtrAndHand((Ptr) p, (Handle) f->flstrs, (LONGINT)U(p[0])+1);
|
|
PtrAndHand((Ptr) &finfo, (Handle) f->flinfo,
|
|
(LONGINT)sizeof(struct flinfostr));
|
|
++f->flnmfil;
|
|
}
|
|
|
|
A3(PRIVATE, int, typeinarray, OSType, ft, INTEGER, numt, SFTypeList, tl)
|
|
{
|
|
OSType *ostp = tl;
|
|
|
|
while (numt--)
|
|
if (ft == *ostp++)
|
|
/*-->*/ return(TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
/*
|
|
* NOTE: stdfcmp is called from qsort, so we can't smash d2.
|
|
*/
|
|
|
|
/* ip1 and ip2 would really be "void *" in ANSI C */
|
|
|
|
A2(PRIVATE, LONGINT, stdfcmp, char *, ip1, char *, ip2)
|
|
{
|
|
struct flinfostr *fp1, *fp2;
|
|
LONGINT retval;
|
|
|
|
fp1 = (struct flinfostr *) ip1;
|
|
fp2 = (struct flinfostr *) ip2;
|
|
retval = ROMlib_strcmp((StringPtr) (MR(*holdstr) + fp1->floffs),
|
|
(StringPtr) (MR(*holdstr) + fp2->floffs));
|
|
return retval;
|
|
}
|
|
|
|
typedef pascal BOOLEAN (*filefiltp)( ParmBlkPtr pbp );
|
|
|
|
#define CALLFILEFILT(pbp, fp) ROMlib_CALLFILEFILT((pbp), (filefiltp)(fp))
|
|
|
|
A2(static inline, BOOLEAN, ROMlib_CALLFILEFILT, ParmBlkPtr, pbp, filefiltp, fp)
|
|
{
|
|
BOOLEAN retval;
|
|
|
|
ROMlib_hook(stdfile_filefiltnumber);
|
|
HOOKSAVEREGS();
|
|
retval = CToPascalCall(fp, CTOP_SystemEvent, pbp);
|
|
HOOKRESTOREREGS();
|
|
return retval;
|
|
}
|
|
|
|
typedef pascal BOOLEAN (*custom_file_filtp) (ParmBlkPtr pbp, UNIV Ptr data);
|
|
|
|
#define CALL_CUSTOM_FILE_FILT(pbp, data, fp) \
|
|
ROMlib_CALL_CUSTOM_FILE_FILT ((pbp), (data), (custom_file_filtp) (fp))
|
|
|
|
PRIVATE BOOLEAN
|
|
ROMlib_CALL_CUSTOM_FILE_FILT (ParmBlkPtr pbp, UNIV Ptr data,
|
|
custom_file_filtp fp)
|
|
{
|
|
BOOLEAN retval;
|
|
|
|
ROMlib_hook(stdfile_filefiltnumber);
|
|
HOOKSAVEREGS();
|
|
retval = CToPascalCall(fp, CTOP_GetAuxCtl, pbp, data);
|
|
HOOKRESTOREREGS();
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE boolean_t
|
|
passes_filter (fltype *f, CInfoPBRec *cinfop, INTEGER numt)
|
|
{
|
|
boolean_t retval;
|
|
|
|
switch (f->flavor)
|
|
{
|
|
case original_sf:
|
|
/* NOTE: the code for original_sf was changed after we ran into
|
|
some trouble with Accordance. It's not clear whether or not
|
|
the new code here should also be used for new_sf. */
|
|
retval = (!f->flfilef.oflfilef
|
|
|| (numt == 0
|
|
&& (cinfop->hFileInfo.ioFlAttrib & ATTRIB_ISADIR))
|
|
|| !CALLFILEFILT ((ParmBlkPtr) cinfop, f->flfilef.oflfilef));
|
|
case new_sf:
|
|
retval = (!f->flfilef.oflfilef
|
|
|| (cinfop->hFileInfo.ioFlAttrib & ATTRIB_ISADIR)
|
|
|| !CALLFILEFILT ((ParmBlkPtr) cinfop, f->flfilef.oflfilef));
|
|
break;
|
|
case new_custom_sf:
|
|
retval = (!f->flfilef.cflfilef
|
|
|| !CALL_CUSTOM_FILE_FILT ((ParmBlkPtr) cinfop, f->mydata,
|
|
f->flfilef.cflfilef));
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", f->flavor);
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
A1(PRIVATE, void, flfill, fltype *, f)
|
|
{
|
|
CInfoPBRec pb;
|
|
OSErr err;
|
|
Str255 s;
|
|
int micon;
|
|
CursHandle watchh;
|
|
INTEGER errcount;
|
|
INTEGER dirindex;
|
|
|
|
SetCursor(STARH((watchh = GetCursor(watchCursor))));
|
|
|
|
pb.hFileInfo.ioNamePtr = RM(&s[0]);
|
|
pb.hFileInfo.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
err = noErr;
|
|
errcount = 0;
|
|
for (dirindex = 1; err != fnfErr && errcount != 3; dirindex++) {
|
|
pb.hFileInfo.ioFDirIndex = CW(dirindex);
|
|
pb.hFileInfo.ioDirID = CurDirStore;
|
|
err = PBGetCatInfo(&pb, FALSE);
|
|
if (err) {
|
|
if (err != fnfErr) {
|
|
warning_unexpected ("PBGetCatInfo err = %d\n", err);
|
|
++errcount;
|
|
/* register int d7 = err; */
|
|
|
|
}
|
|
} else {
|
|
errcount = 0;
|
|
if (f->flnumt <= 0 || (pb.hFileInfo.ioFlAttrib & ATTRIB_ISADIR) ||
|
|
typeinarray(pb.hFileInfo.ioFlFndrInfo.fdType, f->flnumt,
|
|
f->fltl))
|
|
if (passes_filter (f, &pb, f->flnumt))
|
|
{
|
|
if (pb.hFileInfo.ioFlAttrib & ATTRIB_ISADIR)
|
|
micon = MICONCFOLDER;
|
|
else if (pb.hFileInfo.ioFlFndrInfo.fdType == TICKX("APPL"))
|
|
micon = MICONAPP | f->flgraynondirs;
|
|
else
|
|
micon = MICONLETTER | f->flgraynondirs;
|
|
flinsert(f, MR(pb.hFileInfo.ioNamePtr), micon);
|
|
}
|
|
}
|
|
}
|
|
if (f->flnmfil > f->flnmlin) {
|
|
SetCtlMax(f->flsh, f->flnmfil - f->flnmlin);
|
|
SetCtlValue(f->flsh, 0);
|
|
} else
|
|
SetCtlMax(f->flsh, 0);
|
|
|
|
if (f->flnmfil > 0) {
|
|
holdstr = f->flstrs;
|
|
qsort(MR(*f->flinfo), f->flnmfil, sizeof(**f->flinfo), (void *) stdfcmp);
|
|
if (!(MR(*f->flinfo)[0].flicns&GRAYBIT) && !f->flgraynondirs) {
|
|
f->flsel = 0;
|
|
settype(f, 0);
|
|
HiliteControl(f->flch, 0);
|
|
}
|
|
} else
|
|
if (!f->flgraynondirs)
|
|
HiliteControl(f->flch, 255);
|
|
/* i'm not sure this is right, but there is no obvious way to
|
|
save/restore the cursor */
|
|
SetCursor (&arrowX);
|
|
}
|
|
|
|
/*
|
|
* ROMlib_filebox should be renamed to reflect the fact that it also draws the
|
|
* dotted line (whopee!)
|
|
*/
|
|
|
|
P2(PUBLIC, pascal void, ROMlib_filebox, DialogPeek, dp, INTEGER, which)
|
|
{
|
|
HIDDEN_Handle h;
|
|
Rect r, r2;
|
|
INTEGER i;
|
|
int width, strwidth, offset;
|
|
StringPtr diskname;
|
|
HIDDEN_Handle ejhand;
|
|
BOOLEAN ejectable;
|
|
PenState ps;
|
|
|
|
GetPenState(&ps);
|
|
PenNormal();
|
|
|
|
h.p = NULL;
|
|
GetDItem((DialogPtr) dp, which, &i, &h, &r);
|
|
/* h.p = CL(h.p); we don't really use h */
|
|
switch (which) {
|
|
case getNmList:
|
|
case putNmList:
|
|
if (h.p)
|
|
FrameRect(&r);
|
|
flupdate(WINDFL(dp), GetCtlValue(WINDFL(dp)->flsh),
|
|
WINDFL(dp)->flnmlin);
|
|
break;
|
|
case getDotted:
|
|
FillRect(&r, gray);
|
|
break;
|
|
case getDiskName:
|
|
/* case putDiskName: getDiskName and putDiskName are the same */
|
|
EraseRect(&r);
|
|
width = CW(r.right) - CW(r.left);
|
|
diskname = getdiskname( &ejectable, NULL );
|
|
GetDItem((DialogPtr) dp, putEject, &i, &ejhand, &r2);
|
|
ejhand.p = MR(ejhand.p);
|
|
if (ejectable)
|
|
HiliteControl((ControlHandle) ejhand.p, 0);
|
|
else
|
|
HiliteControl((ControlHandle) ejhand.p, 255);
|
|
strwidth = StringWidth(diskname) + 2 + 16 + 3;
|
|
offset = (width - strwidth) / 2;
|
|
if (offset < 3)
|
|
r.left = CW(CW(r.left) + (3));
|
|
else
|
|
r.left = CW(CW(r.left) + (offset));
|
|
r.bottom = CW(WINDFL(dp)->flascent);
|
|
drawinboxwithicon(diskname, &r, ejectable ? MICONFLOPPY : MICONDISK);
|
|
break;
|
|
}
|
|
SetPenState(&ps);
|
|
}
|
|
|
|
|
|
A2(PRIVATE, void, realcd, DialogPeek, dp, LONGINT, dir)
|
|
{
|
|
fltype *fp;
|
|
|
|
CurDirStore = CL(dir);
|
|
fp = WINDFL(dp);
|
|
SetHandleSize((Handle) fp->flinfo, (Size) 0);
|
|
SetHandleSize((Handle) fp->flstrs, (Size) 0);
|
|
fp->flnmfil = 0;
|
|
fp->flsel = -1;
|
|
set_type_and_name (fp, 0, (StringPtr) "");
|
|
flfill(fp);
|
|
fp->flcurdirrect.right = CW(CW(fp->flcurdirrect.right ) + 1);
|
|
fp->flcurdirrect.bottom = CW(CW(fp->flcurdirrect.bottom) + 1);
|
|
EraseRect(&fp->flcurdirrect);
|
|
getcurname(fp);
|
|
fp->flcurdirrect.bottom = CW(CW(fp->flcurdirrect.bottom) - 1);
|
|
/* don't need to do right; getcurname does */
|
|
drawjobberattop(dp);
|
|
C_ROMlib_filebox(dp, getDiskName);
|
|
EraseRect(&fp->flrect);
|
|
if (fp->flgraynondirs)
|
|
C_ROMlib_filebox(dp, putNmList);
|
|
else
|
|
C_ROMlib_filebox(dp, getNmList);
|
|
}
|
|
|
|
A1(PRIVATE, LONGINT, getparent, LONGINT, dirid)
|
|
{
|
|
OSErr err;
|
|
CInfoPBRec cb;
|
|
LONGINT retval;
|
|
|
|
cb.dirInfo.ioCompletion = 0;
|
|
cb.dirInfo.ioNamePtr = 0;
|
|
cb.dirInfo.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
cb.dirInfo.ioFDirIndex = CWC (-1);
|
|
cb.dirInfo.ioDrDirID = CL(dirid);
|
|
err = PBGetCatInfo(&cb, FALSE);
|
|
if (err == noErr)
|
|
retval = CL(cb.dirInfo.ioDrParID);
|
|
else
|
|
{
|
|
warning_unexpected ("PBGetCatInfo return = %d\n", err);
|
|
retval = 2;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE BOOLEAN findparent(INTEGER *vrefp, LONGINT *diridp)
|
|
{
|
|
HVCB *vcbp;
|
|
BOOLEAN retval;
|
|
struct stat sbuf;
|
|
char *namecpy, *slashp;
|
|
INTEGER namelen;
|
|
|
|
vcbp = ROMlib_vcbbyvrn(CW(*vrefp));
|
|
retval = FALSE;
|
|
if (!vcbp->vcbCTRef) {
|
|
namelen = strlen(((VCBExtra *) vcbp)->unixname);
|
|
if (namelen != 1 + SLASH_CHAR_OFFSET) { /* i.e. "/" */
|
|
namecpy = alloca(namelen + 1);
|
|
strcpy(namecpy, ((VCBExtra *) vcbp)->unixname);
|
|
slashp = strrchr(namecpy, '/');
|
|
if (slashp == namecpy + SLASH_CHAR_OFFSET) {
|
|
slashp[1] = 0;
|
|
} else {
|
|
slashp[0] = 0;
|
|
}
|
|
if (Ustat(namecpy, &sbuf) == 0 &&
|
|
(vcbp = ROMlib_vcbbybiggestunixname(namecpy))) {
|
|
*vrefp = vcbp->vcbVRefNum;
|
|
*diridp = CL((LONGINT) ST_INO (sbuf));
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
A1(PRIVATE, BOOLEAN, moveuponedir, DialogPtr, dp)
|
|
{
|
|
LONGINT parent;
|
|
INTEGER vrn;
|
|
BOOLEAN retval;
|
|
|
|
parent = getparent(CL(CurDirStore));
|
|
if (parent != CL(CurDirStore) && parent != 1) {
|
|
CurDirStore = CL(parent);
|
|
retval = TRUE;
|
|
} else {
|
|
vrn = CW(-CW(SFSaveDisk));
|
|
retval = findparent(&vrn, &CurDirStore);
|
|
SFSaveDisk = CW(-CW(vrn));
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
BOOLEAN keyarrow(fltype *fl, INTEGER incr) /* -1: up, 1: down */
|
|
{
|
|
INTEGER nsel, oldval, newval;
|
|
struct flinfostr *flp;
|
|
/*
|
|
* If there's no selection we start at the top or bottom, depending on
|
|
* whether we're going down or p
|
|
*/
|
|
if (fl->flsel == -1)
|
|
nsel = incr > 0 ? 0 : fl->flnmfil - 1;
|
|
else
|
|
nsel = fl->flsel + incr;
|
|
|
|
/*
|
|
* If we land on a grayed out file, advance until non-grayed
|
|
*/
|
|
|
|
for (flp = MR(*fl->flinfo) + nsel;
|
|
(flp->flicns & GRAYBIT) && nsel >= 0 && nsel < fl->flnmfil;
|
|
nsel += incr, flp += incr)
|
|
;
|
|
|
|
/*
|
|
* If we don't find a non-grayed out entry, we leave
|
|
*/
|
|
if (nsel < 0 || nsel >= fl->flnmfil)
|
|
/*-->*/ return FALSE;
|
|
|
|
/*
|
|
* Figure out what should be visible and scroll there if necessary
|
|
*/
|
|
|
|
newval = oldval = GetCtlValue(fl->flsh);
|
|
if (nsel < oldval)
|
|
newval = nsel;
|
|
else if (nsel >= oldval + fl->flnmlin)
|
|
newval = nsel - fl->flnmlin + 1;
|
|
if (newval != oldval) {
|
|
SetCtlValue(fl->flsh, newval);
|
|
flscroll(fl, oldval, newval);
|
|
}
|
|
|
|
/*
|
|
* Get rid of the previously selected rectangle
|
|
*/
|
|
if (fl->flsel != -1)
|
|
safeflflip(fl, fl->flsel);
|
|
/*
|
|
* Flip the new rectangle, set up the type information and make assignment
|
|
*/
|
|
safeflflip(fl, nsel);
|
|
settype(fl, nsel);
|
|
fl->flsel = nsel;
|
|
return TRUE;
|
|
}
|
|
|
|
PRIVATE boolean_t
|
|
folder_selected_p (fltype *fl)
|
|
{
|
|
boolean_t retval;
|
|
|
|
switch (fl->flavor)
|
|
{
|
|
case original_sf:
|
|
retval = !!fl->flreplyp.oreplyp->fType;
|
|
break;
|
|
case new_sf:
|
|
case new_custom_sf:
|
|
retval = fl->flreplyp.nreplyp->sfIsFolder;
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", fl->flavor);
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE INTEGER
|
|
call_magicfp (fltype *fl, DialogPeek dp, EventRecord *evt, INTEGER *ith)
|
|
{
|
|
INTEGER retval;
|
|
|
|
switch (fl->flavor)
|
|
{
|
|
case original_sf:
|
|
case new_sf:
|
|
retval = fl->magicfp.ofilterp
|
|
? CALLFILTERPROC ((DialogPtr) dp, evt, ith, fl->magicfp.ofilterp)
|
|
: FALSE;
|
|
break;
|
|
case new_custom_sf:
|
|
retval = fl->magicfp.cfilterp
|
|
? CALL_NEW_FILTER_PROC ((DialogPtr) dp, evt, ith, fl->mydata,
|
|
fl->magicfp.cfilterp)
|
|
: FALSE;
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", fl->flavor);
|
|
retval = FALSE;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
#define keydownbit 0x1000
|
|
|
|
P3(PUBLIC, pascal INTEGER, ROMlib_stdffilt, DialogPeek, dp,
|
|
EventRecord *, evt, INTEGER *, ith) /* handle disk insert */
|
|
{
|
|
LONGINT ticks;
|
|
INTEGER i, from;
|
|
HIDDEN_ControlHandle h;
|
|
Rect r;
|
|
Point p;
|
|
INTEGER t;
|
|
fltype *fl;
|
|
INTEGER opentoken;
|
|
struct flinfostr *flp, *flep;
|
|
INTEGER nsel, fltop;
|
|
INTEGER part;
|
|
INTEGER retval, retval2;
|
|
|
|
fl = WINDFL(dp);
|
|
opentoken = getOpen; /* getOpen and putSave are both 1 */
|
|
retval = FALSE;
|
|
switch (CW(evt->what)) {
|
|
case keyDown:
|
|
*ith = CW((CL(evt->message) & 0xFF) + keydownbit);
|
|
switch (CL(evt->message) & 0xFF) {
|
|
case NUMPAD_ENTER:
|
|
case '\r' :
|
|
GetDItem((DialogPtr) dp, CW(dp->aDefItem), &i, (HIDDEN_Handle *) &h, &r);
|
|
h.p = MR(h.p);
|
|
if (Hx(h.p, contrlVis) && U(Hx(h.p, contrlHilite)) != 255)
|
|
{
|
|
prefix[0] = 0;
|
|
oldticks = -1000;
|
|
*ith = CW(opentoken);
|
|
retval = -1;
|
|
#if !defined(NEXTSTEP)
|
|
HiliteControl(h.p, inButton);
|
|
Delay((LONGINT)5, (LONGINT *) 0);
|
|
HiliteControl(h.p, 0);
|
|
#endif
|
|
}
|
|
break;
|
|
case ASCIIUPARROW:
|
|
if (CW(evt->modifiers) & cmdKey)
|
|
*ith = CWC(getDiskName); /* the same as putDiskName */
|
|
else
|
|
keyarrow(fl, -1);
|
|
retval = -1;
|
|
break;
|
|
case ASCIIDOWNARROW:
|
|
if ((CW(evt->modifiers) & cmdKey) && fl->flsel != -1 &&
|
|
(MR(*fl->flinfo) + fl->flsel)->flicns == MICONCFOLDER) {
|
|
prefix[0] = 0;
|
|
oldticks = -1000;
|
|
*ith = CWC(opentoken);
|
|
} else
|
|
keyarrow(fl, 1);
|
|
retval = -1;
|
|
break;
|
|
case '\t':
|
|
*ith = CWC(putDrive); /* PutDrive is 6 which is also getDrive. */
|
|
retval = -1;
|
|
break;
|
|
case '.':
|
|
if (evt->modifiers & CWC(cmdKey))
|
|
{
|
|
*ith = CW(fl->fl_cancel_item);
|
|
retval = -1;
|
|
break;
|
|
}
|
|
default:
|
|
/*
|
|
* The Cx(dp->editField) check was made to get HFS_XFer to work. There
|
|
* may be a better place to put it, but not enough tests have been done
|
|
* to say where.
|
|
*/
|
|
if (!fl->flgraynondirs && dp->editField == -1) {
|
|
flep = MR(*fl->flinfo) + fl->flnmfil - 1;
|
|
if (CL(evt->when) > lastkeydowntime + CL(DoubleTime)) {
|
|
flp = MR(*fl->flinfo);
|
|
prefix[0] = 0;
|
|
oldticks = -1000;
|
|
} else
|
|
flp = MR(*fl->flinfo) + ((fl->flsel) == -1 ? 0 : fl->flsel);
|
|
lastkeydowntime = CL(evt->when);
|
|
prefix[++prefix[0]] = CL(evt->message) & 0xff;
|
|
while (flp < flep &&
|
|
RelString((StringPtr) (MR(*fl->flstrs) +
|
|
flp->floffs), prefix, FALSE, TRUE) < 0)
|
|
++flp;
|
|
nsel = flp - MR(*fl->flinfo);
|
|
if (nsel != fl->flsel) {
|
|
safeflflip(fl, fl->flsel);
|
|
fltop = GetCtlValue(fl->flsh);
|
|
if (nsel < fltop || nsel >= fltop + fl->flnmlin) {
|
|
SetCtlValue(fl->flsh, nsel - fl->flnmlin / 2);
|
|
flscroll(fl, fltop, GetCtlValue(fl->flsh));
|
|
}
|
|
safeflflip(fl, fl->flsel = nsel);
|
|
settype(fl, nsel);
|
|
}
|
|
retval = -1;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case mouseDown:
|
|
p = evt->where;
|
|
GlobalToLocal(&p);
|
|
p.h = CW(p.h);
|
|
p.v = CW(p.v);
|
|
if (PtInRect(p, &fl->flrect)) {
|
|
GetDItem((DialogPtr) dp, getOpen, &i, (HIDDEN_Handle *) &h, &r);
|
|
h.p = MR(h.p);
|
|
flmouse(fl, evt->where, h.p);
|
|
ticks = TickCount();
|
|
if (fl->flsel != -1 && savesel == fl->flsel &&
|
|
(ticks < oldticks + CL(DoubleTime))) {
|
|
prefix[0] = 0;
|
|
*ith = CWC(opentoken);
|
|
oldticks = -1000;
|
|
retval = -1;
|
|
} else
|
|
oldticks = ticks;
|
|
savesel = fl->flsel;
|
|
} else if ((t = TestControl(fl->flsh, p))) {
|
|
if (t == inThumb) {
|
|
from = GetCtlValue(fl->flsh);
|
|
TrackControl(fl->flsh, p, (ProcPtr) 0);
|
|
flscroll(fl, from, GetCtlValue(fl->flsh));
|
|
} else
|
|
TrackControl(fl->flsh, p, (ProcPtr) P_ROMlib_stdftrack);
|
|
} else if (PtInRect(p, &fl->flcurdirrect)) {
|
|
*ith = CWC(FAKECURDIR);
|
|
retval = -1;
|
|
} else {
|
|
GetDItem((DialogPtr) dp, getOpen, &i, (HIDDEN_Handle *) &h, &r);
|
|
h.p = MR(h.p);
|
|
if ((part = TestControl(h.p, p)) &&
|
|
TrackControl(h.p, p, (ProcPtr) 0)) {
|
|
prefix[0] = 0;
|
|
oldticks = -1000;
|
|
*ith = CWC(opentoken);
|
|
retval = -1;
|
|
}
|
|
}
|
|
break;
|
|
case nullEvent:
|
|
*ith = CWC(100);
|
|
retval = -1;
|
|
break;
|
|
case updateEvt:
|
|
if ((DialogPeek) MR(evt->message) == dp)
|
|
drawjobberattop(dp);
|
|
*ith = CWC(100);
|
|
break;
|
|
}
|
|
retval2 = call_magicfp (fl, dp, evt, ith);
|
|
|
|
if (*ith == CWC(getOpen) && folder_selected_p (fl)) /* 1 is getOpen and putSave */
|
|
*ith = CWC(FAKEOPENDIR);
|
|
|
|
return retval ? retval : retval2;
|
|
}
|
|
|
|
A3(PRIVATE, void, flinit, fltype *, f, Rect *, r, ControlHandle, sh)
|
|
{
|
|
FontInfo fi;
|
|
THz savezone;
|
|
|
|
GetFontInfo(&fi);
|
|
|
|
f->flsh = sh;
|
|
f->flrect = *r;
|
|
f->fllinht = CW(fi.ascent) + CW(fi.descent) + CW(fi.leading);
|
|
|
|
f->flcurdirrect.top = CW(CW(r->top) - f->fllinht - 5);
|
|
f->flcurdirrect.bottom = CW(CW(f->flcurdirrect.top) + f->fllinht);
|
|
getcurname(f);
|
|
|
|
f->flascent = CW(fi.ascent);
|
|
f->flnmlin = (CW(r->bottom) - CW(r->top)) / f->fllinht;
|
|
f->flnmfil = 0;
|
|
f->flsel = -1;
|
|
savezone = TheZone;
|
|
TheZone = SysZone;
|
|
f->flinfo = (struct flinfostr **) NewHandle((Size)0);
|
|
f->flstrs = (char **) NewHandle((Size)0);
|
|
TheZone = savezone;
|
|
}
|
|
|
|
A3(PRIVATE, void, stdfflip, Rect *, rp, INTEGER, n, INTEGER, height)
|
|
{
|
|
INTEGER savetop;
|
|
|
|
savetop = rp->top;
|
|
rp->top = CW(CW(rp->top) + (n * height + 1));
|
|
rp->bottom = CW(CW(rp->top) + height - 2);
|
|
InvertRect(rp);
|
|
rp->top = savetop;
|
|
}
|
|
|
|
A1(PRIVATE, BOOLEAN, trackdirs, DialogPeek, dp)
|
|
{
|
|
WRAPPER_PIXMAP_FOR_COPY (wrapper);
|
|
PixMapHandle save_bits;
|
|
Rect therect, fillinrect;
|
|
struct link
|
|
{
|
|
Str255 name;
|
|
LONGINT dirid;
|
|
struct link *next;
|
|
INTEGER vrefnum;
|
|
} first, *next;
|
|
int count, i;
|
|
CInfoPBRec hpb;
|
|
int max_width;
|
|
fltype *fl;
|
|
EventRecord evt;
|
|
LONGINT id;
|
|
int sel, newsel, firstsel;
|
|
BOOLEAN done;
|
|
ALLOCABEGIN
|
|
BOOLEAN ejectable;
|
|
boolean_t seen_up_already;
|
|
TEMP_ALLOC_DECL (temp_save_bits);
|
|
|
|
THEPORT_SAVE_EXCURSION
|
|
(MR (wmgr_port),
|
|
{
|
|
int str_width;
|
|
|
|
next = &first;
|
|
hpb.dirInfo.ioCompletion = 0;
|
|
hpb.dirInfo.ioNamePtr = RM (&next->name[0]);
|
|
next->name[0] = 0;
|
|
hpb.dirInfo.ioVRefNum = CW (-CW(SFSaveDisk));
|
|
hpb.dirInfo.ioFDirIndex = CWC (-1);
|
|
hpb.dirInfo.ioDrDirID = CurDirStore;
|
|
max_width = 0;
|
|
count = 0;
|
|
done = FALSE;
|
|
|
|
do
|
|
{
|
|
OSErr err;
|
|
|
|
err = PBGetCatInfo (&hpb, FALSE);
|
|
if (err != noErr)
|
|
{
|
|
warning_unexpected ("PBGetCatInfo returns err = %d\n", err);
|
|
done = TRUE;
|
|
}
|
|
id = next->dirid = CL (hpb.dirInfo.ioDrDirID);
|
|
next->vrefnum = CW (hpb.dirInfo.ioVRefNum);
|
|
next->next = (struct link *) ALLOCA (sizeof (struct link));
|
|
gui_assert (next->next);
|
|
str_width = StringWidth (next->name);
|
|
if (str_width > max_width)
|
|
max_width = str_width;
|
|
next = next->next; /* make Steve Jobs happy */
|
|
hpb.dirInfo.ioDrDirID = hpb.dirInfo.ioDrParID;
|
|
hpb.dirInfo.ioNamePtr = RM (&next->name[0]);
|
|
next->name[0] = 0;
|
|
count++;
|
|
if (id == 2)
|
|
{
|
|
if (!findparent (&hpb.dirInfo.ioVRefNum, &hpb.dirInfo.ioDrDirID))
|
|
done = TRUE;
|
|
}
|
|
} while (!done);
|
|
fl = WINDFL(dp);
|
|
therect.top = CW (CW (fl->flcurdirrect.top)
|
|
- CW (PORT_BOUNDS (dp).top));
|
|
therect.left = CW (CW (fl->flcurdirrect.left)
|
|
- CW (PORT_BOUNDS (dp).left));
|
|
therect.bottom = CW (CW (therect.top) + count * fl->fllinht + 1);
|
|
therect.right = CW (CW (therect.left) + 2 + 16 + 3 + max_width + 4 + 2 + 3);
|
|
ClipRect(&therect);
|
|
|
|
{
|
|
Rect *bounds;
|
|
PixMapHandle port_pixmap;
|
|
INTEGER save_bpp_x;
|
|
int row_bytes;
|
|
void *save_bits_mem;
|
|
|
|
save_bits = NewPixMap ();
|
|
port_pixmap = CPORT_PIXMAP (thePort);
|
|
|
|
bounds = &PIXMAP_BOUNDS (save_bits);
|
|
bounds->top = CWC (0);
|
|
bounds->left = CWC (0);
|
|
bounds->bottom = CW (RECT_HEIGHT (&therect));
|
|
bounds->right = CW (RECT_WIDTH (&therect));
|
|
PIXMAP_PIXEL_SIZE_X (save_bits) = save_bpp_x
|
|
= PIXMAP_PIXEL_SIZE_X (port_pixmap);
|
|
ROMlib_copy_ctab (PIXMAP_TABLE (port_pixmap),
|
|
PIXMAP_TABLE (save_bits));
|
|
row_bytes = ((CW (bounds->right) * CW (save_bpp_x) + 31) / 32) * 4;
|
|
PIXMAP_SET_ROWBYTES_X (save_bits, CW (row_bytes));
|
|
|
|
/* Allocate potentially large temporary pixmap space. */
|
|
TEMP_ALLOC_ALLOCATE (save_bits_mem, temp_save_bits,
|
|
CW (bounds->bottom) * row_bytes);
|
|
PIXMAP_BASEADDR_X (save_bits) = RM (save_bits_mem);
|
|
WRAPPER_SET_PIXMAP_X (wrapper, RM (save_bits));
|
|
|
|
CopyBits (PORT_BITS_FOR_COPY (thePort), wrapper,
|
|
&therect, bounds, srcCopy, NULL);
|
|
}
|
|
|
|
EraseRect(&therect);
|
|
|
|
/* loop through, displaying stuff */
|
|
/* highlite the appropriate box, etc. */
|
|
|
|
fillinrect.top = therect.top;
|
|
fillinrect.left = CW(CW(therect.left) + 2);
|
|
fillinrect.bottom = CW(fl->flascent);
|
|
fillinrect.right = therect.right;
|
|
|
|
for (i = count, next = &first; --i >= 0; next = next->next)
|
|
{
|
|
|
|
/* TODO: ask cliff about a better way to do this */
|
|
/* unused = */
|
|
getdiskname (&ejectable, NULL);
|
|
drawinboxwithicon(next->name, &fillinrect,
|
|
i ? MICONCFOLDER : ejectable ? MICONFLOPPY : MICONDISK);
|
|
/*
|
|
drawinboxwithicon(next->name, &fillinrect,
|
|
i ? MICONCFOLDER : MICONDISK);
|
|
*/
|
|
fillinrect.top = CW(CW(fillinrect.top) + (fl->fllinht));
|
|
}
|
|
|
|
therect.right = CW(CW(therect.right) - (1));
|
|
therect.bottom = CW(CW(therect.bottom) - (1));
|
|
FrameRect(&therect);
|
|
MoveTo(CW(therect.left)+1, CW(therect.bottom));
|
|
LineTo(CW(therect.right), CW(therect.bottom));
|
|
LineTo(CW(therect.right), CW(therect.top)+1);
|
|
therect.right = CW(CW(therect.right) + (1));
|
|
|
|
sel = 0;
|
|
fillinrect.top = therect.top;
|
|
fillinrect.left = CW (CW (fillinrect.left) - 1);
|
|
fillinrect.right = CW (CW (fillinrect.right) - 2);
|
|
stdfflip (&fillinrect, sel, fl->fllinht);
|
|
done = FALSE;
|
|
seen_up_already = FALSE;
|
|
firstsel = -1;
|
|
while (!done)
|
|
{
|
|
evt.where.h = CW (evt.where.h);
|
|
evt.where.v = CW (evt.where.v);
|
|
if (PtInRect (evt.where, &therect))
|
|
newsel = (evt.where.v - CW(therect.top)) / fl->fllinht;
|
|
else
|
|
newsel = -1;
|
|
if (newsel != sel)
|
|
{
|
|
if (firstsel == -1)
|
|
firstsel = newsel;
|
|
if (sel != -1)
|
|
stdfflip (&fillinrect, sel, fl->fllinht);
|
|
if (newsel != -1)
|
|
stdfflip (&fillinrect, newsel, fl->fllinht);
|
|
sel = newsel;
|
|
}
|
|
if (!ROMlib_sticky_menus_p)
|
|
done = GetNextEvent (mUpMask, &evt);
|
|
else
|
|
{
|
|
if (OSEventAvail (mUpMask, &evt))
|
|
{
|
|
if (seen_up_already || (sel != firstsel && firstsel != -1))
|
|
done = TRUE;
|
|
else
|
|
{
|
|
GetOSEvent (mUpMask, &evt);
|
|
seen_up_already = TRUE;
|
|
}
|
|
}
|
|
if (!done && OSEventAvail (mDownMask, &evt))
|
|
{
|
|
GetOSEvent (mDownMask, &evt);
|
|
done = sel != -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
therect.bottom = CW (CW (therect.bottom) + 1);
|
|
|
|
/* restore the rect and clean up after ourselves */
|
|
CopyBits(wrapper, PORT_BITS_FOR_COPY (thePort),
|
|
&PIXMAP_BOUNDS (save_bits), &therect, srcCopy, NULL);
|
|
DisposPixMap (save_bits);
|
|
});
|
|
if (sel != -1)
|
|
{
|
|
for (i = 0, next = &first; i != sel; ++i, next = next->next)
|
|
;
|
|
CurDirStore = CL(next->dirid);
|
|
SFSaveDisk = CW(-next->vrefnum);
|
|
return TRUE;
|
|
}
|
|
ALLOCAEND
|
|
|
|
TEMP_ALLOC_FREE (temp_save_bits);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
PRIVATE void
|
|
makeworking (fltype *f)
|
|
{
|
|
|
|
switch (f->flavor)
|
|
{
|
|
case original_sf:
|
|
{
|
|
WDPBRec wdpb;
|
|
OSErr err;
|
|
|
|
wdpb.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
wdpb.ioWDDirID = CurDirStore;
|
|
wdpb.ioWDProcID = TICKX("STDF");
|
|
wdpb.ioNamePtr = 0;
|
|
err = PBOpenWD(&wdpb, FALSE);
|
|
if (err != noErr)
|
|
warning_unexpected ("PBOpenWD returns %d\n", err);
|
|
|
|
f->flreplyp.oreplyp->vRefNum = wdpb.ioVRefNum;
|
|
}
|
|
break;
|
|
case new_sf:
|
|
case new_custom_sf:
|
|
f->flreplyp.nreplyp->sfFile.vRefNum = CW(-CW(SFSaveDisk));
|
|
f->flreplyp.nreplyp->sfFile.parID = CurDirStore;
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", f->flavor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
A1(PRIVATE, BOOLEAN, ejected, HParmBlkPtr, pb)
|
|
{
|
|
return pb->volumeParam.ioVDrvInfo == 0;
|
|
}
|
|
|
|
/*
|
|
* returns true if the filesystem that pb refers to is part of a single
|
|
* tree, as in UNIX. Under MSDOS, filesystems are distinct (i.e. C:, D:,
|
|
* etc.)
|
|
*/
|
|
|
|
PRIVATE boolean_t single_tree_fs_p(HParmBlkPtr pb)
|
|
{
|
|
#if defined(MSDOS) || defined (CYGWIN32)
|
|
return FALSE;
|
|
#else
|
|
HVCB *vcbp;
|
|
|
|
vcbp = ROMlib_vcbbyvrn(CW(pb->volumeParam.ioVRefNum));
|
|
return vcbp && !vcbp->vcbCTRef;
|
|
#endif
|
|
}
|
|
|
|
#if defined(LINUX)
|
|
PUBLIC int linuxfloppy_open(int disk, LONGINT *bsizep,
|
|
drive_flags_t *flagsp, const char *dname)
|
|
{
|
|
int retval;
|
|
struct cdrom_subchnl sub_info;
|
|
boolean_t force_read_only;
|
|
|
|
force_read_only = FALSE;
|
|
*flagsp = 0;
|
|
#define FLOPPY_PREFIX "/dev/fd"
|
|
if (strncmp (dname, FLOPPY_PREFIX, sizeof(FLOPPY_PREFIX)-1) == 0)
|
|
*flagsp |= DRIVE_FLAGS_FLOPPY;
|
|
|
|
if (!force_read_only)
|
|
retval = Uopen (dname, O_RDWR, 0);
|
|
#if !defined (LETGCCWAIL)
|
|
else
|
|
retval = noErr;
|
|
#endif
|
|
if (force_read_only || retval < 0)
|
|
{
|
|
retval = Uopen (dname, O_RDONLY, 0);
|
|
if (retval >= 0)
|
|
*flagsp |= DRIVE_FLAGS_LOCKED;
|
|
}
|
|
|
|
memset (&sub_info, 0, sizeof sub_info);
|
|
sub_info.cdsc_format = CDROM_MSF;
|
|
if (retval >= 0 && ioctl (retval, CDROMSUBCHNL, &sub_info) != -1)
|
|
{
|
|
switch (sub_info.cdsc_audiostatus)
|
|
{
|
|
case CDROM_AUDIO_PLAY:
|
|
case CDROM_AUDIO_PAUSED:
|
|
case CDROM_AUDIO_COMPLETED:
|
|
case CDROM_AUDIO_ERROR:
|
|
close (retval);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
*bsizep = 512;
|
|
if (retval >= 0)
|
|
{
|
|
/* *ejectablep = TRUE; DRIVE_FLAGS_FIXED not set */
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE int linuxfloppy_close(int disk)
|
|
{
|
|
return close(disk);
|
|
}
|
|
#endif
|
|
|
|
typedef struct {
|
|
const char *dname;
|
|
DrvQExtra *dqp;
|
|
BOOLEAN loaded;
|
|
int fd;
|
|
} dosdriveinfo_t;
|
|
|
|
#define IGNORED (-1) /* doesn't really matter */
|
|
|
|
#if defined(MSDOS) || defined (CYGWIN32)
|
|
|
|
#define N_DRIVES (32)
|
|
|
|
PRIVATE boolean_t drive_loaded [N_DRIVES] = { 0 };
|
|
|
|
PRIVATE char *
|
|
drive_name_of (int i)
|
|
{
|
|
static char retval[] = "A:";
|
|
|
|
retval[0] = 'A' + i;
|
|
return retval;
|
|
}
|
|
|
|
enum { NUM_FLOPPIES = 2, NON_FLOPPY_BIT = 0x80 };
|
|
|
|
PRIVATE int
|
|
fd_of (int i)
|
|
{
|
|
int retval;
|
|
|
|
#if defined (CYGWIN32)
|
|
retval = i;
|
|
#else
|
|
if (i < NUM_FLOPPIES)
|
|
retval = i;
|
|
else
|
|
retval = i - NUM_FLOPPIES + NON_FLOPPY_BIT;
|
|
#endif
|
|
return retval;
|
|
}
|
|
|
|
#define DRIVE_NAME_OF(x) drive_name_of (x)
|
|
#define FD_OF(x) fd_of (x)
|
|
#define DRIVE_LOADED(x) drive_loaded[x]
|
|
|
|
#else
|
|
|
|
#define DRIVE_NAME_OF(x) drives[x].dname
|
|
|
|
#define FD_OF(x) drives[x].fd
|
|
|
|
#define DRIVE_LOADED(x) drives[x].loaded
|
|
|
|
#endif
|
|
|
|
PUBLIC void futzwithdosdisks( void )
|
|
{
|
|
#if defined (MSDOS) || defined (LINUX) || defined(CYGWIN32)
|
|
int i, fd;
|
|
LONGINT mess;
|
|
LONGINT blocksize;
|
|
drive_flags_t flags;
|
|
#if defined(MSDOS) || defined (CYGWIN32)
|
|
/* #warning "We're cheating on DOS drive specs: ejectable, bsize, maxsize, writable" */
|
|
#define OPEN_ROUTINE dosdisk_open
|
|
#define CLOSE_ROUTINE dosdisk_close
|
|
#define EXTRA_CLOSE_PARAM , FALSE
|
|
#define MARKER DOSFDBIT
|
|
#define EXTRA_PARAM
|
|
#define ROMLIB_MACDRIVES ROMlib_macdrives
|
|
#elif defined(LINUX)
|
|
static dosdriveinfo_t drives[] = {
|
|
{ "/dev/fd0", (DrvQExtra *) 0, FALSE, IGNORED },
|
|
{ "/dev/cdrom", (DrvQExtra *) 0, FALSE, IGNORED },
|
|
#if 0
|
|
{ "/dev/fd1", (DrvQExtra *) 0, FALSE, IGNORED },
|
|
#endif
|
|
};
|
|
#define N_DRIVES NELEM(drives)
|
|
#define OPEN_ROUTINE linuxfloppy_open
|
|
#define CLOSE_ROUTINE linuxfloppy_close
|
|
#define EXTRA_CLOSE_PARAM
|
|
#define MARKER 0
|
|
#define EXTRA_PARAM , (DRIVE_NAME_OF (i))
|
|
#define ROMLIB_MACDRIVES (~0)
|
|
#endif
|
|
|
|
/* Since we're scanning for new disks, let's be paranoid and
|
|
* flush all cached disk information.
|
|
*/
|
|
dcache_invalidate_all (TRUE);
|
|
|
|
#if defined (MSDOS)
|
|
aspi_rescan ();
|
|
#endif
|
|
|
|
if (!nodrivesearch_p)
|
|
{
|
|
for (i = 0; i < N_DRIVES; ++i) {
|
|
if (/* DRIVE_LOADED(i) */ ROMLIB_MACDRIVES & (1 << i)) {
|
|
#if defined (MSDOS) || defined (CYGWIN32)
|
|
checkpoint_macdrive (checkpointp, begin, 1 << i);
|
|
#endif
|
|
if (((fd = OPEN_ROUTINE(FD_OF (i), &blocksize, &flags
|
|
EXTRA_PARAM)) >= 0)
|
|
|| (flags & DRIVE_FLAGS_FLOPPY)) {
|
|
try_to_mount_disk( DRIVE_NAME_OF (i), fd|MARKER, &mess,
|
|
blocksize, 16 * PHYSBSIZE,
|
|
flags, 0);
|
|
mess = CL(mess);
|
|
if (mess) {
|
|
if (mess >> 16 == 0) {
|
|
DRIVE_LOADED(i) = TRUE;
|
|
PPostEvent(diskEvt, mess, (HIDDEN_EvQElPtr *) 0);
|
|
/* TODO: we probably should post if mess returns an
|
|
error, but I think we get confused if we do */
|
|
} else {
|
|
if (!(flags & DRIVE_FLAGS_FLOPPY))
|
|
CLOSE_ROUTINE(fd EXTRA_CLOSE_PARAM);
|
|
}
|
|
} else {
|
|
if (!(flags & DRIVE_FLAGS_FLOPPY))
|
|
CLOSE_ROUTINE(fd EXTRA_CLOSE_PARAM);
|
|
}
|
|
}
|
|
#if defined (MSDOS) || defined (CYGWIN32)
|
|
checkpoint_macdrive (checkpointp, end, 1 << i);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
A2(PRIVATE, void, bumpsavedisk, DialogPtr, dp, BOOLEAN, always)
|
|
{
|
|
INTEGER current;
|
|
HParamBlockRec pb;
|
|
INTEGER vref;
|
|
OSErr err;
|
|
BOOLEAN is_single_tree_fs, seenus;
|
|
|
|
#if defined (MSDOS) || defined (CYGWIN32)
|
|
/* static BOOLEAN beenhere = FALSE; */
|
|
|
|
if (ROMlib_drive_check /* || !beenhere */) {
|
|
futzwithdosdisks();
|
|
/* beenhere = TRUE; */
|
|
}
|
|
#endif
|
|
pb.volumeParam.ioVRefNum = CW(-CW(SFSaveDisk));
|
|
pb.volumeParam.ioNamePtr = 0;
|
|
pb.volumeParam.ioVolIndex = 0;
|
|
err = PBHGetVInfo(&pb, FALSE);
|
|
if (err != noErr)
|
|
warning_unexpected ("PBHGetVInfo returns %d", err);
|
|
else if (!SFSaveDisk || ISWDNUM(-CW(SFSaveDisk)))
|
|
SFSaveDisk = CW(-CW(pb.volumeParam.ioVRefNum));
|
|
if (always || pb.ioParam.ioResult != noErr || ejected(&pb)) {
|
|
current = pb.volumeParam.ioVRefNum;
|
|
is_single_tree_fs = single_tree_fs_p(&pb);
|
|
pb.volumeParam.ioVolIndex = 0;
|
|
seenus = FALSE;
|
|
vref = 0;
|
|
do {
|
|
pb.volumeParam.ioVolIndex = CW(CW(pb.volumeParam.ioVolIndex) + 1);
|
|
err = PBHGetVInfo(&pb, FALSE);
|
|
if (err != noErr && !seenus)
|
|
warning_unexpected ("PBHGetVInfo = %d\n", err);
|
|
else {
|
|
if (pb.volumeParam.ioVRefNum == current)
|
|
seenus = TRUE;
|
|
else if (!ejected(&pb) &&
|
|
(!is_single_tree_fs || !single_tree_fs_p(&pb))) {
|
|
if (!vref || seenus)
|
|
vref = CW(pb.volumeParam.ioVRefNum);
|
|
if (seenus)
|
|
/*-->*/ break;
|
|
}
|
|
}
|
|
} while (err == noErr);
|
|
if (vref) {
|
|
SFSaveDisk = CW(-vref);
|
|
CurDirStore = CLC(2);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0 /* needed to construct ctopflags */
|
|
P3 (PUBLIC pascal trap, INTEGER, unused_stdfile_2, INTEGER, ihit,
|
|
DialogPtr, dp, UNIV Ptr, data)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* NOTE: we no longer swap out the refcon when making the sfHookFirstCall (-1)
|
|
* or the sfHookLastCall (-2). This fixes the bug that had Photoshop 3.0
|
|
* dying the second time that SFCustomGetFile was called. This fix
|
|
* was determined by trial and error.
|
|
*
|
|
* I have just verified that the fix is incorrect. It works because we
|
|
* bypass some startup code that Photoshop 3.0 uses to set up its type list.
|
|
* This means that the type list won't work properly. However if we don't
|
|
* swap in 'stdf' then we wind up making calls to InsMenuItem that add
|
|
* entries to the "Format" menu which somehow results in a crash eventually.
|
|
* If we have ROMlib_CALLDHOOK temporarily disable InsMenuItem then PS3.0
|
|
* will work even w/ 'stdf' in the refcon. It will also work if we rig
|
|
* CountMItems to always return 0 inside ROMlib_CALLDHOOK. So something
|
|
* appears to go wrong if we call the startup code and actually add (and
|
|
* notice that we add) items the Format menu.
|
|
*/
|
|
|
|
PRIVATE INTEGER
|
|
ROMlib_CALLDHOOK (fltype *fl, INTEGER ihit, DialogPtr dp, dialog_hook_u dhu)
|
|
{
|
|
INTEGER retval;
|
|
LONGINT save_ref_con;
|
|
|
|
ROMlib_hook(stdfile_dialhooknumber);
|
|
HOOKSAVEREGS();
|
|
|
|
save_ref_con = GetWRefCon (dp);
|
|
emergency_save_ref_con = save_ref_con;
|
|
SetWRefCon (dp, TICK("stdf"));
|
|
|
|
switch (fl->flavor)
|
|
{
|
|
case original_sf:
|
|
case new_sf:
|
|
retval = CToPascalCall (dhu.odh, CTOP_Alert, ihit, dp);
|
|
break;
|
|
case new_custom_sf:
|
|
retval = CToPascalCall (dhu.cdh, CTOP_unused_stdfile_2, ihit, dp,
|
|
fl->mydata);
|
|
break;
|
|
default:
|
|
warning_unexpected ("flavor = %d", fl->flavor);
|
|
retval = 0;
|
|
break;
|
|
}
|
|
HOOKRESTOREREGS();
|
|
SetWRefCon (dp, save_ref_con);
|
|
return retval;
|
|
}
|
|
|
|
A4(PRIVATE, void, transformsfpdialog, DialogPtr, dp, Point *, offset,
|
|
Rect *, scrollrect, BOOLEAN, getting)
|
|
{
|
|
INTEGER numitems, windheight, i, j, extrasizeneeded;
|
|
HIDDEN_Handle h;
|
|
Rect r;
|
|
TEPtr tep;
|
|
|
|
if (getting) {
|
|
extrasizeneeded = 20;
|
|
} else {
|
|
extrasizeneeded = 110;
|
|
SetRect(scrollrect, 16, 24, 231, 106);
|
|
tep = STARH(MR(((DialogPeek)dp)->textH));
|
|
tep->destRect.top = CW(CW(tep->destRect.top) + (extrasizeneeded));
|
|
tep->destRect.bottom = CW(CW(tep->destRect.bottom) + (extrasizeneeded));
|
|
tep->viewRect.top = CW(CW(tep->viewRect.top) + (extrasizeneeded));
|
|
tep->viewRect.bottom = CW(CW(tep->viewRect.bottom) + (extrasizeneeded));
|
|
}
|
|
numitems = CW(*(INTEGER *)STARH((MR(((DialogPeek)dp)->items)))) + 1;
|
|
for (j = 1 ; j <= numitems ; j++) {
|
|
GetDItem(dp, j, &i, &h, &r);
|
|
i = CW(i);
|
|
h.p = MR(h.p);
|
|
if (!getting || CW(r.bottom) > CW(scrollrect->top)) {
|
|
r.top = CW(CW(r.top) + (extrasizeneeded));
|
|
r.bottom = CW(CW(r.bottom) + (extrasizeneeded));
|
|
if (i <= 7 && i >= 4) /* It's a control */
|
|
MoveControl((ControlHandle) h.p, CW(r.left), CW(r.top));
|
|
SetDItem(dp, j, i, h.p, &r);
|
|
}
|
|
}
|
|
windheight = CW(dp->portRect.bottom) - CW(dp->portRect.top) + extrasizeneeded;
|
|
SizeWindow( (WindowPtr) dp, CW(dp->portRect.right) - CW(dp->portRect.left),
|
|
windheight, FALSE);
|
|
if (getting) {
|
|
scrollrect->top = CW(CW(scrollrect->top) + (extrasizeneeded));
|
|
scrollrect->bottom = CW(CW(scrollrect->bottom) + (extrasizeneeded));
|
|
}
|
|
InvalRect(&dp->portRect);
|
|
offset->v -= extrasizeneeded / 2;
|
|
}
|
|
|
|
void adjustdrivebutton(DialogPtr dp)
|
|
{
|
|
INTEGER count;
|
|
HIDDEN_Handle drhand;
|
|
INTEGER i;
|
|
Rect r;
|
|
#if !defined(MSDOS) && !defined(CYGWIN32)
|
|
HVCB *vcbp;
|
|
BOOLEAN seenunix;
|
|
|
|
count = 0;
|
|
seenunix = FALSE;
|
|
for (vcbp = (HVCB *) MR(VCBQHdr.qHead); vcbp;
|
|
vcbp = (HVCB *) MR(vcbp->qLink))
|
|
if (vcbp->vcbCTRef && vcbp->vcbDrvNum)
|
|
++count;
|
|
else if (!seenunix) {
|
|
++count;
|
|
seenunix = TRUE;
|
|
}
|
|
#else /* defined(MSDOS) */
|
|
count = 2; /* always allow the user to hit the drive button */
|
|
#endif /* defined(MSDOS) */
|
|
GetDItem(dp, putDrive, &i, &drhand, &r); /* putDrive == getDrive */
|
|
drhand.p = MR(drhand.p);
|
|
HiliteControl((ControlHandle) drhand.p, count > 1 ? 0 : 255);
|
|
}
|
|
|
|
A1(PRIVATE, void, doeject, DialogPtr, dp)
|
|
{
|
|
Eject((StringPtr) "", -CW(SFSaveDisk));
|
|
adjustdrivebutton(dp);
|
|
bumpsavedisk(dp, TRUE);
|
|
}
|
|
|
|
A3(PRIVATE, OSType, gettypeX, StringPtr, name, INTEGER, vref, LONGINT, dirid)
|
|
{
|
|
OSType retval;
|
|
OSErr err;
|
|
HParamBlockRec pbr;
|
|
|
|
pbr.fileParam.ioNamePtr = RM (name);
|
|
pbr.fileParam.ioVRefNum = CW (vref);
|
|
pbr.fileParam.ioFVersNum = 0;
|
|
pbr.fileParam.ioFDirIndex = CWC (0);
|
|
pbr.fileParam.ioDirID = CL (dirid);
|
|
err = PBHGetFInfo (&pbr, FALSE);
|
|
if (err == noErr)
|
|
retval = pbr.fileParam.ioFlFndrInfo.fdType;
|
|
else
|
|
retval = 0;
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE OSErr
|
|
unixcore (StringPtr namep, INTEGER *vrefnump, LONGINT *diridp)
|
|
{
|
|
INTEGER vrefnum;
|
|
HVCB *vcbp;
|
|
char *newname;
|
|
INTEGER namelen;
|
|
OSErr err;
|
|
ParamBlockRec pb;
|
|
char *pathname, *filename, *endname;
|
|
VCBExtra *vcbp2;
|
|
struct stat sbuf;
|
|
LONGINT templ;
|
|
char *tempcp;
|
|
ParamBlockRec pbr;
|
|
|
|
vrefnum = *vrefnump;
|
|
#if 0
|
|
vcbp = ROMlib_vcbbyvrn(vrefnum);
|
|
#else
|
|
pbr.ioParam.ioNamePtr = CLC(0);
|
|
pbr.ioParam.ioVRefNum = CW(vrefnum);
|
|
vcbp = ROMlib_breakoutioname(&pbr, &templ, &tempcp, (BOOLEAN *) 0, TRUE);
|
|
free (tempcp);
|
|
#endif
|
|
if (vcbp && !vcbp->vcbCTRef)
|
|
{
|
|
pb.ioParam.ioNamePtr = CLC(0);
|
|
pb.ioParam.ioVRefNum = pbr.ioParam.ioVRefNum;
|
|
err = ROMlib_nami(&pb, *diridp, NoIndex, &pathname, &filename,
|
|
&endname, FALSE, &vcbp2, &sbuf);
|
|
if (err == noErr)
|
|
{
|
|
VCBExtra *vcbextrap;
|
|
|
|
namelen = endname - pathname - 1;
|
|
newname = alloca(namelen + 1 + namep[0] + 1);
|
|
strncpy(newname, pathname, namelen);
|
|
newname[namelen] = '/';
|
|
strncpy(newname + namelen + 1, (char *) namep+1, namep[0]);
|
|
newname[namelen + 1 + namep[0]] = 0;
|
|
ROMlib_automount(newname);
|
|
vcbextrap = ROMlib_vcbbyunixname(newname);
|
|
if (vcbextrap)
|
|
{
|
|
*vrefnump = CW(vcbextrap->vcb.vcbVRefNum);
|
|
if (*diridp == vcbextrap->u.ufs.ino)
|
|
*diridp = 2;
|
|
}
|
|
else
|
|
err = nsvErr;
|
|
free (pathname);
|
|
}
|
|
}
|
|
else
|
|
err = nsvErr;
|
|
return err;
|
|
}
|
|
|
|
P1(PUBLIC pascal trap, OSErr, unixmount, CInfoPBRec *, cbp)
|
|
{
|
|
OSErr err;
|
|
|
|
if (!cbp)
|
|
{
|
|
dofloppymount();
|
|
err = noErr;
|
|
}
|
|
else
|
|
{
|
|
INTEGER vrefnum;
|
|
LONGINT dirid;
|
|
|
|
vrefnum = CW(cbp->hFileInfo.ioVRefNum);
|
|
dirid = CL (cbp->hFileInfo.ioDirID);
|
|
err = unixcore(MR(cbp->hFileInfo.ioNamePtr), &vrefnum, &dirid);
|
|
if (err == noErr)
|
|
{
|
|
cbp->hFileInfo.ioVRefNum = CW (vrefnum);
|
|
cbp->hFileInfo.ioDirID = CW (dirid);
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
PRIVATE void unixcd(fltype *f)
|
|
{
|
|
StringPtr name;
|
|
INTEGER vrefnum;
|
|
LONGINT dirid;
|
|
|
|
name = (StringPtr) (MR(*f->flstrs) + MR(*f->flinfo)[f->flsel].floffs);
|
|
vrefnum = -CW(SFSaveDisk);
|
|
dirid = CL (CurDirStore);
|
|
if (unixcore(name, &vrefnum, &dirid) == noErr)
|
|
{
|
|
SFSaveDisk = CW (-vrefnum);
|
|
CurDirStore = CL (dirid);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if (U(rep->fName[0]) > 63) /* remember to clip to 63 characters */
|
|
rep->fName[0] = 63;
|
|
#endif
|
|
|
|
PRIVATE void
|
|
get_starting_point (Point *pp)
|
|
{
|
|
INTEGER screen_width, screen_height;
|
|
Rect main_gd_rect;
|
|
|
|
main_gd_rect = PIXMAP_BOUNDS (GD_PMAP (MR (MainDevice)));
|
|
screen_width = CW (main_gd_rect.right);
|
|
screen_height = CW (main_gd_rect.bottom);
|
|
pp->h = (screen_width - STANDARD_WIDTH) / 2;
|
|
pp->v = (screen_height - STANDARD_HEIGHT) / 2;
|
|
}
|
|
|
|
PRIVATE ControlHandle
|
|
create_new_folder_button (DialogPtr dp)
|
|
{
|
|
ControlHandle retval;
|
|
Handle dial_test;
|
|
|
|
dial_test = GetResource (TICK("DLOG"), -6044);
|
|
if (!dial_test)
|
|
retval = NULL;
|
|
else
|
|
{
|
|
INTEGER i;
|
|
HIDDEN_Handle h;
|
|
Rect r;
|
|
|
|
GetDItem (dp, sfItemNewFolderUser, &i, &h, &r);
|
|
retval = NewControl ((WindowPtr) dp, &r, (StringPtr) "\012New Folder",
|
|
TRUE, 0, 0, 0, 0, 0L);
|
|
SetDItem (dp, sfItemNewFolderUser, ctrlItem|btnCtrl,
|
|
(Handle) retval, &r);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE void
|
|
destroy_new_folder_button (DialogPtr dp, ControlHandle ch)
|
|
{
|
|
/* May not need to do anything since CloseDialog should clean up all
|
|
outstanding controls */
|
|
}
|
|
|
|
#define SF_NAME(fp) ((fp)->flavor == original_sf \
|
|
? (fp)->flreplyp.oreplyp->fName \
|
|
: (fp)->flreplyp.nreplyp->sfFile.name)
|
|
|
|
#define SF_GOOD_XP(fp) ((fp)->flavor == original_sf \
|
|
? &(fp)->flreplyp.oreplyp->good \
|
|
: &(fp)->flreplyp.nreplyp->sfGood)
|
|
|
|
#define SF_FTYPE_XP(fp) ((fp)->flavor == original_sf \
|
|
? &(fp)->flreplyp.oreplyp->fType \
|
|
: &(fp)->flreplyp.nreplyp->sfType)
|
|
|
|
#define SF_VREFNUM_X(fp) ((fp)->flavor == original_sf \
|
|
? (fp)->flreplyp.oreplyp->vRefNum \
|
|
: (fp)->flreplyp.nreplyp->sfFile.vRefNum)
|
|
|
|
#define SF_VREFNUM(fp) (CW (SF_VREFNUM_X (fp)))
|
|
|
|
#define SF_DIRID_X(fp) ((fp)->flavor == original_sf \
|
|
? 0 \
|
|
: (fp)->flreplyp.nreplyp->sfFile.parID)
|
|
|
|
#define SF_DIRID(fp) (CL (SF_DIRID_X (fp)))
|
|
|
|
PRIVATE void
|
|
getditext (DialogPtr dp, INTEGER item, StringPtr text)
|
|
{
|
|
INTEGER i;
|
|
HIDDEN_Handle h;
|
|
Rect r;
|
|
|
|
h.p = 0;
|
|
GetDItem (dp, item, &i, &h, &r);
|
|
if (!h.p)
|
|
text[0] = 0;
|
|
else
|
|
{
|
|
h.p = MR (h.p);
|
|
GetIText (h.p, text);
|
|
}
|
|
}
|
|
|
|
PRIVATE void
|
|
report_new_folder_failure (OSErr err)
|
|
{
|
|
char *message;
|
|
Str255 str;
|
|
|
|
switch (err)
|
|
{
|
|
default:
|
|
message = alloca (256);
|
|
sprintf (message, "Error #%d occurred; you may not be able to create a new folder.", err);
|
|
break;
|
|
case dupFNErr:
|
|
message = "That name is already taken; please use another name.";
|
|
break;
|
|
case dirFulErr:
|
|
message = "This directory is full; you may not be able to create a new folder.";
|
|
break;
|
|
case dskFulErr:
|
|
message = "This disk is full; you may not be able to create a new folder.";
|
|
break;
|
|
case permErr:
|
|
case wrPermErr:
|
|
message = "Filesystem permissions prevent the creation of a new folder.";
|
|
break;
|
|
case vLckdErr:
|
|
message = "This volume is locked; you can not create a new folder.";
|
|
break;
|
|
}
|
|
str255_from_c_string (str, message);
|
|
ParamText (str, 0, 0, 0);
|
|
NoteAlert (GENERIC_COMPLAINT_ID, (ProcPtr) 0);
|
|
}
|
|
|
|
PRIVATE boolean_t
|
|
new_folder_from_dp (DialogPtr dp, fltype *f)
|
|
{
|
|
Str255 str;
|
|
HParamBlockRec hpb;
|
|
OSErr err;
|
|
boolean_t retval;
|
|
|
|
getditext (dp, 3, str);
|
|
hpb.ioParam.ioVRefNum = CW (-CW (SFSaveDisk));
|
|
hpb.fileParam.ioDirID = CurDirStore;
|
|
if (str[0] > 31)
|
|
str[0] = 31;
|
|
hpb.ioParam.ioNamePtr = RM (&str[0]);
|
|
err = PBDirCreate (&hpb, FALSE);
|
|
if (err != noErr)
|
|
report_new_folder_failure (err);
|
|
else
|
|
{
|
|
*SF_FTYPE_XP(f) = hpb.fileParam.ioDirID;
|
|
retval = TRUE;
|
|
}
|
|
retval = err == noErr;
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE boolean_t
|
|
do_new_folder (fltype *f)
|
|
{
|
|
boolean_t retval;
|
|
GrafPtr gp;
|
|
DialogPtr dp;
|
|
|
|
retval = FALSE;
|
|
gp = thePort;
|
|
dp = GetNewDialog (-6044, (Ptr) 0, (WindowPtr)-1);
|
|
if (dp)
|
|
{
|
|
boolean_t done;
|
|
INTEGER ihit;
|
|
|
|
SelIText (dp, 3, 0, 32767);
|
|
ShowWindow (dp);
|
|
SelectWindow (dp);
|
|
done = FALSE;
|
|
while (!done)
|
|
{
|
|
/* TODO: consider a filter that limits the length
|
|
of the string to 31 letters */
|
|
ModalDialog (NULL, &ihit);
|
|
switch (ihit)
|
|
{
|
|
default:
|
|
break;
|
|
case CWC (1):
|
|
done = new_folder_from_dp (dp, f);
|
|
if (done)
|
|
retval = TRUE;
|
|
break;
|
|
case CWC (2):
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
CloseDialog (dp);
|
|
SetPort (gp);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
PRIVATE void
|
|
rep_from_host_reply_block (reply_u *repp,
|
|
const host_spf_reply_block *host_reply)
|
|
{
|
|
}
|
|
|
|
PRIVATE boolean_t
|
|
is_normal_dlgid (getorput_t getorput, INTEGER dig)
|
|
{
|
|
return getorput == get
|
|
? dig == getDlgID || dig == sfGetDialogID
|
|
: dig == putDlgID || dig == sfPutDialogID;
|
|
}
|
|
|
|
PUBLIC void spfcommon(Point p, StringPtr prompt, StringPtr name,
|
|
dialog_hook_u dh, reply_u rep, INTEGER dig, filter_u fp,
|
|
file_filter_u filef, INTEGER numt, SFTypeList tl,
|
|
getorput_t getorput, sf_flavor_t flavor,
|
|
Ptr activeList, ActivateYDProcPtr activateproc,
|
|
UNIV Ptr yourdatap)
|
|
{
|
|
boolean_t reply_valid;
|
|
TRAPBEGIN();
|
|
|
|
reply_valid = FALSE;
|
|
if (is_normal_dlgid (getorput, dig) && host_has_spfcommon ()) {
|
|
host_spf_reply_block reply;
|
|
char *c_prompt;
|
|
char *local_name = "currently ignored";
|
|
|
|
c_prompt = cstring_from_str255 (prompt);
|
|
#if 0
|
|
local_name = ...;
|
|
#else
|
|
#warning "TODO: support native file pickers"
|
|
#endif
|
|
reply_valid = host_spfcommon (&reply, c_prompt, local_name, &fp, &filef,
|
|
numt, tl, getorput, flavor, activeList,
|
|
activateproc, yourdatap);
|
|
free (c_prompt);
|
|
if (reply_valid)
|
|
rep_from_host_reply_block (&rep, &reply);
|
|
}
|
|
if (!reply_valid) {
|
|
HIDDEN_Handle h;
|
|
DialogPtr dp;
|
|
INTEGER ihit, i;
|
|
int done, sav;
|
|
Rect r, scrollrect;
|
|
HIDDEN_Handle pnhand, ejhand, drhand, sahand;
|
|
OSErr err;
|
|
ControlHandle scrollh;
|
|
fltype f;
|
|
GrafPtr gp;
|
|
INTEGER openorsave, promptitem, nmlistitem, diskname, ejectitem, driveitem;
|
|
BOOLEAN transform;
|
|
EventRecord evt;
|
|
ParamBlockRec pbr;
|
|
CInfoPBRec hpb;
|
|
ControlHandle new_folder_button;
|
|
|
|
done = FALSE;
|
|
memset (&f, 0, sizeof f);
|
|
f.magicfp = fp;
|
|
f.mydata = yourdatap;
|
|
f.flavor = flavor;
|
|
f.flreplyp = rep;
|
|
|
|
if (p.h < 2 || p.v < CW(MBarHeight) + 7)
|
|
get_starting_point (&p);
|
|
|
|
*SF_GOOD_XP(&f) = CBC (FALSE);
|
|
if (f.flavor == original_sf)
|
|
f.flreplyp.oreplyp->version = CBC (0);
|
|
else
|
|
{
|
|
f.flreplyp.nreplyp->sfIsFolder = 0;
|
|
f.flreplyp.nreplyp->sfIsVolume = 0;
|
|
}
|
|
*SF_FTYPE_XP(&f) = CLC (0);
|
|
|
|
new_folder_button = NULL;
|
|
if ( getorput == put) {
|
|
str31assign (SF_NAME (&f), name);
|
|
if (f.flavor == original_sf)
|
|
{
|
|
openorsave = putSave;
|
|
promptitem = putPrompt;
|
|
nmlistitem = putNmList;
|
|
diskname = putDiskName;
|
|
ejectitem = putEject;
|
|
driveitem = putDrive;
|
|
f.fl_cancel_item = putCancel;
|
|
}
|
|
else
|
|
{
|
|
openorsave = sfItemOpenButton;
|
|
promptitem = sfItemPromptStaticText;
|
|
nmlistitem = sfItemFileListUser;
|
|
diskname = sfItemVolumeUser;
|
|
ejectitem = sfItemEjectButton;
|
|
driveitem = sfItemDesktopButton;
|
|
f.fl_cancel_item = sfItemCancelButton;
|
|
}
|
|
} else {
|
|
if (f.flavor == original_sf)
|
|
{
|
|
openorsave = getOpen;
|
|
promptitem = 10; /* according to whom? bill? */
|
|
nmlistitem = getNmList;
|
|
diskname = getDiskName;
|
|
ejectitem = getEject;
|
|
driveitem = getDrive;
|
|
f.fl_cancel_item = getCancel;
|
|
}
|
|
else
|
|
{
|
|
openorsave = sfItemOpenButton;
|
|
promptitem = sfItemPromptStaticText;
|
|
nmlistitem = sfItemFileListUser;
|
|
diskname = sfItemVolumeUser;
|
|
ejectitem = sfItemEjectButton;
|
|
driveitem = sfItemDesktopButton;
|
|
f.fl_cancel_item = sfItemCancelButton;
|
|
}
|
|
}
|
|
gp = thePort;
|
|
dp = GetNewDialog(dig, (Ptr)0, (WindowPtr)-1);
|
|
bumpsavedisk(dp, FALSE);
|
|
SetPort(dp);
|
|
GetDItem(dp, openorsave, &i, &sahand, &r);
|
|
sahand.p = MR(sahand.p);
|
|
if (getorput == put && SF_NAME (&f)[0])
|
|
{
|
|
boolean_t writable;
|
|
|
|
getdiskname (NULL, &writable);
|
|
sav = TRUE;
|
|
}
|
|
else
|
|
{
|
|
sav = FALSE;
|
|
HiliteControl((ControlHandle) sahand.p, 255);
|
|
}
|
|
GetDItem(dp, ejectitem, &i, &ejhand, &r);
|
|
ejhand.p = MR(ejhand.p);
|
|
HiliteControl((ControlHandle) ejhand.p, 255);
|
|
GetDItem(dp, driveitem, &i, &drhand, &r);
|
|
drhand.p = MR(drhand.p);
|
|
adjustdrivebutton(dp);
|
|
|
|
if (getorput == put)
|
|
{
|
|
GetDItem(dp, promptitem, &i, &h, &r);
|
|
h.p = MR(h.p);
|
|
SetIText(h.p, prompt ? prompt : (StringPtr) "");
|
|
}
|
|
|
|
GetDItem(dp, nmlistitem, &i, &h, &scrollrect);
|
|
h.p = MR(h.p);
|
|
|
|
if (getorput == put) {
|
|
INTEGER putname;
|
|
|
|
if (f.flavor == original_sf)
|
|
{
|
|
putname = putName;
|
|
transform = CW(scrollrect.right) - CW(scrollrect.left) == 1;
|
|
}
|
|
else
|
|
{
|
|
putname = sfItemFileNameTextEdit;
|
|
transform = FALSE;
|
|
new_folder_button = create_new_folder_button (dp);
|
|
}
|
|
|
|
GetDItem(dp, putname, &i, &pnhand, &r);
|
|
pnhand.p = MR(pnhand.p);
|
|
SetIText(pnhand.p, SF_NAME (&f));
|
|
SelIText((DialogPtr) dp, putname, 0, 32767);
|
|
} else {
|
|
if (f.flavor == original_sf)
|
|
{
|
|
GetDItem(dp, getScroll, &i, &h, &r);
|
|
h.p = MR(h.p);
|
|
transform = CW(r.right) - CW(r.left) == 16;
|
|
GetDItem(dp, getDotted, &i, &h, &r);
|
|
h.p = MR(h.p);
|
|
SetDItem(dp, getDotted, userItem, (Handle) P_ROMlib_filebox, &r);
|
|
}
|
|
else
|
|
transform = FALSE;
|
|
}
|
|
|
|
if ( transform )
|
|
transformsfpdialog(dp, &p, &scrollrect, getorput == get);
|
|
|
|
SetDItem(dp, nmlistitem, userItem, (Handle) P_ROMlib_filebox, &scrollrect);
|
|
|
|
GetDItem(dp, diskname, &i, &h, &r);
|
|
h.p = MR(h.p);
|
|
SetDItem(dp, diskname, userItem, (Handle) P_ROMlib_filebox, &r);
|
|
|
|
r.left = CW(CW(scrollrect.left) + 1);
|
|
r.right = CW(CW(scrollrect.right) - 16);
|
|
r.top = CW(CW(scrollrect.top) + 1);
|
|
r.bottom = CW(CW(scrollrect.bottom) - 1);
|
|
scrollrect.left = CW(CW(scrollrect.right) - 16);
|
|
scrollh = NewControl((WindowPtr) dp, &scrollrect, (StringPtr) "", TRUE,
|
|
0, 0, 0, scrollBarProc, 0L);
|
|
flinit(&f, &r, scrollh);
|
|
f.flfilef = filef;
|
|
f.flnumt = numt;
|
|
f.fltl = tl;
|
|
f.flch = (ControlHandle) sahand.p;
|
|
f.flgraynondirs = getorput == get ? 0 : GRAYBIT;
|
|
|
|
if (getorput == get) {
|
|
if (f.flnmfil > 0) {
|
|
StringPtr ip;
|
|
|
|
ip = (StringPtr) MR(*f.flstrs) + MR(*f.flinfo)[0].floffs;
|
|
str31assign (SF_NAME (&f), ip);
|
|
} else
|
|
(SF_NAME (&f))[0] = 0;
|
|
}
|
|
SetWRefCon((WindowPtr) dp, (LONGINT)(long)US_TO_SYN68K(&f));
|
|
if (CW(dp->portRect.bottom) + p.v + 7 > CW(screenBitsX.bounds.bottom))
|
|
p.v = CW(screenBitsX.bounds.bottom) - CW(dp->portRect.bottom) - 7;
|
|
if (p.v < CW(MBarHeight) + 7)
|
|
p.v = CW(MBarHeight) + 7;
|
|
MoveWindow((WindowPtr) dp, p.h, p.v, FALSE);
|
|
|
|
ihit = -1;
|
|
if (dh.odh)
|
|
ihit = ROMlib_CALLDHOOK(&f, -1, dp, dh); /* the mac does this */
|
|
|
|
flfill(&f); /* moved to after dhook call of -1 suggested by
|
|
Wieslaw Kuzmicz */
|
|
|
|
ShowWindow((WindowPtr) dp);
|
|
SelectWindow((WindowPtr) dp);
|
|
while (!done) {
|
|
ModalDialog((ProcPtr) P_ROMlib_stdffilt, &ihit);
|
|
ihit = CW(ihit);
|
|
if (getorput == put)
|
|
GetIText(pnhand.p, SF_NAME (&f));
|
|
if (dh.odh)
|
|
ihit = ROMlib_CALLDHOOK(&f, ihit, dp, dh);
|
|
if (ihit == openorsave) {
|
|
makeworking (&f);
|
|
if (getorput == get) {
|
|
if (*SF_FTYPE_XP(&f)) /* will never happen unless someone */
|
|
(SF_NAME (&f)) [0] = 0;/* has a tricky filterproc */
|
|
else
|
|
*SF_FTYPE_XP(&f) = gettypeX(SF_NAME (&f), SF_VREFNUM (&f),
|
|
SF_DIRID (&f));
|
|
done = TRUE;
|
|
*SF_GOOD_XP(&f) = CBC (TRUE);
|
|
} else {
|
|
GetIText(pnhand.p, SF_NAME (&f));
|
|
hpb.dirInfo.ioCompletion = 0;
|
|
hpb.dirInfo.ioNamePtr = ((StringPtr)
|
|
RM((char *) SF_NAME (&f)));
|
|
hpb.dirInfo.ioVRefNum = SF_VREFNUM_X (&f);
|
|
hpb.dirInfo.ioFDirIndex = CWC (0);
|
|
hpb.dirInfo.ioDrDirID = 0;
|
|
err = PBGetCatInfo(&hpb, FALSE);
|
|
switch (err) {
|
|
case noErr:
|
|
ParamText(SF_NAME (&f), (StringPtr)0, (StringPtr)0,
|
|
(StringPtr)0);
|
|
if (movealert(-3996) == 1) /* overwrite ... */
|
|
break;
|
|
*SF_FTYPE_XP (&f) = hpb.hFileInfo.ioFlFndrInfo.fdType;
|
|
/* FALL THROUGH */
|
|
default:
|
|
if (err != noErr)
|
|
warning_unexpected ("err = %d", err);
|
|
/* FALL THROUGH */
|
|
case fnfErr:
|
|
done = TRUE;
|
|
*SF_GOOD_XP(&f) = CBC (TRUE); /* great. That's a take */
|
|
break;
|
|
case bdNamErr:
|
|
case nsvErr:
|
|
case paramErr:
|
|
movealert(-3994); /* disknotfound */
|
|
break;
|
|
}
|
|
}
|
|
} else if ((ihit == f.fl_cancel_item) ||
|
|
(ihit == putCancel)) { /* MYM 6.0 suggests that putCancel
|
|
cancels a get, too */
|
|
done = TRUE;
|
|
} else if (ihit == ejectitem) {
|
|
doeject(dp);
|
|
ihit = FAKEREDRAW;
|
|
} else if (ihit == driveitem) {
|
|
bumpsavedisk(dp, TRUE);
|
|
ihit = FAKEREDRAW;
|
|
} else if (ihit == diskname) {
|
|
if (moveuponedir(dp))
|
|
ihit = FAKEREDRAW;
|
|
} else if (ihit == FAKECURDIR) {
|
|
if (trackdirs((DialogPeek) dp))
|
|
ihit = FAKEREDRAW;
|
|
} else if (ihit == FAKEOPENDIR) {
|
|
CurDirStore = *SF_FTYPE_XP(&f);
|
|
unixcd(&f);
|
|
ihit = FAKEREDRAW;
|
|
} else if (ihit == sfItemNewFolderUser)
|
|
{
|
|
if (do_new_folder (&f))
|
|
{
|
|
CurDirStore = *SF_FTYPE_XP(&f);
|
|
unixcd (&f);
|
|
ihit = FAKEREDRAW;
|
|
}
|
|
}
|
|
if (getorput == put) {
|
|
Str255 file_name;
|
|
boolean_t writable;
|
|
|
|
GetIText(pnhand.p, file_name);
|
|
str31assign (SF_NAME (&f), file_name);
|
|
getdiskname (NULL, &writable);
|
|
if ((SF_NAME (&f))[0] && writable && !sav) {
|
|
HiliteControl((ControlHandle) sahand.p, 0);
|
|
sav = TRUE;
|
|
} else if ((!(SF_NAME (&f)[0]) || !writable) && sav) {
|
|
HiliteControl((ControlHandle) sahand.p, 255);
|
|
sav = FALSE;
|
|
}
|
|
}
|
|
if (WaitNextEvent(diskMask, &evt, 4, 0) &&
|
|
(evt.message & CLC(0xFFFF0000)) == 0) {
|
|
pbr.volumeParam.ioNamePtr = 0;
|
|
pbr.volumeParam.ioVolIndex = 0;
|
|
pbr.volumeParam.ioVRefNum = CW(CL(evt.message) & 0xFFFF);
|
|
err = PBGetVInfo(&pbr, FALSE);
|
|
gui_assert(err == noErr);
|
|
if (err == noErr) {
|
|
adjustdrivebutton(dp);
|
|
SFSaveDisk = CW(-CW(pbr.volumeParam.ioVRefNum));
|
|
CurDirStore = CLC(2);
|
|
ihit = FAKEREDRAW;
|
|
}
|
|
}
|
|
if (ihit == FAKEREDRAW)
|
|
realcd((DialogPeek) dp, CL(CurDirStore));
|
|
}
|
|
if (f.flavor != original_sf && dh.odh)
|
|
ihit = ROMlib_CALLDHOOK(&f, -2, dp, dh); /* the mac does this */
|
|
flfinit(&f);
|
|
destroy_new_folder_button (dp, new_folder_button);
|
|
CloseDialog((DialogPtr) dp);
|
|
makeworking (&f);
|
|
SetPort(gp);
|
|
}
|
|
TRAPEND();
|
|
}
|
|
|
|
P7(PUBLIC pascal trap, void, SFPPutFile, Point, p, StringPtr, prompt,
|
|
StringPtr, name, ProcPtr, dh, SFReply *, rep, INTEGER, dig, ProcPtr, fp)
|
|
{
|
|
dialog_hook_u dhu;
|
|
reply_u repu;
|
|
filter_u filteru;
|
|
file_filter_u zero_file_filter = { 0 };
|
|
|
|
dhu.odh = dh;
|
|
repu.oreplyp = rep;
|
|
filteru.ofilterp = fp;
|
|
|
|
spfcommon(p, prompt, name, dhu, repu, dig, filteru, zero_file_filter, -1,
|
|
(OSType *) 0, put, original_sf, 0, 0, 0);
|
|
}
|
|
|
|
P5(PUBLIC pascal trap, void, SFPutFile, Point, p, StringPtr, prompt,
|
|
StringPtr, name, ProcPtr, dh, SFReply *, rep)
|
|
{
|
|
SFPPutFile(p, prompt, name, dh, rep, putDlgID, (ProcPtr) 0);
|
|
}
|
|
|
|
P9(PUBLIC pascal trap, void, SFPGetFile, Point, p, StringPtr, prompt,
|
|
ProcPtr, filef, INTEGER, numt, SFTypeList, tl, ProcPtr, dh,
|
|
SFReply *, rep, INTEGER, dig, ProcPtr, fp)
|
|
{
|
|
dialog_hook_u dhu;
|
|
reply_u repu;
|
|
filter_u filteru;
|
|
file_filter_u file_filteru;
|
|
|
|
dhu.odh = dh;
|
|
repu.oreplyp = rep;
|
|
filteru.ofilterp = fp;
|
|
file_filteru.oflfilef = filef;
|
|
|
|
spfcommon(p, prompt, (StringPtr) "", dhu, repu, dig, filteru, file_filteru,
|
|
numt, tl, get, original_sf, 0, 0, 0);
|
|
}
|
|
|
|
P7(PUBLIC pascal trap, void, SFGetFile, Point, p, StringPtr, prompt,
|
|
ProcPtr, filef, INTEGER, numt, SFTypeList, tl, ProcPtr, dh, SFReply *, rep)
|
|
{
|
|
SFPGetFile(p, prompt, filef, numt, tl, dh, rep, getDlgID, (ProcPtr) 0);
|
|
}
|
|
|
|
P10(PUBLIC pascal trap, void, CustomPutFile, Str255, prompt,
|
|
Str255, defaultName, StandardFileReply *, replyp, INTEGER, dlgid,
|
|
Point, where, DlgHookYDProcPtr, dlghook, ModalFilterYDProcPtr, filterproc,
|
|
Ptr, activeList, ActivateYDProcPtr, activateproc, UNIV Ptr, yourdatap)
|
|
{
|
|
dialog_hook_u dhu;
|
|
reply_u repu;
|
|
filter_u filteru;
|
|
file_filter_u file_filteru;
|
|
|
|
dhu.cdh = dlghook;
|
|
repu.nreplyp = replyp;
|
|
file_filteru.cflfilef = 0;
|
|
filteru.cfilterp = filterproc;
|
|
|
|
if (dlgid == 0)
|
|
dlgid = sfPutDialogID;
|
|
|
|
|
|
spfcommon (where, prompt, defaultName, dhu, repu, dlgid, filteru,
|
|
file_filteru, -1, 0, put, new_custom_sf, activeList,
|
|
activateproc, yourdatap);
|
|
}
|
|
|
|
P11(PUBLIC pascal trap, void, CustomGetFile, FileFilterYDProcPtr, filefilter,
|
|
INTEGER, numtypes, SFTypeList, typelist, StandardFileReply *, replyp,
|
|
INTEGER, dlgid, Point, where, DlgHookYDProcPtr, dlghook,
|
|
ModalFilterYDProcPtr, filterproc, Ptr, activeList,
|
|
ActivateYDProcPtr, activateproc, UNIV Ptr, yourdatap)
|
|
{
|
|
dialog_hook_u dhu;
|
|
reply_u repu;
|
|
filter_u filteru;
|
|
file_filter_u file_filteru;
|
|
|
|
dhu.cdh = dlghook;
|
|
repu.nreplyp = replyp;
|
|
filteru.cfilterp = filterproc;
|
|
file_filteru.cflfilef = filefilter;
|
|
|
|
if (dlgid == 0)
|
|
dlgid = sfGetDialogID;
|
|
|
|
spfcommon (where, (StringPtr) "", (StringPtr) "", dhu, repu, dlgid,
|
|
filteru, file_filteru, numtypes,
|
|
typelist, get, new_custom_sf, activeList, activateproc,
|
|
yourdatap);
|
|
}
|
|
|
|
P4(PUBLIC pascal trap, void, StandardGetFile, ProcPtr, filef, INTEGER, numt,
|
|
SFTypeList, tl, StandardFileReply *, replyp)
|
|
{
|
|
Point p;
|
|
reply_u repu;
|
|
file_filter_u file_filteru;
|
|
dialog_hook_u dhu;
|
|
filter_u filteru;
|
|
|
|
repu.nreplyp = replyp;
|
|
file_filteru.oflfilef = filef;
|
|
dhu.cdh = 0;
|
|
filteru.cfilterp = 0;
|
|
|
|
p.h = -1;
|
|
p.v = -1;
|
|
spfcommon (p, (StringPtr) "", (StringPtr) "", dhu, repu, sfGetDialogID,
|
|
filteru, file_filteru, numt, tl, get, new_sf, 0, 0, 0);
|
|
}
|
|
|
|
P3(PUBLIC pascal trap, void, StandardPutFile, Str255, prompt,
|
|
Str255, defaultname, StandardFileReply *, replyp)
|
|
{
|
|
Point p;
|
|
reply_u repu;
|
|
file_filter_u file_filteru;
|
|
dialog_hook_u dhu;
|
|
filter_u filteru;
|
|
|
|
filteru.cfilterp = 0;
|
|
repu.nreplyp = replyp;
|
|
file_filteru.cflfilef = 0;
|
|
dhu.cdh = 0;
|
|
|
|
p.h = -1;
|
|
p.v = -1;
|
|
spfcommon (p, prompt, defaultname, dhu, repu, sfPutDialogID, filteru,
|
|
file_filteru, -1, 0, put, new_sf, 0, 0, 0);
|
|
}
|