home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / suntar1.cpt / folderStdfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-13  |  23.3 KB  |  780 lines

  1. /*******************************************************************************\
  2.  
  3. customized standard file module
  4.  
  5. ⌐ March 1991 Gabriele Speranza
  6. modified 31 dec 1991, feb 92, apr 92
  7.  
  8. This program is public domain, feel free to use it or part of it for anything
  9.  
  10. \*******************************************************************************/
  11.  
  12. #include "system7.h"
  13. #include "PB_sync.h"
  14. #include "antiglue.h"
  15.  
  16. #include <string.h>
  17. #include "suntar.h"
  18. #include "windows.h"
  19.  
  20. #define SETDITL
  21. #define CLOSE_SF_WD
  22. #define DA_CANCEL     /* always force Cancel even when an Open would have the same effect */
  23.  
  24. int curr_vrefnum;
  25. extern unsigned char PNS[];
  26. extern Boolean gHasCustomPutFile;
  27. char *p2cstr();
  28. SFReply        reply;
  29. Point        where[7];
  30. static short n_open_WD=0;
  31. #define max_open_WD 20
  32. static int open_WD[max_open_WD];
  33. unsigned char*nomeFormato;
  34. Boolean SB3_compatibility=false;
  35.  
  36. #ifndef NULL
  37. #define NULL 0L
  38. #endif
  39. #define sfHookNullEvent 100
  40.  
  41. void set_DITL_title(short,unsigned char *);
  42.  
  43.  
  44. /************* routine per selezionare un file o directory ******************/
  45.  
  46. #define writeButton        11
  47. #define cancelButton    3
  48. #define openButton        1
  49.  
  50. static long        current_dir_ID;
  51. static short    current_val_OK;
  52.  
  53. static unsigned char string_1[]="\pSalva qui",
  54.     string_2[]="\pAnnulla",
  55.     string_3[]="\pEspelli",
  56.     string_4[]="\pUnitê Disco",
  57.     string_5[]="\pgvu1h5%&#*├«@╣î┤╫┘╗",
  58.     /*string_5[]="\p\10\0\37";*/    /* an "impossible" file name: no more useful since
  59.         now I simulate a Cancel. Well, not exactly: AppleShare may see the name even 
  60.         when Cancel is simulated, hence there must be a name and it must not contain
  61.         "absurd" characters, otherwise you get a System Error */
  62.     string_6[]="\pApri",
  63.     string_7[]="\pOpen";
  64.  
  65. #define ESC 27
  66.  
  67. pascal Boolean SF_filter(DialogPtr,EventRecord*,short *);
  68. static pascal Boolean SF_filter(theDialog, theEvent, itemHit)
  69. DialogPtr theDialog;
  70. EventRecord* theEvent;
  71. short * itemHit;
  72. {
  73.  
  74. if(theEvent->what==nullEvent){
  75.     /* under System 7, the update events for windows below the System 6-like
  76.     standard file dialogs are not received if I don't explicitly ask for them.
  77.     I don't know whether it's a bug or an attempt to solve the problem described
  78.     in TN304, which for some reason believes that suntar belongs to the category
  79.     of programs which must be cheated.
  80.     System 7 is wonderful, but all its tricks are a damnation for programmers !
  81.     And they are not documented... and there is no way to tell to System 7 that
  82.     I know that I must behave well and I must not be cheated...
  83.     */
  84.     if(!EventAvail (updateMask,theEvent) )
  85.         return false;
  86.       }
  87. if(theEvent->what==updateEvt||theEvent->what==activateEvt){
  88.     /*SetPort(theEvent->message);*/
  89.     UpdateFilter(theEvent);
  90.     }
  91. else if(theEvent->what==keyDown){
  92.     short    kind;
  93.     Handle    h;
  94.     Rect    r;
  95.     if((unsigned char)theEvent->message==CR || (unsigned char)theEvent->message==enter_key){
  96.         GetDItem(theDialog,1,&kind,&h,&r);
  97.         SelectButton(h);
  98.         *itemHit=1;
  99.         return true;
  100.         }
  101.     else if((unsigned char)theEvent->message==ESC ||
  102.             (unsigned char)theEvent->message=='.'&&(theEvent->modifiers&cmdKey) ){
  103.         GetDItem(theDialog,3,&kind,&h,&r);        /* the Cancel button is item 3 in a
  104.                         get dialog, it's 2 in a put (and 3 is the prompt string, not
  105.                         a button) */
  106.         if(kind==ctrlItem+btnCtrl)
  107.             *itemHit= 3;
  108.         else
  109.             GetDItem(theDialog,(*itemHit= 2),&kind,&h,&r);
  110.         SelectButton(h);
  111.         return true;
  112.         }
  113.     }
  114. return false;
  115. }
  116.  
  117.  
  118. void my_SF_Put(prompt,fname)
  119. unsigned char *prompt,*fname;
  120. {
  121.     SFPPutFile(where[2],prompt,fname,NULL,&reply, -3999, SF_filter);
  122.     #ifdef CLOSE_SF_WD
  123.     if(reply.good) register_WD(reply.vRefNum);
  124.     #endif
  125. }
  126.  
  127. void my_SF_Get(numTypes,typeList)
  128. short numTypes;
  129. SFTypeList typeList;
  130. {
  131.     SFPGetFile(where[3],PNS,NULL,numTypes,typeList,NULL,&reply, -4000, SF_filter);
  132. #ifdef CLOSE_SF_WD
  133.     if(reply.good) register_WD(reply.vRefNum);
  134. #endif
  135. }
  136.  
  137.  
  138. pascal short file_or_folder_hook(short,DialogPtr);
  139. static pascal short file_or_folder_hook(item, theDialog)
  140.     short        item;
  141.     DialogPtr    theDialog;
  142. {
  143.     short    kind;
  144.     Handle    h;
  145.     Rect    r;
  146.     extern Boolean in_Italia;
  147.  
  148.     if(item==-1) {
  149. /* initialization: translate button titles to Italian */
  150.         if(in_Italia){
  151.             #ifndef SETDITL
  152.             GetDItem(theDialog,1,&kind,&h,&r);
  153.             SetCTitle(h,string_6);
  154.             #endif
  155.             GetDItem(theDialog,3,&kind,&h,&r);
  156.             SetCTitle(h,string_2);
  157.             GetDItem(theDialog,5,&kind,&h,&r);
  158.             SetCTitle(h,string_3);
  159.             GetDItem(theDialog,6,&kind,&h,&r);
  160.             SetCTitle(h,string_4);
  161.             GetDItem(theDialog,11,&kind,&h,&r);
  162.             SetCTitle(h,"\pScrivi");
  163.             GetDItem(theDialog,12,&kind,&h,&r);
  164.             SetIText(h,"\pScegli il file o cartella da archiviare");
  165.             }
  166.         GetDItem(theDialog,13,&kind,&h,&r);
  167.         SetIText(h,nomeFormato);
  168.         current_val_OK = false;
  169.         }
  170.     else if(item==writeButton){        /* file o directory selezionata*/
  171.         if (reply.fType != 0 || reply.fName[0]!=0) {
  172.         /* remember which folder was currently selected, if it was a folder */
  173.             current_dir_ID = reply.fType;    /* if the current selection is a folder,
  174.                         this field contains its dir ID */
  175.             current_val_OK = reply.fName[0]==0 ? 1 : -1;    /*cioÅ, solo se Å una directory, non un file
  176.                          -- the name is NOT stored here if it was a folder (se IM vol IV) */
  177.             return cancelButton; /* 
  178.                     declare that the cancel button was pressed, remembering that 
  179.                     it's not so; for files, I could return openButton, but there is 
  180.                     a problem: if the selected file is an alias under System 7, 
  181.                     the alias is NOT resolved and a beep is done: I wish that 
  182.                     unresolved alias, but I don't wish that beep ! */
  183.             }
  184.         else
  185.             return sfHookNullEvent;    /* per dirgli di ignorare la cosa... non dovrebbe capitare comunque
  186.                         grazie al filtro di eventi che disabilita il bottone
  187.                         -- Really, the event filter disables the button when nothing
  188.                         is selected, so I should not receive "button pressed" items,
  189.                         but if I do, I ignore it */
  190.         }
  191.     return item;
  192. }
  193.  
  194. pascal Boolean file_or_folder_filter(DialogPtr,EventRecord*,short *);
  195. static pascal Boolean file_or_folder_filter(theDialog, theEvent, itemHit)
  196. DialogPtr theDialog;
  197. EventRecord* theEvent;
  198. short * itemHit;
  199. {
  200. short    kind;
  201. Rect    r;
  202. ControlHandle openH,writeH;
  203.  
  204. GetDItem(theDialog,openButton,&kind,&openH,&r);
  205. GetDItem(theDialog,writeButton,&kind,&writeH,&r);
  206. HiliteControl(writeH, (**openH).contrlHilite);    /* the write button is enabled/disabled
  207.             to follow the current state of the Open Button */
  208. return SF_filter(theDialog,theEvent,itemHit);
  209. }
  210.  
  211. int get_file_or_folder(s,n_types,myTypes)
  212. /* presents a modified file dialog which allows to choose either a file or
  213. a folder, with the extra "Write" button
  214. returns:
  215. -1 cancel
  216. 0 folder
  217. 1 file
  218. */
  219. Str255    s;
  220. short n_types;
  221. SFTypeList        *myTypes;
  222. {int i;
  223.  
  224. #ifdef SETDITL
  225.     set_DITL_title(200,in_Italia?string_6:string_7);
  226. #endif
  227.  
  228.     SFPGetFile(where[1],PNS,NULL,n_types,myTypes,file_or_folder_hook,&reply,
  229.         200,file_or_folder_filter);
  230.  
  231.     reply.fName[1+reply.fName[0]]=0;
  232.     if (current_val_OK>0){
  233.     /* write folder.
  234.     the vRefNum in the reply is not correct, but the low memory variable SFSaveDisk 
  235.     holds the negative of the right value */
  236. #ifdef V_122
  237.         if(i=PathNameFromDirID(current_dir_ID,(curr_vrefnum= -SFSaveDisk),s)) {
  238.             /* TN 238 sconsiglia di creare dei full path name, perchÄ in A/UX i
  239.             full path name vogliono la '/' anche se si fanno chiamate alle routine
  240.             HFS del toolbox... */
  241.             SysBeep(5);
  242.             printf("Pathname error\n");
  243.             raise_error();
  244.             }
  245. #else
  246.         /* get the name of the folder */
  247.         {
  248.         CInfoPBRec    block;
  249.         Str255        directoryName;
  250.         OSErr err;
  251.  
  252.         block.dirInfo.ioNamePtr = &s[1];
  253.         block.dirInfo.ioDrParID = current_dir_ID;
  254.  
  255.         block.dirInfo.ioVRefNum = curr_vrefnum= -SFSaveDisk;
  256.         block.dirInfo.ioFDirIndex = -1;
  257.         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  258.  
  259.         err = PBGetCatInfoSync(&block);
  260.         if(err!=noErr) error_message_1("Folder error %d\n",err);
  261.         if(current_dir_ID==2){        /* root directory, it's already a refnum... */
  262.             mcopy(s,&s[1],s[1]+1);    /* must not add a semicolon */
  263.             }
  264.         else{
  265.             WDPBRec param;
  266.             s[0] = s[1]+1;
  267.             s[1]=':';
  268.  
  269.             /* open a WD on the parent directory */
  270.  
  271.             param.ioVRefNum= curr_vrefnum;
  272.             param.ioNamePtr=NULL;
  273.             param.ioWDProcID=signature;
  274.             param.ioWDDirID= block.dirInfo.ioDrParID;
  275.             if(err=PBOpenWDSync(¶m)) error_message_1("Working directory error %d\n",err);
  276.             /* printf("selected=%d %ld %p\n",curr_vrefnum,block.dirInfo.ioDrParID,s); */
  277.             curr_vrefnum=param.ioVRefNum;
  278.             register_WD(param.ioVRefNum);
  279.             }
  280.         /* Append a Macintosh style colon (':') */
  281.         pStrcat(s,"\p:");
  282.         SetVol(NULL,curr_vrefnum);
  283.         }
  284. #endif
  285.         return 0;
  286.         }
  287.     if(current_val_OK<0){    /* write file */
  288.         WDPBRec param;
  289.         param.ioVRefNum= -SFSaveDisk;
  290.         param.ioNamePtr=NULL;
  291.         param.ioWDProcID=signature;
  292.         param.ioWDDirID=CurDirStore;
  293.         if(PBOpenWDSync(¶m)) error_message("Working directory error\n");
  294.         reply.vRefNum=param.ioVRefNum;    /* ad uso delle varie open...*/
  295.         register_WD(param.ioVRefNum);
  296.         }
  297.     else if(!reply.good)
  298.         return -1;    /* cancel */
  299.     /* if I am here, it was a open/write file */
  300.     SetVol(NULL,reply.vRefNum);    /* the old version of the program usually passed
  301.             0 as vrefnum relying on a SetVol, the new one prefers to pass explicitly
  302.             curr_vrefnum, but if we have forgotten to modify one call, doing
  303.             also the SetVol avoid troubles: one day all these SetVol will be
  304.             deleted, but then an accurate beta testing should follow... */
  305. #ifdef CLOSE_SF_WD
  306.     register_WD(reply.vRefNum);
  307. #endif
  308.     curr_vrefnum=reply.vRefNum;
  309.     pStrcpy(s,reply.fName);
  310.     return 1;
  311. }
  312.  
  313. /********** routines per la selezione di una directory di destinazione *********/
  314.  
  315. pascal short select_dir_hook (short,DialogPtr);
  316. static pascal short select_dir_hook (item, theDialog)
  317.  short item;
  318.  DialogPtr theDialog;
  319. {
  320.  
  321. if(item==-1 && in_Italia){
  322.     short    kind;
  323.     Handle    h;
  324.     Rect    r;
  325.     #ifndef SETDITL
  326.     GetDItem(theDialog,1,&kind,&h,&r);
  327.     SetCTitle(h,string_1);
  328.     #endif
  329.     GetDItem(theDialog,2,&kind,&h,&r);
  330.     SetCTitle(h,string_2);
  331.     GetDItem(theDialog,5,&kind,&h,&r);
  332.     SetCTitle(h,string_3);
  333.     GetDItem(theDialog,6,&kind,&h,&r);
  334.     SetCTitle(h,string_4);
  335.     }
  336. else if(item==1){    /* Save here */
  337.     current_val_OK=true;
  338.     #ifdef DA_CANCEL
  339.     return 2;    /* Cancel: hence, no risk to get a dialog "file existing, OK to replace ?" */
  340.     #endif
  341.     }
  342. return item;
  343. }
  344.  
  345. pascal Boolean select_dir_filter(DialogPtr,EventRecord*,short *);
  346. static pascal Boolean select_dir_filter(theDialog, theEvent, itemHit)
  347. DialogPtr theDialog;
  348. EventRecord* theEvent;
  349. short * itemHit;
  350. {
  351.  
  352. if(theEvent->what==keyDown||theEvent->what==autoKey){
  353.     theEvent->what=nullEvent;
  354.     }    /* se no si puÿ cancellare il nome, e il bottone per
  355.                                 salvare viene disabilitato...
  356.                                 -- the file name can't be modified ! It will be ignored,
  357.                                 but if you delete it, the save button will be disabled,
  358.                                 and save here IS the save button */
  359. /* no, niente da fare, lo standard file non me li passa affatto
  360. -- useless, such events are not passed to my filter
  361. else if(theEvent->what==diskEvt){
  362.     unexpected_disk_insertion(theEvent->message);
  363.     theEvent->what=nullEvent;
  364.     }
  365. */
  366.  
  367. return SF_filter(theDialog, theEvent, itemHit);
  368. }
  369.  
  370. static Boolean need_update,is_outline;
  371.  
  372. pascal Boolean sys7_select_dir_filter(DialogPtr,EventRecord*,short *,Ptr);
  373. static pascal Boolean sys7_select_dir_filter(theDialog, theEvent, itemHit, myDataPtr)
  374. DialogPtr theDialog;
  375. EventRecord* theEvent;
  376. short * itemHit;
  377. Ptr myDataPtr;
  378. {
  379. if(theEvent->what==updateEvt && (DialogPtr)theEvent->message==theDialog)
  380.     need_update=true;
  381. return SF_filter(theDialog, theEvent, itemHit);
  382. }
  383.  
  384.  
  385. pascal short sys7_select_dir_hook(short,DialogPtr,Ptr);
  386. static pascal short sys7_select_dir_hook(item,theDialog,myDataPtr)
  387. short item;
  388. DialogPtr theDialog;
  389. Ptr myDataPtr;
  390. {
  391. /* it is correct to draw an outline to the "save here" button, however
  392. ther are two problems:
  393. 1) there is not a good place to do that: in the event filter, I could do that as an
  394.     answer to the update event, but it should be between BeginUpdate and EndUpdate,
  395.     or in the worst case after EndUpdate, while I'm called before. In my_modal
  396.     I handle the whole update by myself, but here doing that could cause 
  397.     incompatibility problems (if something is redrawn directly and not through
  398.     the redraw routine of a dialog item... for example, Boomerang's file info
  399.     disappear in case of an update). Hence I do that periodically, that's
  400.     NOT a good solution but I haven't found a better one
  401.     (probably the "Better" way is to install an user item for the outline...
  402.     maybe I'll try that one day)
  403. 2) The return and enter key mean "open" or "click on the default button"
  404.     according to what is currently selected (a folder/volume, or a file/nothing):
  405.     hence, I should outline the Save here button only when return means Save,
  406.     but the in StandardFileReply record only parID and vRefNum are updated, (the name,
  407.     sfIsFolder and sfIsVolume are updated only by Custom G E T file). Furthermore,
  408.     if the current volume is locked the Save button is dimmed, and must not be
  409.     outlined: this time, I should update things when the state change happens, that is
  410.     AFTER the handling of clicks on items which change the situation, but my
  411.     hook routine is called BEFORE the standard handling is performed: this time, a
  412.     periodic action looks like the only way to do things
  413. */
  414.  
  415. short    kind;
  416. ControlHandle    h;
  417. Rect    r;
  418. int i;
  419. ControlHandle saveH;
  420. /*
  421. StandardFileReply *sfrep=myDataPtr;
  422. printf("%d %d %ld %d %p\n",sfrep->sfIsFolder,sfrep->sfIsVolume,sfrep->sfFile.parID,
  423. sfrep->sfFile.vRefNum,sfrep->sfFile.name);
  424. */
  425.  
  426. if(((WindowPeek)theDialog)->refCon!='stdf') return item;
  427.  
  428. GetDItem(theDialog,1,&kind,&h,&r);
  429. GetDItem(theDialog,13,&kind,&saveH,&r);
  430. if((**h).contrlHilite!=(**saveH).contrlHilite)
  431.     HiliteControl(saveH, (**h).contrlHilite);    /* the save here button is 
  432.             enabled/disabled to follow the current state of the save Button */
  433. if(!(i=(**h).contrlHilite)){
  434.     char buffer[20];
  435.     GetCTitle(h,buffer);
  436.     i=strcmp("Save",p2cstr(buffer));    /* the "Open" string is chosen from the
  437.                                         system, depending on the nation, but the
  438.                                         Save string is from my resource... */
  439.     }
  440. if(i){    /* erase the outline */
  441.     /* probably it's possible to avoid all that by exploiting the calls described in
  442.     Technical Note 304, but beta testing of 1.2 has already started, it's too late to
  443.     try new routines */
  444.     if(is_outline){
  445.         Rect r1;
  446.         SetPort(theDialog);
  447.         r1.left=r.left-4;
  448.         r1.right=r.left;
  449.         r1.top=r.top-4;
  450.         r1.bottom=r.bottom+4;
  451.         EraseRect(&r1);
  452.         r1.left=r.right;
  453.         r1.right=r.right+4;
  454.         EraseRect(&r1);
  455.         r1.left=r.left;
  456.         r1.right=r.right;
  457.         r1.top=r.top-4;
  458.         r1.bottom=r.top;
  459.         EraseRect(&r1);
  460.         r1.top=r.bottom;
  461.         r1.bottom=r.bottom+4;
  462.         EraseRect(&r1);
  463.         }
  464.     is_outline=false;
  465.     }
  466. else{
  467.     if(!is_outline||need_update){
  468.         OutlineControl(saveH);
  469.         need_update=false;
  470.         }
  471.     is_outline=true;
  472.     }
  473.  
  474. if(item==-1&&in_Italia){
  475.     GetDItem(theDialog,13,&kind,&h,&r);
  476.     SetCTitle(h,string_1);
  477.     GetDItem(theDialog,2,&kind,&h,&r);
  478.     SetCTitle(h,string_2);
  479.     GetDItem(theDialog,5,&kind,&h,&r);
  480.     SetCTitle(h,string_3);
  481.     GetDItem(theDialog,6,&kind,&h,&r);
  482.     SetCTitle(h,"\pScrivania");
  483.     }
  484. else if(item==13){    /* Save here */
  485.     current_val_OK=true;
  486.     return 2;    /* Cancel */
  487.     }
  488. else if(item==1){    /* the Save button is out of screen,
  489.             but it's still the default button hence it's "pressed" by a return key */
  490.     GetDItem(theDialog,13,&kind,&h,&r);
  491.     SelectButton(h);
  492.     current_val_OK=true;
  493.     return 2;    /* Cancel */
  494.     }
  495. return item;
  496. }
  497.  
  498.  
  499.  
  500. void select_directory()
  501. {
  502. /* Presents a standard Put File where the save button is replaced by a "Save here"
  503. button and the filename box is not visible. The caller will ignore the name field
  504. in the reply record, using this routine to select the destination folder
  505. */
  506.     current_val_OK=false;
  507.     if(!gHasCustomPutFile || !useSys7_SF){
  508. #ifdef SETDITL
  509.         set_DITL_title(199,in_Italia?string_1:"\pSave here");
  510. #endif
  511.         SFPPutFile(where[0],PNS,
  512.             string_5,select_dir_hook,&reply,199,select_dir_filter);
  513. #ifndef DA_CANCEL
  514.         if(reply.good)
  515.             SetVol(NULL,curr_vrefnum=reply.vRefNum); /* setta la directory */
  516.         return;
  517. #endif
  518.         }
  519.     else{
  520.         /* the system 6 dialog is particularly annoying when used under system 7
  521.         (the "Save here" button is renamed open when a folder is selected) and
  522.         it's here that the new "new folder" button is more useful: hence the privilege
  523.         of being the only call to the standard file package done in the system 7 way */
  524.         StandardFileReply sfrep;
  525.         static int act_list[2]={1,7};
  526.         need_update=is_outline=false;
  527.         CustomPutFile(PNS,string_5,&sfrep,1043,where[4],sys7_select_dir_hook,
  528.             sys7_select_dir_filter, act_list,NULL, &sfrep);
  529.         reply.good=false;
  530.         }
  531.  
  532.     if(current_val_OK){
  533.         OSErr err;
  534. #define LOW_LEVEL_OWD
  535. #ifdef LOW_LEVEL_OWD
  536.         WDPBRec param;
  537.         param.ioVRefNum= -SFSaveDisk;
  538.         param.ioNamePtr=NULL;
  539.         param.ioWDProcID=signature;
  540.         param.ioWDDirID=CurDirStore;
  541.         err=PBOpenWDSync(¶m);
  542.         if(err){
  543.             error_message_1("Working directory error %d\n",err);
  544.             }
  545.         else
  546.             curr_vrefnum=param.ioVRefNum;
  547. #else
  548.         if((err=OpenWD(-SFSaveDisk,CurDirStore,0L,&curr_vrefnum))){
  549.             error_message_1("Working directory error %d\n",err);
  550.             }
  551. #endif
  552.  
  553.         register_WD(curr_vrefnum);
  554.  
  555.         SetVol(NULL,curr_vrefnum); /* setta la directory */
  556.         reply.vRefNum=curr_vrefnum;
  557.         reply.good=true;
  558.         }
  559. }
  560.  
  561. #define checkbox_state need_update    /* just to avoid using another variable */
  562.  
  563. pascal short checkbox_hook(short,DialogPtr);
  564. static pascal short checkbox_hook(item, theDialog)
  565.     short        item;
  566.     DialogPtr    theDialog;
  567. {
  568.     short    kind;
  569.     Handle    h;
  570.     Rect    r;
  571.     extern Boolean in_Italia;
  572.  
  573.     if(item==-1) {
  574. /* initialization: translate button titles to Italian */
  575.         GetDItem(theDialog,11,&kind,&h,&r);
  576.         SetCtlValue((ControlHandle)h,checkbox_state);
  577.         if(in_Italia){
  578.             SetCTitle(h,"\pscelta formato automatica");
  579.             #ifndef SETDITL
  580.             GetDItem(theDialog,1,&kind,&h,&r);
  581.             SetCTitle(h,string_6);
  582.             #endif
  583.             GetDItem(theDialog,3,&kind,&h,&r);
  584.             SetCTitle(h,string_2);
  585.             GetDItem(theDialog,5,&kind,&h,&r);
  586.             SetCTitle(h,string_3);
  587.             GetDItem(theDialog,6,&kind,&h,&r);
  588.             SetCTitle(h,string_4);
  589.             }
  590.         }
  591.     else if (item==11){
  592.         SetCheckBox(theDialog,item);
  593.         checkbox_state= ! checkbox_state;
  594.         }
  595.     return item;
  596. }
  597.  
  598. Boolean get_file_with_checkbox(ck_state)
  599. Boolean *ck_state;
  600. {
  601. SFTypeList        myTypes;
  602.  
  603. checkbox_state=true;;
  604.  
  605. #ifdef SETDITL
  606. set_DITL_title(400,in_Italia?string_6:string_7);
  607. #endif
  608. SFPGetFile(where[5],PNS,NULL,-1,myTypes,checkbox_hook,&reply,
  609.         400, SF_filter);
  610.  
  611. if(reply.good){
  612. #ifdef CLOSE_SF_WD
  613.     register_WD(reply.vRefNum);
  614. #endif
  615.     *ck_state= checkbox_state;
  616.     }
  617. return reply.good;
  618. }
  619.  
  620. #define premuto_pausa need_update    /* just to avoid using another variable */
  621.  
  622. pascal short SFP_pausa_hook(short,DialogPtr);
  623. static pascal short SFP_pausa_hook(item, theDialog)
  624.     short        item;
  625.     DialogPtr    theDialog;
  626. {
  627.  
  628.     if(item==-1) {
  629. /* initialization: translate button titles to Italian */
  630.         if(in_Italia){
  631.             short    kind;
  632.             Handle    h;
  633.             Rect    r;
  634.  
  635.             #ifndef SETDITL
  636.             GetDItem(theDialog,1,&kind,&h,&r);
  637.             SetCTitle(h,"\pSalva");
  638.             #endif
  639.             GetDItem(theDialog,2,&kind,&h,&r);
  640.             SetCTitle(h,"\pNon salvare");
  641.             GetDItem(theDialog,5,&kind,&h,&r);
  642.             SetCTitle(h,string_3);
  643.             GetDItem(theDialog,6,&kind,&h,&r);
  644.             SetCTitle(h,string_4);
  645.             GetDItem(theDialog,9,&kind,&h,&r);
  646.             SetCTitle(h,"\pPausa");
  647.             }
  648.         }
  649.     else if (item==9){
  650.         premuto_pausa=true;
  651.         return 2; /* cancel...*/
  652.         }
  653.     return item;
  654. }
  655.  
  656.  
  657.  
  658. Boolean SFPut_con_pausa(fname)
  659. unsigned char *fname;
  660. {
  661. premuto_pausa=false;
  662. #ifdef SETDITL
  663. set_DITL_title(399,in_Italia?"\pSalva":"\pSave");
  664. #endif
  665. SFPPutFile(where[6],in_Italia?"\pIl file esiste giê,\rsalvalo come:":
  666.     "\pThe file is already existing,\rsave as:",
  667.     fname,SFP_pausa_hook,&reply,399,SF_filter);
  668. if(premuto_pausa) return true;
  669.  
  670. #ifdef CLOSE_SF_WD
  671. if(reply.good) register_WD(reply.vRefNum);
  672. #endif
  673. return false;
  674. }
  675.  
  676.  
  677. /*********************************************************************/
  678.  
  679. #ifdef SETDITL
  680. static void set_DITL_title(id,title)
  681. short id;
  682. unsigned char *title;
  683. {
  684. /* System 7 changes the name of the "open" or "save" button to reflect the two
  685. different meanings (open a folder or select a file). In doing that, it forgets
  686. any SetCTitle and restores the title stored in the DITL: hence, the only way to
  687. change the title of those buttons at run time is to modify the DITL itself,
  688. an horribly dirty thing; really, in suntar the two strings usually happen to have
  689. the same size, but it's better not to exploit special cases
  690. */
  691. unsigned char **h,cur_l,new_l;
  692.  
  693. h = Get1Resource('DITL',id);
  694. if(h==NULL) return;
  695. HNoPurge (h);    /* modifying a resource in memory would be useless if it may be purged */
  696.  
  697. cur_l= (*(*h+15)+1)&~1;    /* the affected button is always item 1, hence I may
  698.                         use a fixed offset; otherwise, I should skip the previous
  699.                         items by adding their (size+1)&~1 to the pointer */
  700. new_l= (title[0]+1)&~1;
  701. if(cur_l != new_l){
  702.     Size s=GetHandleSize(h);
  703.     if(s<0) return;
  704.     if(new_l==cur_l)
  705.         ;
  706.     else if(new_l<cur_l){
  707.         BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
  708.         SetHandleSize (h,s+new_l-cur_l);
  709.         }
  710.     else{    /* new_l>cur_l */
  711.         SetHandleSize (h,s+new_l-cur_l);
  712.         BlockMove(*h+15+cur_l,*h+15+new_l,s-15-cur_l);
  713.         }
  714.     }
  715. pStrcpy(*h+15,title);
  716. if(new_l!=title[0]) *(*h+16+new_l)=0;
  717. }
  718. #endif
  719.  
  720. /*
  721.  Working directories must be closed: because there is a limited space,
  722. but above all because a folder in the trashcan can't be deleted when an
  723. open WD refers to it, causing an annoying dialog when doing an "empty trash".
  724. But there are some problems.
  725.   PBOpenWD does not create a WD if it already exists, but PBCloseWD closes it even 
  726. if it existed before the PBOpenWD, hence opening and closing it I might close a WD 
  727. which was already used and is still used by another part of the program. The 
  728. ioWDProcID field was meant to solve that problem, but under MultiFinder that field
  729. loses its original meaning.
  730.   TN 190 says that WDs created by standard file must NOT be closed, but it does
  731. not explain why, on the contrary there is that very good reason to close them.
  732.   By experimenting I discovered that:
  733. -) Under System 6, ioWDProcID is really ignored: if I open and close a WD on a folder
  734. already opened by standard file, the closeWD closes the WD created by standard file:
  735. hence, there should be no problem closing it anyway.
  736. -) Under System 7, ioWDProcID is used, and WDs created by standard file are marked 'ERIK',
  737. there is a way (nondocumented ?) so that a process identifier is stored together
  738. with ioWDProcID, so that different applications have a different set of WDs, in 
  739. this situation it could be more dangerous to violate Apple rules and close the WDs
  740. created by standard file, but we've done that for a while without any problem.
  741. (To be safe, the 1.2.2 does not do that, however).
  742.  
  743.  By now my solution is to remember the vrefnum and close it in the main command 
  744. loop (when no folder is been visited and no file is closed but going to be opened again).
  745.  However, SuperBoomerang 3 has some problems if I close a WD (even if I created
  746. it by OpenWD ! Remember that it could return a previously existing one ). The result
  747. is that in ANY case it's an error to close them and it's an error to leave them open.
  748.  People at Apple are not totally stupid, a different solution
  749. must exist: probably the only good solution would be NOT to create any WD but use PBH
  750. calls to exploit directly the triple information vrefnum-dirID-filename. But then,
  751. all standard file calls should be modified in order to avoid creating a WD 
  752. (that is using the System 7 calls when it's possible, since simulating a Cancel
  753. does not update the list of recently opened files kept by Boomerang) and
  754. I would be forbidden to perform even one non-PBH routine, a large part of
  755. the program should be carefully searched and modified... too much work.
  756. */
  757.  
  758.  
  759. void register_WD(n_WD)
  760. short n_WD;
  761. {
  762. register int i=0;
  763. /*printf("register %d\n",n_WD);*/
  764. while(i<n_open_WD)
  765.     if(n_WD==open_WD[i++]) return;
  766. if(n_open_WD<max_open_WD) open_WD[n_open_WD++]=n_WD;
  767. }
  768.  
  769. void close_all_open_WD()
  770. {
  771. int i;
  772. WDPBRec param;
  773. for(i=0;i<n_open_WD;i++){
  774.     param.ioVRefNum=open_WD[i];
  775.     /*printf("closeWD=%d\n",open_WD[i]);*/
  776.     if(!SB3_compatibility) PBCloseWDSync(¶m);
  777.     }
  778. n_open_WD=0;
  779. }
  780.