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.
TumblerSource/Tumbler_file.c
// file.c |
// |
// File Input/Output routines. |
// |
// |
// Author: Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team |
// Date: Thursday, January 26, 1992 |
// |
// Modification History: |
// |
// 11/27/94 nick there seems to be a problem reading metafiles into the app |
// 01/25/95 nick slotted in spin code (thanks kent), updated for viewhints. |
// If we have view hints, then we can export things like the |
// renderer type and lighting and camera in a drag or cut/copy |
// |
// |
// To Do: |
// factor for AppleEvents |
// |
// Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved |
#include "Tumbler_globals.h" |
#include "Tumbler_prototypes.h" |
#include "Tumbler_resources.h" |
#include "QD3DStorage.h" |
#include "QD3DGroup.h" |
#include "QD3DIO.h" |
#include "QD3DShader.h" |
#include "QD3DView.h" |
#include "Tumbler_file.h" |
#include "Tumbler_camera.h" |
#include "Tumbler_document.h" |
#include "Tumbler_PICTImport.h" |
#include "Tumbler_utility.h" |
#include <string.h> |
static OSErr WriteDocumentFile(DocumentPtr theDocument); |
//----------------------------------------------------------------------------- |
TQ3Status Tumbler_ReadScene( |
TQ3FileObject file, |
short isText, |
TQ3SharedObject *viewHints, |
TQ3Object *model) |
{ |
char filename[64]; |
// TQ3Object group; |
TQ3Object object; |
TQ3Boolean isEOF; |
*viewHints = NULL; |
if( *model ) { |
Q3Object_Dispose(*model); |
} |
*model = Q3DisplayGroup_New(); |
// group = NULL; |
object = NULL; |
SetCursor(*GetCursor(watchCursor)); |
if (Q3File_OpenRead(file, NULL) != kQ3Success) |
{ |
SetCursor(&qd.arrow); |
return kQ3Failure; |
} |
while ((isEOF = Q3File_IsEndOfFile(file)) == kQ3False) |
{ |
object = NULL; |
object = Q3File_ReadObject(file); |
if (object == NULL) |
{ |
/* |
Check and handle errors here - |
Some errors may mean more objects are left in the file. |
*/ |
break; |
} |
if (Q3Object_IsType(object, kQ3SharedTypeViewHints)) |
{ |
if (*viewHints == NULL) |
{ |
*viewHints = object; |
object = NULL; |
} |
} |
else if (Q3Object_IsDrawable(object)) |
{ |
if (*model) |
{ |
Q3Group_AddObject(*model, object); |
} |
// else |
// { |
// group = Q3DisplayGroup_New(); |
// |
// Q3Group_AddObject(group, *model); |
// Q3Group_AddObject(group, object); |
// Q3Object_Dispose(*model); |
// |
// *model = group; |
// } |
} |
if (object != NULL) |
Q3Object_Dispose(object); |
} |
Q3File_Close(file); |
if (isEOF == kQ3False) |
{ |
if (*model != NULL) |
{ Q3Object_Dispose(*model); *model = NULL; } |
if (*viewHints != NULL) |
{ Q3Object_Dispose(*viewHints); *viewHints = NULL; } |
SetCursor(&qd.arrow); |
return kQ3Failure; |
} |
SetCursor(&qd.arrow); |
return kQ3Success; |
} |
//----------------------------------------------------------------------------- |
// |
// Tumbler_WriteScene() |
// |
void Tumbler_WriteScene( |
TQ3FileObject file, |
short textMode, |
DocumentPtr theDocument) |
{ |
TQ3GroupPosition gPos; |
TQ3Object object; |
TQ3ViewStatus fileStatus; |
SetCursor(*GetCursor(watchCursor)); |
if (Q3File_OpenWrite(file, kQ3FileModeText) != kQ3Success) |
{ |
SetCursor(&qd.arrow); |
return; |
} |
Q3View_StartWriting(theDocument->theView, file); |
if (theDocument->viewHints != NULL) |
{ |
if (Q3Object_Submit(theDocument->viewHints, theDocument->theView) == kQ3Failure) |
{ |
Q3File_Cancel(file); |
SetCursor(&qd.arrow); |
return; |
} |
} |
do { |
if (theDocument->documentGroup != NULL) |
{ |
Q3Group_GetFirstPosition(theDocument->documentGroup, &gPos); |
while (gPos) |
{ |
TQ3Status status; |
Q3Group_GetPositionObject(theDocument->documentGroup, gPos, &object); |
status = Q3Object_Submit(object, theDocument->theView); |
Q3Object_Dispose(object); |
if (status != kQ3Failure) |
{ |
Q3Group_GetNextPosition(theDocument->documentGroup, &gPos); |
} |
} |
} |
} while ((fileStatus = Q3View_EndWriting(theDocument->theView)) == kQ3ViewStatusRetraverse); |
if( Q3File_Close(file) == kQ3Failure ) { |
SetCursor(&qd.arrow); |
return; |
} |
SetCursor(&qd.arrow); |
return ; |
} |
//----------------------------------------------------------------------------- |
// ReadDocumentFile |
short ReadDocumentFile(DocumentPtr theDocument, TQ3Boolean isText) |
{ |
TQ3StorageObject storage; |
TQ3FileObject fd; |
TQ3Object objects = nil; |
TQ3Object viewHints; |
storage = Q3MacintoshStorage_New( theDocument->fRefNum ); |
if (storage == nil) |
goto bail; |
fd = Q3File_New(); |
if (fd == nil) |
goto bail; |
Q3File_SetStorage(fd, storage); |
Q3Object_Dispose(storage); |
Tumbler_ReadScene( |
fd, |
isText, |
&viewHints, |
&theDocument->documentGroup) ; |
TumblerDocument_UpdateView( theDocument, viewHints ) ; |
AdjustLightsPositions(theDocument); |
if (viewHints) |
Q3Object_Dispose(viewHints); |
Q3Object_Dispose(fd); |
return(noErr); |
bail: |
Q3Object_Dispose(fd); |
return(fnOpnErr); |
} |
//- |
PicHandle OpenPICTFile( |
FSSpec *theFile) |
{ |
OSErr err; |
long curEOF; |
PicHandle my_pic; |
long count; |
Ptr buffer; |
short refNum; |
if (FSpOpenDF(theFile, fsRdWrPerm, &refNum)) |
return(0); |
/* get size of file */ |
err = GetEOF(refNum, &curEOF); |
if (err != 0) { |
return(0); |
} |
/* move the file mark to 512 */ |
err = SetFPos(refNum, fsFromStart, 512L); |
if (err != 0) { |
return(0); |
} |
/* size of data to read */ |
count = curEOF - 512; |
/* create the PicHandle */ |
my_pic = (PicHandle)NewHandle(count); |
HLock((Handle)my_pic); |
/* read the PICT info */ |
buffer = (Ptr)(*my_pic); |
err = FSRead(refNum, &count, buffer); |
if (err != 0) { |
return(0); |
} |
HUnlock((Handle)my_pic); |
FSClose(refNum); |
return (my_pic); |
} |
OSErr WriteDocumentFile(DocumentPtr theDocument) |
{ |
OSErr theResult; |
long length; |
char *bufPtr; |
SetCursor(*GetCursor(watchCursor)); |
if (! theDocument->fRefNum) |
return(fnOpnErr); |
if ((theResult = SetFPos(theDocument->fRefNum, fsFromStart, 0)) != noErr ) |
return(theResult); |
if( theDocument->documentGroup ) { |
TQ3StorageObject storage; |
TQ3FileObject fd; |
storage = Q3MacintoshStorage_New(theDocument->fRefNum); |
if (storage == nil) |
goto bail; |
fd = Q3File_New(); |
if (fd == nil) |
goto bail; |
Q3File_SetStorage(fd, storage); |
Q3Object_Dispose(storage); |
Tumbler_WriteScene(fd, |
kQ3FileModeText, |
theDocument) ; |
Q3Object_Dispose(fd); |
} |
return(noErr); |
bail: |
return(fnOpnErr); |
} |
void DoNewDocument(void) |
{ DocumentPtr theDocument; |
if ((theDocument = NewDocument(NULL, NULL)) != nil) { |
ShowWindow(theDocument->theWindow); |
} |
} |
OSErr DoOpenFile(FSSpec *theFile) |
{ OSErr result; |
short refNum; |
DocumentPtr theDocument; |
FInfo fndrInfo ; |
TQ3Boolean isText ; |
// we assume the FSSpec passed in was valid, get the file information |
// we need to know the file type, this routine may get called by an appleEvent |
// handler, so we can't assume a type, we need to get it from the fsspec. |
FSpGetFInfo( theFile, &fndrInfo ) ; |
// pull out the file type |
isText = (fndrInfo.fdType == 'TEXT') ; |
if ((result = FSpOpenDF(theFile, fsRdWrPerm, &refNum)) != noErr) |
return(result); |
if ((theDocument = NewDocument(NULL, NULL)) != nil) { |
theDocument->fRefNum = refNum; |
theDocument->theFileSpec = *theFile ; |
SetCursor(*GetCursor(watchCursor)); |
ReadDocumentFile( theDocument, isText ) ; |
SetWTitle(theDocument->theWindow, theFile->name); |
ShowWindow(theDocument->theWindow); |
AdjustCamera(theDocument, |
theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left, |
theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top); |
SetCursor(&qd.arrow); |
} else { |
SysBeep(1); |
FSClose(refNum); |
return(memFullErr); |
} |
return(noErr); |
} |
void DoImport3DMFDocument(DocumentPtr theDocument) |
{ |
short refNum; |
StandardFileReply theReply; |
SFTypeList theTypeList = { 'TEXT', '3DMF', 0 }; |
short numtypes = 2 ; |
if(theDocument == nil) |
return; |
StandardGetFile(0L, numtypes, theTypeList, &theReply); |
// read for podium files |
if (theReply.sfGood) { |
if(theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') { |
// did we try to open a metafile ??? |
OSErr result; |
short refNum; |
DocumentPtr theDocument; |
FInfo fndrInfo ; |
TQ3Boolean isText ; |
isText = (theReply.sfType == 'TEXT') ; |
if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr) |
return ; |
theDocument->fRefNum = refNum; |
ReadDocumentFile( theDocument, isText ) ; |
#ifdef PODIUM_APP |
AdjustCamera(theDocument, |
theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left, |
theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top); |
#else |
AdjustCamera(theDocument, |
theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left, |
theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top); |
#endif |
} |
} |
} |
//-------------------------------------------------------------------------------- |
void DoOpenDocument(DocumentPtr theDocument) |
{ short refNum; |
#ifndef PODIUM_APP |
SFTypeList theTypeList = { 'TEXT', '3DMF', 'PICT', 0 }; |
short numtypes = 3 ; |
#else |
SFTypeList theTypeList = { 'PICT', 0 }; |
short numtypes = 1 ; |
#endif |
StandardFileReply theReply; |
StandardGetFile(0L, numtypes, theTypeList, &theReply); |
#ifndef PODIUM_APP |
// read for Tumbler files |
if (theReply.sfGood) { |
if( theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') { |
DoOpenFile(&theReply.sfFile); |
} else if( theReply.sfType == 'PICT' && theDocument && theDocument->documentGroup) { |
PicHandle thePict; |
TQ3StoragePixmap textureImage; |
// get the picture from the file |
thePict = OpenPICTFile(&theReply.sfFile); |
// make a texture |
TextureFromPICT( thePict, &textureImage); |
AddTextureToDocument( theDocument, &textureImage); |
// and free the space occupied by the picture |
KillPicture(thePict) ; |
} |
} |
#else |
// read for podium files |
if (theReply.sfGood) { |
// podium's slide files are PICT files |
if( theReply.sfType == 'PICT' ) { |
short refNum; |
DocumentPtr theDocument; |
PicHandle theBackgroundPict ; |
OSErr theErr ; |
if((theErr = FSpOpenDF(&theReply.sfFile, fsRdPerm, &refNum)) != noErr ) |
return ; |
if ((theDocument = NewDocument(NULL, NULL)) != nil) { |
Rect bounds; |
PicHandle thePict; |
GWorldPtr savedGWorld ; |
GDHandle savedDevice ; |
GetGWorld(&savedGWorld,&savedDevice); |
theBackgroundPict = OpenPICTFile(&theReply.sfFile); |
bounds = (**theBackgroundPict).picFrame; |
theErr = UpdateGWorld(&theDocument->screenBuffer, 16, &bounds, nil, nil, 0L ) ; |
if( (theErr = UpdateGWorld(&theDocument->bgOffscreen, 16, &bounds, nil, nil, 0L )) != noErr ) { |
return ; |
} |
// draw the picture into the offscreen |
SetGWorld( theDocument->bgOffscreen , nil ) ; |
DrawPicture( theBackgroundPict, &bounds ) ; |
SetGWorld(savedGWorld,savedDevice); |
SizeWindow(theDocument->theWindow, bounds.right - bounds.left, bounds.bottom - bounds.top, false); |
{ |
Rect screenRect = (**GetMainDevice()).gdRect; |
Rect winRect = theDocument->theWindow->portRect ; |
CenterRectInRect(&screenRect, &winRect) ; |
MoveWindow(theDocument->theWindow,winRect.left,winRect.top,false); |
} |
SetWTitle(theDocument->theWindow, theReply.sfFile.name); |
ShowWindow(theDocument->theWindow) ; |
} else { |
SysBeep(1); |
FSClose(refNum); |
return; |
} |
} |
else if(theDocument != nil && (theReply.sfType == 'TEXT' || theReply.sfType == '3DMF')) { |
// did we try to open a metafile ??? |
OSErr result; |
short refNum; |
DocumentPtr theDocument; |
FInfo fndrInfo ; |
TQ3Boolean isText ; |
isText = (theReply.sfType == 'TEXT') ; |
if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr) |
return ; |
theDocument->fRefNum = refNum; |
ReadDocumentFile( theDocument, isText ) ; |
AdjustCamera(theDocument, |
theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left, |
theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top); |
} |
} |
#endif |
} |
Boolean DoSaveAsDocument(DocumentPtr theDocument) |
{ short theResult; |
Str255 thePrompt, theName; |
StandardFileReply theReply; |
if (! theDocument) |
return(false); |
GetIndString(thePrompt, FileStringsID, slSavePromptIndex); |
GetWTitle(theDocument->theWindow, theName); |
StandardPutFile( (ConstStr255Param) &thePrompt, (ConstStr255Param) &theName, &theReply); |
if (theReply.sfGood) { |
if (!theReply.sfReplacing) { |
if ((theResult = FSpCreate(&theReply.sfFile, FileCreator, FileType, theReply.sfScript)) != noErr) { |
SysBeep(1); |
return(false); |
} |
} |
if (theDocument->fRefNum) { |
theResult = FSClose(theDocument->fRefNum); |
} |
if ((theResult = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &theDocument->fRefNum)) != noErr) { |
SysBeep(1); |
return(false); |
} |
if ((theResult = WriteDocumentFile(theDocument)) != noErr) { |
SysBeep(1); |
return(false); |
} |
SetWTitle(theDocument->theWindow, theReply.sfFile.name); |
theDocument->dirty = false; |
} else { |
return(false); |
} |
return(true); |
} |
Boolean DidSaveDocument(DocumentPtr theDocument) |
{ |
if ( theDocument == nil ) |
return(false); |
if (theDocument->fRefNum) { |
if (WriteDocumentFile(theDocument)) { |
SysBeep(1); |
return(false); |
} else { |
theDocument->dirty = false; |
} |
return(true); |
} else { |
return(DoSaveAsDocument(theDocument)); |
} |
} |
void DoRevertDocument(DocumentPtr theDocument) |
{ Str255 theName; |
if (! theDocument) |
return; |
if (theDocument->fRefNum) { |
GetWTitle(theDocument->theWindow, theName); |
ParamText( (ConstStr255Param) &theName, (ConstStr255Param) "", (ConstStr255Param) "", (ConstStr255Param) ""); |
if (Alert(idRevertALRT, 0L) == 1) { |
FInfo fndrInfo ; |
// we assume the FSSpec in the document is valid, get the file information |
// we need to know the file type |
FSpGetFInfo( &theDocument->theFileSpec, &fndrInfo ) ; |
// pull out the file type |
ReadDocumentFile(theDocument, (fndrInfo.fdType == 'TEXT')) ; |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14