home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Muddweller 1.2 / source code / Main / EDStuff.cp < prev    next >
Encoding:
Text File  |  1994-02-11  |  15.3 KB  |  624 lines  |  [TEXT/MPS ]

  1. /* EDStuff - Implementation of the ed-based file-transfer routines            */
  2.  
  3. #include "EDStuff.h"
  4.  
  5.  
  6.         // • Toolbox
  7. #ifndef __TOOLUTILS__
  8. #include "ToolUtils.h"
  9. #endif
  10.  
  11.         // • Implementation use
  12. #ifndef __FILTERS__
  13. #include "Filters.h"
  14. #endif
  15.  
  16. #ifndef __GLOBALS__
  17. #include "Globals.h"
  18. #endif
  19.  
  20. #ifndef __MTPSTUFF__
  21. #include "MTPStuff.h"
  22. #endif
  23.  
  24.  
  25. //------------------------------------------------------------------------------
  26.  
  27. const int kTmpBufferSize = 2 * 1024;
  28. const int kBlockSize = 1024;
  29. const int kNumLines = 20;
  30.  
  31. static short dRef, rRef;
  32. static Boolean done;
  33. static TMUDDoc *doc;
  34. static TFilter *filter;
  35.  
  36. //------------------------------------------------------------------------------
  37.  
  38. typedef enum {kerReturn, kerDone, kerSkip} ReceiveEchoState;
  39.  
  40. typedef enum {ksrStart, ksrReceive, ksrEnd, ksrSkip} ReceiveState;
  41.  
  42. class TReceiveFilter: public TFilter {
  43. public:
  44.     ReceiveEchoState fEcho;
  45.     ReceiveState fState;
  46.     unsigned char *fBuf, fEdPrompt, fPrompt;
  47.     long fCurLine, fLinesRcv, fOut, fFilePos, fLastPos, fMatched;
  48.     Boolean fPass, fBlocks;
  49.     Str255 fUnrecognized;
  50.  
  51.     virtual pascal long Filter (unsigned char *theChars, long count);
  52.     virtual pascal void FlushBuffer (void);
  53.     virtual pascal void Free (void);
  54.     virtual pascal void IFilter (TDocument *itsDoc);
  55. };
  56.  
  57. //------------------------------------------------------------------------------
  58.  
  59. #pragma segment SEDStuff
  60.  
  61. pascal long TReceiveFilter::Filter (unsigned char *theChars, long count)
  62. {
  63.     unsigned char ch, c, *cp, buf [kTmpBufferSize], echo [kTmpBufferSize];
  64.     long act, out, length, cnt, pos, lines, expected;
  65.     Str255 tmp;
  66.     
  67.     act = 0;
  68.     out = 0;
  69.     cp = buf;
  70.     while ((count > act) && (out < kTmpBufferSize)) {
  71.         ch = *theChars++;
  72.         ++act;
  73.         switch (fEcho) {
  74.         case kerReturn:
  75.             if ((ch == fEdPrompt) && (fState != ksrSkip) &&
  76.                     ((fState != ksrReceive) || (fLinesRcv > 0))) {
  77.                 switch (fState) {
  78.                 case ksrStart:
  79.                     fPass = FALSE;
  80.                     if (fBlocks)
  81.                         GetIndString (tmp, kMUDStrings, kmsFirstBlk);
  82.                     else
  83.                         GetIndString (tmp, kMUDStrings, kmsFirst);
  84.                     ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  85.                     fLastPos = fFilePos;
  86.                     fLinesRcv = 0;
  87.                     if (((TMUDDoc *) fDocument)->fDoEcho)
  88.                         fState = ksrReceive;
  89.                     else
  90.                         fState = ksrSkip;
  91.                     break;
  92.                 case ksrReceive:
  93.                     FlushBuffer ();
  94.                     if (fBlocks && (fLinesRcv >= 20))
  95.                         expected = 20;
  96.                     else
  97.                         expected = 1;
  98.                     if ((fLinesRcv > expected) &&
  99.                             ((TMUDDoc *) fDocument)->fDoEcho) {
  100.                         length = fFilePos - fLastPos;
  101.                         lines = expected;
  102.                         FailOSErr (SetFPos (dRef, fsFromStart, fLastPos));
  103.                         while ((length > 0) && (lines < fLinesRcv)) {
  104.                             if (length > kTmpBufferSize)
  105.                                 cnt = kTmpBufferSize;
  106.                             else
  107.                                 cnt = length;
  108.                             FailOSErr (FSRead (dRef, &cnt, (Ptr) echo));
  109.                             pos = 0;
  110.                             while ((pos < cnt) && (lines < fLinesRcv)) {
  111.                                 c = echo [pos];
  112.                                 pos += 1;
  113.                                 *cp++ = c;
  114.                                 ++out;
  115.                                 if (out >= kTmpBufferSize) {
  116.                                     inherited::Filter (buf, out);
  117.                                     out = 0;
  118.                                     cp = buf;
  119.                                 }
  120.                                 if (c == chReturn) lines += 1;
  121.                             }
  122.                         }
  123.                     }
  124.                     if (fMatched != fUnrecognized [0]) {
  125.                         if (fLinesRcv > expected) {
  126.                             FailOSErr (SetFPos (dRef, fsFromStart, fLastPos));
  127.                             if (fBlocks)
  128.                                 GetIndString (tmp, kMUDStrings, kmsAgainBlk);
  129.                             else
  130.                                 GetIndString (tmp, kMUDStrings, kmsAgain);
  131.                         } else {
  132.                             fLastPos = fFilePos;
  133.                             if (fBlocks)
  134.                                 GetIndString (tmp, kMUDStrings, kmsNextBlk);
  135.                             else
  136.                                 GetIndString (tmp, kMUDStrings, kmsNext);
  137.                         }
  138.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  139.                         fLinesRcv = 0;
  140.                         if (!((TMUDDoc *) fDocument)->fDoEcho) fState = ksrSkip;
  141.                     } else if (fBlocks) {
  142.                         fBlocks = FALSE;
  143.                         FailOSErr (SetFPos (dRef, fsFromStart, fLastPos));
  144.                         if (fLastPos == 0)
  145.                             GetIndString (tmp, kMUDStrings, kmsAgain);
  146.                         else
  147.                             GetIndString (tmp, kMUDStrings, kmsNext);
  148.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  149.                         fLinesRcv = 0;
  150.                         if (!((TMUDDoc *) fDocument)->fDoEcho) fState = ksrSkip;
  151.                     } else {
  152.                         FailOSErr (SetEOF (dRef, fLastPos));
  153.                         GetIndString (tmp, kMUDStrings, kmsQuit);
  154.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  155.                         fState = ksrEnd;
  156.                     }
  157.                     break;
  158.                 default:
  159.                     if (ch != chReturn) fEcho = kerSkip;
  160.                     if (fPass) {
  161.                         *cp++ = ch;
  162.                         ++out;
  163.                     }
  164.                     break;
  165.                 }
  166.             } else if ((ch == fPrompt) && (fState == ksrEnd)) {
  167.                 fEcho = kerDone;
  168.                 done = TRUE;
  169.                 *cp++ = ch;
  170.                 ++out;
  171.             } else {
  172.                 if (fState == ksrReceive) {
  173.                     if (ch == fUnrecognized [1])
  174.                         fMatched = 1;
  175.                     else
  176.                         fMatched = -1;
  177.                     fLinesRcv += 1;
  178.                     *(fBuf + fOut) = ch;
  179.                     fOut += 1;
  180.                     if (fOut >= kTmpBufferSize) FlushBuffer ();
  181.                 }
  182.                 if (fPass) {
  183.                     *cp++ = ch;
  184.                     ++out;
  185.                 }
  186.                 if (ch != chReturn)
  187.                     fEcho = kerSkip;
  188.                 else if (fState == ksrSkip)
  189.                     fState = ksrReceive;
  190.             }
  191.             break;
  192.         case kerSkip:
  193.             if (fState == ksrReceive) {
  194.                 if (fMatched > 0) {
  195.                     fMatched += 1;
  196.                     if (ch != fUnrecognized [fMatched]) fMatched = -1;
  197.                 }
  198.                 *(fBuf + fOut) = ch;
  199.                 fOut += 1;
  200.                 if (fOut >= kTmpBufferSize) FlushBuffer ();
  201.             }
  202.             if (fPass) {
  203.                 *cp++ = ch;
  204.                 ++out;
  205.             }
  206.             if (ch == chReturn) {
  207.                 fEcho = kerReturn;
  208.                 if (fState == ksrSkip) fState = ksrReceive;
  209.             }
  210.             break;
  211.         default: /* kerDone */
  212.             *cp++ = ch;
  213.             ++out;
  214.             break;
  215.         }
  216.     }
  217.     inherited::Filter (buf, out);
  218.     return act;
  219. }
  220.  
  221. //------------------------------------------------------------------------------
  222.  
  223. #pragma segment SEDStuff
  224.  
  225. pascal void TReceiveFilter::FlushBuffer ()
  226. {
  227.     long tmp;
  228.     
  229.     if (fOut > 0) {
  230.         tmp = fOut;
  231.         FailOSErr (FSWrite (dRef, &tmp, (Ptr) fBuf));
  232.         FailOSErr (GetFPos (dRef, &tmp));
  233.         fFilePos = tmp;
  234.         fOut = 0;
  235.     }
  236. }
  237.  
  238. //------------------------------------------------------------------------------
  239.  
  240. #pragma segment SEDStuff
  241.  
  242. pascal void TReceiveFilter::Free ()
  243. {
  244.     if (fBuf != NULL) DisposIfPtr (fBuf);
  245.     inherited::Free ();
  246. }
  247.  
  248. //------------------------------------------------------------------------------
  249.  
  250. #pragma segment SEDStuff
  251.  
  252. pascal void TReceiveFilter::IFilter (TDocument *itsDoc)
  253. {
  254.     Str255 tmp;
  255.     
  256.     fBuf = NULL;
  257.     inherited::IFilter (itsDoc);
  258.     fBuf = (unsigned char *) NewPermPtr (kTmpBufferSize);
  259.     fEcho = kerReturn;
  260.     fState = ksrStart;
  261.     GetIndString (tmp, kMUDStrings, kmsEdPrompt);
  262.     fEdPrompt = tmp [1];
  263.     GetIndString (tmp, kMUDStrings, kmsPrompt);
  264.     fPrompt = tmp [1];
  265.     fCurLine = 1;
  266.     fOut = 0;
  267.     fFilePos = 0;
  268.     fPass = TRUE;
  269.     fBlocks = TRUE;
  270.     GetIndString (tmp, kMUDStrings, kmsUnrecognized);
  271.     CopyStr255 (tmp, fUnrecognized);
  272. }
  273.  
  274. //------------------------------------------------------------------------------
  275.  
  276. #pragma segment SEDStuff
  277.  
  278. pascal void EDReceiveHandler (short , long , void * )
  279. {
  280.     TFilter *aFilter;
  281.     
  282.     gDisableMenus = FALSE;
  283.     InvalidateMenuBar ();
  284.     aFilter = doc->fInputFilter;
  285.     while ((aFilter != NULL) && (aFilter->fNext != filter))
  286.         aFilter = aFilter->fNext;
  287.     if (aFilter != NULL) aFilter->fNext = NULL;
  288.     if (filter != NULL) filter->Free ();
  289.     CloseFile (dRef, rRef);
  290. }
  291.  
  292. pascal void EDReceive (TMUDDoc *theDoc, Str255 path, Str255 fileName,
  293.         short vRefNum)
  294. {
  295.     FailInfo fi;
  296.     TReceiveFilter *aReceiveFilter;
  297.     TFilter *aFilter;
  298.     Str255 aStr;
  299.     
  300.     FailOSErr (Create (fileName, vRefNum, theDoc->fTextSig, 'TEXT'));
  301.     FailOSErr (MAOpenFile (fileName, vRefNum, TRUE, FALSE, fsRdWrPerm, fsRdPerm,
  302.         &dRef, &rRef));
  303.     doc = theDoc;
  304.     filter = NULL;
  305.     CatchFailures (&fi, EDReceiveHandler, kDummyLink);
  306.     gDisableMenus = TRUE;
  307.     InvalidateMenuBar ();
  308.     done = FALSE;
  309.     aReceiveFilter = new TReceiveFilter;
  310.     FailNIL (aReceiveFilter);
  311.     aReceiveFilter->IFilter (theDoc);
  312.     aFilter = doc->fInputFilter;
  313.     while (aFilter->fNext != NULL) aFilter = aFilter->fNext;
  314.     aFilter->fNext = aReceiveFilter;
  315.     GetIndString (aStr, kMUDStrings, kmsEd);
  316.     theDoc->Send (aStr + 1, aStr [0]);
  317.     theDoc->Send (path + 1, path [0]);
  318.     aStr [0] = chReturn;
  319.     theDoc->Send (aStr, 1);
  320.     while (!done) {
  321.         gApplication->PollEvent (kAllowApplicationToSleep);
  322.         if (gStop) Failure (noErr, msgCancelled);
  323.     }
  324.     Success (&fi);
  325.     gDisableMenus = FALSE;
  326.     InvalidateMenuBar ();
  327.     gApplication->SetupTheMenus ();
  328.     aFilter = doc->fInputFilter;
  329.     while ((aFilter != NULL) && (aFilter->fNext != filter))
  330.         aFilter = aFilter->fNext;
  331.     if (aFilter != NULL) aFilter->fNext = NULL;
  332.     if (filter != NULL) filter->Free ();
  333.     FailOSErr (CloseFile (dRef, rRef));
  334.     FailOSErr (FlushVol (NULL, vRefNum));
  335. }
  336.  
  337. //------------------------------------------------------------------------------
  338.  
  339. typedef enum {kesReturn, kesDone, kesSkip} SendEchoState;
  340.  
  341. typedef enum {kssStart, kssSend, kssWrite, kssQuit, kssEnd} SendState;
  342.  
  343. class TSendFilter: public TFilter {
  344. public:
  345.     SendEchoState fEcho;
  346.     SendState fState;
  347.     long fRemaining, fPos, fCount, fSkipColon;
  348.     unsigned char *fBuf, fEdPrompt, fPrompt;
  349.     Str255 fPath;
  350.     Boolean fPass, fWasColon;
  351.     
  352.     virtual pascal void IFilter (TDocument *itsDoc);
  353.     virtual pascal long Filter (unsigned char *theChars, long count);
  354.     virtual pascal void Free (void);
  355.     virtual pascal void GetBlock (void);
  356.     virtual pascal void SendBlock (void);
  357. };
  358.  
  359. //------------------------------------------------------------------------------
  360.  
  361. #pragma segment SEDStuff
  362.  
  363. pascal long TSendFilter::Filter (unsigned char *theChars, long count)
  364. {
  365.     unsigned char ch, *cp, buf [kTmpBufferSize];
  366.     long act, out;
  367.     Str255 tmp;
  368.     
  369.     act = 0;
  370.     out = 0;
  371.     cp = buf;
  372.     while ((count > act) && (out < kTmpBufferSize)) {
  373.         ch = *theChars++;
  374.         ++act;
  375.         switch (fEcho) {
  376.         case kesReturn:
  377.             if (ch == fEdPrompt) {
  378.                 if (fSkipColon > 0)
  379.                     fSkipColon -= 1;
  380.                 else {
  381.                     switch (fState) {
  382.                     case kssStart:
  383.                         fPass = FALSE;
  384.                         GetIndString (tmp, kMUDStrings, kmsDelete);
  385.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  386.                         fState = kssSend;
  387.                         break;
  388.                     case kssSend:
  389.                         fPass = ((TMUDDoc *) fDocument)->fDoEcho;
  390.                         SendBlock ();
  391.                         if ((fRemaining == 0) && (fPos >= fCount))
  392.                             fState = kssWrite;
  393.                         break;
  394.                     case kssWrite:
  395.                         fPass = TRUE;
  396.                         GetIndString (tmp, kMUDStrings, kmsWrite);
  397.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  398.                         CopyStr255 (fPath, tmp);
  399.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  400.                         tmp [0] = chReturn;
  401.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp, 1);
  402.                         fState = kssQuit;
  403.                         break;
  404.                     case kssQuit:
  405.                         fPass = FALSE;
  406.                         GetIndString (tmp, kMUDStrings, kmsQuit);
  407.                         ((TMUDDoc *) fDocument)->SendNoEcho (tmp + 1, tmp [0]);
  408.                         fState = kssEnd;
  409.                         break;
  410.                     default:
  411.                         if (ch != chReturn) fEcho = kesSkip;
  412.                         if (fPass) {
  413.                             *cp++ = ch;
  414.                             ++out;
  415.                         }
  416.                         break;
  417.                     }
  418.                 }
  419.             } else if ((ch == fPrompt) && (fState == kssEnd)) {
  420.                 fPass = TRUE;
  421.                 fEcho = kesDone;
  422.                 done = TRUE;
  423.                 *cp++ = ch;
  424.                 ++out;
  425.             } else if (ch != '*') {
  426.                 if (ch != chReturn) fEcho = kesSkip;
  427.                 if (fPass) {
  428.                     *cp++ = ch;
  429.                     ++out;
  430.                 }
  431.             }
  432.             break;
  433.         case kesSkip:
  434.             if (ch == chReturn) fEcho = kesReturn;
  435.             if (fPass) {
  436.                 *cp++ = ch;
  437.                 ++out;
  438.             }
  439.             break;
  440.         default: /* kesDone */
  441.             *cp++ = ch;
  442.             ++out;
  443.             break;
  444.         }
  445.     }
  446.     inherited::Filter (buf, out);
  447.     return act;
  448. }
  449.  
  450. //------------------------------------------------------------------------------
  451.  
  452. #pragma segment SEDStuff
  453.  
  454. pascal void TSendFilter::Free ()
  455. {
  456.     if (fBuf != NULL) DisposIfPtr (fBuf);
  457.     inherited::Free ();
  458. }
  459.  
  460. //------------------------------------------------------------------------------
  461.  
  462. #pragma segment SEDStuff
  463.  
  464. pascal void TSendFilter::GetBlock ()
  465. {
  466.     long count;
  467.     
  468.     if (fRemaining > kTmpBufferSize)
  469.         count = kTmpBufferSize;
  470.     else
  471.         count = fRemaining;
  472.     FailOSErr (FSRead (dRef, &count, (Ptr) fBuf));
  473.     fRemaining -= count;
  474.     fCount = count;
  475.     fPos = 0;
  476. }
  477.  
  478. //------------------------------------------------------------------------------
  479.  
  480. #pragma segment SEDStuff
  481.  
  482. pascal void TSendFilter::IFilter (TDocument *itsDoc)
  483. {
  484.     long length;
  485.     Str255 tmp;
  486.     
  487.     fBuf = NULL;
  488.     inherited::IFilter (itsDoc);
  489.     fBuf = (unsigned char *) NewPermPtr (kTmpBufferSize);
  490.     fEcho = kesReturn;
  491.     fState = kssStart;
  492.     FailOSErr (GetEOF (dRef, &length));
  493.     fRemaining = length;
  494.     fPos = 0;
  495.     fCount = 0;
  496.     fSkipColon = 0;
  497.     fPass = TRUE;
  498.     fWasColon = FALSE;
  499.     GetIndString (tmp, kMUDStrings, kmsEdPrompt);
  500.     fEdPrompt = tmp [1];
  501.     GetIndString (tmp, kMUDStrings, kmsPrompt);
  502.     fPrompt = tmp [1];
  503. }
  504.  
  505. //------------------------------------------------------------------------------
  506.  
  507. #pragma segment SEDStuff
  508.  
  509. pascal void TSendFilter::SendBlock ()
  510. {
  511.     unsigned char ch, buf [kTmpBufferSize];
  512.     long pos, out, outSent;
  513.     Str255 aStr;
  514.     
  515.     GetIndString (aStr, kMUDStrings, kmsAppend);
  516.     ((TMUDDoc *) fDocument)->SendNoEcho (aStr + 1, aStr [0]);
  517.     pos = 0;
  518.     out = 0;
  519.     outSent = 0;
  520.     while (((fRemaining > 0) || (fPos < fCount)) &&
  521.             ((pos != 0) || (outSent + out < kBlockSize))) {
  522.         if (fPos >= fCount) GetBlock ();
  523.         ch = *(fBuf + fPos);
  524.         if ((ch == chTab) && ((TMUDDoc *) fDocument)->fCvtTab) {
  525.             buf [out] = ' ';
  526.             out += 1;
  527.             pos += 1;
  528.             if ((pos % ((TMUDDoc *) fDocument)->fSTab) == 0) fPos += 1;
  529.         } else if ((ch == chReturn) || (ch == chLineFeed)) {
  530.             buf [out] = ch;
  531.             out += 1;
  532.             pos = 0;
  533.             fPos += 1;
  534.         } else {
  535.             if (((pos == 0) || fWasColon) && (ch == fEdPrompt) &&
  536.                     !((TMUDDoc *) fDocument)->fDoEcho) {
  537.                 fSkipColon += 1;
  538.                 fWasColon = TRUE;
  539.             } else
  540.                 fWasColon = FALSE;
  541.             buf [out] = ch;
  542.             out += 1;
  543.             pos += 1;
  544.             fPos += 1;
  545.         }
  546.         if (out >= kTmpBufferSize) {
  547.             ((TMUDDoc *) fDocument)->SendNoEcho (buf, out);
  548.             outSent += out;
  549.             out = 0;
  550.         }
  551.     }
  552.     if (out > 0) ((TMUDDoc *) fDocument)->SendNoEcho (buf, out);
  553.     if (pos != 0) {
  554.         buf [0] = chReturn;
  555.         ((TMUDDoc *) fDocument)->SendNoEcho (buf, 1);
  556.     }
  557.     GetIndString (aStr, kMUDStrings, kmsStop);
  558.     ((TMUDDoc *) fDocument)->SendNoEcho (aStr + 1, aStr [0]);
  559. }
  560.  
  561. //------------------------------------------------------------------------------
  562.  
  563. #pragma segment SEDStuff
  564.  
  565. pascal void EDSendHandler (short , long , void * )
  566. {
  567.     TFilter *aFilter;
  568.     
  569.     gDisableMenus = FALSE;
  570.     InvalidateMenuBar ();
  571.     aFilter = doc->fInputFilter;
  572.     while ((aFilter != NULL) && (aFilter->fNext != filter))
  573.         aFilter = aFilter->fNext;
  574.     if (aFilter != NULL) aFilter->fNext = NULL;
  575.     if (filter != NULL) filter->Free ();
  576.     CloseFile (dRef, rRef);
  577. }
  578.  
  579. pascal void EDSend (TMUDDoc *theDoc, AppFile *theFile, Str255 path)
  580. {
  581.     TSendFilter *aSendFilter;
  582.     TFilter *aFilter;
  583.     FailInfo fi;
  584.     Str255 aStr;
  585.     
  586.     FailOSErr (MAOpenFile (theFile->fName, theFile->vRefNum, TRUE, FALSE,
  587.         fsRdPerm, fsRdPerm, &dRef, &rRef));
  588.     doc = theDoc;
  589.     filter = NULL;
  590.     CatchFailures (&fi, EDSendHandler, kDummyLink);
  591.     gDisableMenus = TRUE;
  592.     InvalidateMenuBar ();
  593.     done = FALSE;
  594.     aSendFilter = new TSendFilter;
  595.     FailNIL (aSendFilter);
  596.     aSendFilter->IFilter (theDoc);
  597.     aFilter = doc->fInputFilter;
  598.     while (aFilter->fNext != NULL) aFilter = aFilter->fNext;
  599.     aFilter->fNext = aSendFilter;
  600.     CopyStr255 (path, aSendFilter->fPath);
  601.     GetIndString (aStr, kMUDStrings, kmsEd);
  602.     theDoc->Send (aStr + 1, aStr [0]);
  603.     theDoc->Send (path + 1, path [0]);
  604.     aStr [0] = chReturn;
  605.     theDoc->Send (aStr, 1);
  606.     while (!done) {
  607.         gApplication->PollEvent (kAllowApplicationToSleep);
  608.         if (gStop) Failure (noErr, msgCancelled);
  609.     }
  610.     Success (&fi);
  611.     gDisableMenus = FALSE;
  612.     InvalidateMenuBar ();
  613.     gApplication->SetupTheMenus ();
  614.     aFilter = doc->fInputFilter;
  615.     while ((aFilter != NULL) && (aFilter->fNext != filter))
  616.         aFilter = aFilter->fNext;
  617.     if (aFilter != NULL) aFilter->fNext = NULL;
  618.     if (filter != NULL) filter->Free ();
  619.     FailOSErr (CloseFile (dRef, rRef));
  620.     FailOSErr (FlushVol (NULL, theFile->vRefNum));
  621. }
  622.  
  623. //------------------------------------------------------------------------------
  624.