home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / MacPerl / MPSave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  19.8 KB  |  1,049 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPSave.c            -    Handle all the runtimes
  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: MPSave.c,v $
  12. Revision 1.1  1994/02/27  23:01:45  neeri
  13. Initial revision
  14.  
  15. Revision 0.1  1993/10/03  00:00:00  neeri
  16. Compiles correctly
  17.  
  18. *********************************************************************/
  19.  
  20. #include <Errors.h>
  21. #include <Resources.h>
  22. #include <PLStringFuncs.h>
  23. #include <LowMem.h>
  24. #include <Folders.h>
  25. #include <Finder.h>
  26. #include <TFileSpec.h>
  27.  
  28. #include "MPSave.h"
  29. #include "MPGlobals.h"
  30. #include "MPFile.h"
  31. #include "MPUtils.h"
  32.  
  33. #if defined(powerc) || defined (__powerc)
  34. #pragma options align=mac68k
  35. #endif
  36.  
  37. #define SERsrcBase    32700
  38.  
  39. typedef struct {
  40.     OSType            version; 
  41.     OSType            id;
  42.     OSType            fType;
  43.     OSType            fCreator;
  44.     
  45.     unsigned            wantsBundle     : 1;
  46.     unsigned            hasCustomIcon     : 1;
  47. } SEPackage, ** SEPackageHdl;
  48.  
  49. typedef struct {
  50.     OSType    type;
  51.     OSType    realType;
  52.     short        id;
  53.     short        realID;
  54. } ShoppingList, ** ShoppingListHdl;
  55.  
  56. typedef struct {
  57.     OSType    type;
  58.     short        id;
  59. } OwnerList;
  60.  
  61. #if defined(powerc) || defined (__powerc)
  62. #pragma options align=reset
  63. #endif
  64.  
  65. typedef struct {
  66.     OSType            id;
  67.     OSType            fType;
  68.     OSType            fCreator;
  69.     StringHandle    name;
  70.     Boolean            wantsBundle;
  71.     Boolean            hasCustomIcon;
  72.     FSSpec            file;
  73. } SaveExtension;
  74.  
  75. typedef struct {
  76.     short                count;
  77.     SaveExtension    ext[1];
  78. } SERec, * SEPtr, ** SEHdl;
  79.  
  80. SEHdl            SaveExtensions    =    nil;
  81. OSType **    FileTypeH = nil;
  82. OSType *     MacPerlFileTypes;
  83. short            MacPerlFileTypeCount;
  84.  
  85. OwnerList noOwner[] = {
  86.     0, 0
  87. };
  88.  
  89. OwnerList ancientOwner[] = {
  90.     'ALRT', 256,
  91.     'ALRT', 257,
  92.     'ALRT', 262,
  93.     'ALRT', 266,
  94.     'ALRT', 270,
  95.     'ALRT', 274,
  96.     'ALRT', 300,
  97.     'ALRT', 302,
  98.     'ALRT', 3850,
  99.     'BNDL', 128,
  100.     'CNTL', 192,
  101.     'CODE', 0,
  102.     'CODE', 1,
  103.     'CODE', 2,
  104.     'CODE', 3,
  105.     'CODE', 4,
  106.     'CODE', 5,
  107.     'CODE', 6,
  108.     'CODE', 7,
  109.     'CODE', 8,
  110.     'CODE', 9,
  111.     'CODE', 10,
  112.     'CODE', 11,
  113.     'CODE', 12,
  114.     'CODE', 13,
  115.     'CODE', 14,
  116.     'CODE', 15,
  117.     'CODE', 16,
  118.     'CODE', 17,
  119.     'CODE', 18,
  120.     'CODE', 19,
  121.     'CODE', 20,
  122.     'CODE', 21,
  123.     'CODE', 22,
  124.     'CODE', 23,
  125.     'CODE', 24,
  126.     'CODE', 25,
  127.     'CODE', 26,
  128.     'CODE', 27,
  129.     'CODE', 28,
  130.     'CODE', 29,
  131.     'CODE', 30,
  132.     'CODE', 31,
  133.     'CODE', 32,
  134.     'CODE', 33,
  135.     'CODE', 34,
  136.     'CODE', 35,
  137.     'CODE', 36,
  138.     'CODE', 37,
  139.     'CODE', 38,
  140.     'CODE', 39,
  141.     'CODE', 40,
  142.     'CODE', 41,
  143.     'CODE', 42,
  144.     'CODE', 43,
  145.     'CODE', 44,
  146.     'CODE', 45,
  147.     'CODE', 46,
  148.     'CODE', 47,
  149.     'CODE', 48,
  150.     'CODE', 49,
  151.     'CODE', 50,
  152.     'CODE', 51,
  153.     'CURS', 128,
  154.     'CURS', 129,
  155.     'CURS', 130,
  156.     'CURS', 131,
  157.     'CURS', 132,
  158.     'CURS', 144,
  159.     'CURS', 145,
  160.     'CURS', 146,
  161.     'CURS', 147,
  162.     'CURS', 148,
  163.     'CURS', 160,
  164.     'CURS', 161,
  165.     'CURS', 162,
  166.     'CURS', 163,
  167.     'DITL', 192,
  168.     'DITL', 256,
  169.     'DITL', 257,
  170.     'DITL', 258,
  171.     'DITL', 262,
  172.     'DITL', 266,
  173.     'DITL', 270,
  174.     'DITL', 274,
  175.     'DITL', 300,
  176.     'DITL', 302,
  177.     'DITL', 320,
  178.     'DITL', 384,
  179.     'DITL', 385,
  180.     'DITL', 386,
  181.     'DITL', 387,
  182.     'DITL', 512,
  183.     'DITL', 1005,
  184.     'DITL', 2001,
  185.     'DITL', 2002,
  186.     'DITL', 2003,
  187.     'DITL', 2010,
  188.     'DITL', 2020,
  189.     'DITL', 3850,
  190.     'DITL', 10240,
  191.     'DLOG', 192,
  192.     'DLOG', 258,
  193.     'DLOG', 320,
  194.     'DLOG', 384,
  195.     'DLOG', 512,
  196.     'DLOG', 1005,
  197.     'DLOG', 2001,
  198.     'DLOG', 2002,
  199.     'DLOG', 2003,
  200.     'DLOG', 2010,
  201.     'DLOG', 2020,
  202.     'DLOG', 10240,
  203.     'FOND', 19999,
  204.     'FOND', 32268,
  205.     'FREF', 128,
  206.     'FREF', 129,
  207.     'FREF', 130,
  208.     'FREF', 131,
  209.     'FREF', 132,
  210.     'FREF', 133,
  211.     'FREF', 134,
  212.     'GU╖I', 10240,
  213.     'ICN#', 10240,
  214.     'ICN#', 128,
  215.     'ICN#', 129,
  216.     'ICN#', 130,
  217.     'ICN#', 131,
  218.     'ICN#', 385,
  219.     'ICN#', 386,
  220.     'ICN#', 387,
  221.     'IRng', 128,
  222.     'LDEF', 128,
  223.     'MDEF', 1,
  224.     'MENU', 128,
  225.     'MENU', 129,
  226.     'MENU', 130,
  227.     'MENU', 131,
  228.     'MENU', 132,
  229.     'MENU', 192,
  230.     'McPL', 0,
  231.     'MrP#', 128,
  232.     'MrP4', 128,
  233.     'MrP8', 128,
  234.     'MrPA', 4096,
  235.     'MrPB', 128,
  236.     'MrPC', 0,
  237.     'MrPC', 1,
  238.     'MrPC', 2,
  239.     'MrPD', 4096,
  240.     'MrPF', 132,
  241.     'MrPF', 133,
  242.     'MrPF', 134,
  243.     'MrPI', 128,
  244.     'MrPL', 0,
  245.     'MrPS', -1,
  246.     'NFNT', 2816,
  247.     'NFNT', 2825,
  248.     'NFNT', 2828,
  249.     'NFNT', 32268,
  250.     'PICT', 128,
  251.     'SIZE', -1,
  252.     'STR ', 133,
  253.     'STR#', 129,
  254.     'STR#', 130,
  255.     'STR#', 132,
  256.     'STR#', 256,
  257.     'STR#', 32268,
  258.     'STR#', 384,
  259.     'TMPL', 10240,
  260.     'WIND', 128,
  261.     'WIND', 129,
  262.     'WIND', 130,
  263.     'acur', 0,
  264.     'acur', 128,
  265.     'acur', 129,
  266.     'aete', 0,
  267.     'dctb', 384,
  268.     'hmnu', 129,
  269.     'hmnu', 130,
  270.     'hmnu', 132,
  271.     'icl4', 128,
  272.     'icl4', 129,
  273.     'icl4', 130,
  274.     'icl4', 131,
  275.     'icl4', 385,
  276.     'icl4', 386,
  277.     'icl4', 387,
  278.     'icl8', 128,
  279.     'icl8', 129,
  280.     'icl8', 130,
  281.     'icl8', 131,
  282.     'icl8', 385,
  283.     'icl8', 386,
  284.     'icl8', 387,
  285.     'icm#', 256,
  286.     'icm#', 257,
  287.     'icm#', 264,
  288.     'icm#', 265,
  289.     'icm#', 266,
  290.     'ics#', 128,
  291.     'vers', 1,
  292.     'vers', 2,
  293.     0,      0
  294. };
  295.  
  296. OwnerList * noOwnerPtr = noOwner;
  297. OwnerList * ancientOwnerPtr = ancientOwner;
  298.  
  299. Boolean InOwnerList(OSType type, short id, OwnerList * list)
  300. {
  301.     while (list->type)
  302.         if (list->type == type && list->id == id)
  303.             return true;
  304.         else
  305.             ++list;
  306.     
  307.     return false;
  308. }
  309.  
  310. OSErr CopySomeResources(short origFile, short resFile)
  311. {
  312.     OSErr                err;
  313.     Handle             rsrc;
  314.     Handle            nur;
  315.     short                typeCnt;
  316.     short                typeIdx;
  317.     short                rsrcCnt;
  318.     short                rsrcIdx;
  319.     short                rsrcID;
  320.     Boolean            wantItBadly;
  321.     ResType            rsrcType;
  322.     Str255            rsrcName;
  323.     OwnerList **    include;
  324.     OwnerList **    exclude;
  325.     
  326.     UseResFile(origFile);
  327.     
  328.     if (!(exclude = (OwnerList **) Get1Resource('McPo', 128)))
  329.         exclude = &ancientOwnerPtr;
  330.  
  331.     if (!(include = (OwnerList **) Get1Resource('McPo', 129)))
  332.         include = &noOwnerPtr;
  333.     
  334.     typeCnt = Count1Types();
  335.     
  336.     for (typeIdx = 0; typeIdx++ < typeCnt; ) {
  337.         Get1IndType(&rsrcType, typeIdx);
  338.         
  339.         rsrcCnt = Count1Resources(rsrcType);
  340.         
  341.         for (rsrcIdx = 0; rsrcIdx++ < rsrcCnt; ) {
  342.             rsrc = Get1IndResource(rsrcType, rsrcIdx);
  343.             
  344.             if (!rsrc) 
  345.                 return ResError();
  346.             
  347.             GetResInfo(rsrc, &rsrcID, &rsrcType, rsrcName);
  348.             
  349.             if (rsrcType == 'McPo' && rsrcID == 128)
  350.                 continue;
  351.             if (rsrcType == 'McPo' && rsrcID == 129) {
  352.                 wantItBadly = true;
  353.                 HandToHand(&rsrc);
  354.             } else {
  355.                 wantItBadly = InOwnerList(rsrcType, rsrcID, *include);
  356.                 DetachResource(rsrc);
  357.             }
  358.             
  359.             if (wantItBadly || !InOwnerList(rsrcType, rsrcID, *exclude)) {
  360.                 UseResFile(resFile);
  361.         
  362.                 if (nur = Get1Resource(rsrcType, rsrcID))
  363.                     if (wantItBadly) {
  364.                         RmveResource(nur);
  365.                         
  366.                         nur = nil;
  367.                     }
  368.                 
  369.                 if (!nur) {    
  370.                     AddResource(rsrc, rsrcType, rsrcID, rsrcName);
  371.                 
  372.                     if (err = ResError()) {
  373.                         DisposeHandle(rsrc);
  374.                         return err;
  375.                     }
  376.                 } else 
  377.                     DisposeHandle(rsrc);
  378.                 
  379.                 UseResFile(origFile);
  380.             } else
  381.                 DisposeHandle(rsrc);
  382.         }
  383.     }
  384.     
  385.     return noErr;
  386. }
  387.  
  388. OSErr    CopyShoppingList(short from, short to, ShoppingList * list)
  389. {
  390.     OSErr            err;
  391.     
  392.     for (; list->type; ++list) {
  393.         Handle    rsrc;
  394.         Handle    nur;
  395.                 
  396.         UseResFile(from);
  397.         
  398.         rsrc = Get1Resource(list->type, list->id);
  399.         
  400.         if (!rsrc)
  401.             return ResError();
  402.         
  403.         UseResFile(to);
  404.         
  405.         if (nur = Get1Resource(list->realType, list->realID))
  406.             RmveResource(nur);
  407.             
  408.         HandToHand(&rsrc);
  409.         AddResource(rsrc, list->realType, list->realID, (StringPtr) "\p");
  410.         
  411.         if (err = ResError())
  412.             goto finish;
  413.         
  414. nextrsrc:
  415.         ;
  416.     }
  417.     
  418. finish:
  419.     UseResFile(from);
  420.     
  421.     return err;
  422. }
  423.  
  424. #if !defined(powerc) && !defined(__powerc)
  425. #pragma segment File
  426. #endif
  427.  
  428. static OSType    WantsType;
  429. static OSType    WantsCreator;
  430. static Boolean    WantsBundle;
  431. static Boolean    HasCustomIcon;
  432.  
  433. OSErr DoOpenResFile(FSSpec * spec, short * resFile)
  434. {
  435.     OSErr    err;
  436.     FInfo info;
  437.     
  438.     *resFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  439.     if (*resFile == -1) {
  440.         if (err = DoCreate(*spec))
  441.             return err;
  442.  
  443.         *resFile =  HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  444.         if (*resFile == -1) {
  445.             FileError((StringPtr) "\perror opening file ", spec->name);
  446.             
  447.             return ResError();
  448.         }
  449.     }
  450.     
  451.     HGetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  452.     
  453.     info.fdType        =    WantsType;
  454.     info.fdCreator    =    WantsCreator;
  455.     
  456.     if (WantsBundle)
  457.         info.fdFlags     |= kHasBundle;
  458.     if (HasCustomIcon)
  459.         info.fdFlags     |= kHasCustomIcon;
  460.         
  461.     HSetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  462.     
  463.     return noErr;
  464. }
  465.  
  466. OSErr CopyRsrc(FSSpec * from, FSSpec * to)
  467. {
  468.     OSErr        err;
  469.     short     res;
  470.     short        fromRef;
  471.     short        toRef;
  472.     Handle    copy;
  473.     Ptr        buffer;
  474.     long        len;
  475.     
  476.     copy         = NewHandle(4096);
  477.     buffer     = *copy;
  478.     HLock(copy);
  479.     
  480.     if (err = DoOpenResFile(to, &res))
  481.         goto disposeBuffer;
  482.     
  483.     CloseResFile(res);
  484.     
  485.     if (err = HOpenRF(from->vRefNum, from->parID, from->name, fsRdPerm, &fromRef))
  486.         goto disposeBuffer;
  487.     if (err = HOpenRF(to->vRefNum, to->parID, to->name, fsRdWrPerm, &toRef))
  488.         goto closeFrom;
  489.  
  490.     do {
  491.         len    =    4096;
  492.         
  493.         FSRead(fromRef, &len, buffer);
  494.         FSWrite(toRef, &len, buffer);
  495.     } while (len == 4096);
  496.     
  497.     FSClose(toRef);
  498.     
  499. closeFrom:
  500.     FSClose(fromRef);
  501. disposeBuffer:
  502.     DisposeHandle(copy);
  503.     
  504.     return err;
  505. }
  506.  
  507. OSErr CopyData(FSSpec * from, FSSpec * to)
  508. {
  509.     OSErr        err;
  510.     short     res;
  511.     short        fromRef;
  512.     short        toRef;
  513.     Handle    copy;
  514.     Ptr        buffer;
  515.     long        len;
  516.     
  517.     copy         = NewHandle(4096);
  518.     buffer     = *copy;
  519.     HLock(copy);
  520.     
  521.     if (err = HOpen(from->vRefNum, from->parID, from->name, fsRdPerm, &fromRef))
  522.         goto disposeBuffer;
  523.     if (err = HOpen(to->vRefNum, to->parID, to->name, fsRdWrPerm, &toRef))
  524.         goto closeFrom;
  525.  
  526.     do {
  527.         len    =    4096;
  528.         
  529.         FSRead(fromRef, &len, buffer);
  530.         FSWrite(toRef, &len, buffer);
  531.     } while (len == 4096);
  532.     
  533.     FSClose(toRef);
  534.     
  535. closeFrom:
  536.     FSClose(fromRef);
  537. disposeBuffer:
  538.     DisposeHandle(copy);
  539.     
  540.     return err;
  541. }
  542.  
  543. OSErr MakePackage(FSSpec * spec, short * resFile, DocType type)
  544. {
  545.     OSErr                    err;
  546.     short                    index;
  547.     short                    packFile;
  548.     ShoppingListHdl    shopping;
  549.  
  550.     BuildSEList();
  551.     
  552.     for (index = 0; index < (*SaveExtensions)->count; ++index)
  553.         if ((*SaveExtensions)->ext[index].id == type)
  554.             break;
  555.     
  556.     if (index == (*SaveExtensions)->count)
  557.         return errAEWrongDataType;
  558.  
  559.     WantsType         = (*SaveExtensions)->ext[index].fType;
  560.     WantsCreator    = (*SaveExtensions)->ext[index].fCreator;
  561.     WantsBundle        = (*SaveExtensions)->ext[index].wantsBundle;
  562.     HasCustomIcon    = (*SaveExtensions)->ext[index].hasCustomIcon;
  563.  
  564.     if (err = DoOpenResFile(spec, resFile))
  565.         return err;
  566.     
  567.     {
  568.         FSSpec *    spec = &(*SaveExtensions)->ext[index].file;
  569.         
  570.         packFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  571.     }
  572.     
  573.     if (packFile == -1) {
  574.         err = fnfErr;
  575.         goto done;
  576.     }
  577.     
  578.     if (!(shopping = (ShoppingListHdl) Get1Resource('McPs', SERsrcBase))) {
  579.         err = ResError();
  580.         goto closePackage;
  581.     }
  582.     
  583.     HLock((Handle) shopping);
  584.     err = CopyShoppingList(packFile, *resFile, *shopping);
  585.  
  586. closePackage:
  587.     CloseResFile(packFile);
  588. done:    
  589.     if (err)
  590.         CloseResFile(*resFile);
  591.  
  592.     UseResFile(gAppFile);
  593.         
  594.     return err;
  595. }
  596.  
  597. OSErr Make6Runtime(FSSpec * spec, short * resFile)
  598. {
  599.     OSErr        err;
  600.     FSSpec    from;
  601.     
  602.     from.vRefNum    =    gAppVol;
  603.     from.parID        =    gAppDir;
  604.     PLstrcpy(from.name, (StringPtr) "\pMacPerl Runtime");
  605.     
  606.     if (!CopyRsrc(&from, spec))
  607.         return DoOpenResFile(spec, resFile);
  608.     
  609.     err = 
  610.         FindFolder(
  611.             kOnSystemDisk, 
  612.             kPreferencesFolderType, 
  613.             true, 
  614.             &from.vRefNum,
  615.             &from.parID);
  616.     
  617.     if (err || (err = CopyRsrc(&from, spec))) {
  618.         DialogPtr    dlg;
  619.         short            item;
  620.         
  621.         ParamText(    
  622.             (StringPtr) "\pTo create System 6 compatible Perl runtimes, I need"
  623.             "\"MacPerl Runtime\" in the same folder as this application or"
  624.             "in the preferences folder.", (StringPtr) "\pOK", (StringPtr) "\p", (StringPtr) "\p");
  625.         
  626.         dlg = GetNewDialog(2001, (WindowPtr) nil, (WindowPtr) -1);
  627.         ShowWindow(dlg);
  628.         ModalDialog(nil, &item);
  629.         DisposeDialog(dlg);
  630.         
  631.         return userCanceledErr;
  632.     }
  633.         
  634.     return DoOpenResFile(spec, resFile);
  635. }
  636.  
  637. ShoppingList Runtime7Shopping[] =
  638. {
  639.     { 'MrPB',  128, 'BNDL' },
  640.     { 'MrPI',  128, 'ICN#' },
  641.     { 'MrP4',  128, 'icl4' },
  642.     { 'MrP8',  128, 'icl8' },
  643.     { 'MrP#',  128, 'ics#' },
  644.     {          0,    0,      0 }
  645. };
  646.  
  647. OSErr Make7Runtime(FSSpec * spec, short * resFile)
  648. {
  649.     OSErr        err;
  650.     FSSpec    from;
  651.     
  652.     from.vRefNum    =    gAppVol;
  653.     from.parID        =    gAppDir;
  654.     PLstrcpy(from.name, LMGetCurApName());
  655.  
  656.     if (err = CopyRsrc(&from, spec))
  657.         return err;
  658.         
  659.     if (err = CopyData(&from, spec))
  660.         return err;
  661.         
  662.     if (err = DoOpenResFile(spec, resFile))
  663.         return err;
  664.         
  665.     return CopyShoppingList(gAppFile, *resFile, Runtime7Shopping);
  666. }
  667.  
  668. #ifdef RUNTIME
  669. #define HOpenDF    HOpen
  670. #endif
  671.  
  672. pascal OSErr DoSave(DPtr theDocument, FSSpec theFSSpec)
  673. {
  674.     OSErr               err;
  675.     short                resFile;
  676.     short                origFile;
  677.     Handle            text    =     (*theDocument->theText)->hText;
  678.     OwnerList **    exceptions;
  679.     Handle            thePHandle;
  680.     HHandle            theHHandle;
  681.     StringHandle    theAppName;
  682.  
  683.     HDelete(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  684.     
  685.     switch (theDocument->type) {
  686.     case kPlainTextDoc:
  687.         {
  688.             short        refNum;
  689.             long        length;
  690.             
  691.             WantsCreator    =    MPAppSig;
  692.             WantsType        =    'TEXT';
  693.             WantsBundle        =    false;
  694.             HasCustomIcon    =    false;
  695.             
  696.             if (err = DoOpenResFile(&theFSSpec, &resFile))
  697.                 return err;
  698.             
  699.             if (err = 
  700.                 HOpenDF(
  701.                     theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  702.                     fsRdWrPerm, &refNum)
  703.             ) {
  704.                 if (err = DoCreate(theFSSpec))
  705.                     goto closeResource;
  706.                 
  707.                 if (err =
  708.                     HOpenDF(
  709.                         theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  710.                         fsRdWrPerm, &refNum)
  711.                 ) {
  712.                     FileError((StringPtr) "\perror opening file ", theFSSpec.name);
  713.                     
  714.                     goto closeResource;
  715.                 }
  716.             }
  717.             
  718.             length     = GetHandleSize(text);
  719.             
  720.             HLock(text);
  721.             
  722.             err = FSWrite(refNum, &length, *text);
  723.             
  724.             HUnlock(text);
  725.             FSClose(refNum);
  726.             
  727.             if (err)
  728.                 goto closeResource;
  729.         }
  730.         break;
  731. #ifndef RUNTIME
  732.     default:
  733.         if (err = MakePackage(&theFSSpec, &resFile, theDocument->type))
  734.             return err;
  735.         
  736.         goto writeScript;
  737. #endif
  738.     case kRuntime6Doc:
  739.         WantsCreator    =    MPRtSig;
  740.         WantsType        =    'APPL';
  741.         WantsBundle        =    true;
  742.         HasCustomIcon    =    false;
  743.  
  744.         if (err = Make6Runtime(&theFSSpec, &resFile))
  745.             return err;
  746.         
  747. #ifndef RUNTIME
  748.         goto writeScript;
  749.     case kRuntime7Doc:
  750.         WantsCreator    =    MPRtSig;
  751.         WantsType        =    'APPL';
  752.         WantsBundle        =    true;
  753.         HasCustomIcon    =    false;
  754.  
  755.         if (err = Make7Runtime(&theFSSpec, &resFile))
  756.             return err;
  757. #endif
  758.         
  759. writeScript:            
  760.         if (err = HandToHand(&text))
  761.             goto closeResource;
  762.         
  763.         UseResFile(resFile);
  764.         
  765.         AddResource(text, 'TEXT', 128, (StringPtr) "\p!");
  766.         if (err = ResError()) {
  767.             DisposeHandle(text);
  768.             
  769.             goto closeResource;
  770.         }
  771.         
  772.         if (err = PtrToHand(&theDocument->type, &text, 4))
  773.             goto closeResource;
  774.         
  775.         AddResource(text, 'MrPL', 128, (StringPtr) "\p");
  776.         if (err = ResError()) {
  777.             DisposeHandle(text);
  778.             
  779.             goto closeResource;
  780.         }
  781.             
  782.         break;
  783.     }
  784.     
  785.     /* write out the printer info */
  786.     if (theDocument->thePrintSetup) {
  787.         thePHandle = (Handle)theDocument->thePrintSetup;
  788.         HandToHand(&thePHandle);
  789.  
  790.         AddResource(thePHandle, 'TFSP', 255, (StringPtr) "\pPrinter Info");
  791.         err = ResError();
  792.         if (err = ResError()) {
  793.             ShowError((StringPtr) "\pAddResource TFSP", err);
  794.             goto closeResource;
  795.         }
  796.     }
  797.  
  798.     theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  799.      HLock((Handle)theHHandle);
  800.  
  801.     (*theHHandle)->theRect     = theDocument->theWindow->portRect;
  802.     OffsetRect(
  803.         &(*theHHandle)->theRect,
  804.         -theDocument->theWindow->portBits.bounds.left,
  805.         -theDocument->theWindow->portBits.bounds.top);
  806.         
  807.     GetFontName((*(theDocument->theText))->txFont, (StringPtr) &(*theHHandle)->theFont);
  808.     
  809.     (*theHHandle)->theSize     = (*(theDocument->theText))->txSize;
  810.     (*theHHandle)->lastID      = theDocument->kind == kDocumentWindow ? theDocument->u.reg.lastID : 0;
  811.     (*theHHandle)->numSections = theDocument->kind == kDocumentWindow ? theDocument->u.reg.numSections : 0;
  812.  
  813.     HUnlock((Handle)theHHandle);
  814.  
  815.     AddResource((Handle)theHHandle, 'TFSS', 255, (StringPtr) "\pHeader Info");
  816.     if (err = ResError()) {
  817.         ShowError((StringPtr) "\pAddResource- TFSS", err);
  818.         goto closeResource;
  819.     }
  820.  
  821. #ifndef RUNTIME
  822.     /*if we have any sections, write out the records and resources*/
  823.  
  824.     if (theDocument->kind == kDocumentWindow && theDocument->u.reg.numSections) {
  825.         /*now write out the section records*/
  826.         SaveSections(theDocument);
  827.  
  828.         /*write the latest versions of all editions to their containers*/
  829.  
  830.         WriteAllEditions(theDocument);
  831.     }
  832. #endif
  833.  
  834.     if (theDocument->type == kPlainTextDoc) {
  835.         /*Now put an AppName in for Finder in 7.0*/
  836.     
  837.         theAppName = (StringHandle)NewHandle(8);
  838.         PLstrcpy(*theAppName,(StringPtr) "\pMacPerl");
  839.     
  840.         AddResource((Handle)theAppName, 'STR ', - 16396, (StringPtr) "\pFinder App Info");
  841.         if (err = ResError()) {
  842.             ShowError((StringPtr) "\pAppName", err);
  843.             goto closeResource;
  844.         }
  845.     }
  846.  
  847.     if (theDocument->kind == kDocumentWindow && theDocument->u.reg.everLoaded) {
  848.         /* Copy all resources that need copying */
  849.         
  850.         origFile = 
  851.             HOpenResFile(
  852.                 theDocument->u.reg.origFSSpec.vRefNum,
  853.                 theDocument->u.reg.origFSSpec.parID,
  854.                 theDocument->u.reg.origFSSpec.name,
  855.                 fsRdPerm);
  856.         if (origFile != -1) {
  857.             err = CopySomeResources(origFile, resFile);
  858.                 
  859.             CloseResFile(origFile);
  860.         } 
  861.         /* Otherwise, let's just assume the file had no resource fork */
  862.     }
  863.  
  864. closeResource:
  865.     CloseResFile(resFile);
  866.     UseResFile(gAppFile);
  867.     
  868.     return err;
  869. }
  870.  
  871. void ScanExtensions(OSType type, void (*found)(const FSSpec * spec, CInfoPBRec * info))
  872. {
  873.     OSErr            err;
  874.     short            runs;
  875.     short         index;
  876.     FSSpec        spec;
  877.     CInfoPBRec    info;
  878.     
  879.     spec.vRefNum    =    gAppVol;
  880.     spec.parID        =    gAppDir;
  881.     
  882.     FSpUp(&spec);
  883.     
  884.     for (runs = 0; runs++ < 2; Special2FSSpec(kExtensionFolderType, 0, 0, &spec)) {
  885.         if (FSpDown(&spec, (StringPtr) "\pMacPerl Extensions"))
  886.             continue;
  887.         if (FSpDown(&spec, (StringPtr) "\p"))
  888.             continue;
  889.         for (index = 1; !FSpIndex(&spec, index++); )
  890.             if (!FSpCatInfo(&spec, &info) && info.hFileInfo.ioFlFndrInfo.fdType == type)
  891.                 found(&spec, &info);
  892.     }
  893. }
  894.  
  895. #ifndef RUNTIME
  896. void AddSaveExtension(const FSSpec * spec, CInfoPBRec * info)
  897. {
  898.     short                 res;
  899.     short                    index;
  900.     SEPackageHdl        pack;    
  901.     StringHandle        name;
  902.     SaveExtension *    ext;
  903.     OSType                fType;
  904.     
  905.     res = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  906.     
  907.     if (res == -1)
  908.         return;
  909.         
  910.     if (!(pack = (SEPackageHdl) Get1Resource('McPp', SERsrcBase)))
  911.         goto closeIt;
  912.     
  913.     for (index = 0; index<(*SaveExtensions)->count; ++index)
  914.         if ((*pack)->id == (*SaveExtensions)->ext[index].id)
  915.             goto closeIt;
  916.     
  917.     name    =    (StringHandle) Get1Resource('STR ', SERsrcBase);
  918.     
  919.     SetHandleSize(
  920.         (Handle) SaveExtensions, GetHandleSize((Handle) SaveExtensions) + sizeof(SaveExtension));
  921.     
  922.     ext                         = (*SaveExtensions)->ext + (*SaveExtensions)->count++;
  923.     ext->id                    = (*pack)->id;
  924.     ext->fType                = (*pack)->fType;
  925.     ext->fCreator            = (*pack)->fCreator;
  926.     ext->wantsBundle        = (*pack)->wantsBundle;
  927.     ext->hasCustomIcon    = (*pack)->hasCustomIcon;
  928.     ext->name        = name;
  929.     ext->file         = *spec;
  930.     
  931.     DetachResource((Handle) name);
  932.     
  933.     fType = ext->fType;
  934.     
  935.     for (index = 0; index<MacPerlFileTypeCount; ++index)
  936.         if (fType == ext->fType)
  937.             goto closeIt;
  938.     
  939.     PtrAndHand(&fType, (Handle) FileTypeH, sizeof(OSType));
  940.     
  941.     ++MacPerlFileTypeCount;
  942. closeIt:
  943.     CloseResFile(res);
  944. }
  945.  
  946. pascal void BuildSEList()
  947. {
  948.     if (SaveExtensions)
  949.         return;
  950.     
  951.     SaveExtensions                 = (SEHdl) NewHandle(2);
  952.     (*SaveExtensions)->count     = 0;
  953.     
  954.     PtrToHand("APPLTEXT", (Handle *) &FileTypeH, 8);
  955.     MacPerlFileTypeCount            = 2;
  956.     
  957.     ScanExtensions('McPp', AddSaveExtension);
  958.     
  959.     MoveHHi((Handle) FileTypeH);
  960.     HLock((Handle) FileTypeH);
  961.     
  962.     MacPerlFileTypes                = *FileTypeH;
  963. }
  964.  
  965. pascal Boolean CanSaveAs(DocType type)
  966. {
  967.     short    index;
  968.     
  969.     BuildSEList();
  970.     
  971.     switch (type) {
  972.     case kPlainTextDoc:
  973.     case kRuntime7Doc:
  974.         return true;
  975.     default:
  976.         break;
  977.     }
  978.     
  979.     for (index = 0; index<(*SaveExtensions)->count; ++index)
  980.         if (type == (*SaveExtensions)->ext[index].id)
  981.             return true;
  982.             
  983.     return false;
  984. }
  985.  
  986.  
  987. pascal void AddExtensionsToMenu(MenuHandle menu)
  988. {
  989.     short                index;
  990.     StringHandle    name;
  991.     
  992.     BuildSEList();
  993.     
  994.     for (index = 0; index < (*SaveExtensions)->count; ++index) {
  995.         name = (*SaveExtensions)->ext[index].name;
  996.         
  997.         HLock((Handle) name);
  998.         AppendMenu(menu, (StringPtr) "\px");
  999.         SetMenuItemText(menu, index+4, *name);
  1000.         HUnlock((Handle) name);
  1001.     }
  1002. }
  1003.  
  1004. pascal short Type2Menu(DocType type)
  1005. {
  1006.     short    index;
  1007.  
  1008.     BuildSEList();
  1009.     
  1010.     switch (type) {
  1011.     case kPlainTextDoc:
  1012.         return 1;
  1013.     case kRuntime6Doc:
  1014.         return 2;
  1015.     case kRuntime7Doc:
  1016.         return 3;
  1017.     default:
  1018.         for (index = 0; index < (*SaveExtensions)->count; ++index)
  1019.             if ((*SaveExtensions)->ext[index].id == type)
  1020.                 return index + 4;
  1021.     }
  1022.     
  1023.     /* Should never happen */
  1024.     
  1025.     return 0;
  1026. }
  1027.  
  1028. pascal DocType Menu2Type(short item)
  1029. {
  1030.     BuildSEList();
  1031.     
  1032.     switch (item) {
  1033.     case 1:
  1034.         return kPlainTextDoc;
  1035.     case 2:
  1036.         return kRuntime6Doc;
  1037.     case 3:
  1038.         return kRuntime7Doc;
  1039.     default:
  1040.         item -= 4;
  1041.         
  1042.         if (item < 0 || item >= (*SaveExtensions)->count)
  1043.             return kUnknownDoc;
  1044.         
  1045.         return (*SaveExtensions)->ext[item].id;
  1046.     }
  1047. }
  1048. #endif
  1049.