home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Sample Applications / MenuScripter 1.0d4.1 / MenuScripter Source / MSFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-24  |  14.9 KB  |  666 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSFile.c
  3.     
  4.     Version 1.0d4
  5.     
  6.     Copyright © Apple Computer UK Ltd. 1992
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : UK Developer Technical Support
  11.     AppleLink   : UK.DTS
  12. */
  13. /*
  14.     Changes for 1.0d3:
  15.     
  16.     27-Aug-92    : NH : Fix length of 'STR ' #-16396
  17. */
  18.     
  19. #include <Errors.h>
  20. #include <Resources.h>
  21. #include <Desk.h>
  22. #include <PLStringFuncs.h>
  23. #include <AppleEvents.h>
  24. #include <AERegistry.h>
  25. #include "MSFile.h"
  26.  
  27. /**-----------------------------------------------------------------------
  28.         Name:             FileError
  29.         Purpose:        Puts up an error alert.
  30.     -----------------------------------------------------------------------**/
  31.  
  32.     
  33. #pragma segment File
  34.  
  35. pascal void FileError(Str255 s, Str255 f)
  36.   {
  37.     short    alertResult;
  38.  
  39.     SetCursor(&qd.arrow);
  40.         ParamText(s, f, "", "");
  41.     alertResult = Alert(ErrorAlert, nil);
  42.     }
  43.  
  44. /**-----------------------------------------------------------------------
  45.         Name:             DoClose
  46.         Purpose:        Closes a window.
  47.     -----------------------------------------------------------------------**/
  48.  
  49. #pragma segment File
  50.  
  51. pascal OSErr DoClose(WindowPtr aWindow,Boolean canInteract,DescType dialogAnswer)
  52.   {
  53.     DPtr    aDocument;
  54.     short   alertResult;
  55.     Str255  theName;
  56.         OSErr   myErr;
  57.                         
  58.         myErr = noErr;
  59.         
  60.     if (gWCount>0)
  61.       {
  62.         aDocument = DPtrFromWindowPtr(aWindow);
  63.             
  64.                 if (aDocument->dirty)
  65.                     if (canInteract && (dialogAnswer==kAEAsk))
  66.                         {
  67.                             if (aDocument->everSaved == false)
  68.                                 GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
  69.                             else
  70.                                 PLstrcpy(theName, aDocument->theFileName);
  71.                                 
  72.                             ParamText("\pSave Changes for ", theName, "", "");
  73.                           SetCursor(&qd.arrow);
  74.                             alertResult = Alert(AdviseAlert, nil);
  75.                             switch (alertResult) {
  76.                               case aaSave    :if (aDocument->everSaved == false)
  77.                                                                     {
  78.                                                                         myErr = GetFileNameToSaveAs(aDocument);
  79.                                                                         if (myErr == noErr)
  80.                                                                             myErr = DoSave(aDocument, aDocument->theFSSpec);
  81.                                                                             
  82.                                                                         if (myErr==noErr)
  83.                                                                             AssocAllSections(aDocument);
  84.                                                                     }
  85.                                                                 else
  86.                                                                     myErr = SaveUsingTemp(aDocument);
  87.                                                                 break;
  88.                                                                 
  89.                                 case aaCancel : return(userCanceledErr);
  90.                                                 break;
  91.                                                                 
  92.                                 case aaDiscard: aDocument->dirty = false;
  93.                             }
  94.                         }
  95.                     else
  96.                         {
  97.                             if (dialogAnswer==kAEYes)
  98.                                 if (aDocument->everSaved == false)
  99.                                     {
  100.                                         if (canInteract)
  101.                                             {
  102.                                               myErr = GetFileNameToSaveAs(aDocument);
  103.                                                 if (myErr==noErr)
  104.                                                     myErr = DoSave(aDocument, aDocument->theFSSpec);
  105.                                                 if (myErr==noErr)
  106.                                                     AssocAllSections(aDocument);
  107.                                             }
  108.                                         else    
  109.                                             return(errAENoUserInteraction);
  110.                                     }
  111.                                 else
  112.                                     myErr = SaveUsingTemp(aDocument);
  113.                             else
  114.                                 myErr = noErr; /* Don't save */
  115.                         }
  116.                 
  117.                 if (myErr==noErr)
  118.                     {
  119.                         if (aDocument->numSections)
  120.                             DeRegisterAllSections(aDocument);
  121.                         CloseMyWindow(aWindow);
  122.                     }
  123.             }
  124.         else
  125.           myErr = errAEIllegalIndex;
  126.             
  127.         return(myErr);
  128.     }
  129.  
  130. #pragma segment File
  131.  
  132. //  DoQuit
  133. //  saveOpt - one of kAEAsk,kAEYes,kAENo
  134. //  if kAEYes or kAEAsk then AEInteactWithUser should have been called
  135. //  before DoQuit. Assumes that it can interact if it needs to.
  136.  
  137. pascal void DoQuit(DescType saveOpt)
  138.   {
  139.     WindowPtr    aWindow;
  140.     WindowPtr    nextWindow;
  141.     WindowPeek   nextWPeek;
  142.     short        theKind;
  143.     OSErr        check;
  144.  
  145.     aWindow = FrontWindow();
  146.      
  147.         while (aWindow)
  148.             {
  149.                 nextWPeek  = ((WindowPeek)aWindow)->nextWindow;
  150.                 nextWindow = &nextWPeek->port;
  151.                 if (Ours(aWindow))
  152.                     {
  153.                         check = DoClose(aWindow, true, saveOpt);
  154.                         if (check!=noErr)
  155.                             return;
  156.                     }
  157.                 else
  158.                     {
  159.                         theKind = ((WindowPeek)aWindow)->windowKind;
  160.                         if (theKind < 0)
  161.                             CloseDeskAcc(theKind);
  162.                     }
  163.                 aWindow = nextWindow;
  164.             }     /*WHILE loop*/
  165.         gQuitting = true;
  166.     }
  167.  
  168. pascal OSErr GetFile(FSSpec *theFSSpec)
  169.   {
  170.     SFTypeList         myTypes;
  171.     StandardFileReply  reply;
  172.  
  173.         myTypes[0] = 'TEXT';
  174.  
  175.         StandardGetFile(nil, 1, myTypes, &reply);
  176.  
  177.         if (reply.sfGood)
  178.             {
  179.                 *theFSSpec = reply.sfFile;
  180.                 return(noErr);
  181.             }
  182.         else
  183.             return(userCanceledErr);
  184.  }
  185.  
  186. #pragma segment File
  187.  
  188.  
  189. pascal OSErr DoCreate(FSSpec theSpec)
  190.   {
  191.       OSErr err;
  192.  
  193.       err = FSpCreate(&theSpec, MenuScripterAppSig, 'TEXT', smSystemScript);
  194.  
  195.       if (err != noErr)
  196.               ShowError("\pDoCreate", err);
  197.                 
  198.             return(err);
  199.     }
  200.  
  201. #pragma segment File
  202.  
  203.  
  204. pascal OSErr WriteFile(DPtr      theDocument,
  205.                                              short     refNum,
  206.                        FSSpec    theFSSpec)
  207.   {
  208.     short        resFile;
  209.     long         length;
  210.     HHandle      theHHandle;
  211.     StScrpHandle theSHandle;
  212.     OSErr        err;
  213.     StringHandle theAppName;
  214.         short        oldSelStart;
  215.         short        oldSelEnd;
  216.         Handle       thePHandle;
  217.         Handle       myText;
  218.                 
  219. /*        WriteFile := 1; */
  220.  
  221.     /*first write out the text to the data fork*/
  222.         
  223.         length = (*(theDocument->theText))->teLength;
  224.         
  225.         myText = (*(theDocument->theText))->hText;
  226.         
  227.     HLock(myText);
  228.     
  229.         err = FSWrite(refNum, &length, *myText);
  230.         if (err)
  231.           return(err);
  232.             
  233.     HUnlock(myText);
  234.  
  235.         /*we are writing to a temporary file, so we need to create the resource file*/
  236.         /*before writing out the resources*/
  237.         /*now open the resource file*/
  238.         
  239.         HCreateResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  240.         err = ResError();
  241.         if (err)
  242.           {
  243.                 ShowError("\pHCreateResFile", err);
  244.                 return(err);
  245.             }
  246.  
  247.     resFile = HOpenResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, fsWrPerm);
  248.     err = ResError();
  249.  
  250.     if (err)
  251.           {
  252.                 ShowError("\pHOpenResFile", err);
  253.                 return(err);
  254.             }
  255.  
  256.      /*write out our 'TFSF' resource to file*/
  257.                 
  258.         oldSelStart = (*(theDocument->theText))->selStart;
  259.         oldSelEnd   = (*(theDocument->theText))->selEnd;
  260.         TESetSelect(0,32000, theDocument->theText);
  261.                 
  262.     theSHandle = GetStylScrap(theDocument->theText);
  263.                 
  264.         TESetSelect(oldSelStart,oldSelEnd, theDocument->theText);
  265.                 
  266.     AddResource((Handle)theSHandle, 'TFSF', 255, "\pStyle Info");
  267.     err = ResError();
  268.     if (err)
  269.           {
  270.                 ShowError("\pAddResource- TFSF", err);
  271.                 return(err);
  272.             }
  273.                     
  274.         /* write out the printer info */
  275.                 
  276.         if (theDocument->thePrintSetup)
  277.             {
  278.                 thePHandle = (Handle)theDocument->thePrintSetup;
  279.                 err = HandToHand(&thePHandle);
  280.                 
  281.                 AddResource(thePHandle, 'TFSP', 255, "\pPrinter Info");
  282.                 err = ResError();
  283.                 if (err)
  284.                     {
  285.                         ShowError("\pAddResource- TFSP", err);
  286.                         return(err);
  287.                     }
  288.             }
  289.                 
  290.                 
  291.         theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  292.     HLock((Handle)theHHandle);
  293.  
  294.         GetFontName(theDocument->theFont, &(*theHHandle)->theFont);
  295.         (*theHHandle)->theSize     = theDocument->theSize;
  296.         (*theHHandle)->theStyle    = theDocument->theStyle;
  297.         (*theHHandle)->lastID      = theDocument->lastID;
  298.         (*theHHandle)->numSections = theDocument->numSections;
  299.  
  300.         HUnlock((Handle)theHHandle);
  301.  
  302.         AddResource((Handle)theHHandle, 'TFSS', 255, "\pHeader Info");
  303.  
  304.         err = ResError();
  305.         if (err)
  306.             {
  307.                 ShowError("\pAddResource- TFSS", err);
  308.                 return(err);
  309.             }
  310.  
  311.         /*if we have any sections, write out the records and resources*/
  312.         
  313.         if (theDocument->numSections)
  314.             {
  315.                 /*now write out the section records*/
  316.                 SaveSections(theDocument);
  317.                 
  318.                 /*write the latest versions of all editions to their containers*/
  319.  
  320.                 WriteAllEditions(theDocument);
  321.                 /*now close the resource file*/
  322.                 err = ResError();
  323.                 if (err)
  324.                     {
  325.                         ShowError("\pCloseResFile", err);
  326.                         return(err);
  327.                     }
  328.             }
  329.  
  330.         /*Now put an AppName in for Finder in 7.0*/
  331.  
  332.         theAppName = (StringHandle)NewHandle(20); // at least as long as "\pMenuScripter"
  333.         PLstrcpy(*theAppName,"\pMenuScripter");
  334.         
  335.         AddResource((Handle)theAppName, 'STR ', -16396, "\pFinder App Info");
  336.  
  337.         err = ResError();
  338.  
  339.         if (err)
  340.             {
  341.                 ShowError("\pAppName", err);
  342.                 return(err);
  343.             }
  344.  
  345.         CloseResFile(resFile);
  346.  
  347.         return(noErr);
  348.     } /* WriteFile */
  349.  
  350. #pragma segment File
  351.  
  352. pascal OSErr ReadFile(DPtr   theDocument,
  353.                                             short  refNum,
  354.                       Str255 fn)
  355.  {
  356.         long            theSize;
  357.         short           resFile;
  358.         OSErr           err;
  359.         HHandle         aHandle;
  360.         Handle          gHandle;
  361.  
  362.         err = GetEOF(refNum, &theSize);
  363.                 if (err)
  364.           return(err);
  365.  
  366.         /*we're only using TE, so check that there is not more than 32K worth of text*/
  367.                 
  368.         if (theSize > 32000)
  369.           return(1);
  370.  
  371.         gHandle = NewHandle(theSize);
  372.         HLock(gHandle);
  373.                 err = FSRead(refNum, &theSize, *gHandle);
  374.                 
  375.         if (err)
  376.           {
  377.             HUnlock(gHandle);
  378.                         return(err);
  379.           }
  380.                                 
  381.                 resFile = HOpenResFile(theDocument->theFSSpec.vRefNum, 
  382.                                                              theDocument->theFSSpec.parID,
  383.                                                              fn,
  384.                                                              fsWrPerm);
  385.                 if (resFile == -1)
  386.                     err = fnfErr;
  387.                     
  388.                 theDocument->numSections = 0;
  389.                 
  390.                 if (err==noErr)
  391.                     {
  392.                         aHandle = nil;
  393.         
  394.                         if (Count1Resources('TFSS'))
  395.                             aHandle = (HHandle)Get1Resource('TFSS', 255);
  396.         
  397.                         if (aHandle)
  398.                             theDocument->numSections = (*aHandle)->numSections;
  399.                             
  400.                         /*
  401.                             New Format Info
  402.                         */
  403.                         
  404.                         aHandle = nil;
  405.                         
  406.                         if (Count1Resources('TFSF'))
  407.                             aHandle = (HHandle)Get1Resource('TFSF', 255);
  408.                             
  409.                         HLock(gHandle);
  410.                         TEStylInsert(    *gHandle,
  411.                                                     GetHandleSize(gHandle),
  412.                                                     (StScrpHandle)aHandle,
  413.                                                     theDocument->theText);
  414.                                         
  415.                         HUnlock(gHandle);
  416.                         
  417.                         /*
  418.                             If there is a print record saved, ditch the old one
  419.                             created by new document and fill this one in
  420.                         */
  421.                         if (Count1Resources('TFSP'))
  422.                             {
  423.                                 if (theDocument->thePrintSetup)
  424.                                     DisposHandle((Handle)theDocument->thePrintSetup);
  425.                                 
  426.                                 theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
  427.                               err = HandToHand((Handle *)&theDocument->thePrintSetup);
  428.                                 
  429.                                 PrValidate(theDocument->thePrintSetup);
  430.                             }
  431.                                                     
  432.                         if (theDocument->numSections)
  433.                             {
  434.                                 ReadSectionRecords(theDocument);
  435.                                 ReadAllSectionResources(theDocument);
  436.                             }
  437.         
  438.                         CloseResFile(resFile);
  439.         
  440.                         err = ResError();
  441.                         if (err)
  442.                             {
  443.                                 ShowError("\pread file- CloseResFile", err);
  444.                                 return(err);
  445.                             }
  446.           }
  447.                 else
  448.                     TESetText(*gHandle, 
  449.                               GetHandleSize(gHandle), 
  450.                                         theDocument->theText);
  451.                     
  452.                 if (gHandle)
  453.                     DisposHandle(gHandle);
  454.                     
  455.                 if (err==fnfErr)
  456.                     err = noErr;
  457.  
  458.         return(err);
  459.         } /* ReadFile */
  460.  
  461. /** -----------------------------------------------------------------------
  462.         Name:             GetFileContents
  463.         Purpose:        Opens the document specified by theFSSpec and puts
  464.                                 the contents into theDocument.
  465.      -----------------------------------------------------------------------**/
  466.  
  467.     
  468. #pragma segment File
  469.  
  470. pascal OSErr GetFileContents(FSSpec theFSSpec, DPtr theDocument)
  471.   {
  472.      OSErr            err;
  473.      short            theRefNum;
  474.  
  475.             /*this can be called from two places- on an OpenDoc AppleEvent*/
  476.             /*and by the user just selecting Open from the File Menu*/
  477.             /*assume that the CFS is correct when the routine is called*/
  478.  
  479.             err = FSpOpenDF(&theFSSpec,
  480.                                           fsRdWrPerm,
  481.                                           &theRefNum);
  482.             if (err)
  483.                 {
  484.                     ShowError("\pFSpOpenDF", err);
  485.                     return(err);
  486.                 }
  487.             else
  488.                 {
  489.                     err = ReadFile(theDocument, theRefNum, theFSSpec.name);
  490.                     if (err)
  491.                         {
  492.                             ShowError("\pReadFile", err);
  493.                             return(err);
  494.                         }
  495.                     err=FSClose(theRefNum);
  496.                     if (err)
  497.                         {
  498.                             ShowError("\pFSClose", err);
  499.                             return(err);
  500.                         }
  501.                     return(noErr);
  502.                 }
  503.         }
  504.  
  505.     
  506. #pragma segment File
  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.         GetTempFileName(theDocument, &tempName);
  522.         /*create this file on disk*/
  523.  
  524.         tempFSSpec      = theDocument->theFSSpec;
  525.         PLstrcpy(tempFSSpec.name,tempName);
  526.             
  527.         err = DoCreate(tempFSSpec);    
  528.  
  529.         /*now save the file as normal*/
  530.         
  531.         if (err==noErr)
  532.             err = DoSave(theDocument, tempFSSpec);
  533.         
  534.         if (err == noErr)
  535.             err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec);
  536.  
  537.         /*we've exchanged the files, now delete the temporary one*/
  538.         
  539.         if (err==noErr)
  540.           err = FSpDelete(&tempFSSpec);
  541.  
  542.         return(err);
  543.     }
  544.  
  545.     
  546. #pragma segment File
  547.  
  548. /*
  549.     Fills in the document record with the user chosen destination
  550. */
  551.  
  552. pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
  553.     {            
  554.     StandardFileReply   reply;
  555.     OSErr               err;
  556.         Str255              suggestName;
  557.  
  558.         GetWTitle(theDocument->theWindow, suggestName);
  559.  
  560.         StandardPutFile("\pSave Document As:", suggestName, &reply);
  561.  
  562.     if (reply.sfGood)
  563.             {                
  564.                 err = FSpDelete(&reply.sfFile);
  565.                 
  566.                 if (!((err==noErr) || (err==fnfErr)))
  567.                     return(err);
  568.                 else
  569.                     err = noErr;
  570.                     
  571.                 theDocument->theFSSpec = reply.sfFile;
  572.                 PLstrcpy(theDocument->theFileName, reply.sfFile.name);
  573.             }
  574.         else
  575.             err = userCanceledErr;
  576.         
  577.         return(err);
  578.  } /* GetFileNameToSaveAs */
  579.  
  580.     
  581. #pragma segment File
  582.  
  583. pascal OSErr DoSave(DPtr   theDocument, FSSpec theFSSpec)
  584.   {
  585.     short      refNum;
  586.     OSErr      fileErr;
  587.  
  588.         fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  589.         
  590.         if (fileErr == fnfErr)
  591.             {
  592.               fileErr = DoCreate(theFSSpec);
  593.                 
  594.                 if (fileErr)
  595.                     return(fileErr);
  596.                     
  597.                 fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  598.             }
  599.  
  600.         if (fileErr == noErr)
  601.             {
  602.               fileErr = WriteFile(theDocument, refNum, theFSSpec);
  603.                 
  604.                 if (fileErr==noErr)
  605.                     theDocument->dirty = false;
  606.                     
  607.                 fileErr = FSClose(refNum);
  608.             }
  609.         else
  610.             FileError("\perror opening file ", theFSSpec.name);
  611.         
  612.         return(fileErr);
  613.     }
  614.  
  615.     
  616. #pragma segment File
  617.  
  618. pascal OSErr OpenOld(FSSpec aFSSpec)
  619.     {        
  620.       DPtr  theDocument;
  621.         OSErr fileErr;
  622.  
  623.         theDocument = NewDocument(true);
  624.         
  625.         SetWTitle(theDocument->theWindow, aFSSpec.name);
  626.         
  627.         SetPort(theDocument->theWindow);
  628.         
  629.         theDocument->theFSSpec   = aFSSpec;
  630.         
  631.         PLstrcpy(theDocument->theFileName,aFSSpec.name);
  632.         
  633.         theDocument->dirty       = false;
  634.         theDocument->everSaved   = true;
  635.  
  636.     fileErr = GetFileContents(aFSSpec, theDocument);
  637.         
  638.         if (fileErr == noErr)
  639.             {
  640.                 ResizeWindow(theDocument);
  641.                 ShowWindow(theDocument->theWindow);
  642.             }
  643.         else
  644.             FileError("\pError Opening ", aFSSpec.name);
  645.                     
  646.         return(fileErr);
  647.     } /* OpenOld */
  648.  
  649.     
  650. #pragma segment File
  651.  
  652. pascal OSErr OpenUsingAlias(AliasHandle theAliasH)
  653.   {
  654.     OSErr    err;
  655.     FSSpec   aFSSpec;
  656.     Boolean  dummy;
  657.  
  658.         err = ResolveAlias(nil, theAliasH, &aFSSpec, &dummy);
  659.         
  660.         if (err == noErr)
  661.             err = OpenOld(aFSSpec);
  662.                     
  663.         return(err);
  664.     }
  665.  
  666.