home *** CD-ROM | disk | FTP | other *** search
- /*
- 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);
- }
-
-
-