/* * 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 #include #include #include #include #include #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); }