home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Science / µSim 1.0 folder / source / ControlStore.c < prev    next >
Encoding:
Text File  |  1995-04-07  |  12.6 KB  |  484 lines  |  [TEXT/MMCC]

  1. /*
  2. Copyright © 1993,1994 by Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware: you can copy, exchange, modify this
  5. code as you wish. You may include this code in any kind of application: freeware,
  6. shareware, or commercial, provided that full credits are given.
  7. You may not sell or distribute this code for profit.
  8. */
  9.  
  10. //#pragma load "MacDump"
  11.  
  12. #include    "UtilsSys7.h"
  13. #include    "Globals.h"
  14. #include    "Animation.h"
  15. #include    "ControlStore.h"
  16. #include    "DoMenu.h"
  17. #include    "Microprogram_Ed.h"
  18. #include    "SimUtils.h"
  19.  
  20. #if defined(FabSystem7orlater)
  21.  
  22. #pragma segment Rare
  23.  
  24. const short controlStoreObject[] = {kP_CONTSTORE, 0 };
  25.  
  26. short    myFileRefN;
  27. Boolean    DocIsOpen;
  28.  
  29. static FSSpec    workingFile;
  30. static ScriptCode    wkFileScript;
  31. static Boolean    dirtyCSFlag = false;
  32.  
  33. /*====== internal routines ======*/
  34. static OSErr gotSave(Handle buf);
  35. static OSErr gotSaveAs(Handle buf, OSType);
  36. static OSErr SafeSave(Handle wrBuf, FSSpec *onWhichFile, ScriptCode);
  37.  
  38. /* RevertFile: we revert to the last saved version of the doc */
  39.  
  40. OSErr RevertFile(void)
  41. {
  42. FSSpec    tempNewFile = workingFile;
  43.  
  44. FSClose(myFileRefN);
  45. myFileRefN = 0;
  46. DocumentIsDirty(false);
  47. return myOpenCSFile(&tempNewFile, wkFileScript, false);
  48. }
  49.  
  50. /* myOpenCSFile: we read all that stuff (the microprogram) from the file */
  51.  
  52. OSErr myOpenCSFile(FSSpec *theFile, ScriptCode theScript, Boolean StationeryDoc)
  53. {
  54. Str255    tempS;
  55. ParamBlockRec    myPB;
  56. EventRecord    dummyEv;
  57. Rect    tempRect;
  58. GrafPtr    savePort;
  59. register Handle    tempBuffer;
  60. unsigned long    fileSize;
  61. short    length;
  62. register OSErr    err;
  63. register Boolean    isLocked = false;
  64.  
  65. SetCursor(*gWatchHandle);
  66. GetPort(&savePort);
  67. SetPort(gWPtr_Microprogram_Ed);
  68. if ((err = FSpOpenDFCompat(theFile, StationeryDoc ? fsRdPerm : fsRdWrPerm, &myFileRefN)) == permErr) {
  69.     err = FSpOpenDFCompat(theFile, fsRdPerm, &myFileRefN);
  70.     isLocked = true;
  71.     }
  72. if (err == noErr) {
  73.     if ((err = GetEOF(myFileRefN, (long *)&fileSize)) == noErr) {
  74.         if ((tempBuffer = NewHandleGeneral(fileSize)) != 0L) {
  75.             myPB.ioParam.ioCompletion = 0L;
  76.             myPB.ioParam.ioRefNum = myFileRefN;
  77.             HLock(tempBuffer);
  78.             myPB.ioParam.ioBuffer = *tempBuffer;
  79.             myPB.ioParam.ioReqCount = fileSize;
  80.             myPB.ioParam.ioPosMode = fsFromStart;
  81.             myPB.ioParam.ioPosOffset = 0L;
  82.             (void)PBReadAsync(&myPB);
  83.             while (myPB.ioParam.ioResult > 0) {
  84.                 SystemTask();
  85.                 (void)EventAvail(everyEvent, &dummyEv);
  86.                 }
  87.             HUnlock(tempBuffer);
  88.             if ((err = myPB.ioParam.ioResult) == noErr) {
  89.                 Point    tempCell;
  90.                 register unsigned char *spanningPtr;
  91.                 register short    i;
  92.  
  93.                 LSetDrawingMode(false, Lists[kL_COMMENTS]);
  94.                 DoNew();
  95.                 BlockMoveData(*tempBuffer, gCsMemory, kSIZE_CSMEM + kSIZE_ASSMEM);
  96.                 tempCell.h = 0;
  97.                 HLock(tempBuffer);
  98.                 for (spanningPtr = (unsigned char *)*tempBuffer + kSIZE_CSMEM + kSIZE_ASSMEM,
  99.                     i = 0; i <= maxLLine[kL_COMMENTS]; i++) {
  100.  
  101.                     tempCell.v = i;
  102.                     LSetCell(spanningPtr + 1, *spanningPtr, tempCell, Lists[kL_COMMENTS]);
  103.                     spanningPtr += *spanningPtr + 1;
  104.                     }
  105.                 HUnlock(tempBuffer);
  106.                 LSetDrawingMode(true, Lists[kL_COMMENTS]);
  107.                 if (StationeryDoc == false) {
  108.                     workingFile = *theFile;
  109.                     wkFileScript = theScript;
  110.                     SetWTitle(gWPtr_Microprogram_Ed, theFile->name);
  111.                     }
  112.                 DocumentIsDirty(false);
  113.             /* get cell contents and put into TextEdit field */
  114.                 length = 255;    /* maximum length of text */
  115.                 tempCell.h = 0;
  116.                 tempCell.v = theSelection[kL_COMMENTS];
  117.                 LGetCell(&tempS, &length, tempCell, Lists[kL_COMMENTS]);
  118.                 TESetText(&tempS, length, TEs[kKEY_COMMENT]);
  119.                 RefreshTE(kKEY_COMMENT);
  120.         //        UnloadSeg(RefreshTE);
  121.                 SetMir((*(gCsMemory + theSelection[kL_COMMENTS])).cstore);
  122.                 tempRect = *keyrects[kKEY_LIST];
  123.                 tempRect.right -= kScrollbarAdjust;
  124.                 InvalRect(&tempRect);
  125.                 DoMenuWindows(kMItem_Microprogram);
  126.                 }
  127.             DisposeHandle(tempBuffer);
  128.             }
  129.         else err = MemError();
  130.         }
  131.     if (err || StationeryDoc || isLocked)
  132.         (void)FSClose(myFileRefN);
  133.     }
  134. if (err || StationeryDoc || isLocked)
  135.     myFileRefN = 0;
  136. SetPort(savePort);
  137. InitCursor();
  138. return err;
  139. }
  140.  
  141. /* mySaveCSFile: the user has chosen Save or Save As… from the menus */
  142.  
  143. OSErr mySaveCSFile(short selector)
  144. {
  145. Point    tempCell;
  146. register Handle    readyBuffer;
  147. register OSErr    err;
  148.  
  149. SetCursor(*gWatchHandle);
  150. tempCell.h = 0;
  151. tempCell.v = theSelection[kL_COMMENTS];
  152. ChangedListSelection(tempCell, kL_COMMENTS, false);
  153. if (readyBuffer = PrepareBufferFromList()) {
  154.     switch (selector) {
  155.         case kGOT_SAVE: err = gotSave(readyBuffer);
  156.             break;
  157.         case kGOT_SAVEAS: err = gotSaveAs(readyBuffer, kFTY_CSTORE);
  158.             break;
  159.         case kGOT_SAVESTATIONERY: err = gotSaveAs(readyBuffer, kFTY_CSTOREPAD);
  160.             break;
  161.         }
  162.     DisposeHandle(readyBuffer);
  163.     }
  164. else err = MemError();
  165. InitCursor();
  166. return err;
  167. }
  168.  
  169. /* gotSave: the user has told us to Save. Is he working at a previously saved
  170. document or not? */
  171.  
  172. static OSErr gotSave(Handle buf)
  173. {
  174. register OSErr    err;
  175.  
  176. if (myFileRefN != 0)
  177.     err = SafeSave(buf, &workingFile, wkFileScript);
  178. else
  179.     err = gotSaveAs(buf, kFTY_CSTORE);
  180. return err;
  181. }
  182.  
  183. /* gotSaveAs: we must definitely show up the dialog box for "save-a-file"
  184. and save it if asked for */
  185.  
  186. static OSErr gotSaveAs(Handle buf, OSType theType)
  187. {
  188. enum {
  189. kSTR_CSPROMPT = 135,
  190. kSTR_CSDEFNAME
  191. };
  192.  
  193. StandardFileReply    mySFR;
  194. FInfo    fndrInfo;
  195. register Handle    sH1;
  196. register Handle    sH2;
  197. short    tmpFRefN;
  198. register SignedByte    state1, state2;
  199. register OSErr    err;
  200.  
  201. state1 = WantThisHandleSafe(sH1 = (Handle)GetString(kSTR_CSPROMPT));
  202. state2 = WantThisHandleSafe(sH2 = (Handle)GetString(kSTR_CSDEFNAME));
  203. InitCursor();
  204. StandardPutFile((ConstStr255Param)*sH1, (ConstStr255Param)*sH2, &mySFR);
  205. SetCursor(*gWatchHandle);
  206. if (mySFR.sfGood) {
  207.     if (mySFR.sfReplacing) {
  208.         if (noErr == (err = FSpGetFInfoCompat(&mySFR.sfFile, &fndrInfo))) {
  209.             if (fndrInfo.fdType == theType)
  210.                 err = SafeSave(buf, &mySFR.sfFile, mySFR.sfScript);
  211.             else
  212.                 (void)StopAlert_UPP(kALRT_WRONGEXISTINGDOC, myStdFilterProcNoCancel);
  213.             }
  214.         }
  215. /* not replacing an existing file */
  216.     else if ((err = FSpCreateCompat(&mySFR.sfFile, kFCR_MINE, theType, mySFR.sfScript)) == noErr)
  217.         if ((err = FSpOpenDFCompat(&mySFR.sfFile, fsRdWrPerm, &tmpFRefN)) == noErr)
  218.             if ((err = WriteMicroprogramData(buf, &mySFR.sfFile, theType, tmpFRefN, mySFR.sfScript)) == noErr) {
  219.                 if (theType == kFTY_CSTORE) {
  220.                     if (myFileRefN)    /* close old working file if any */
  221.                         (void)FSClose(myFileRefN);
  222.                     myFileRefN = tmpFRefN;    /* this is the new work file */
  223.                     workingFile = mySFR.sfFile;
  224.                     wkFileScript = mySFR.sfScript;
  225.                     SetWTitle(gWPtr_Microprogram_Ed, mySFR.sfFile.name);
  226.                     DocumentIsDirty(false);
  227.                     }
  228.                 else if (theType == kFTY_CSTOREPAD) {
  229.                     (void) FSpSetIsStationery(&mySFR.sfFile);
  230.                     (void)FSClose(tmpFRefN);
  231.                     }
  232.                 }
  233.             else {    /* error writing data */
  234.                 (void)FSClose(tmpFRefN);
  235.                 (void)FSpDeleteCompat(&mySFR.sfFile);
  236.                 }
  237.     }
  238. else err = 1;
  239. HSetState(sH1, state1);
  240. HSetState(sH2, state2);
  241. return(err);
  242. }
  243.  
  244. /* SafeSave: we should do a safe save of the document
  245. (a previously saved version already exists) */
  246.  
  247. OSErr SafeSave(Handle buf, FSSpec *onWhichFile, ScriptCode myFScript)
  248. {
  249. Str255    tempFName;
  250. FSSpec    thisFSSpec;
  251. long    thisDirID;
  252. short    thisVRefNum, newFileRefn;
  253. register OSErr    err;
  254.  
  255. if (0)    /* test if file locked (FSpExchange does not) */
  256.     err = fLckdErr;
  257. else {
  258.     MyNumToString(TickCount(), tempFName);
  259.     if ((err = FindFolder(onWhichFile->vRefNum, kTemporaryFolderType, kCreateFolder,
  260.                     &thisVRefNum, &thisDirID)) == noErr) {
  261.         (void)FSMakeFSSpecCompat(thisVRefNum, thisDirID, (ConstStr255Param)&tempFName, &thisFSSpec);
  262.         if ((err = FSpCreateCompat(&thisFSSpec, kFCR_MINE, kFTY_CSTORE,
  263.                             myFScript)) == noErr)
  264.             if ((err = FSpOpenDFCompat(&thisFSSpec, fsRdWrPerm, &newFileRefn)) == noErr)
  265.                 if ((err = WriteMicroprogramData(buf, &thisFSSpec, kFTY_CSTORE, newFileRefn, myFScript)) == noErr) {
  266.                     if ((err = FSpExchangeFilesCompat(&thisFSSpec, onWhichFile)) == noErr) {
  267.                         if (myFileRefN)
  268.                             (void)FSClose(myFileRefN);
  269.                         myFileRefN = newFileRefn;
  270.                         workingFile = *onWhichFile;
  271.                         wkFileScript = myFScript;
  272.                         SetWTitle(gWPtr_Microprogram_Ed, onWhichFile->name);
  273.                         DocumentIsDirty(false);
  274.                         err = FSpDeleteCompat(&thisFSSpec);
  275.                         }
  276.                     }
  277.                 else {
  278.                     (void)FSClose(newFileRefn);
  279.                     (void)FSpDeleteCompat(&thisFSSpec);    // the temporary one
  280.                     if (err == dskFulErr) {
  281.                         (void)StopAlert_UPP(kALRT_NOSAVE, myStdFilterProcNoCancel);
  282.                         err = 1;
  283.                         }
  284.                     }
  285.         }
  286.     }
  287. return(err);
  288. }
  289.  
  290. /* WriteMicroprogramData: writes physically the data into the file */
  291.  
  292. OSErr WriteMicroprogramData(Handle prepBuffer, FSSpec *theFSpec, OSType theType, short theOpenedFile,
  293.                         ScriptCode theFileSc)
  294. {
  295. ParamBlockRec    myPB;
  296. EventRecord    dummyEv;
  297. register OSErr    err;
  298.  
  299. myPB.ioParam.ioCompletion = 0L;
  300. myPB.ioParam.ioBuffer = (Ptr)gCsMemory;
  301. myPB.ioParam.ioReqCount = kSIZE_CSMEM + kSIZE_ASSMEM;
  302. myPB.ioParam.ioPosMode = fsFromStart;
  303. myPB.ioParam.ioRefNum = theOpenedFile;
  304. myPB.ioParam.ioPosOffset = 0L;
  305. (void)PBWriteAsync(&myPB);
  306. while (myPB.ioParam.ioResult > 0) {
  307.     SystemTask();
  308.     (void)EventAvail(everyEvent, &dummyEv);
  309.     }
  310. if ((err = myPB.ioParam.ioResult) == noErr) {
  311.     myPB.ioParam.ioBuffer = *prepBuffer;
  312.     myPB.ioParam.ioReqCount = InlineGetHandleSize(prepBuffer);
  313.     myPB.ioParam.ioPosMode = fsAtMark;
  314.     myPB.ioParam.ioRefNum = theOpenedFile;
  315.     myPB.ioParam.ioPosOffset = 0L;
  316.     HLock(prepBuffer);
  317.     (void)PBWriteAsync(&myPB);
  318.     while (myPB.ioParam.ioResult > 0) {
  319.         SystemTask();
  320.         (void)EventAvail(everyEvent, &dummyEv);
  321.         }
  322.     HUnlock(prepBuffer);
  323.     if ((err = myPB.ioParam.ioResult) == noErr)
  324.         err = AddSTRRes2Doc(theFSpec, kFCR_MINE, theType, kSTR_ApplicationName, theFileSc);
  325.     }
  326. return err;
  327. }
  328.  
  329. /* DoNew: starts afresh with a new microprogram */
  330.  
  331. void DoNew(void)
  332. {
  333. enum {
  334. kSTR_UNTITLED = 137
  335. };
  336.  
  337. register StringHandle    UntitledStr;
  338. register SignedByte    oldstate;
  339.  
  340. ResetMicroprogramWindow();
  341. DocIsOpen = true;
  342. ActivateObjs(controlStoreObject);
  343. if (UntitledStr = GetString(kSTR_UNTITLED)) {
  344.     oldstate = WantThisHandleSafe((Handle)UntitledStr);
  345.     SetWTitle(gWPtr_Microprogram_Ed, *UntitledStr);
  346.     (void) PLstrcpy(workingFile.name, *UntitledStr);
  347.     HSetState((Handle)UntitledStr, oldstate);
  348.     }
  349. }
  350.  
  351. /* ResetMicroprogramWindow: wipes out the window to an empty one */
  352.  
  353. void ResetMicroprogramWindow(void)
  354. {
  355. Str255    tempS;
  356. register Point tempCell = { 0, 0};
  357. short    leng;
  358. register short    i;
  359.  
  360. for ( i = 0; i <= maxLLine[kL_COMMENTS]; i++) {
  361.     tempCell.v = i;
  362.     LClrCell(tempCell, Lists[kL_COMMENTS]);
  363.     }
  364. tempCell.v = 0;
  365. leng = 255;
  366. LGetCell(&tempS, &leng, tempCell, Lists[kL_COMMENTS]);
  367. TESetText(&tempS, leng, TEs[kKEY_COMMENT]);
  368. keyDownDest = kKEY_BRTO;
  369.  
  370.     {
  371.     register union u_mir tempmir;
  372.  
  373.     tempmir.cstore = 0L;
  374.     tempmir.bits.c = 15;
  375.     tempmir.bits.dsc = 1;
  376.     SetControlsFromMir(tempmir);
  377. //    UnloadSeg(SetControlsFromMir);
  378.     }
  379. }
  380.  
  381. /* PrepareBufferFromList: sets up a buffer containing all the info
  382. about the microprogram, so that it is ready to be saved into a file. */
  383.  
  384. Handle PrepareBufferFromList(void)
  385. {
  386. Str255    tempS;
  387. Point    tempCell;
  388. register Handle    myH = nil;
  389. short    len;
  390. register OSErr    err;
  391. register short i;
  392.  
  393. if (Lists[kL_COMMENTS] && gCsMemory)
  394.     if (myH = NewHandleGeneral(0L)) {
  395.         tempCell.h = 0;
  396.         for (i = 0; i <= maxLLine[kL_COMMENTS]; i++) {
  397.             tempCell.v = i;
  398.             len = 255;
  399.             LGetCell(&tempS[1], &len, tempCell, Lists[kL_COMMENTS]);
  400.             tempS[0] = len;
  401.             if (err = PtrAndHand(&tempS, myH, len + 1))
  402.                 break;
  403.             }
  404.         if (err) {
  405.             DisposeHandle(myH);
  406.             myH = nil;
  407.             }
  408.         }
  409. return myH;
  410. }
  411.  
  412. #pragma segment Main
  413.  
  414. /* ReadyToTerminate: we decide if we are ready to quit gracefully;
  415. shall we save an unsaved document? Let the user choose… */
  416.  
  417. Boolean ReadyToTerminate(void)
  418. {
  419. enum {
  420. kPUSH_SAVE = 1,
  421. kPUSH_CANCEL,
  422. kPUSH_DONTSAVE
  423. };
  424.  
  425. register OSErr    err;
  426.  
  427. if (gRstatus) {
  428.     if (CautionAlert_UPP(kALRT_CPURUNNING, myStdFilterProc) == cancel)
  429.         return false;
  430.     }
  431. if (dirtyCSFlag) {
  432.     ParamText(workingFile.name, nil, nil, nil);
  433.     switch (CautionAlert_UPP(kALRT_SAVE, myStdFilterProc)) {
  434.         case kPUSH_SAVE:
  435.             err = mySaveCSFile(kGOT_SAVE);
  436.             UnloadSeg(mySaveCSFile);
  437.             if (err) {
  438.                 if (err != 1)
  439.                     ErrorAlert(err);
  440.                 return false;
  441.                 }
  442.             break;
  443.         case kPUSH_CANCEL:
  444.             return false;
  445.             break;
  446.         case kPUSH_DONTSAVE:
  447.             break;
  448.         }
  449.     }
  450. if (myFileRefN) {
  451.     FSClose(myFileRefN);
  452.     myFileRefN = 0;
  453.     }
  454. DocumentIsDirty(false);
  455. DocIsOpen = false;
  456. DeactivateObjs(controlStoreObject);
  457. MyZeroBuffer((long *)gCsMemory, numOfLongs(kSIZE_ASSMEM + kSIZE_CSMEM));
  458. CloseMicroProg(gWPtr_Microprogram_Ed);
  459. SetMir(0L);
  460. return true;
  461. }
  462.  
  463. /* DocumentIsDirty: we are told if the document has been modified
  464. since last save. */
  465.  
  466. void DocumentIsDirty(Boolean dirtiness)
  467. {
  468. if (dirtyCSFlag != dirtiness) {
  469.     if (dirtyCSFlag = dirtiness) {
  470.         EnableItem(gMenu_File, kMItem_Save_Control_St);
  471.         }
  472.     else {
  473.         DisableItem(gMenu_File, kMItem_Save_Control_St);
  474.         }
  475.     if (myFileRefN && dirtyCSFlag)
  476.         EnableItem(gMenu_File, kMItem_Revert_to_Saved);
  477.     else
  478.         DisableItem(gMenu_File, kMItem_Revert_to_Saved);
  479.     }
  480. }
  481.  
  482. #endif
  483.  
  484.