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.
CustomPutSuffix.c
/* |
File: CustomPutSuffix.c |
Contains: This demonstrates a CustomPutDialog with an Save button that checks |
to see if several files (with the name filename+suffix) already exist. |
a dialog hook procedure is responsible for presenting separate "Replace?" dialogs. When the Save button is hit and, if the user allows the save, |
the Save action is map to a Cancel action but the reply is marked as good. |
Written by: David Hayward |
Copyright: Copyright © 1993-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/1/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
5/12/95 updated project for Metrowerks |
5/3/93 first draft |
*/ |
#include <stddef.h> |
#include <QuickDraw.h> |
#include <Memory.h> |
#include <Files.h> |
#include <Errors.h> |
#include <Fonts.h> |
#include <Resources.h> |
#include <StandardFile.h> |
#include <Files.h> |
#include <Dialogs.h> |
#include <TextUtils.h> |
#include "InitMac.h" |
/**\ |
|**| ============================================================================== |
|**| DEFINES |
|**| ============================================================================== |
\**/ |
#define outputDlogID 128 |
#define outputQuit 1 |
#define outputAgain 2 |
#define replaceDlogID 6045 |
#define replaceCancel 1 |
#define replaceOK 2 |
#define SuffixID 128 |
/**\ |
|**| ============================================================================== |
|**| TYPEDEFS |
|**| ============================================================================== |
\**/ |
/*------------------------------------------------------------------------------*\ |
myData |
*------------------------------------------------------------------------------* |
the 'myData' structure is passed to CustomPutFile() so that |
MyDlgHook() can access the list of suffixes and return the results |
\*------------------------------------------------------------------------------*/ |
typedef struct myData |
{ |
StandardFileReply *replyPtr; /* we also need to pass in the SFR so that */ |
/* MyDlgHook() knows what user specified in */ |
/* the CustomPutFile dialog */ |
short num; /* the number of entries in the array */ |
struct |
{ /* struct for each suffix to check */ |
Str63 suffix; /* suffix string to append */ |
FSSpec spec; /* FSSpec for the file */ |
FInfo info; /* returned info and err just in case */ |
OSErr err; /* we need this information later */ |
} files[]; /* variable length array of the above */ |
} myData, *myDataPtr; |
/**\ |
|**| ============================================================================== |
|**| FUNCTION PROTOTYPES |
|**| ============================================================================== |
\**/ |
void AppendStrToStr ( StringPtr dst, StringPtr src, unsigned char maxDstLen ); |
void AppendStrToHdl ( Handle dst, StringPtr src ); |
pascal short MyDlgHook ( short item, DialogPtr theDialog, void *data ); |
short myReplaceAlert ( myDataPtr dataPtr ); |
short outputDlog ( myDataPtr dataPtr ); |
void initializeData ( myDataPtr *dataPtr, StandardFileReply *replyPtr ); |
void main ( void ); |
/*------------------------------------------------------------------------------*\ |
AppendStrToStr() |
*------------------------------------------------------------------------------* |
utility function to append one string to another |
this function should be improved to handle errors |
\*------------------------------------------------------------------------------*/ |
void AppendStrToStr ( StringPtr dst, StringPtr src, unsigned char maxDstLen ) |
{ |
short offset = dst[0]+1; |
short size = src[0]; |
if ( dst[0] + src[0] > maxDstLen) // make sure were not too big |
size = maxDstLen - dst[0]; // you should return a warning here |
BlockMove( src+1, dst+offset, size); |
dst[0] += size; |
} |
/*------------------------------------------------------------------------------*\ |
AppendStrToHdl() |
*------------------------------------------------------------------------------* |
utility function to append a string to a handle |
this function should be improved to handle errors |
\*------------------------------------------------------------------------------*/ |
void AppendStrToHdl ( Handle dst, StringPtr src ) |
{ |
short size = src[0]; |
PtrAndHand( src+1, dst, size); |
} |
/*------------------------------------------------------------------------------*\ |
MyDlgHook() |
*------------------------------------------------------------------------------* |
the dialog hook procedure responsible for presenting my own "Replace?" |
dialogs when the Save button is hit and, if the user allows the save, |
then map the Save action to a Cancel action but mark the reply as good. |
\*------------------------------------------------------------------------------*/ |
pascal short MyDlgHook ( short item, DialogPtr theDialog, void *data ) |
{ |
long refCon; |
short r; |
refCon = GetWRefCon((WindowPtr)theDialog); /* get the refCon of the current dialog */ |
if (refCon == sfMainDialogRefCon) /* if its the "Save AsÉ" dialog */ |
{ |
if (item == sfItemOpenButton) /* if user hit Save button */ |
{ |
r = myReplaceAlert((myDataPtr)data); /* present my "Replce? dialogs */ |
if ( r == replaceCancel ) /* if user hit a Cancel button */ |
item = sfHookNullEvent; /* then do nothing */ |
else /* if user hit replace button */ |
{ /* then user wants to save so...*/ |
item = sfItemCancelButton; /* change to Cancel action but */ |
((myDataPtr)data)->replyPtr->sfGood = 1;/* mark reply as good */ |
} |
} |
} |
return item; |
} |
/*------------------------------------------------------------------------------*\ |
myReplaceAlert() |
*------------------------------------------------------------------------------* |
this routine, called from MyDlgHook(), presents a "Replce? dialog |
for any filename+suffix that already exist. If one of these |
dialogs is canceles then this procedure returns 'cancel' |
\*------------------------------------------------------------------------------*/ |
short myReplaceAlert ( myDataPtr dataPtr ) |
{ |
short i, item; |
OSErr err; |
FSSpec spec; |
FInfo info; |
for (i=0; i<dataPtr->num; i++) /* loop thru each suffix in dataPtr ... */ |
{ |
spec = dataPtr->replyPtr->sfFile; /* spec starts out as the FSSpec (vRefNum, */ |
/* parID & name) the user specified in the */ |
/* CustomPutFile dialog */ |
AppendStrToStr( spec.name, |
dataPtr->files[i].suffix, 63); /* append suffix to filename */ |
err = FSpGetFInfo(&spec, &info); /* try to get info for this spec */ |
dataPtr->files[i].spec = spec; /* save the spec, info & err for this */ |
dataPtr->files[i].info = info; /* file in dataPtr just in case we need */ |
dataPtr->files[i].err = err; /* this information later */ |
if (err == 0) /* filename+suffix already exists so.. */ |
{ |
ParamText( spec.name, nil, nil, nil); /* setup param text for "Replace?" alert*/ |
item = Alert(replaceDlogID,nil); /* put up alert */ |
if (item == replaceCancel) /* if user hit cancel button */ |
return replaceCancel; /* then stop and return 'cancel' */ |
} |
else if (err == fnfErr) /* if filename+suffix doesn't exist */ |
{ |
/* all you need to do in here is make sure that filename+suffix */ |
/* isn't a directory and put up an an alert if it is */ |
} |
else /* if some other err was returned ... */ |
{ |
/* here you need to handle other errors such as 'badNamErr' */ |
} |
} |
return replaceOK; |
} |
/*------------------------------------------------------------------------------*\ |
outputDlog() |
*------------------------------------------------------------------------------* |
output vital stats of the StandardFileReply to an dialog box |
\*------------------------------------------------------------------------------*/ |
short outputDlog ( myDataPtr dataPtr ) |
{ |
DialogPtr dlg; |
Rect iRect; |
Handle iHndl; |
short iType; |
short item; |
short i; |
dlg = GetNewDialog(outputDlogID, nil, (WindowPtr)-1); |
GetDialogItem( dlg, 3, &iType, &iHndl, &iRect ); /* get handle to static text field */ |
if (dataPtr->replyPtr->sfGood == 0) /* if reply is not good */ |
AppendStrToHdl (iHndl, "\pUser canceled."); |
else |
{ |
for (i=0; i<dataPtr->num; i++) /* loop thru each suffix in dataPtr ... */ |
{ |
AppendStrToHdl( iHndl, dataPtr->files[i].spec.name); /* append filename */ |
if ( dataPtr->files[i].err == 0) /* if filename+suffix already exists */ |
AppendStrToHdl( iHndl, "\p (exists)"); /* append (exists) */ |
else if ( dataPtr->files[i].err != fnfErr) |
AppendStrToHdl( iHndl, "\p (error)"); /* append (error) */ |
AppendStrToHdl( iHndl, "\p\r"); /* append CR */ |
} |
} |
ShowWindow( dlg ); |
do |
{ |
ModalDialog(0,&item); |
} while ( (item != outputAgain) && (item != outputQuit)); |
DisposeDialog(dlg); |
return item; |
} |
/*------------------------------------------------------------------------------*\ |
initializeData() |
*------------------------------------------------------------------------------* |
initialize data stucture to be passed to CustomPutFile |
this means alocating a pointer of the right size and filling |
in the suffix strings from the apps resource fork |
\*------------------------------------------------------------------------------*/ |
void initializeData ( myDataPtr *dataPtr, StandardFileReply *replyPtr ) |
{ |
short i=0, num=0; |
Str255 temp; |
do /* figure out how many suffixes */ |
{ /* are in the apps resource fork */ |
GetIndString( temp, SuffixID, num+1); |
num++; |
} while (temp[0] !=0); /* if temp[0]==0 then no more */ |
num--; /* counted 1 too many so decrement */ |
/* allocate myDataPtr stucture */ |
*dataPtr = (myDataPtr) NewPtrClear ( offsetof(myData,files[num]) ); |
(**dataPtr).replyPtr = replyPtr; /* fill in StandardFileReply ptr */ |
(**dataPtr).num = num; /* fill in num of suffixes */ |
for (i=0; i<num; i++) /* fill in suffix strings */ |
GetIndString( (**dataPtr).files[i].suffix, SuffixID, i+1); |
} |
/*------------------------------------------------------------------------------*\ |
main() |
*------------------------------------------------------------------------------* |
initialize mamagers and the keep doing |
CustomPutFile until the user has had enough |
the structure 'dataPtr' is passed to CustomPutFile() so that |
MyDlgHook() can access the list of suffixes and return the results |
\*------------------------------------------------------------------------------*/ |
void main ( void ) |
{ |
myDataPtr dataPtr; |
StandardFileReply reply; |
Point where = {-1,-1}; /* center dialog on main screen */ |
InitToolBox(2); |
initializeData (&dataPtr, &reply); |
do |
{ |
CustomPutFile( "\pSave files as:", /* the prompt string */ |
"\pUntitled", /* the default filename */ |
&reply, /* the StandardFileReply structure */ |
0, /* the default dialog */ |
where, /* position of dialog on screen */ |
NewDlgHookYDProc(MyDlgHook),/* the Dialog Hook procedure */ |
nil, /* no modal dialog filterProc */ |
nil, /* no activeListPtr */ |
nil, /* no activateProc */ |
dataPtr /* pass in myDataPtr struct so that */ |
); /* dlgHook() can access its contents */ |
} |
while (outputDlog(dataPtr)==outputAgain); /* repeat until user has had enough */ |
DisposePtr( (Ptr)dataPtr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-13