Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/SVEditFile.c
/* |
File: SVEditFile.c |
Contains: |
Written by: Original version by Jon Lansdell and Nigel Humphreys. |
3.1 updates by Greg Sutton. |
Copyright: Copyright ©1995-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/19/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include <Errors.h> |
#include <Resources.h> |
#include <Desk.h> |
#include <DriverServices.h> |
#include <AppleEvents.h> |
#include <AERegistry.h> |
#include <StandardFile.h> |
#include "SVEditFile.h" |
#include "Offscreen.h" |
#include <TextUtils.h> |
/**----------------------------------------------------------------------- |
Name: FileError |
Purpose: Puts up an error alert. |
-----------------------------------------------------------------------**/ |
#pragma segment File |
pascal void FileError(Str255 s, Str255 f) |
{ |
short alertResult; |
SetCursor(&qd.arrow); |
ParamText(s, f, (unsigned char *)"", (unsigned char *)""); |
alertResult = Alert(ErrorAlert, nil); |
} |
/**----------------------------------------------------------------------- |
Name: DoClose |
Purpose: Closes a window. |
-----------------------------------------------------------------------**/ |
#pragma segment File |
pascal OSErr DoClose(WindowPtr aWindow,Boolean canInteract,DescType dialogAnswer) |
{ |
DPtr aDocument; |
short alertResult; |
OSErr myErr; |
myErr = noErr; |
if (gWCount>0) |
{ |
aDocument = DPtrFromWindowPtr(aWindow); |
if (aDocument->dirty) |
if (canInteract && (dialogAnswer==kAEAsk)) |
{ |
alertResult = DoFileDialog ( kSaveDontsaveDialog, aWindow ); |
switch ( alertResult ) |
{ |
case kStdOkItemIndex: |
if (aDocument->everSaved == false) |
{ |
myErr = GetFileNameToSaveAs(aDocument); |
if (myErr == noErr) |
myErr = DoSave(aDocument, aDocument->theFSSpec); |
} |
else |
myErr = SaveUsingTemp(aDocument); |
break; |
case kStdCancelItemIndex: |
return(userCanceledErr); |
break; |
case kDontSaveItemIndex: |
aDocument->dirty = false; |
break; |
} |
} |
else |
{ |
if (dialogAnswer==kAEYes) |
if (aDocument->everSaved == false) |
{ |
if (canInteract) |
{ |
myErr = GetFileNameToSaveAs(aDocument); |
if (myErr==noErr) |
myErr = DoSave(aDocument, aDocument->theFSSpec); |
} |
else |
return(errAENoUserInteraction); |
} |
else |
myErr = SaveUsingTemp(aDocument); |
else |
myErr = noErr; /* Don't save */ |
} |
if (myErr==noErr) |
{ |
CloseMyWindow(aWindow); |
} |
} |
else |
myErr = errAEIllegalIndex; |
return(myErr); |
} |
// |
// This is called to display the "save before closing" and "revert" dialogs. |
// |
short DoFileDialog ( short theDlogID, WindowRef theWindow ) |
{ |
short theItem; |
DialogRef theDialog; |
WindowRef dialogWindow; |
DPtr theDocument; |
Str255 theTitle, theReason; |
theDocument = DPtrFromWindowPtr ( theWindow ); |
theDialog = GetNewDialog ( theDlogID, nil, (WindowRef) -1 ); |
dialogWindow = GetDialogWindow ( theDialog ); |
SetPortWindowPort ( dialogWindow ); |
if ( theDocument->everSaved == false ) |
GetWTitle ( theWindow, theTitle ); // Pick it up as a script may have changed it |
else |
PStrCopy ( theTitle, theDocument->theFileName ); |
if ( gQuitting ) |
GetIndString ( theReason, kMiscStrings, kQuittingIndex ); |
else |
GetIndString ( theReason, kMiscStrings, kClosingindex ); |
SetCursor ( &qd.arrow ); |
ParamText ( theTitle, theReason, nil, nil ); |
ShowWindow ( dialogWindow ); |
SelectWindow ( dialogWindow ); |
SetDialogDefaultItem ( theDialog, kStdOkItemIndex ); |
SetDialogCancelItem ( theDialog, kStdCancelItemIndex ); |
// As long as the only enabled items are the dimissers, |
// there is no need to call ModalDialog within a loop. |
ModalDialog ( nil, &theItem ); |
DisposeDialog ( theDialog ); |
return theItem; |
} |
#pragma segment File |
// DoQuit |
// saveOpt - one of kAEAsk,kAEYes,kAENo |
// if kAEYes or kAEAsk then AEInteactWithUser should have been called |
// before DoQuit. Assumes that it can interact if it needs to. |
pascal void DoQuit ( DescType saveOpt ) |
{ |
WindowPtr aWindow; |
WindowPtr nextWindow; |
WindowPeek nextWPeek; |
short theKind; |
OSErr check; |
aWindow = FrontWindow(); |
gQuitting = true; |
while ( aWindow ) |
{ |
nextWPeek = ((WindowPeek)aWindow)->nextWindow; |
nextWindow = &nextWPeek->port; |
if (Ours(aWindow)) |
{ |
check = DoClose(aWindow, true, saveOpt); |
if ( check != noErr ) |
{ |
gQuitting = false; |
return; |
} |
} |
else |
{ |
theKind = ((WindowPeek)aWindow)->windowKind; |
if (theKind < 0) |
CloseDeskAcc(theKind); |
} |
aWindow = nextWindow; |
} |
return; |
} // DoQuit |
pascal OSErr GetFile(FSSpec *theFSSpec) |
{ |
SFTypeList myTypes; |
StandardFileReply reply; |
myTypes[0] = 'TEXT'; |
StandardGetFile(nil, 1, myTypes, &reply); |
if (reply.sfGood) |
{ |
*theFSSpec = reply.sfFile; |
return(noErr); |
} |
else |
return(userCanceledErr); |
} |
#pragma segment File |
pascal OSErr DoCreate(FSSpec theSpec) |
{ |
OSErr err; |
err = FSpCreate(&theSpec, SVEditAppSig, 'TEXT', smSystemScript); |
if (err != noErr) |
ShowError((unsigned char *)"\pDoCreate", err); |
return(err); |
} |
#pragma segment File |
pascal OSErr WriteFile(DPtr theDocument, short refNum, FSSpec theFSSpec) |
{ |
short resFile; |
long length; |
HHandle theHHandle; |
StScrpHandle theSHandle; |
OSErr err; |
StringHandle theAppName; |
short oldSelStart; |
short oldSelEnd; |
Handle thePHandle; |
Handle myText; |
tWindowOffscreen* theOffscreen = nil; |
/* WriteFile := 1; */ |
/*first write out the text to the data fork*/ |
length = (*(theDocument->theText))->teLength; |
myText = (*(theDocument->theText))->hText; |
HLock(myText); |
err = FSWrite(refNum, &length, *myText); |
if (err) |
return(err); |
HUnlock(myText); |
/*we are writing to a temporary file, so we need to create the resource file*/ |
/*before writing out the resources*/ |
/*now open the resource file*/ |
HCreateResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pHCreateResFile", err); |
return(err); |
} |
resFile = HOpenResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, fsWrPerm); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pHOpenResFile", err); |
return(err); |
} |
/*write out our 'TFSF' resource to file*/ |
// Draw everything into offscreen pixmap. |
theOffscreen = DrawOffscreen ( theDocument->theWindow ); |
if ( theOffscreen ) |
(*theDocument->theText)->inPort = (GrafPtr) theOffscreen->offscreenWorld; |
oldSelStart = (*(theDocument->theText))->selStart; |
oldSelEnd = (*(theDocument->theText))->selEnd; |
TESetSelect(0,32000, theDocument->theText); |
theSHandle = TEGetStyleScrapHandle(theDocument->theText); |
TESetSelect(oldSelStart,oldSelEnd, theDocument->theText); |
if ( theOffscreen ) |
{ |
// If it wasn't for the caret, we wouldn't need to draw this |
theOffscreen = DrawOnscreen ( theOffscreen ); |
(*theDocument->theText)->inPort = theDocument->theWindow; |
} |
AddResource((Handle)theSHandle, 'TFSF', 255, (unsigned char *)"\pStyle Info"); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pAddResource- TFSF", err); |
return(err); |
} |
// write out the printer info |
// First the QD info |
if (theDocument->thePrintSetup) |
{ |
thePHandle = (Handle)theDocument->thePrintSetup; |
err = HandToHand(&thePHandle); |
AddResource(thePHandle, 'TFSP', 255, (unsigned char *)"\pPrinter Info"); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pAddResource- TFSP", err); |
return(err); |
} |
} |
theHHandle = (HHandle)NewHandle(sizeof(HeaderRec)); |
HLock((Handle)theHHandle); |
GetFontName(theDocument->theFont, (unsigned char *)&(*theHHandle)->theFont); |
(*theHHandle)->theSize = theDocument->theSize; |
(*theHHandle)->theStyle = theDocument->theStyle; |
(*theHHandle)->lastID = theDocument->lastID; |
HUnlock((Handle)theHHandle); |
AddResource((Handle)theHHandle, 'TFSS', 255, (unsigned char *)"\pHeader Info"); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pAddResource- TFSS", err); |
return(err); |
} |
/*if we have any sections, write out the records and resources*/ |
/*Now put an AppName in for Finder in 7.0*/ |
theAppName = (StringHandle)NewHandle(6); |
PStrCopy(*theAppName,(unsigned char *)"\p7Edit"); |
AddResource((Handle)theAppName, 'STR ', - 16396, (unsigned char *)"\pFinder App Info"); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pAppName", err); |
return(err); |
} |
CloseResFile(resFile); |
return(noErr); |
} /* WriteFile */ |
#pragma segment File |
pascal OSErr ReadFile(DPtr theDocument, short refNum, Str255 fn) |
{ |
long theSize; |
short resFile; |
OSErr err; |
HHandle aHandle; |
Handle gHandle; |
Boolean gotQDPrintRec; |
gotQDPrintRec = false; |
err = GetEOF(refNum, &theSize); |
if (err) |
return(err); |
/*we're only using TE, so check that there is not more than 32K worth of text*/ |
if (theSize > 32000) |
return(1); |
gHandle = NewHandle(theSize); |
HLock(gHandle); |
err = FSRead(refNum, &theSize, *gHandle); |
if (err) |
{ |
HUnlock(gHandle); |
return(err); |
} |
resFile = HOpenResFile(theDocument->theFSSpec.vRefNum, |
theDocument->theFSSpec.parID, |
fn, |
fsWrPerm); |
if (resFile == -1) |
err = fnfErr; |
if (err==noErr) |
{ |
aHandle = nil; |
if (Count1Resources('TFSS')) |
aHandle = (HHandle)Get1Resource('TFSS', 255); |
/* |
New Format Info |
*/ |
aHandle = nil; |
if (Count1Resources('TFSF')) |
aHandle = (HHandle)Get1Resource('TFSF', 255); |
HLock(gHandle); |
TEStyleInsert( *gHandle, |
GetHandleSize(gHandle), |
(StScrpHandle)aHandle, |
theDocument->theText); |
HUnlock(gHandle); |
/* |
If there is a print record saved, ditch the old one |
created by new document and fill this one in |
*/ |
if (Count1Resources('TFSP')) |
{ |
if (theDocument->thePrintSetup) |
DisposeHandle((Handle)theDocument->thePrintSetup); |
theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255); |
err = HandToHand((Handle *)&theDocument->thePrintSetup); |
gotQDPrintRec = true; |
} |
CloseResFile(resFile); |
err = ResError(); |
if (err) |
{ |
ShowError((unsigned char *)"\pread file- CloseResFile", err); |
return(err); |
} |
} |
else |
TESetText(*gHandle, |
GetHandleSize(gHandle), |
theDocument->theText); |
if (gHandle) |
DisposeHandle(gHandle); |
if (err==fnfErr) |
err = noErr; |
return(err); |
} /* ReadFile */ |
/** ----------------------------------------------------------------------- |
Name: GetFileContents |
Purpose: Opens the document specified by theFSSpec and puts |
the contents into theDocument. |
-----------------------------------------------------------------------**/ |
#pragma segment File |
pascal OSErr GetFileContents(FSSpec theFSSpec, DPtr theDocument) |
{ |
OSErr err; |
short theRefNum; |
/*this can be called from two places- on an OpenDoc AppleEvent*/ |
/*and by the user just selecting Open from the File Menu*/ |
/*assume that the CFS is correct when the routine is called*/ |
err = FSpOpenDF(&theFSSpec, |
fsRdWrPerm, |
&theRefNum); |
if (err) |
{ |
ShowError((unsigned char *)"\pFSpOpenDF", err); |
return(err); |
} |
else |
{ |
err = ReadFile(theDocument, theRefNum, theFSSpec.name); |
if (err) |
{ |
ShowError((unsigned char *)"\pReadFile", err); |
return(err); |
} |
err=FSClose(theRefNum); |
if (err) |
{ |
ShowError((unsigned char *)"\pFSClose", err); |
return(err); |
} |
return(noErr); |
} |
} |
#pragma segment File |
pascal OSErr SaveUsingTemp(DPtr theDocument) |
{ |
Str255 tempName; |
OSErr err; |
FSSpec tempFSSpec; |
/*save the file to disk using a temporary file*/ |
/*this is the recommended way of doing things*/ |
/*first write out the file to disk using a temporary filename*/ |
/*if it is sucessfully written, exchange the temporary file with the last one saved*/ |
/*then delete the temporary file- so if anything goes wrong, the original version is still there*/ |
/*first generate the temporary filename*/ |
GetTempFileName(theDocument, tempName); |
/*create this file on disk*/ |
tempFSSpec = theDocument->theFSSpec; |
PStrCopy(tempFSSpec.name,tempName); |
err = DoCreate(tempFSSpec); |
/*now save the file as normal*/ |
if (err==noErr) |
err = DoSave(theDocument, tempFSSpec); |
if (err == noErr) |
err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec); |
/*we've exchanged the files, now delete the temporary one*/ |
if (err==noErr) |
err = FSpDelete(&tempFSSpec); |
return(err); |
} |
#pragma segment File |
/* |
Fills in the document record with the user chosen destination |
*/ |
pascal OSErr GetFileNameToSaveAs(DPtr theDocument) |
{ |
StandardFileReply reply; |
OSErr err; |
Str255 suggestName; |
GetWTitle(theDocument->theWindow, suggestName); |
StandardPutFile((unsigned char *)"\pSave Document As:", suggestName, &reply); |
if (reply.sfGood) |
{ |
err = FSpDelete(&reply.sfFile); |
if (!((err==noErr) || (err==fnfErr))) |
return(err); |
else |
err = noErr; |
theDocument->theFSSpec = reply.sfFile; |
PStrCopy(theDocument->theFileName, reply.sfFile.name); |
} |
else |
err = userCanceledErr; |
return(err); |
} /* GetFileNameToSaveAs */ |
#pragma segment File |
pascal OSErr DoSave(DPtr theDocument, FSSpec theFSSpec) |
{ |
short refNum; |
OSErr fileErr; |
fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum); |
if (fileErr == fnfErr) |
{ |
fileErr = DoCreate(theFSSpec); |
if (fileErr) |
return(fileErr); |
fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum); |
} |
if (fileErr == noErr) |
{ |
fileErr = WriteFile(theDocument, refNum, theFSSpec); |
if (fileErr==noErr) |
theDocument->dirty = false; |
fileErr = FSClose(refNum); |
} |
else |
FileError((unsigned char *)"\perror opening file ", theFSSpec.name); |
return(fileErr); |
} |
#pragma segment File |
pascal OSErr OpenOld(FSSpec aFSSpec) |
{ |
DPtr theDocument; |
OSErr fileErr; |
theDocument = NewDocument(true, (WindowPtr)-1L); |
SetWTitle(theDocument->theWindow, aFSSpec.name); |
SetPort(theDocument->theWindow); |
theDocument->theFSSpec = aFSSpec; |
PStrCopy(theDocument->theFileName,aFSSpec.name); |
theDocument->dirty = false; |
theDocument->everSaved = true; |
fileErr = GetFileContents(aFSSpec, theDocument); |
if (fileErr == noErr) |
{ |
DoResizeWindow(theDocument); |
ShowWindow(theDocument->theWindow); |
} |
else |
FileError((unsigned char *)"\pError Opening ", aFSSpec.name); |
return(fileErr); |
} /* OpenOld */ |
#pragma segment File |
pascal OSErr OpenUsingAlias(AliasHandle theAliasH) |
{ |
OSErr err; |
FSSpec aFSSpec; |
Boolean dummy; |
err = ResolveAlias(nil, theAliasH, &aFSSpec, &dummy); |
if (err == noErr) |
err = OpenOld(aFSSpec); |
return(err); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22