home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
luschsrc.sit
/
document.c
< prev
next >
Wrap
Text File
|
1990-05-23
|
13KB
|
635 lines
/********************************************************************************
* document.c
*
* File Management Package
*
* Written by Paco Xander Nathan
* ⌐1990, Motorola Inc. Public domain source code.
********************************************************************************/
#include "applic.h"
#include "window.h"
#include "dialog.h"
#include "context.h"
#include "text.h"
#include "list.h"
#include "error.h"
#include "string.h"
#include "ascii.h"
#include "document.h"
#include "print.h"
#include "gnosis.h"
/* Local Function Prototypes
*/
#ifdef PROTOTYPES
void DocReadLine (WORD refNum, LONG count, BYTE *data);
void DocWriteLine (WORD refNum, LONG count, BYTE *data);
void DocReadNum (WORD refNum, WORD *theNum);
void DocWriteNum (WORD refNum, WORD theNum);
void DocReadText (WORD refNum, Handle textHdl);
void DocWriteText (WORD refNum, Handle textHdl);
void DocReadGnos (WORD refNum, GnosPtr gnosPtr);
void DocWriteGnos (WORD refNum, GnosPtr gnosPtr);
void DocRecurGnos (WORD refNum, GnosPtr gnosPtr);
#endif
void
DocReadLine (refNum, count, data)
register WORD refNum;
LONG count;
register BYTE *data;
{
LONG bufLen = count + 1;
BYTE theBuf[100];
FSRead(refNum, &bufLen, theBuf);
BlockMove(theBuf, data, count);
}
void
DocWriteLine (refNum, count, data)
register WORD refNum;
LONG count;
register BYTE *data;
{
BYTE theEnd = asciiReturn;
FSWrite(refNum, &count, data);
count = 1L;
FSWrite(refNum, &count, &theEnd);
}
void
DocReadNum (refNum, theNum)
register WORD refNum;
register WORD *theNum;
{
BYTE lineBuf[100];
BYTE *theLine = lineBuf;
LONG count = 1L;
/* Get the length word
*/
while ((FSRead(refNum, &count, theLine) == noErr) && (*theLine++ != asciiReturn))
;
/* Parse the length word
*/
*--theLine = '\0';
sscanf(lineBuf, "%d", theNum);
}
void
DocWriteNum (refNum, theNum)
register WORD refNum;
register WORD theNum;
{
BYTE theEnd = asciiReturn;
BYTE lineBuf[100];
LONG theLen;
theLen = sprintf(lineBuf, "%d", theNum);
FSWrite(refNum, &theLen, lineBuf);
/* Write a separator
*/
theLen = 1L;
FSWrite(refNum, &theLen, &theEnd);
}
void
DocReadText (refNum, textHdl)
register WORD refNum;
register Handle textHdl;
{
WORD textLen;
LONG count;
BYTE theEnd;
/* Get the length word, allocate a handle
*/
DocReadNum(refNum, &textLen);
count = textLen;
SetHandleSize(textHdl, count);
/* Read the text
*/
HLock(textHdl);
FSRead(refNum, &count, *textHdl);
HUnlock(textHdl);
/* Read a separator
*/
count = 1L;
FSRead(refNum, &count, &theEnd);
}
void
DocWriteText (refNum, textHdl)
register WORD refNum;
register Handle textHdl;
{
BYTE theEnd = asciiReturn;
LONG count;
/* Write the length word
*/
count = GetHandleSize(textHdl);
DocWriteNum(refNum, (WORD) count);
/* Write the text
*/
HLock(textHdl);
FSWrite(refNum, &count, *textHdl);
HUnlock(textHdl);
/* Write a separator
*/
count = 1L;
FSWrite(refNum, &count, &theEnd);
}
void
DocReadGnos (refNum, gnosPtr)
register WORD refNum;
register GnosPtr gnosPtr;
{
WORD titleLen;
DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->color);
DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->pair);
DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->mark);
DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->anxiety);
DocReadLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->stress);
DocReadNum(refNum, &(gnosPtr->total[0]));
DocReadNum(refNum, &(gnosPtr->total[1]));
DocReadNum(refNum, &titleLen);
DocReadLine(refNum, titleLen, (BYTE *) (gnosPtr->title + 1));
gnosPtr->title[0] = titleLen;
DocReadText(refNum, gnosPtr->textHdl);
}
void
DocWriteGnos (refNum, gnosPtr)
register WORD refNum;
register GnosPtr gnosPtr;
{
WORD titleLen;
DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->color);
DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->pair);
DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->mark);
DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->anxiety);
DocWriteLine(refNum, MAXPAD * 2, (BYTE *) gnosPtr->stress);
DocWriteNum(refNum, gnosPtr->total[0]);
DocWriteNum(refNum, gnosPtr->total[1]);
titleLen = gnosPtr->title[0];
DocWriteNum(refNum, titleLen);
DocWriteLine(refNum, titleLen, (BYTE *) (gnosPtr->title + 1));
DocWriteText(refNum, gnosPtr->textHdl);
}
/* Recursively output the prognosis list in reverse to preserve order
* next time this document is read
*/
void
DocRecurGnos (refNum, gnosPtr)
register WORD refNum;
register GnosPtr gnosPtr;
{
if (gnosPtr) {
ApplSpinCurs(FALSE);
DocRecurGnos(refNum, gnosPtr->next);
DocWriteGnos(refNum, gnosPtr);
}
}
/* Read the named file
*/
Boolean
DocReadFile (fileName, vRefNum)
register StringPtr fileName;
register WORD vRefNum;
{
register Boolean result = TRUE;
register OSErr IOResult;
WORD gnosCount;
ioParam pb;
/* Set up the pb. Note that it's set up as read-only
*/
pb.ioCompletion = NULL;
pb.ioNamePtr = fileName;
pb.ioVRefNum = vRefNum;
pb.ioVersNum = 0;
pb.ioPermssn = fsRdPerm;
pb.ioMisc = NULL;
/* If we can't open it for some reason, signal an error and return
*/
ApplSpinCurs(FALSE);
if (!(result = !PBOpen(&pb, FALSE))) {
ErrFileMgr(pb.ioResult, fileName);
return FALSE;
}
/* Read file into handle and set the new text
*/
ApplSpinCurs(FALSE);
DocReadNum(pb.ioRefNum, &gnosCount);
for (; gnosCount--; ) {
ApplSpinCurs(FALSE);
DocReadGnos(pb.ioRefNum, GnosNew());
}
/* Close file before returning
*/
FSClose(pb.ioRefNum);
return result;
}
/* Write the named file
*/
Boolean
DocWriteFile (fileName, vRefNum)
register StringPtr fileName;
register WORD vRefNum;
{
register OSErr IOResult = noErr;
register Boolean result = TRUE;
WORD refNum;
LONG logEOF;
FInfo theFInfo;
/* Try the open the specified file
*/
if (IOResult = FSOpen(fileName, vRefNum, &refNum)) {
ErrFileMgr(IOResult, fileName);
result = FALSE;
}
/* Try to make the file empty, as a test
*/
ApplSpinCurs(FALSE);
logEOF = 0L;
if (result && (IOResult = SetEOF(refNum, logEOF))) {
/* Don't forget to close it! Otherwise it will remain
* open until you reboot the machine
*/
FSClose(refNum);
ErrFileMgr(IOResult, fileName);
result = FALSE;
}
/* Write out the list of data
*/
ApplSpinCurs(FALSE);
if (result) {
DocWriteNum(refNum, gnosList.count);
DocRecurGnos(refNum, gnosList.head);
}
/* Close the file and flush the volume, to make sure disk is correct
*/
if (result) {
FSClose(refNum);
FlushVol(NULL, vRefNum);
/* Update the creatrix so that the icon will be correct and the file
* will launch our application
*/
if (!GetFInfo(fileName, vRefNum, &theFInfo)) {
theFInfo.fdCreator = LUCH_TAG;
SetFInfo(fileName, vRefNum, &theFInfo);
}
}
ApplSpinCurs(FALSE);
return result;
}
/* Open the named file into the specified window
*/
Boolean
DocOpenFile (theWindow, fileName, vRefNum)
register WindowPtr theWindow;
register StringPtr fileName;
register WORD vRefNum;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register Boolean result;
GrafPtr savePort;
GetPort(&savePort);
SetPort(theWindow);
/* Open the file
*/
ApplSpinCurs(FALSE);
if (result = DocReadFile(fileName, vRefNum)) {
infoPtr->named = TRUE;
StrPCpy(infoPtr->fileName, fileName);
SetWTitle(theWindow, fileName);
infoPtr->vRefNum = vRefNum;
WindSwitch(theWindow, TRUE);
GnosRefresh();
GnosLearn();
}
SetPort(savePort);
return result;
}
/* Save the contents of the window into the designated file
*/
Boolean
DocSaveFile (theWindow, fileName, vRefNum)
register WindowPtr theWindow;
register StringPtr fileName;
register WORD vRefNum;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register Boolean result = TRUE;
register OSErr IOResult;
GrafPtr savePort;
GetPort(&savePort);
SetPort(theWindow);
/* Delete the former contents of the file, without changing
*/
FSDelete(fileName, vRefNum);
/* Now try to create it again
*/
if (IOResult = Create(fileName, vRefNum, LUCH_TAG, LUCH_TAG)) {
ErrFileMgr(IOResult, fileName);
result = FALSE;
}
/* Try to write, then update the name and volume ref
*/
if (result && (result = DocWriteFile(fileName, vRefNum))) {
StrPCpy(infoPtr->fileName, fileName);
SetWTitle(theWindow, fileName);
ApplSpinCurs(FALSE);
infoPtr->vRefNum = vRefNum;
infoPtr->dirty = FALSE;
infoPtr->named = TRUE;
}
SetPort(savePort);
return result;
}
/* Open a new document
*/
void
DocNew (theWindow)
register WindowPtr theWindow;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
GrafPtr savePort;
GetPort(&savePort);
SetPort(theWindow);
GetIndString(infoPtr->fileName, RSRCBASE, strUntitled);
SetWTitle(theWindow, infoPtr->fileName);
ApplSpinCurs(FALSE);
infoPtr->dirty = FALSE;
infoPtr->named = FALSE;
/* Switch to the window and redraw it
*/
WindSwitch(theWindow, TRUE);
SetPort(savePort);
}
/* Prompt for an existing document file
*/
void
DocOpen (theWindow)
register WindowPtr theWindow;
{
static SFTypeList myTypes = { LUCH_TAG };
static Point SFGwhere = { 80, 72 };
SFReply theReply;
GrafPtr savePort;
GetPort(&savePort);
SetPort(theWindow);
/* Select on input
*/
DlogOrigin(getDlgID, &SFGwhere);
SFPGetFile(SFGwhere, NULL, NULL, 1, myTypes, NULL, &theReply, getDlgID, (Ptr) DlogModalEvent);
ApplSpinCurs(TRUE);
if (theReply.good)
DocOpenFile(theWindow, theReply.fName, theReply.vRefNum);
SetPort(savePort);
}
/* Close the document, saving if needed and the user agrees
*/
Boolean
DocClose (theWindow)
register WindowPtr theWindow;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register Boolean result = TRUE;
register WORD prompt;
Str255 param1, param2;
/* Prompt the user whether or not to save before closing
*/
if (infoPtr->dirty) {
GetIndString(param1, RSRCBASE, strDocMod);
GetIndString(param2, RSRCBASE, strDocSave);
prompt = ErrWarning(warnCancel, FALSE, infoPtr->fileName, param1, param2, NullStr);
if (prompt == warnYes)
result = DocSave(theWindow);
else if (prompt == warnCancel)
result = FALSE;
}
/* Back to the business of closing shop
*/
if (result) {
GnosClose();
infoPtr->dirty = FALSE;
infoPtr->named = FALSE;
}
return result;
}
/* Save the document to disk; return FALSE is the user decides to cancel...
*/
Boolean
DocSave (theWindow)
register WindowPtr theWindow;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register Boolean result;
/* Give the user a chance to name or cancel an unnamed buffer
*/
if (!infoPtr->named)
result = DocSaveAs(theWindow);
else
result = DocSaveFile(theWindow, infoPtr->fileName, infoPtr->vRefNum);
return result;
}
/* Save the document into a file; return FALSE if cancelled
*/
Boolean
DocSaveAs (theWindow)
register WindowPtr theWindow;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register Boolean result = FALSE;
static Point SFPwhere = { 80, 72 };
SFReply theReply;
Str255 param1;
/* Prompt for the new file name... If cancelled, don't change anything
*/
DlogOrigin(putDlgID, &SFPwhere);
GetIndString(param1, RSRCBASE, strSaveAs);
SFPPutFile(SFPwhere, param1, infoPtr->fileName, NULL, &theReply, putDlgID, (Ptr) DlogModalEvent);
ApplSpinCurs(TRUE);
if (theReply.good && DocSaveFile(theWindow, theReply.fName, theReply.vRefNum))
result = TRUE;
return result;
}
/* Reload a previous version of the file
*/
void
DocRevert (theWindow)
register WindowPtr theWindow;
{
register InfoPtr infoPtr = (InfoPtr) GetWRefCon(theWindow);
register WORD prompt;
Str255 param1, param2;
/* Prompt for reverting
*/
GetIndString(param1, RSRCBASE, strRevert);
GetIndString(param2, RSRCBASE, strQuestion);
prompt = ErrWarning(warnNo, FALSE, param1, infoPtr->fileName, param2, NullStr);
/* Read in the document again if the user so wishes
*/
if (prompt == warnYes) {
ApplSpinCurs(TRUE);
infoPtr->dirty = FALSE;
if (DocClose(theWindow))
DocOpenFile(theWindow, infoPtr->fileName, infoPtr->vRefNum);
else
infoPtr->dirty = TRUE;
}
}
/* Execute file menu selection
*/
void
DocMenu (theItem)
register WORD theItem;
{
switch (theItem) {
case fmNew:
DocNew(wPtrGnos);
break;
case fmOpen:
DocOpen(wPtrGnos);
break;
case fmClose:
DocClose(wPtrGnos);
break;
case fmSave:
DocSave(wPtrGnos);
break;
case fmSaveAs:
DocSaveAs(wPtrGnos);
break;
case fmRevert:
DocRevert(wPtrGnos);
break;
case fmSetUp:
PrintDocument(NULL);
UnloadSeg((Ptr) PrintDocument);
break;
case fmPrint:
PrintDocument(wPtrGnos);
UnloadSeg((Ptr) PrintDocument);
break;
case fmQuit:
ApplQuit();
break;
default:
break;
}
}