home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / MacPerl5 / MPFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-28  |  18.3 KB  |  829 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPFile.c            -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPFile.c,v $
  12. Revision 1.1  1994/02/27  23:00:47  neeri
  13. Initial revision
  14.  
  15. Revision 0.6  1993/09/17  00:00:00  neeri
  16. Runtime version
  17.  
  18. Revision 0.5  1993/08/28  00:00:00  neeri
  19. Handle multiple preference files
  20.  
  21. Revision 0.4  1993/08/17  00:00:00  neeri
  22. Enable Save
  23.  
  24. Revision 0.3  1993/08/13  00:00:00  neeri
  25. Write bounds rectangles
  26.  
  27. Revision 0.2  1993/05/30  00:00:00  neeri
  28. Support Console Windows
  29.  
  30. Revision 0.1  1993/05/29  00:00:00  neeri
  31. Compiles correctly
  32.  
  33. *********************************************************************/
  34.  
  35. #include <Errors.h>
  36. #include <Resources.h>
  37. #include <Desk.h>
  38. #include <PLStringFuncs.h>
  39. #include <AppleEvents.h>
  40. #include <AERegistry.h>
  41. #include <StandardFile.h>
  42. #include <TFileSpec.h>
  43. #include <Balloons.h>
  44.  
  45. #include "MPFile.h"
  46. #include "MPSave.h"
  47.  
  48. /**-----------------------------------------------------------------------
  49.         Name:             FileError
  50.         Purpose:        Puts up an error alert.
  51.     -----------------------------------------------------------------------**/
  52.  
  53.  
  54. #if !defined(powerc) && !defined(__powerc)
  55. #pragma segment File
  56. #endif
  57.  
  58. pascal void FileError(Str255 s, Str255 f)
  59. {
  60.     SetCursor(&qd.arrow);
  61.     ParamText(s, f, (StringPtr) "\p", (StringPtr) "\p");
  62.      Alert(ErrorAlert, nil);
  63. }
  64.  
  65. /**-----------------------------------------------------------------------
  66.         Name:             DoClose
  67.         Purpose:        Closes a window.
  68.     -----------------------------------------------------------------------**/
  69.  
  70. #if !defined(powerc) && !defined(__powerc)
  71. #pragma segment File
  72. #endif
  73.  
  74. pascal OSErr DoClose(WindowPtr aWindow, Boolean canInteract, DescType dialogAnswer)
  75. {
  76.      DPtr    aDocument;
  77.      short   alertResult;
  78.      Str255  theName;
  79.     OSErr   myErr;
  80.  
  81.     myErr = noErr;
  82.  
  83.      if (gWCount > 0) {
  84.         aDocument = DPtrFromWindowPtr(aWindow);
  85.  
  86.         if (aDocument->kind == kDocumentWindow) {
  87.             if (aDocument->dirty)
  88.                 if (canInteract && (dialogAnswer==kAEAsk)) {
  89.                     if (aDocument->u.reg.everSaved == false)
  90.                         GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
  91.                     else
  92.                         PLstrcpy(theName, aDocument->theFileName);
  93.     
  94.                     ParamText(theName, (StringPtr) "\p", (StringPtr) "\p", (StringPtr) "\p");
  95.                     SetCursor(&qd.arrow);
  96.                     alertResult = Alert(SaveAlert, nil);
  97.                     switch (alertResult) {
  98.                     case aaSave:
  99.                         myErr = SaveAskingName(aDocument, canInteract);
  100.                         break;
  101.     
  102.                     case aaCancel:
  103.                         return userCanceledErr;
  104.     
  105.                     case aaDiscard:
  106.                         aDocument->dirty = false;
  107.                         break;
  108.                     }
  109.                 } else {
  110.                     if (dialogAnswer==kAEYes)
  111.                         myErr = SaveAskingName(aDocument, canInteract);
  112.                     else
  113.                         myErr = noErr; /* Don't save */
  114.                 }
  115.                 
  116.             if (!myErr) {
  117.                 if (aDocument->kind == kDocumentWindow && aDocument->u.reg.numSections)
  118.                     DeRegisterAllSections(aDocument);
  119.  
  120.                 CloseMyWindow(aWindow);
  121.             }
  122.         } else if (aDocument->u.cons.selected) {
  123.             if (!gQuitting) {
  124.                 SysBeep(0);
  125.     
  126.                 return userCanceledErr;
  127.             }
  128.         } else 
  129.             SaveConsole(aDocument);
  130.     } else
  131.         myErr = errAEIllegalIndex;
  132.  
  133.     return myErr;
  134. }
  135.  
  136. #if !defined(powerc) && !defined(__powerc)
  137. #pragma segment File
  138. #endif
  139.  
  140. //  DoQuit
  141. //  saveOpt - one of kAEAsk,kAEYes,kAENo
  142. //  if kAEYes or kAEAsk then AEInteactWithUser should have been called
  143. //  before DoQuit. Assumes that it can interact if it needs to.
  144.  
  145. pascal void DoQuit(DescType saveOpt)
  146. {
  147.     WindowPeek    aWindow;
  148.     WindowPeek    nextWindow;
  149.     short            theKind;
  150.  
  151.     if (gRunningPerl && (Alert(AbortAlert, nil) == 2))
  152.         return;
  153.         
  154.     gQuitting = true;
  155.  
  156.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  157.         nextWindow = aWindow->nextWindow;
  158.         if (Ours((WindowPtr) aWindow)) {
  159.             if (DoClose((WindowPtr) aWindow, true, saveOpt)) {
  160.                 gQuitting = false;
  161.                 
  162.                 return;
  163.             }
  164.         } else {
  165.             theKind = aWindow->windowKind;
  166.             if (theKind < 0)
  167.                 CloseDeskAcc(theKind);
  168.         }
  169.     }
  170. }
  171.  
  172. pascal Boolean GetFileFilter(CInfoPBPtr pb)
  173. {
  174.     switch (GetDocTypeFromInfo(pb)) {
  175.     case kPreferenceDoc:
  176.         /* We don't want preference files here. Maybe we should */
  177.     case kUnknownDoc:
  178.         return true;
  179.     default:
  180.         return false;
  181.     }
  182. }
  183.  
  184. #if USESROUTINEDESCRIPTORS
  185. RoutineDescriptor    uGetFileFilter = 
  186.         BUILD_ROUTINE_DESCRIPTOR(uppFileFilterProcInfo, GetFileFilter);
  187. #else
  188. #define uGetFileFilter *(FileFilterUPP)&GetFileFilter
  189. #endif
  190.  
  191. pascal OSErr GetFile(FSSpec *theFSSpec)
  192. {
  193.     StandardFileReply  reply;
  194.  
  195.     BuildSEList();
  196.     
  197.     StandardGetFile(&uGetFileFilter, MacPerlFileTypeCount, MacPerlFileTypes, &reply);
  198.  
  199.     if (reply.sfGood) {
  200.         *theFSSpec = reply.sfFile;
  201.         return noErr;
  202.     } else
  203.         return userCanceledErr;
  204. }
  205.  
  206. #if !defined(powerc) && !defined(__powerc)
  207. #pragma segment File
  208. #endif
  209.  
  210. pascal OSErr DoCreate(FSSpec theSpec)
  211. {
  212.     OSErr err;
  213.  
  214.     err = FSpCreate(&theSpec, MPAppSig, 'TEXT', smSystemScript);
  215.  
  216.     if (!err)
  217.         HCreateResFile(theSpec.vRefNum, theSpec.parID, theSpec.name);
  218.     else
  219.         ShowError((StringPtr) "\pCreating", err);
  220.  
  221.     return err;
  222. }
  223.  
  224. pascal OSErr SaveConsole(DPtr doc)
  225. {
  226.     OSErr            err;
  227.     short       resFile;
  228.     HHandle     theHHandle;
  229.     Str255        title;
  230.     Boolean        existing;
  231.     
  232.     if (gPrefsFile) {
  233.         resFile    =    CurResFile();
  234.         UseResFile(gPrefsFile);
  235.         GetWTitle(doc->theWindow, title);
  236.         
  237.         if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
  238.             existing = true;
  239.         } else {
  240.             existing = false;
  241.             theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  242.         }
  243.         
  244.         HLock((Handle)theHHandle);
  245.     
  246.         (*theHHandle)->theRect     = doc->theWindow->portRect;
  247.         OffsetRect(
  248.             &(*theHHandle)->theRect,
  249.             -doc->theWindow->portBits.bounds.left,
  250.             -doc->theWindow->portBits.bounds.top);
  251.             
  252.         GetFontName((*(doc->theText))->txFont, (StringPtr) &(*theHHandle)->theFont);
  253.         
  254.         (*theHHandle)->theSize     = (*(doc->theText))->txSize;
  255.         (*theHHandle)->lastID      = 0;
  256.         (*theHHandle)->numSections = 0;
  257.     
  258.         HUnlock((Handle)theHHandle);
  259.     
  260.         if (existing) {
  261.             ChangedResource((Handle) theHHandle);
  262.             WriteResource((Handle) theHHandle);
  263.             UpdateResFile(gPrefsFile);
  264.         } else {
  265.             AddResource((Handle)theHHandle, 'TFSS', Unique1ID('TFSS'), title);
  266.         }
  267.         
  268.         err = ResError();
  269.         
  270.         UseResFile(resFile);
  271.     }
  272.     
  273.     if (doc->u.cons.cookie) {
  274.         /* We might need this window again. */
  275.         DoHideWindow(doc->theWindow);
  276.         TESetSelect(0, 32767, doc->theText);
  277.         TEDelete(doc->theText);
  278.     
  279.         if (doc->u.cons.fence < 32767)
  280.             doc->u.cons.fence    = 0;
  281.     } else /* Done with this window */
  282.         CloseMyWindow(doc->theWindow);
  283.     
  284.     return err;
  285.  
  286. pascal void ApplySettings(DPtr doc, HPtr settings)
  287. {
  288.     short        fNum;
  289.     FontInfo    info;
  290.     Rect        bounds;
  291.     
  292.     GetFNum(settings->theFont, &fNum);
  293.     SetPort(doc->theWindow);
  294.     TextFont(fNum);
  295.     TextSize(settings->theSize);
  296.     GetFontInfo(&info);
  297.     
  298.     (*doc->theText)->txFont         = fNum;
  299.     (*doc->theText)->txSize         = settings->theSize;
  300.     (*doc->theText)->lineHeight    = info.ascent+info.descent+info.leading;
  301.     (*doc->theText)->fontAscent    = info.ascent;
  302.     
  303.     bounds.top                            = settings->theRect.top - 13;
  304.     bounds.left                            = settings->theRect.left + 5;
  305.     bounds.bottom                        = settings->theRect.top  - 5;
  306.     bounds.right                        = settings->theRect.right - 5;
  307.     
  308.     if (settings->theRect.right > settings->theRect.left + 50 &&
  309.         settings->theRect.bottom > settings->theRect.top  + 50 &&
  310.         RectInRgn(&bounds, GetGrayRgn())
  311.     ) {
  312.         MoveWindow(doc->theWindow, settings->theRect.left, settings->theRect.top, false);
  313.         SizeWindow(
  314.             doc->theWindow,
  315.             settings->theRect.right - settings->theRect.left,
  316.             settings->theRect.bottom - settings->theRect.top,
  317.             false);
  318.     }
  319.         
  320.     ResizeWindow(doc);
  321. }
  322.  
  323. pascal void RestoreConsole(DPtr doc)
  324. {
  325.     short       resFile;
  326.     HHandle     theHHandle;
  327.     Str255        title;
  328.     
  329.     if (!gPrefsFile)
  330.         return;
  331.         
  332.     resFile    =    CurResFile();
  333.     UseResFile(gPrefsFile);
  334.     GetWTitle(doc->theWindow, title);
  335.     
  336.     if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
  337.          HLock((Handle)theHHandle);
  338.         
  339.         ApplySettings(doc, *theHHandle);
  340.         
  341.         HUnlock((Handle)theHHandle);
  342.     }
  343.     
  344.     UseResFile(resFile);
  345. }
  346.  
  347.  
  348. /** -----------------------------------------------------------------------
  349.         Name:         GetFileContents
  350.         Purpose:        Opens the document specified by theFSSpec and puts
  351.                         the contents into theDocument.
  352.      -----------------------------------------------------------------------**/
  353.  
  354. #if !defined(powerc) && !defined(__powerc)
  355. #pragma segment File
  356. #endif
  357.  
  358. pascal OSErr GetFileContents(FSSpec spec, DPtr theDocument)
  359. {
  360.     long            theSize;
  361.     short            oldRes;
  362.     short            resFile;
  363.     short            refNum;
  364.     OSErr            err;
  365.     HHandle        aHandle;
  366.     Handle        gHandle;
  367.  
  368.     oldRes    =    CurResFile();
  369.     resFile     =    HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
  370.     
  371.     theDocument->u.reg.everLoaded = true;
  372.     theDocument->u.reg.origFSSpec = spec;
  373.     
  374.     if (theDocument->inDataFork) {
  375.         if (err = HOpenDF(spec.vRefNum, spec.parID, spec.name, fsRdPerm, &refNum)) {
  376.             ShowError((StringPtr) "\pread file - HOpenDF", err);
  377.             refNum = 0;
  378.             
  379.             goto giveUp;
  380.         }
  381.     
  382.         if (err = GetEOF(refNum, &theSize))
  383.             goto giveUp;
  384.  
  385.           gHandle = NewHandle(theSize);
  386.  
  387.         HLock(gHandle);
  388.         if (err = FSRead(refNum, &theSize, *gHandle))
  389.             return err;
  390.         HUnlock(gHandle);
  391.         FSClose(refNum);
  392.     } else {
  393.         gHandle    =    Get1NamedResource('TEXT', (StringPtr) "\p!");
  394.         
  395.         if (gHandle) 
  396.             DetachResource(gHandle);
  397.         else {
  398.             err = ResError();
  399.             
  400.             goto giveUp;
  401.         }
  402.     }
  403.  
  404.     theDocument->u.reg.numSections = 0;
  405.  
  406.     if (resFile != -1) {
  407.         aHandle = nil;
  408.  
  409.         if (Count1Resources('TFSS'))
  410.             aHandle = (HHandle)Get1Resource('TFSS', 255);
  411.  
  412.         if (aHandle) {
  413.             theDocument->u.reg.numSections = (*aHandle)->numSections;
  414.             
  415.             HLock((Handle) aHandle);
  416.             ApplySettings(theDocument, *aHandle);
  417.         }
  418.  
  419.         /*
  420.             If there is a print record saved, ditch the old one
  421.             created by new document and fill this one in
  422.         */
  423.         if (Count1Resources('TFSP')) {
  424.             if (theDocument->thePrintSetup)
  425.                 DisposHandle((Handle)theDocument->thePrintSetup);
  426.  
  427.             theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
  428.               HandToHand((Handle *)&theDocument->thePrintSetup);
  429.  
  430.             PrOpen();
  431.             PrValidate(theDocument->thePrintSetup);
  432.             PrClose();
  433.         }
  434.  
  435.         if (theDocument->u.reg.numSections) {
  436.             ReadSectionRecords(theDocument);
  437.             ReadAllSectionResources(theDocument);
  438.         }
  439.  
  440.         CloseResFile(resFile);
  441.  
  442.         if (err = ResError()) {
  443.             ShowError((StringPtr) "\pread file- CloseResFile", err);
  444.             return err;
  445.         }
  446.     }
  447.  
  448.     HLock(gHandle);
  449.     if (GetHandleSize(gHandle) > 32000) {
  450.         PtrToXHand(
  451.             *gHandle, 
  452.             (*theDocument->theText)->hText, 
  453.             GetHandleSize(gHandle));
  454.         
  455.         err = elvisErr;
  456.     } else
  457.         TESetText(*gHandle, GetHandleSize(gHandle), theDocument->theText);
  458.     DisposHandle(gHandle);
  459.  
  460.     if (err == fnfErr)
  461.         return noErr;
  462.     else
  463.           return err;
  464.  
  465. giveUp:    
  466.     if (refNum)
  467.         FSClose(refNum);
  468.         
  469.     if (resFile > -1)
  470.         CloseResFile(resFile);
  471.     
  472.     UseResFile(oldRes);
  473.     
  474.     return err;
  475. } /* GetFileContents */
  476.  
  477.  
  478. #if !defined(powerc) && !defined(__powerc)
  479. #pragma segment File
  480. #endif
  481.  
  482. pascal OSErr SaveAskingName(DPtr aDocument, Boolean canInteract)
  483. {
  484.     OSErr    myErr;
  485.  
  486.     if (aDocument->kind != kDocumentWindow || !aDocument->u.reg.everSaved) {
  487.  
  488.         if (canInteract) {
  489.             if (myErr = GetFileNameToSaveAs(aDocument))
  490.                 return myErr;
  491.  
  492.             if (myErr = SaveWithoutTemp(aDocument, aDocument->theFSSpec))
  493.                 return myErr;            
  494.             AssocAllSections(aDocument);
  495.  
  496.             return noErr;
  497.         } else
  498.             return errAENoUserInteraction;
  499.  
  500.     } else
  501.         return SaveUsingTemp(aDocument);
  502. }
  503.  
  504. #if !defined(powerc) && !defined(__powerc)
  505. #pragma segment File
  506. #endif
  507.  
  508. pascal OSErr SaveUsingTemp(DPtr theDocument)
  509. {
  510.     Str255    tempName;
  511.     OSErr        err;
  512.     FSSpec    tempFSSpec;
  513.  
  514.     /*save the file to disk using a temporary file*/
  515.     /*this is the recommended way of doing things*/
  516.     /*first write out the file to disk using a temporary filename*/
  517.     /*if it is sucessfully written, exchange the temporary file with the last one saved*/
  518.     /*then delete the temporary file- so if anything goes wrong, the original version is still there*/
  519.     /*first generate the temporary filename*/
  520.  
  521.     GetTempFSSpec(theDocument, &tempFSSpec);
  522.  
  523.     if (err = DoCreate(tempFSSpec))
  524.         return err;
  525.  
  526.     if (err = DoSave(theDocument, tempFSSpec))
  527.         return err;
  528.     
  529.     if (err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec))
  530.         return err;
  531.     
  532.     /*we've exchanged the files, now delete the temporary one*/
  533.  
  534.     FSpDelete(&tempFSSpec);
  535.     
  536.     if (!err && theDocument->kind == kDocumentWindow) {
  537.         theDocument->dirty                 = false;
  538.         theDocument->u.reg.everSaved     = true;
  539.         theDocument->u.reg.origFSSpec = theDocument->theFSSpec;
  540.     }
  541.  
  542.     return err;
  543. }
  544.  
  545. pascal OSErr SaveWithoutTemp(DPtr theDocument, FSSpec spec)
  546. {
  547.     OSErr        err;
  548.     
  549.     if (err = DoSave(theDocument, spec))
  550.         return err;
  551.  
  552.     if (theDocument->kind == kDocumentWindow) {
  553.         theDocument->dirty                 = false;
  554.         theDocument->u.reg.everSaved     = true;
  555.         theDocument->u.reg.origFSSpec = theDocument->theFSSpec = spec;
  556.                 
  557.         SetWTitle(theDocument->theWindow, theDocument->theFSSpec.name);
  558.     }
  559.     
  560.     return noErr;
  561. }
  562.  
  563. #if !defined(powerc) && !defined(__powerc)
  564. #pragma segment File
  565. #endif
  566.  
  567. pascal short SaveScriptHook(short item, DialogPtr dlg, void * params)
  568. {
  569.     short                kind;
  570.     ControlHandle    type;
  571.     MenuHandle        typeMenu;
  572.     Rect                r;
  573.     DPtr                doc = (DPtr) params;
  574.     
  575.     if (GetWRefCon(dlg) != 'stdf')
  576.         return item;
  577.         
  578.     switch (item) {
  579.     case sfHookFirstCall:
  580.         GetDItem(dlg, ssd_Type, &kind, (Handle *) &type, &r);
  581.         typeMenu = (*(PopupPrivateDataHandle)(*type)->contrlData)->mHandle;
  582.         
  583.         AddExtensionsToMenu(typeMenu);
  584.         SetControlMaximum(type, CountMItems(typeMenu));
  585.         SetCtlValue(type, Type2Menu(doc->type));
  586.         
  587.         return sfHookFirstCall;
  588.     case ssd_Type:
  589.         GetDItem(dlg, item, &kind, (Handle *) &type, &r);
  590.         
  591.         doc->type = (DocType) Menu2Type(GetCtlValue(type));
  592.         
  593.         return sfHookNullEvent;
  594.     default:
  595.         return item;
  596.     }
  597. }
  598.  
  599. #if USESROUTINEDESCRIPTORS
  600. RoutineDescriptor    uSaveScriptHook = 
  601.         BUILD_ROUTINE_DESCRIPTOR(uppDlgHookYDProcInfo, SaveScriptHook);
  602. #else
  603. #define uSaveScriptHook *(DlgHookYDUPP)&SaveScriptHook
  604. #endif
  605.  
  606. /*
  607.     Fills in the document record with the user chosen destination
  608. */
  609.  
  610. pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
  611. {
  612.     OSErr                    err;
  613.     StandardFileReply    reply;
  614.     Str255            suggestName;
  615.     Point                    where;
  616.     
  617.     where.h = where.v = -1;
  618.  
  619.     GetWTitle(theDocument->theWindow, suggestName);
  620.  
  621.     HMSetDialogResID(SaveScriptDialog);
  622.     CustomPutFile(
  623.         (StringPtr) "\pSave Document As:", suggestName, &reply,
  624.         SaveScriptDialog,
  625.         where,
  626.         &uSaveScriptHook,
  627.         (ModalFilterYDUPP) nil,
  628.         nil,
  629.         (ActivateYDUPP) nil,
  630.         theDocument);
  631.     HMSetDialogResID(-1);
  632.  
  633.     if (reply.sfGood)
  634.         switch (err = FSpDelete(&reply.sfFile)) {
  635.         case noErr:
  636.         case fnfErr:
  637.             theDocument->theFSSpec = reply.sfFile;
  638.             PLstrcpy(theDocument->theFileName, reply.sfFile.name);
  639.  
  640.             return noErr;
  641.         default:
  642.             return err;
  643.         }
  644.     else
  645.         return userCanceledErr;
  646. } /* GetFileNameToSaveAs */
  647.  
  648. #if !defined(powerc) && !defined(__powerc)
  649. #pragma segment File
  650. #endif
  651.  
  652. pascal DPtr MakeOldDoc(FSSpec aFSSpec, DocType type)
  653. {
  654.     DPtr          theDocument;
  655.     
  656.     theDocument = NewDocument(true, kDocumentWindow);
  657.  
  658.     SetWTitle(theDocument->theWindow, aFSSpec.name);
  659.  
  660.     SetPort(theDocument->theWindow);
  661.  
  662.     theDocument->theFSSpec   = aFSSpec;
  663.  
  664.     PLstrcpy(theDocument->theFileName, aFSSpec.name);
  665.  
  666.     theDocument->dirty               = false;
  667.     theDocument->inDataFork            = type == kPlainTextDoc;
  668.     
  669.     /* We *can* open documents created by unknown save extensions, but we can't
  670.        save them again 
  671.     */
  672.     if (CanSaveAs(type)) {
  673.         theDocument->type                 = type;
  674.         theDocument->u.reg.everSaved    = true;
  675.     } else {
  676.         theDocument->type                    = kPlainTextDoc;
  677.         theDocument->u.reg.everSaved    = false;
  678.     }
  679.  
  680.     return theDocument;
  681. }
  682.  
  683. pascal OSErr OpenOld(FSSpec aFSSpec, DocType type)
  684. {
  685.     DPtr          theDocument;
  686.     OSErr         fileErr;
  687.     WindowPtr    win;
  688.  
  689.     if (win = AlreadyOpen(&aFSSpec, nil)) {
  690.         SelectWindow(win);
  691.         
  692.         return noErr;
  693.     }
  694.     
  695.     theDocument    =    MakeOldDoc(aFSSpec, type);
  696.     
  697.     fileErr = GetFileContents(aFSSpec, theDocument);
  698.  
  699.     if (!fileErr) {
  700.         ResizeWindow(theDocument);
  701.         DoShowWindow(theDocument->theWindow);
  702.     } else {
  703.         if (fileErr == elvisErr) {
  704.             theDocument->u.reg.everSaved    = false;
  705. #ifdef RUNTIME
  706.             if (AEInteractWithUser(kAEDefaultTimeout, nil, nil))
  707. #endif
  708.                 if (Alert(ElvisAlert, nil) == 1)
  709.                     SaveAskingName(theDocument, true);
  710.         } else
  711.             FileError((StringPtr) "\pError Opening ", aFSSpec.name);
  712.         
  713.         CloseMyWindow(theDocument->theWindow);
  714.     }
  715.  
  716.     return fileErr;
  717. } /* OpenOld */
  718.  
  719. pascal OSErr File2File(FSSpec aFSSpec, DocType type, FSSpec toFSSpec, DocType newtype)
  720. {
  721.     DPtr          theDocument;
  722.     OSErr         fileErr;
  723.  
  724.     theDocument    =    MakeOldDoc(aFSSpec, type);
  725.     
  726.     switch (fileErr = GetFileContents(aFSSpec, theDocument)) {
  727.     case elvisErr:
  728.         fileErr = noErr;
  729.         /* Fall through */
  730.     case noErr:
  731.         theDocument->type = newtype;
  732.         theDocument->u.reg.everSaved    = false;
  733.         if (SameFSSpec(&aFSSpec, &toFSSpec))
  734.             fileErr = SaveUsingTemp(theDocument);
  735.         else
  736.             fileErr = SaveWithoutTemp(theDocument, toFSSpec);
  737.         
  738.         /* Fall through */
  739.     default:
  740.         CloseMyWindow(theDocument->theWindow);
  741.     }
  742.  
  743.     return fileErr;
  744. } /* File2File */
  745.  
  746. pascal OSErr Handle2File(Handle text, FSSpec toFSSpec, DocType newtype)
  747. {
  748.     DPtr          theDocument;
  749.     OSErr         fileErr;
  750.  
  751.     theDocument = NewDocument(true, kDocumentWindow);
  752.     
  753.     HLock(text);
  754.     PtrToXHand(*text, (*theDocument->theText)->hText, GetHandleSize(text));
  755.     HUnlock(text);
  756.     
  757.     theDocument->u.reg.everSaved    = false;
  758.     theDocument->type                 = newtype;
  759.  
  760.     fileErr = SaveWithoutTemp(theDocument, toFSSpec);
  761.     
  762.     CloseMyWindow(theDocument->theWindow);
  763.  
  764.     return fileErr;
  765. } /* Handle2File */
  766.  
  767. pascal DocType GetDocTypeFromFile(short vRefNum, long dirID, StringPtr name)
  768. {
  769.     short            resFile;
  770.     short            nuFile;
  771.     OSType    **    rtType;
  772.     DocType        type    =    kUnknownDoc;
  773.     
  774.     resFile    = CurResFile();
  775.     nuFile    = HOpenResFile(vRefNum, dirID, name, fsRdPerm);
  776.     
  777.     if (nuFile != -1) {
  778.         if (rtType = (OSType **) Get1Resource('MrPL', 128))
  779.             type = **(DocType **) rtType;
  780.             
  781.         CloseResFile(nuFile);
  782.     }
  783.     UseResFile(resFile);
  784.     
  785.     return type;
  786. }
  787.  
  788. pascal DocType GetDocTypeFromInfo(CInfoPBPtr info)
  789. {
  790.     DocType        type    =    kUnknownDoc;
  791.     
  792.     switch (info->hFileInfo.ioFlFndrInfo.fdType) {
  793.     case 'APPL':
  794.         if (info->hFileInfo.ioFlFndrInfo.fdCreator == MPAppSig) 
  795.             /* A heuristic to separate old runtimes from PowerPC executables */
  796.             if (info->hFileInfo.ioFlLgLen && info->hFileInfo.ioFlLgLen < 100000)
  797.                 return kOldRuntime6Doc; 
  798.         
  799.         break;
  800.     case 'TEXT':
  801.         return kPlainTextDoc;
  802.     case 'pref':
  803.         switch (info->hFileInfo.ioFlFndrInfo.fdCreator) {
  804.         case MPAppSig:
  805.         case MPRtSig:
  806.             return kPreferenceDoc;
  807.         }
  808.         break;
  809.     default:
  810.         break;
  811.     }
  812.     
  813.     /* Ultimately, with save extensions, every file could be ours */
  814.     return GetDocTypeFromFile(
  815.         info->hFileInfo.ioVRefNum, 
  816.         info->hFileInfo.ioFlParID, 
  817.         info->hFileInfo.ioNamePtr);;
  818. }
  819.  
  820. pascal DocType GetDocType(FSSpec * spec)
  821. {
  822.     CInfoPBRec    info;
  823.  
  824.     if (FSpCatInfo(spec, &info))
  825.         return kUnknownDoc;
  826.     else
  827.         return GetDocTypeFromInfo(&info);
  828. }