home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************\
-
- customized standard file module
-
- ⌐ March 1991 Gabriele Speranza
- modified 31 dec 1991, feb 92, apr 92
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
- #include "system7.h"
- #include "PB_sync.h"
- #include "antiglue.h"
-
- #include <string.h>
- #include "suntar.h"
- #include "windows.h"
-
- #define SETDITL
- #define CLOSE_SF_WD
- #define DA_CANCEL /* always force Cancel even when an Open would have the same effect */
-
- int curr_vrefnum;
- extern unsigned char PNS[];
- extern Boolean gHasCustomPutFile;
- char *p2cstr();
- SFReply reply;
- Point where[7];
- static short n_open_WD=0;
- #define max_open_WD 20
- static int open_WD[max_open_WD];
- unsigned char*nomeFormato;
- Boolean SB3_compatibility=false;
-
- #ifndef NULL
- #define NULL 0L
- #endif
- #define sfHookNullEvent 100
-
- void set_DITL_title(short,unsigned char *);
-
-
- /************* routine per selezionare un file o directory ******************/
-
- #define writeButton 11
- #define cancelButton 3
- #define openButton 1
-
- static long current_dir_ID;
- static short current_val_OK;
-
- static unsigned char string_1[]="\pSalva qui",
- string_2[]="\pAnnulla",
- string_3[]="\pEspelli",
- string_4[]="\pUnitê Disco",
- string_5[]="\pgvu1h5%*├«@╣î┤╫┘╗",
- /*string_5[]="\p\10\0\37";*/ /* an "impossible" file name: no more useful since
- now I simulate a Cancel. Well, not exactly: AppleShare may see the name even
- when Cancel is simulated, hence there must be a name and it must not contain
- "absurd" characters, otherwise you get a System Error */
- string_6[]="\pApri",
- string_7[]="\pOpen";
-
- #define ESC 27
-
- pascal Boolean SF_filter(DialogPtr,EventRecord*,short *);
- static pascal Boolean SF_filter(theDialog, theEvent, itemHit)
- DialogPtr theDialog;
- EventRecord* theEvent;
- short * itemHit;
- {
-
- if(theEvent->what==nullEvent){
- /* under System 7, the update events for windows below the System 6-like
- standard file dialogs are not received if I don't explicitly ask for them.
- I don't know whether it's a bug or an attempt to solve the problem described
- in TN304, which for some reason believes that suntar belongs to the category
- of programs which must be cheated.
- System 7 is wonderful, but all its tricks are a damnation for programmers !
- And they are not documented... and there is no way to tell to System 7 that
- I know that I must behave well and I must not be cheated...
- */
- if(!EventAvail (updateMask,theEvent) )
- return false;
- }
- if(theEvent->what==updateEvt||theEvent->what==activateEvt){
- /*SetPort(theEvent->message);*/
- UpdateFilter(theEvent);
- }
- else if(theEvent->what==keyDown){
- short kind;
- Handle h;
- Rect r;
- if((unsigned char)theEvent->message==CR || (unsigned char)theEvent->message==enter_key){
- GetDItem(theDialog,1,&kind,&h,&r);
- SelectButton(h);
- *itemHit=1;
- return true;
- }
- else if((unsigned char)theEvent->message==ESC ||
- (unsigned char)theEvent->message=='.'&&(theEvent->modifiers&cmdKey) ){
- GetDItem(theDialog,3,&kind,&h,&r); /* the Cancel button is item 3 in a
- get dialog, it's 2 in a put (and 3 is the prompt string, not
- a button) */
- if(kind==ctrlItem+btnCtrl)
- *itemHit= 3;
- else
- GetDItem(theDialog,(*itemHit= 2),&kind,&h,&r);
- SelectButton(h);
- return true;
- }
- }
- return false;
- }
-
-
- void my_SF_Put(prompt,fname)
- unsigned char *prompt,*fname;
- {
- SFPPutFile(where[2],prompt,fname,NULL,&reply, -3999, SF_filter);
- #ifdef CLOSE_SF_WD
- if(reply.good) register_WD(reply.vRefNum);
- #endif
- }
-
- void my_SF_Get(numTypes,typeList)
- short numTypes;
- SFTypeList typeList;
- {
- SFPGetFile(where[3],PNS,NULL,numTypes,typeList,NULL,&reply, -4000, SF_filter);
- #ifdef CLOSE_SF_WD
- if(reply.good) register_WD(reply.vRefNum);
- #endif
- }
-
-
- pascal short file_or_folder_hook(short,DialogPtr);
- static pascal short file_or_folder_hook(item, theDialog)
- short item;
- DialogPtr theDialog;
- {
- short kind;
- Handle h;
- Rect r;
- extern Boolean in_Italia;
-
- if(item==-1) {
- /* initialization: translate button titles to Italian */
- if(in_Italia){
- #ifndef SETDITL
- GetDItem(theDialog,1,&kind,&h,&r);
- SetCTitle(h,string_6);
- #endif
- GetDItem(theDialog,3,&kind,&h,&r);
- SetCTitle(h,string_2);
- GetDItem(theDialog,5,&kind,&h,&r);
- SetCTitle(h,string_3);
- GetDItem(theDialog,6,&kind,&h,&r);
- SetCTitle(h,string_4);
- GetDItem(theDialog,11,&kind,&h,&r);
- SetCTitle(h,"\pScrivi");
- GetDItem(theDialog,12,&kind,&h,&r);
- SetIText(h,"\pScegli il file o cartella da archiviare");
- }
- GetDItem(theDialog,13,&kind,&h,&r);
- SetIText(h,nomeFormato);
- current_val_OK = false;
- }
- else if(item==writeButton){ /* file o directory selezionata*/
- if (reply.fType != 0 || reply.fName[0]!=0) {
- /* remember which folder was currently selected, if it was a folder */
- current_dir_ID = reply.fType; /* if the current selection is a folder,
- this field contains its dir ID */
- current_val_OK = reply.fName[0]==0 ? 1 : -1; /*cioÅ, solo se Å una directory, non un file
- -- the name is NOT stored here if it was a folder (se IM vol IV) */
- return cancelButton; /*
- declare that the cancel button was pressed, remembering that
- it's not so; for files, I could return openButton, but there is
- a problem: if the selected file is an alias under System 7,
- the alias is NOT resolved and a beep is done: I wish that
- unresolved alias, but I don't wish that beep ! */
- }
- else
- return sfHookNullEvent; /* per dirgli di ignorare la cosa... non dovrebbe capitare comunque
- grazie al filtro di eventi che disabilita il bottone
- -- Really, the event filter disables the button when nothing
- is selected, so I should not receive "button pressed" items,
- but if I do, I ignore it */
- }
- return item;
- }
-
- pascal Boolean file_or_folder_filter(DialogPtr,EventRecord*,short *);
- static pascal Boolean file_or_folder_filter(theDialog, theEvent, itemHit)
- DialogPtr theDialog;
- EventRecord* theEvent;
- short * itemHit;
- {
- short kind;
- Rect r;
- ControlHandle openH,writeH;
-
- GetDItem(theDialog,openButton,&kind,&openH,&r);
- GetDItem(theDialog,writeButton,&kind,&writeH,&r);
- HiliteControl(writeH, (**openH).contrlHilite); /* the write button is enabled/disabled
- to follow the current state of the Open Button */
- return SF_filter(theDialog,theEvent,itemHit);
- }
-
- int get_file_or_folder(s,n_types,myTypes)
- /* presents a modified file dialog which allows to choose either a file or
- a folder, with the extra "Write" button
- returns:
- -1 cancel
- 0 folder
- 1 file
- */
- Str255 s;
- short n_types;
- SFTypeList *myTypes;
- {int i;
-
- #ifdef SETDITL
- set_DITL_title(200,in_Italia?string_6:string_7);
- #endif
-
- SFPGetFile(where[1],PNS,NULL,n_types,myTypes,file_or_folder_hook,&reply,
- 200,file_or_folder_filter);
-
- reply.fName[1+reply.fName[0]]=0;
- if (current_val_OK>0){
- /* write folder.
- the vRefNum in the reply is not correct, but the low memory variable SFSaveDisk
- holds the negative of the right value */
- #ifdef V_122
- if(i=PathNameFromDirID(current_dir_ID,(curr_vrefnum= -SFSaveDisk),s)) {
- /* TN 238 sconsiglia di creare dei full path name, perchÄ in A/UX i
- full path name vogliono la '/' anche se si fanno chiamate alle routine
- HFS del toolbox... */
- SysBeep(5);
- printf("Pathname error\n");
- raise_error();
- }
- #else
- /* get the name of the folder */
- {
- CInfoPBRec block;
- Str255 directoryName;
- OSErr err;
-
- block.dirInfo.ioNamePtr = &s[1];
- block.dirInfo.ioDrParID = current_dir_ID;
-
- block.dirInfo.ioVRefNum = curr_vrefnum= -SFSaveDisk;
- block.dirInfo.ioFDirIndex = -1;
- block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
-
- err = PBGetCatInfoSync(&block);
- if(err!=noErr) error_message_1("Folder error %d\n",err);
- if(current_dir_ID==2){ /* root directory, it's already a refnum... */
- mcopy(s,&s[1],s[1]+1); /* must not add a semicolon */
- }
- else{
- WDPBRec param;
- s[0] = s[1]+1;
- s[1]=':';
-
- /* open a WD on the parent directory */
-
- param.ioVRefNum= curr_vrefnum;
- param.ioNamePtr=NULL;
- param.ioWDProcID=signature;
- param.ioWDDirID= block.dirInfo.ioDrParID;
- if(err=PBOpenWDSync(¶m)) error_message_1("Working directory error %d\n",err);
- /* printf("selected=%d %ld %p\n",curr_vrefnum,block.dirInfo.ioDrParID,s); */
- curr_vrefnum=param.ioVRefNum;
- register_WD(param.ioVRefNum);
- }
- /* Append a Macintosh style colon (':') */
- pStrcat(s,"\p:");
- SetVol(NULL,curr_vrefnum);
- }
- #endif
- return 0;
- }
- if(current_val_OK<0){ /* write file */
- WDPBRec param;
- param.ioVRefNum= -SFSaveDisk;
- param.ioNamePtr=NULL;
- param.ioWDProcID=signature;
- param.ioWDDirID=CurDirStore;
- if(PBOpenWDSync(¶m)) error_message("Working directory error\n");
- reply.vRefNum=param.ioVRefNum; /* ad uso delle varie open...*/
- register_WD(param.ioVRefNum);
- }
- else if(!reply.good)
- return -1; /* cancel */
- /* if I am here, it was a open/write file */
- SetVol(NULL,reply.vRefNum); /* the old version of the program usually passed
- 0 as vrefnum relying on a SetVol, the new one prefers to pass explicitly
- curr_vrefnum, but if we have forgotten to modify one call, doing
- also the SetVol avoid troubles: one day all these SetVol will be
- deleted, but then an accurate beta testing should follow... */
- #ifdef CLOSE_SF_WD
- register_WD(reply.vRefNum);
- #endif
- curr_vrefnum=reply.vRefNum;
- pStrcpy(s,reply.fName);
- return 1;
- }
-
- /********** routines per la selezione di una directory di destinazione *********/
-
- pascal short select_dir_hook (short,DialogPtr);
- static pascal short select_dir_hook (item, theDialog)
- short item;
- DialogPtr theDialog;
- {
-
- if(item==-1 && in_Italia){
- short kind;
- Handle h;
- Rect r;
- #ifndef SETDITL
- GetDItem(theDialog,1,&kind,&h,&r);
- SetCTitle(h,string_1);
- #endif
- GetDItem(theDialog,2,&kind,&h,&r);
- SetCTitle(h,string_2);
- GetDItem(theDialog,5,&kind,&h,&r);
- SetCTitle(h,string_3);
- GetDItem(theDialog,6,&kind,&h,&r);
- SetCTitle(h,string_4);
- }
- else if(item==1){ /* Save here */
- current_val_OK=true;
- #ifdef DA_CANCEL
- return 2; /* Cancel: hence, no risk to get a dialog "file existing, OK to replace ?" */
- #endif
- }
- return item;
- }
-
- pascal Boolean select_dir_filter(DialogPtr,EventRecord*,short *);
- static pascal Boolean select_dir_filter(theDialog, theEvent, itemHit)
- DialogPtr theDialog;
- EventRecord* theEvent;
- short * itemHit;
- {
-
- if(theEvent->what==keyDown||theEvent->what==autoKey){
- theEvent->what=nullEvent;
- } /* se no si puÿ cancellare il nome, e il bottone per
- salvare viene disabilitato...
- -- the file name can't be modified ! It will be ignored,
- but if you delete it, the save button will be disabled,
- and save here IS the save button */
- /* no, niente da fare, lo standard file non me li passa affatto
- -- useless, such events are not passed to my filter
- else if(theEvent->what==diskEvt){
- unexpected_disk_insertion(theEvent->message);
- theEvent->what=nullEvent;
- }
- */
-
- return SF_filter(theDialog, theEvent, itemHit);
- }
-
- static Boolean need_update,is_outline;
-
- pascal Boolean sys7_select_dir_filter(DialogPtr,EventRecord*,short *,Ptr);
- static pascal Boolean sys7_select_dir_filter(theDialog, theEvent, itemHit, myDataPtr)
- DialogPtr theDialog;
- EventRecord* theEvent;
- short * itemHit;
- Ptr myDataPtr;
- {
- if(theEvent->what==updateEvt && (DialogPtr)theEvent->message==theDialog)
- need_update=true;
- return SF_filter(theDialog, theEvent, itemHit);
- }
-
-
- pascal short sys7_select_dir_hook(short,DialogPtr,Ptr);
- static pascal short sys7_select_dir_hook(item,theDialog,myDataPtr)
- short item;
- DialogPtr theDialog;
- Ptr myDataPtr;
- {
- /* it is correct to draw an outline to the "save here" button, however
- ther are two problems:
- 1) there is not a good place to do that: in the event filter, I could do that as an
- answer to the update event, but it should be between BeginUpdate and EndUpdate,
- or in the worst case after EndUpdate, while I'm called before. In my_modal
- I handle the whole update by myself, but here doing that could cause
- incompatibility problems (if something is redrawn directly and not through
- the redraw routine of a dialog item... for example, Boomerang's file info
- disappear in case of an update). Hence I do that periodically, that's
- NOT a good solution but I haven't found a better one
- (probably the "Better" way is to install an user item for the outline...
- maybe I'll try that one day)
- 2) The return and enter key mean "open" or "click on the default button"
- according to what is currently selected (a folder/volume, or a file/nothing):
- hence, I should outline the Save here button only when return means Save,
- but the in StandardFileReply record only parID and vRefNum are updated, (the name,
- sfIsFolder and sfIsVolume are updated only by Custom G E T file). Furthermore,
- if the current volume is locked the Save button is dimmed, and must not be
- outlined: this time, I should update things when the state change happens, that is
- AFTER the handling of clicks on items which change the situation, but my
- hook routine is called BEFORE the standard handling is performed: this time, a
- periodic action looks like the only way to do things
- */
-
- short kind;
- ControlHandle h;
- Rect r;
- int i;
- ControlHandle saveH;
- /*
- StandardFileReply *sfrep=myDataPtr;
- printf("%d %d %ld %d %p\n",sfrep->sfIsFolder,sfrep->sfIsVolume,sfrep->sfFile.parID,
- sfrep->sfFile.vRefNum,sfrep->sfFile.name);
- */
-
- if(((WindowPeek)theDialog)->refCon!='stdf') return item;
-
- GetDItem(theDialog,1,&kind,&h,&r);
- GetDItem(theDialog,13,&kind,&saveH,&r);
- if((**h).contrlHilite!=(**saveH).contrlHilite)
- HiliteControl(saveH, (**h).contrlHilite); /* the save here button is
- enabled/disabled to follow the current state of the save Button */
- if(!(i=(**h).contrlHilite)){
- char buffer[20];
- GetCTitle(h,buffer);
- i=strcmp("Save",p2cstr(buffer)); /* the "Open" string is chosen from the
- system, depending on the nation, but the
- Save string is from my resource... */
- }
- if(i){ /* erase the outline */
- /* probably it's possible to avoid all that by exploiting the calls described in
- Technical Note 304, but beta testing of 1.2 has already started, it's too late to
- try new routines */
- if(is_outline){
- Rect r1;
- SetPort(theDialog);
- r1.left=r.left-4;
- r1.right=r.left;
- r1.top=r.top-4;
- r1.bottom=r.bottom+4;
- EraseRect(&r1);
- r1.left=r.right;
- r1.right=r.right+4;
- EraseRect(&r1);
- r1.left=r.left;
- r1.right=r.right;
- r1.top=r.top-4;
- r1.bottom=r.top;
- EraseRect(&r1);
- r1.top=r.bottom;
- r1.bottom=r.bottom+4;
- EraseRect(&r1);
- }
- is_outline=false;
- }
- else{
- if(!is_outline||need_update){
- OutlineControl(saveH);
- need_update=false;
- }
- is_outline=true;
- }
-
- if(item==-1&&in_Italia){
- GetDItem(theDialog,13,&kind,&h,&r);
- SetCTitle(h,string_1);
- GetDItem(theDialog,2,&kind,&h,&r);
- SetCTitle(h,string_2);
- GetDItem(theDialog,5,&kind,&h,&r);
- SetCTitle(h,string_3);
- GetDItem(theDialog,6,&kind,&h,&r);
- SetCTitle(h,"\pScrivania");
- }
- else if(item==13){ /* Save here */
- current_val_OK=true;
- return 2; /* Cancel */
- }
- else if(item==1){ /* the Save button is out of screen,
- but it's still the default button hence it's "pressed" by a return key */
- GetDItem(theDialog,13,&kind,&h,&r);
- SelectButton(h);
- current_val_OK=true;
- return 2; /* Cancel */
- }
- return item;
- }
-
-
-
- void select_directory()
- {
- /* Presents a standard Put File where the save button is replaced by a "Save here"
- button and the filename box is not visible. The caller will ignore the name field
- in the reply record, using this routine to select the destination folder
- */
- current_val_OK=false;
- if(!gHasCustomPutFile || !useSys7_SF){
- #ifdef SETDITL
- set_DITL_title(199,in_Italia?string_1:"\pSave here");
- #endif
- SFPPutFile(where[0],PNS,
- string_5,select_dir_hook,&reply,199,select_dir_filter);
- #ifndef DA_CANCEL
- if(reply.good)
- SetVol(NULL,curr_vrefnum=reply.vRefNum); /* setta la directory */
- return;
- #endif
- }
- else{
- /* the system 6 dialog is particularly annoying when used under system 7
- (the "Save here" button is renamed open when a folder is selected) and
- it's here that the new "new folder" button is more useful: hence the privilege
- of being the only call to the standard file package done in the system 7 way */
- StandardFileReply sfrep;
- static int act_list[2]={1,7};
- need_update=is_outline=false;
- CustomPutFile(PNS,string_5,&sfrep,1043,where[4],sys7_select_dir_hook,
- sys7_select_dir_filter, act_list,NULL, &sfrep);
- reply.good=false;
- }
-
- if(current_val_OK){
- OSErr err;
- #define LOW_LEVEL_OWD
- #ifdef LOW_LEVEL_OWD
- WDPBRec param;
- param.ioVRefNum= -SFSaveDisk;
- param.ioNamePtr=NULL;
- param.ioWDProcID=signature;
- param.ioWDDirID=CurDirStore;
- err=PBOpenWDSync(¶m);
- if(err){
- error_message_1("Working directory error %d\n",err);
- }
- else
- curr_vrefnum=param.ioVRefNum;
- #else
- if((err=OpenWD(-SFSaveDisk,CurDirStore,0L,&curr_vrefnum))){
- error_message_1("Working directory error %d\n",err);
- }
- #endif
-
- register_WD(curr_vrefnum);
-
- SetVol(NULL,curr_vrefnum); /* setta la directory */
- reply.vRefNum=curr_vrefnum;
- reply.good=true;
- }
- }
-
- #define checkbox_state need_update /* just to avoid using another variable */
-
- pascal short checkbox_hook(short,DialogPtr);
- static pascal short checkbox_hook(item, theDialog)
- short item;
- DialogPtr theDialog;
- {
- short kind;
- Handle h;
- Rect r;
- extern Boolean in_Italia;
-
- if(item==-1) {
- /* initialization: translate button titles to Italian */
- GetDItem(theDialog,11,&kind,&h,&r);
- SetCtlValue((ControlHandle)h,checkbox_state);
- if(in_Italia){
- SetCTitle(h,"\pscelta formato automatica");
- #ifndef SETDITL
- GetDItem(theDialog,1,&kind,&h,&r);
- SetCTitle(h,string_6);
- #endif
- GetDItem(theDialog,3,&kind,&h,&r);
- SetCTitle(h,string_2);
- GetDItem(theDialog,5,&kind,&h,&r);
- SetCTitle(h,string_3);
- GetDItem(theDialog,6,&kind,&h,&r);
- SetCTitle(h,string_4);
- }
- }
- else if (item==11){
- SetCheckBox(theDialog,item);
- checkbox_state= ! checkbox_state;
- }
- return item;
- }
-
- Boolean get_file_with_checkbox(ck_state)
- Boolean *ck_state;
- {
- SFTypeList myTypes;
-
- checkbox_state=true;;
-
- #ifdef SETDITL
- set_DITL_title(400,in_Italia?string_6:string_7);
- #endif
- SFPGetFile(where[5],PNS,NULL,-1,myTypes,checkbox_hook,&reply,
- 400, SF_filter);
-
- if(reply.good){
- #ifdef CLOSE_SF_WD
- register_WD(reply.vRefNum);
- #endif
- *ck_state= checkbox_state;
- }
- return reply.good;
- }
-
- #define premuto_pausa need_update /* just to avoid using another variable */
-
- pascal short SFP_pausa_hook(short,DialogPtr);
- static pascal short SFP_pausa_hook(item, theDialog)
- short item;
- DialogPtr theDialog;
- {
-
- if(item==-1) {
- /* initialization: translate button titles to Italian */
- if(in_Italia){
- short kind;
- Handle h;
- Rect r;
-
- #ifndef SETDITL
- GetDItem(theDialog,1,&kind,&h,&r);
- SetCTitle(h,"\pSalva");
- #endif
- GetDItem(theDialog,2,&kind,&h,&r);
- SetCTitle(h,"\pNon salvare");
- GetDItem(theDialog,5,&kind,&h,&r);
- SetCTitle(h,string_3);
- GetDItem(theDialog,6,&kind,&h,&r);
- SetCTitle(h,string_4);
- GetDItem(theDialog,9,&kind,&h,&r);
- SetCTitle(h,"\pPausa");
- }
- }
- else if (item==9){
- premuto_pausa=true;
- return 2; /* cancel...*/
- }
- return item;
- }
-
-
-
- Boolean SFPut_con_pausa(fname)
- unsigned char *fname;
- {
- premuto_pausa=false;
- #ifdef SETDITL
- set_DITL_title(399,in_Italia?"\pSalva":"\pSave");
- #endif
- SFPPutFile(where[6],in_Italia?"\pIl file esiste giê,\rsalvalo come:":
- "\pThe file is already existing,\rsave as:",
- fname,SFP_pausa_hook,&reply,399,SF_filter);
- if(premuto_pausa) return true;
-
- #ifdef CLOSE_SF_WD
- if(reply.good) register_WD(reply.vRefNum);
- #endif
- return false;
- }
-
-
- /*********************************************************************/
-
- #ifdef SETDITL
- static void set_DITL_title(id,title)
- short id;
- unsigned char *title;
- {
- /* System 7 changes the name of the "open" or "save" button to reflect the two
- different meanings (open a folder or select a file). In doing that, it forgets
- any SetCTitle and restores the title stored in the DITL: hence, the only way to
- change the title of those buttons at run time is to modify the DITL itself,
- an horribly dirty thing; really, in suntar the two strings usually happen to have
- the same size, but it's better not to exploit special cases
- */
- unsigned char **h,cur_l,new_l;
-
- h = Get1Resource('DITL',id);
- if(h==NULL) return;
- HNoPurge (h); /* modifying a resource in memory would be useless if it may be purged */
-
- cur_l= (*(*h+15)+1)&~1; /* the affected button is always item 1, hence I may
- use a fixed offset; otherwise, I should skip the previous
- items by adding their (size+1)&~1 to the pointer */
- new_l= (title[0]+1)&~1;
- if(cur_l != new_l){
- Size s=GetHandleSize(h);
- if(s<0) return;
- if(new_l==cur_l)
- ;
- else if(new_l<cur_l){
- BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
- SetHandleSize (h,s+new_l-cur_l);
- }
- else{ /* new_l>cur_l */
- SetHandleSize (h,s+new_l-cur_l);
- BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
- }
- }
- pStrcpy(*h+15,title);
- if(new_l!=title[0]) *(*h+16+new_l)=0;
- }
- #endif
-
- /*
- Working directories must be closed: because there is a limited space,
- but above all because a folder in the trashcan can't be deleted when an
- open WD refers to it, causing an annoying dialog when doing an "empty trash".
- But there are some problems.
- PBOpenWD does not create a WD if it already exists, but PBCloseWD closes it even
- if it existed before the PBOpenWD, hence opening and closing it I might close a WD
- which was already used and is still used by another part of the program. The
- ioWDProcID field was meant to solve that problem, but under MultiFinder that field
- loses its original meaning.
- TN 190 says that WDs created by standard file must NOT be closed, but it does
- not explain why, on the contrary there is that very good reason to close them.
- By experimenting I discovered that:
- -) Under System 6, ioWDProcID is really ignored: if I open and close a WD on a folder
- already opened by standard file, the closeWD closes the WD created by standard file:
- hence, there should be no problem closing it anyway.
- -) Under System 7, ioWDProcID is used, and WDs created by standard file are marked 'ERIK',
- there is a way (nondocumented ?) so that a process identifier is stored together
- with ioWDProcID, so that different applications have a different set of WDs, in
- this situation it could be more dangerous to violate Apple rules and close the WDs
- created by standard file, but we've done that for a while without any problem.
- (To be safe, the 1.2.2 does not do that, however).
-
- By now my solution is to remember the vrefnum and close it in the main command
- loop (when no folder is been visited and no file is closed but going to be opened again).
- However, SuperBoomerang 3 has some problems if I close a WD (even if I created
- it by OpenWD ! Remember that it could return a previously existing one ). The result
- is that in ANY case it's an error to close them and it's an error to leave them open.
- People at Apple are not totally stupid, a different solution
- must exist: probably the only good solution would be NOT to create any WD but use PBH
- calls to exploit directly the triple information vrefnum-dirID-filename. But then,
- all standard file calls should be modified in order to avoid creating a WD
- (that is using the System 7 calls when it's possible, since simulating a Cancel
- does not update the list of recently opened files kept by Boomerang) and
- I would be forbidden to perform even one non-PBH routine, a large part of
- the program should be carefully searched and modified... too much work.
- */
-
-
- void register_WD(n_WD)
- short n_WD;
- {
- register int i=0;
- /*printf("register %d\n",n_WD);*/
- while(i<n_open_WD)
- if(n_WD==open_WD[i++]) return;
- if(n_open_WD<max_open_WD) open_WD[n_open_WD++]=n_WD;
- }
-
- void close_all_open_WD()
- {
- int i;
- WDPBRec param;
- for(i=0;i<n_open_WD;i++){
- param.ioVRefNum=open_WD[i];
- /*printf("closeWD=%d\n",open_WD[i]);*/
- if(!SB3_compatibility) PBCloseWDSync(¶m);
- }
- n_open_WD=0;
- }
-