home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / luschsrc.sit / document.c < prev    next >
Text File  |  1990-05-23  |  13KB  |  635 lines

  1. /********************************************************************************
  2.  *    document.c
  3.  *
  4.  *    File Management Package
  5.  *
  6.  *    Written by Paco Xander Nathan
  7.  *    ⌐1990, Motorola Inc.  Public domain source code.
  8.  ********************************************************************************/
  9.  
  10. #include "applic.h"
  11. #include "window.h"
  12. #include "dialog.h"
  13. #include "context.h"
  14. #include "text.h"
  15. #include "list.h"
  16. #include "error.h"
  17. #include "string.h"
  18. #include "ascii.h"
  19. #include "document.h"
  20. #include "print.h"
  21. #include "gnosis.h"
  22.  
  23.  
  24. /* Local Function Prototypes
  25.  */
  26. #ifdef PROTOTYPES
  27. void DocReadLine (WORD refNum, LONG count, BYTE *data);
  28. void DocWriteLine (WORD refNum, LONG count, BYTE *data);
  29.  
  30. void DocReadNum (WORD refNum, WORD *theNum);
  31. void DocWriteNum (WORD refNum, WORD theNum);
  32.  
  33. void DocReadText (WORD refNum, Handle textHdl);
  34. void DocWriteText (WORD refNum, Handle textHdl);
  35.  
  36. void DocReadGnos (WORD refNum, GnosPtr gnosPtr);
  37. void DocWriteGnos (WORD refNum, GnosPtr gnosPtr);
  38. void DocRecurGnos (WORD refNum, GnosPtr gnosPtr);
  39. #endif
  40.  
  41.  
  42. void
  43. DocReadLine (refNum, count, data)
  44.     register WORD refNum;
  45.     LONG count;
  46.     register BYTE *data;
  47. {
  48.     LONG bufLen = count + 1;
  49.     BYTE theBuf[100];
  50.  
  51.     FSRead(refNum, &bufLen, theBuf);
  52.     BlockMove(theBuf, data, count);
  53. }
  54.  
  55.  
  56. void
  57. DocWriteLine (refNum, count, data)
  58.     register WORD refNum;
  59.     LONG count;
  60.     register BYTE *data;
  61. {
  62.     BYTE theEnd = asciiReturn;
  63.  
  64.     FSWrite(refNum, &count, data);
  65.     
  66.     count = 1L;
  67.     FSWrite(refNum, &count, &theEnd);
  68. }
  69.  
  70.  
  71. void
  72. DocReadNum (refNum, theNum)
  73.     register WORD refNum;
  74.     register WORD *theNum;
  75. {
  76.     BYTE lineBuf[100];
  77.     BYTE *theLine = lineBuf;
  78.     LONG count = 1L;
  79.  
  80.     /* Get the length word
  81.      */
  82.     while ((FSRead(refNum, &count, theLine) == noErr) && (*theLine++ != asciiReturn))
  83.         ;
  84.     
  85.     /* Parse the length word
  86.      */
  87.     *--theLine = '\0';
  88.     sscanf(lineBuf, "%d", theNum);
  89. }
  90.  
  91.  
  92. void
  93. DocWriteNum (refNum, theNum)
  94.     register WORD refNum;
  95.     register WORD theNum;
  96. {
  97.     BYTE theEnd = asciiReturn;
  98.     BYTE lineBuf[100];
  99.     LONG theLen;
  100.  
  101.     theLen = sprintf(lineBuf, "%d", theNum);
  102.     FSWrite(refNum, &theLen, lineBuf);
  103.     
  104.     /* Write a separator
  105.      */
  106.     theLen = 1L;
  107.     FSWrite(refNum, &theLen, &theEnd);
  108. }
  109.  
  110.  
  111. void
  112. DocReadText (refNum, textHdl)
  113.     register WORD refNum;
  114.     register Handle textHdl;
  115. {
  116.     WORD textLen;
  117.     LONG count;
  118.     BYTE theEnd;
  119.  
  120.     /* Get the length word, allocate a handle
  121.      */
  122.     DocReadNum(refNum, &textLen);
  123.     count = textLen;
  124.     SetHandleSize(textHdl, count);
  125.     
  126.     /* Read the text
  127.      */
  128.     HLock(textHdl);
  129.     FSRead(refNum, &count, *textHdl);
  130.     HUnlock(textHdl);
  131.  
  132.     /* Read a separator
  133.      */
  134.     count = 1L;
  135.     FSRead(refNum, &count, &theEnd);
  136. }
  137.  
  138.  
  139. void
  140. DocWriteText (refNum, textHdl)
  141.     register WORD refNum;
  142.     register Handle textHdl;
  143. {
  144.     BYTE theEnd = asciiReturn;
  145.     LONG count;
  146.  
  147.     /* Write the length word
  148.      */
  149.     count = GetHandleSize(textHdl);
  150.     DocWriteNum(refNum, (WORD) count);
  151.     
  152.     /* Write the text
  153.      */
  154.     HLock(textHdl);
  155.     FSWrite(refNum, &count, *textHdl);
  156.     HUnlock(textHdl);
  157.     
  158.     /* Write a separator
  159.      */
  160.     count = 1L;
  161.     FSWrite(refNum, &count, &theEnd);
  162. }
  163.  
  164.  
  165. void
  166. DocReadGnos (refNum, gnosPtr)
  167.     register WORD refNum;
  168.     register GnosPtr gnosPtr;
  169. {
  170.     WORD titleLen;
  171.  
  172.     DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->color);
  173.     DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->pair);
  174.     DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->mark);
  175.     DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->anxiety);
  176.     DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->stress);
  177.  
  178.     DocReadNum(refNum, &(gnosPtr->total[0]));
  179.     DocReadNum(refNum, &(gnosPtr->total[1]));
  180.  
  181.     DocReadNum(refNum, &titleLen);
  182.     DocReadLine(refNum, titleLen, (BYTE *) (gnosPtr->title + 1));
  183.     gnosPtr->title[0] = titleLen;
  184.  
  185.     DocReadText(refNum, gnosPtr->textHdl);
  186. }
  187.  
  188.  
  189. void
  190. DocWriteGnos (refNum, gnosPtr)
  191.     register WORD refNum;
  192.     register GnosPtr gnosPtr;
  193. {
  194.     WORD titleLen;
  195.  
  196.     DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->color);
  197.     DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->pair);
  198.     DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->mark);
  199.     DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->anxiety);
  200.     DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->stress);
  201.  
  202.     DocWriteNum(refNum, gnosPtr->total[0]);
  203.     DocWriteNum(refNum, gnosPtr->total[1]);
  204.  
  205.     titleLen = gnosPtr->title[0];
  206.     DocWriteNum(refNum, titleLen);
  207.     DocWriteLine(refNum, titleLen, (BYTE *) (gnosPtr->title + 1));
  208.  
  209.     DocWriteText(refNum, gnosPtr->textHdl);
  210. }
  211.  
  212.  
  213. /* Recursively output the prognosis list in reverse to preserve order
  214.  * next time this document is read
  215.  */
  216. void
  217. DocRecurGnos (refNum, gnosPtr)
  218.     register WORD refNum;
  219.     register GnosPtr gnosPtr;
  220. {
  221.     if (gnosPtr) {
  222.         ApplSpinCurs(FALSE);
  223.         DocRecurGnos(refNum, gnosPtr->next);
  224.         DocWriteGnos(refNum, gnosPtr);
  225.     }
  226. }
  227.  
  228.  
  229. /* Read the named file
  230.  */
  231. Boolean
  232. DocReadFile (fileName, vRefNum)
  233.     register StringPtr fileName;
  234.     register WORD vRefNum;
  235. {
  236.     register Boolean result = TRUE;
  237.     register OSErr IOResult;
  238.     WORD gnosCount;
  239.     ioParam pb;
  240.  
  241.     /* Set up the pb.  Note that it's set up as read-only
  242.      */
  243.     pb.ioCompletion = NULL;
  244.     pb.ioNamePtr = fileName;
  245.     pb.ioVRefNum = vRefNum;
  246.     pb.ioVersNum = 0;
  247.     pb.ioPermssn = fsRdPerm;
  248.     pb.ioMisc = NULL;
  249.  
  250.     /* If we can't open it for some reason, signal an error and return
  251.      */
  252.     ApplSpinCurs(FALSE);
  253.     
  254.     if (!(result = !PBOpen(&pb, FALSE))) {
  255.         ErrFileMgr(pb.ioResult, fileName);
  256.         return FALSE;
  257.     }
  258.  
  259.     /* Read file into handle and set the new text
  260.      */
  261.     ApplSpinCurs(FALSE);
  262.     DocReadNum(pb.ioRefNum, &gnosCount);
  263.  
  264.     for (; gnosCount--; ) {
  265.         ApplSpinCurs(FALSE);
  266.         DocReadGnos(pb.ioRefNum, GnosNew());
  267.     }
  268.  
  269.     /* Close file before returning
  270.      */
  271.     FSClose(pb.ioRefNum);
  272.     return result;
  273. }
  274.  
  275.  
  276. /* Write the named file
  277.  */
  278. Boolean
  279. DocWriteFile (fileName, vRefNum)
  280.     register StringPtr fileName;
  281.     register WORD vRefNum;
  282. {
  283.     register OSErr IOResult = noErr;
  284.     register Boolean result = TRUE;
  285.     WORD refNum;
  286.     LONG logEOF;
  287.     FInfo theFInfo;
  288.  
  289.     /* Try the open the specified file
  290.      */
  291.     if (IOResult = FSOpen(fileName, vRefNum, &refNum)) {
  292.         ErrFileMgr(IOResult, fileName);
  293.         result = FALSE;
  294.     }
  295.  
  296.     /* Try to make the file empty, as a test
  297.      */
  298.     ApplSpinCurs(FALSE);
  299.     logEOF = 0L;
  300.  
  301.     if (result && (IOResult = SetEOF(refNum, logEOF))) {
  302.         /* Don't forget to close it!  Otherwise it will remain
  303.          * open until you reboot the machine
  304.          */
  305.         FSClose(refNum);
  306.         ErrFileMgr(IOResult, fileName);
  307.         result = FALSE;
  308.     }
  309.  
  310.     /* Write out the list of data
  311.      */
  312.     ApplSpinCurs(FALSE);
  313.  
  314.     if (result) {
  315.         DocWriteNum(refNum, gnosList.count);
  316.         DocRecurGnos(refNum, gnosList.head);
  317.     }
  318.  
  319.     /* Close the file and flush the volume, to make sure disk is correct
  320.      */
  321.     if (result) {
  322.         FSClose(refNum);
  323.         FlushVol(NULL, vRefNum);
  324.  
  325.         /* Update the creatrix so that the icon will be correct and the file
  326.          * will launch our application
  327.          */
  328.         if (!GetFInfo(fileName, vRefNum, &theFInfo)) {
  329.             theFInfo.fdCreator = LUCH_TAG;
  330.             SetFInfo(fileName, vRefNum, &theFInfo);
  331.         }
  332.     }
  333.  
  334.     ApplSpinCurs(FALSE);
  335.     return result;
  336. }
  337.  
  338.  
  339. /* Open the named file into the specified window
  340.  */
  341. Boolean
  342. DocOpenFile (theWindow, fileName, vRefNum)
  343.     register WindowPtr theWindow;
  344.     register StringPtr fileName;
  345.     register WORD vRefNum;
  346. {
  347.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  348.     register Boolean result;
  349.     GrafPtr savePort;
  350.  
  351.     GetPort(&savePort);
  352.     SetPort(theWindow);
  353.  
  354.     /* Open the file
  355.      */
  356.     ApplSpinCurs(FALSE);
  357.     
  358.     if (result = DocReadFile(fileName, vRefNum)) {
  359.         infoPtr->named = TRUE;
  360.  
  361.         StrPCpy(infoPtr->fileName, fileName);
  362.         SetWTitle(theWindow, fileName);
  363.         infoPtr->vRefNum = vRefNum;
  364.  
  365.         WindSwitch(theWindow, TRUE);
  366.         GnosRefresh();
  367.         GnosLearn();
  368.     }
  369.  
  370.     SetPort(savePort);
  371.     return result;
  372. }
  373.  
  374.  
  375. /* Save the contents of the window into the designated file
  376.  */
  377. Boolean
  378. DocSaveFile (theWindow, fileName, vRefNum)
  379.     register WindowPtr theWindow;
  380.     register StringPtr fileName;
  381.     register WORD vRefNum;
  382. {
  383.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  384.     register Boolean result = TRUE;
  385.     register OSErr IOResult;
  386.     GrafPtr savePort;
  387.  
  388.     GetPort(&savePort);
  389.     SetPort(theWindow);
  390.  
  391.     /* Delete the former contents of the file, without changing
  392.      */
  393.     FSDelete(fileName, vRefNum);
  394.  
  395.     /* Now try to create it again
  396.      */
  397.     if (IOResult = Create(fileName, vRefNum, LUCH_TAG, LUCH_TAG)) {
  398.         ErrFileMgr(IOResult, fileName);
  399.         result = FALSE;
  400.     }
  401.  
  402.     /* Try to write, then update the name and volume ref
  403.      */
  404.     if (result && (result = DocWriteFile(fileName, vRefNum))) {
  405.         StrPCpy(infoPtr->fileName, fileName);
  406.         SetWTitle(theWindow, fileName);
  407.         ApplSpinCurs(FALSE);
  408.  
  409.         infoPtr->vRefNum = vRefNum;
  410.         infoPtr->dirty = FALSE;
  411.         infoPtr->named = TRUE;
  412.     }
  413.     
  414.     SetPort(savePort);
  415.     return result;
  416. }
  417.  
  418.  
  419. /* Open a new document
  420.  */
  421. void
  422. DocNew (theWindow)
  423.     register WindowPtr theWindow;
  424. {
  425.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  426.     GrafPtr savePort;
  427.  
  428.     GetPort(&savePort);
  429.     SetPort(theWindow);
  430.  
  431.     GetIndString(infoPtr->fileName, RSRCBASE, strUntitled);
  432.     SetWTitle(theWindow, infoPtr->fileName);
  433.     ApplSpinCurs(FALSE);
  434.  
  435.     infoPtr->dirty = FALSE;
  436.     infoPtr->named = FALSE;
  437.  
  438.     /* Switch to the window and redraw it
  439.      */
  440.     WindSwitch(theWindow, TRUE);
  441.     SetPort(savePort);
  442. }
  443.  
  444.  
  445. /* Prompt for an existing document file
  446.  */
  447. void
  448. DocOpen (theWindow)
  449.     register WindowPtr theWindow;
  450. {
  451.     static SFTypeList myTypes = { LUCH_TAG };
  452.     static Point SFGwhere = { 80, 72 };
  453.     SFReply theReply;
  454.     GrafPtr savePort;
  455.  
  456.     GetPort(&savePort);
  457.     SetPort(theWindow);
  458.  
  459.     /* Select on input
  460.      */
  461.     DlogOrigin(getDlgID, &SFGwhere);
  462.     SFPGetFile(SFGwhere, NULL, NULL, 1, myTypes, NULL, &theReply, getDlgID, (Ptr) DlogModalEvent);
  463.     ApplSpinCurs(TRUE);
  464.  
  465.     if (theReply.good)
  466.         DocOpenFile(theWindow, theReply.fName, theReply.vRefNum);
  467.  
  468.     SetPort(savePort);
  469. }
  470.  
  471.  
  472. /* Close the document, saving if needed and the user agrees
  473.  */
  474. Boolean
  475. DocClose (theWindow)
  476.     register WindowPtr theWindow;
  477. {
  478.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  479.     register Boolean result = TRUE;
  480.     register WORD prompt;
  481.     Str255 param1, param2;
  482.  
  483.     /* Prompt the user whether or not to save before closing
  484.      */
  485.     if (infoPtr->dirty) {
  486.         GetIndString(param1, RSRCBASE, strDocMod);
  487.         GetIndString(param2, RSRCBASE, strDocSave);
  488.         
  489.         prompt = ErrWarning(warnCancel, FALSE, infoPtr->fileName, param1, param2, NullStr);
  490.         
  491.         if (prompt == warnYes)
  492.             result = DocSave(theWindow);
  493.         else if (prompt == warnCancel)
  494.             result = FALSE;
  495.     }
  496.  
  497.     /* Back to the business of closing shop
  498.      */
  499.     if (result) {
  500.         GnosClose();
  501.         
  502.         infoPtr->dirty = FALSE;
  503.         infoPtr->named = FALSE;
  504.     }
  505.     
  506.     return result;
  507. }
  508.  
  509.  
  510. /* Save the document to disk; return FALSE is the user decides to cancel...
  511.  */
  512. Boolean 
  513. DocSave (theWindow)
  514.     register WindowPtr theWindow;
  515. {
  516.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  517.     register Boolean result;
  518.  
  519.     /* Give the user a chance to name or cancel an unnamed buffer
  520.      */
  521.     if (!infoPtr->named)
  522.         result = DocSaveAs(theWindow);
  523.     else 
  524.         result = DocSaveFile(theWindow, infoPtr->fileName, infoPtr->vRefNum);
  525.  
  526.     return result;
  527. }
  528.  
  529.  
  530. /* Save the document into a file; return FALSE if cancelled
  531.  */
  532. Boolean 
  533. DocSaveAs (theWindow)
  534.     register WindowPtr theWindow;
  535. {
  536.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  537.     register Boolean result = FALSE;
  538.     static Point SFPwhere = { 80, 72 };
  539.     SFReply theReply;
  540.     Str255 param1;
  541.  
  542.     /* Prompt for the new file name...  If cancelled, don't change anything
  543.      */
  544.     DlogOrigin(putDlgID, &SFPwhere);
  545.     GetIndString(param1, RSRCBASE, strSaveAs);
  546.     SFPPutFile(SFPwhere, param1, infoPtr->fileName, NULL, &theReply, putDlgID, (Ptr) DlogModalEvent);
  547.     ApplSpinCurs(TRUE);
  548.     
  549.     if (theReply.good && DocSaveFile(theWindow, theReply.fName, theReply.vRefNum))
  550.         result = TRUE;
  551.  
  552.     return result;
  553. }
  554.  
  555.  
  556. /* Reload a previous version of the file
  557.  */
  558. void
  559. DocRevert (theWindow)
  560.     register WindowPtr theWindow;
  561. {
  562.     register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
  563.     register WORD prompt;
  564.     Str255 param1, param2;
  565.  
  566.     /* Prompt for reverting
  567.      */
  568.     GetIndString(param1, RSRCBASE, strRevert);
  569.     GetIndString(param2, RSRCBASE, strQuestion);
  570.     prompt = ErrWarning(warnNo, FALSE, param1, infoPtr->fileName, param2, NullStr);
  571.  
  572.     /* Read in the document again if the user so wishes
  573.      */
  574.     if (prompt == warnYes) {
  575.         ApplSpinCurs(TRUE);
  576.         infoPtr->dirty = FALSE;
  577.  
  578.         if (DocClose(theWindow))
  579.             DocOpenFile(theWindow, infoPtr->fileName, infoPtr->vRefNum);
  580.         else
  581.             infoPtr->dirty = TRUE;
  582.     }
  583. }
  584.  
  585.  
  586. /* Execute file menu selection
  587.  */
  588. void
  589. DocMenu (theItem)
  590.     register WORD theItem;
  591. {
  592.     switch (theItem) {
  593.     case fmNew: 
  594.         DocNew(wPtrGnos);
  595.         break;
  596.  
  597.     case fmOpen:
  598.         DocOpen(wPtrGnos);
  599.         break;
  600.  
  601.     case fmClose:
  602.         DocClose(wPtrGnos);
  603.         break;
  604.     
  605.     case fmSave:
  606.         DocSave(wPtrGnos);
  607.         break;
  608.  
  609.     case fmSaveAs:
  610.         DocSaveAs(wPtrGnos);
  611.         break;
  612.  
  613.     case fmRevert:
  614.         DocRevert(wPtrGnos);
  615.         break;
  616.         
  617.     case fmSetUp:
  618.         PrintDocument(NULL);
  619.         UnloadSeg((Ptr) PrintDocument);
  620.         break;
  621.  
  622.     case fmPrint:
  623.         PrintDocument(wPtrGnos);
  624.         UnloadSeg((Ptr) PrintDocument);
  625.         break;
  626.  
  627.     case fmQuit:
  628.         ApplQuit();
  629.         break;
  630.  
  631.     default:
  632.         break;
  633.     }
  634. }
  635.