home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / suntar1.cpt / suntar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-20  |  72.7 KB  |  2,727 lines

  1. /*******************************************************************************\
  2.  
  3. main module
  4.  
  5. suntar 1.3, ⌐1991-92 Sauro & Gabriele Speranza
  6.  
  7. This program is public domain, feel free to use it or part of it for anything
  8.  
  9. \*******************************************************************************/
  10.  
  11.  
  12. #include "PB_sync.h"
  13. #include "antiglue.h"
  14.  
  15. /*#include    <EventMgr.h>
  16. #include    <QuickDraw.h>
  17. #include    <StdFilePkg.h>
  18. */
  19. #include    <IntlPkg.h>
  20. /*
  21.  
  22. #include    <DiskDvr.h>
  23. #include    <DeviceMgr.h>
  24. */
  25.  
  26. #include <string.h>
  27.  
  28. #include "windows.h"
  29. #include "suntar.h"
  30.  
  31. #define dp printf  /* use it for debug, so it's easy to */
  32.                 /* find&delete all the extra print instructions */
  33.  
  34.  
  35. MenuHandle writeMenu,hackersMenu,tarPopupMenu,ntAPopupMenu;
  36.  
  37. int err_code;
  38. short drive_number=0;
  39.  
  40. options_type options;
  41. long last_selection=0;
  42. short again_command=0;
  43. sector_t sectors_on_floppy;
  44. OSType tar_creator,bar_creator,bar_type;
  45. static Boolean append_mode;
  46. Boolean in_Italia=false;
  47. Boolean ignore_errors=false;
  48. Boolean confirm_saves=false;
  49. Boolean expert_mode=false;
  50. Boolean non_convertire=false;
  51. Boolean disco_espulso;        /* was my disk ejected ? */
  52. Boolean sto_lavorando=false;    /* non usarlo se non per lo scopo attuale, dire al calcolo del
  53.                                 tempo di sleep per WaitNextEvent di ritornare sempre 0, e sapere
  54.                                 se devo abilitare il comando Pause 
  55.                                 -- consider it as a read only variable !*/
  56. unsigned char file_aperto=0;
  57. static unsigned char check_ev_timing;
  58. #ifdef V_122
  59. Boolean smallFilesAreASCII;
  60. #endif
  61. short disable_binhex;            /* bit 0: disable conversion
  62.                                    bit 1: show info in extract
  63.                                    bit 2: show info in list
  64.                                    bit 3: save .info */
  65.  
  66. short last_drive,preferred_drive;
  67. short back_prio;
  68.  
  69. struct disk_info di;
  70.  
  71. static Boolean preferences_changed=0;    /* Apple (TN 188) discourages to call 
  72.         ChangedResource if it's not followed immediately by WriteResource, 
  73.         and I want to modify the file only once, and not to modify it if nothing 
  74.         changed */
  75. sector_t settori_passati;
  76.  
  77. enum tipo_fase fase;
  78. short n_superdrives;
  79. sector_t file_current_s;
  80. short drive_type[max_drive];
  81. extern sector_t next_header_for_AIX;
  82. unsigned char window_title[]="\psuntar 1.3 - console";
  83. short default_flags =READONLY|CONSOLE|NOCLOSEBOX;
  84. extern short floppy_buffer_size;
  85. extern unsigned int hd_buffer_size;
  86.  
  87. void handle_menus(long);
  88. void add_menu(void);
  89. int my_quit_handler(void);
  90.  
  91.  
  92. static char diskReadErrMsg[]="Disk read error %d\n",
  93.         diskReadErrIta[]="Errore di lettura ní %d\n";
  94. static char diskWriteErrMsg[]="Disk write error %d\n";
  95. char DONE[]="Done\n",FINITO[]="Finito\n";
  96. char START_READ[]="Start reading\n";
  97.  
  98.  
  99. /***************** main ******************/
  100.  
  101.  
  102. /*
  103. suntar use an architecture which is unusual, at least in the Mac world:
  104. it has not a main event loop.
  105.  When you have passed the first wave of horror and astonishment, I'll
  106. tell you how it works.
  107.  The MainEvent routine calls GetNextEvent and serves the event, but:
  108. 1) it returns to the caller, it does not loop internally
  109. 2) it does not know how to serve all events, since it's part of the
  110.    windows module and does not know anything about the tar/untar modules:
  111.    you must enlarge its capabilities by providing an event filter and an 
  112.    "application specific menus handler", and maybe some "updaters" and
  113.    "activaters" for windows (e.g. other filters)
  114. 3) some menu items are handled immediately, but others only set the
  115.    "last_selection" variable which the caller then examines and handles.
  116.  That is, MainEvent is a relatively low-level routine, which is not allowed to
  117. take important decisions.
  118.  So, suntar has several event loops, which call MainEvent, usually after installing
  119. different event filters. Furthermore, MainEvent is called periodically
  120. while suntar is working, with one further event filter which disables all the
  121. events which are not essential. This architecture may easily emulate
  122. a typical Mac behaviour, but it's more flexible and powerful.
  123.   Finally, MainEvent was broken into two parts, and sometimes one calls
  124. the two parts, doing its own event handling between the two calls, so reducing the
  125. need for a lot of filters.
  126. */
  127.  
  128. void main()
  129. {
  130. int command;
  131.  
  132. /* install the handlers for events which the window module doesn't know how
  133. to handle */
  134. my_handle_menus=handle_menus;
  135. my_add_menus=add_menu;
  136.  
  137. /* initialize everything */
  138. /* l'ordine Å importante perchÄ a) ci sono delle dipendenze da variabili
  139.    inizializzate da un'altra di esse, e b) determina dove sono caricate le
  140.    risorse di codice e quindi la frammentazione della memoria */
  141. init_hqx_tab();
  142. InitConsole();
  143. prefs_da_risorsa();
  144. init_hd_buffering();
  145. init_buffering();
  146.  
  147. /* look at what disk drives and device driver are available */
  148. identifica_hardware();
  149.  
  150. /* install the Quit handler */
  151. my_at_exit= my_quit_handler;
  152.  
  153. /* main loop */
  154.  
  155. /* debugging: open a second window so debugging prints don't mix with the
  156. normal outputs * /
  157. printf("inizio\n");
  158. pStrcpy(window_title,"\pDebug");
  159. new_window();
  160. / * */
  161.  
  162. for(;;){
  163.     fase=non_faccio_nulla;
  164.     set_skip_all(0);
  165.     close_all_open_WD();
  166.     check_ev_timing=120;
  167.     flush_buffers();
  168.  
  169.     last_selection=0;
  170.     while(last_selection==0)
  171.         MainEvent();
  172.     fase=ricevuto_comando;
  173.     settori_passati=0;
  174.  
  175. /* sono possibili solo i men¥ Special e File, perchÄ Preferences ed Edit sono gestiti 
  176. subito e Write non Å abilitato */
  177.     if(hiword(last_selection)==hackID){
  178.         if(loword(last_selection)==hmDriveList)
  179.             DriveList();    /* it's the only command which needs no disk...*/
  180.         else
  181.             hacking(loword(last_selection));
  182.         }
  183. /* non faccio else perchÄ si puÿ uscire dall'hacking anche con un comando
  184. del men¥ File, che va eseguito 
  185. -- don't do 'else': I can exit from hacking with a File menu command which must be
  186. executed */
  187.  
  188.     command=loword(last_selection);
  189.  
  190.     if(hiword(last_selection)==fileID){
  191.         again_command=0;
  192.         last_selection=0;
  193.         if(command==fmGetInfo){
  194.             listonly=2;
  195.             apri_archivio();
  196.             }
  197.         else if(command==fmOpen){
  198.             listonly=0;
  199.             apri_archivio();
  200.             }
  201.         else if(command==fmClose){
  202.             if(file_aperto)
  203.                 chiudi_archivio();
  204.             else
  205.                 diskEject();
  206.             }
  207.         else if(command ==fmCopy)
  208.             copia_da_disco_a_file();
  209.         else if(command==fmList){
  210.             listonly=1;
  211.             estrai_da_floppy();
  212.             }
  213.         else if(command==fmExtract){ /* extract, con de-macBinarizzazione e conversione LF->CR */
  214.             listonly=0;
  215.             estrai_da_floppy();
  216.             }
  217.         else if(command==fmSelect)
  218.             select_and_extract();
  219.         else if(command==fmWriteTar||command==fmWriteBar||command==fmAppend){
  220.             bar_archive= command==fmWriteBar;    /* non valido nel caso di append */
  221.             append_mode= command==fmAppend;
  222.             scrivi_su_floppy();
  223.             }
  224.         else if(command==fmFormat){
  225.             disk_initialize();
  226.             }
  227.         }
  228.     }
  229. }
  230.  
  231. /**************** apri/chiudi archivio su file ***********/
  232.  
  233. void apri_archivio()        /* open a file archive */
  234. {
  235. long filesize;
  236. int nLF,forza_formato;
  237. FileParam fpb;
  238. Boolean not_ask_type,do_not_open;
  239. extern long file_date;
  240.  
  241. if(setjmp(main_loop)<0) {
  242.     return;
  243.     }
  244.  
  245. if(listonly){
  246.     SFTypeList    myTypes;
  247.     my_SF_Get(-1,myTypes);
  248.     if(!reply.good) return;
  249.     not_ask_type=true;
  250.     }
  251. else{
  252.     if(! get_file_with_checkbox(¬_ask_type)) return;
  253.     }
  254.  
  255. fpb.ioFVersNum = 0;
  256. fpb.ioFDirIndex = 0;
  257. fpb.ioVRefNum=reply.vRefNum;
  258. fpb.ioNamePtr=reply.fName;
  259. if (PBGetFInfoSync(&fpb)) pbsyserr(&fpb);
  260. filesize=fpb.ioFlLgLen;
  261. sectors_on_floppy= (filesize+511)>>9;
  262.  
  263. if(listonly){
  264.     disable_autoflush();
  265.     one_empty_line();
  266.     printf("File %p ",reply.fName);
  267.     printf("(data %ld+res %ld bytes)",fpb.ioFlLgLen,fpb.ioFlRLgLen);
  268. #if 0
  269. #define ALIAS_BIT 0x8000
  270.     if(fpb.ioFlFndrInfo.fdFlags & ALIAS_BIT) printf(" alias");    /* currently
  271.     that's useless, I'm using a non-custom standard file, which resolves aliases ! */
  272. #endif
  273.     printf("\n");
  274.     print_one_date(fpb.ioFlCrDat,in_Italia?"creato     ":"created  ");
  275.     printf("\n");
  276.     print_one_date(fpb.ioFlMdDat,in_Italia?"modificato ":"modified ");
  277.     printf("\n");
  278.     print_type_creator(fpb.ioFlFndrInfo.fdType,fpb.ioFlFndrInfo.fdCreator);
  279.     printf("\n");
  280.     enable_autoflush();
  281.     }
  282. else
  283.     one_empty_line();
  284.  
  285. pStrcpy(tarh.name,reply.fName);
  286. p2cstr(tarh.name);    /* these statements are useful only if the file is not */
  287. bar_archive=0;        /* a tar/bar archive */
  288.  
  289. /* tarh.mtime is examined later, nothing bad happens if it contains garbage
  290. but that's not good programming style */
  291. strcpy(tarh.mtime,"0");
  292. sect_n=0;
  293. end_of_file();    /* forse non necessario, ma prudente */
  294. copia_ultimo_header(&tarh,(sector_t)0);    /* gli devo passare il numero del
  295.                         settore successivo all'header */
  296.  
  297. if(filesize!=0 && !not_ask_type)
  298.     forza_formato=dialogo_tipo_file();
  299. else
  300.     forza_formato=0;
  301.  
  302. do_not_open=true;
  303. if(!forza_formato && fpb.ioFlFndrInfo.fdType=='APPL')
  304.     printf(in_Italia?"Applicazione\n":"Application\n");
  305. else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='INIT')
  306.     printf(in_Italia?"Estensione\n":"Extension\n");
  307. else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='cdev')
  308.     printf(in_Italia?"Pannello di controllo\n":"Control panel\n");
  309. else if(!forza_formato && (fpb.ioFlFndrInfo.fdType=='DFIL'||fpb.ioFlFndrInfo.fdType=='dfil'))
  310.     printf(in_Italia?"Accessorio di scrivania\n":"Desk Accessory\n");
  311. else if(filesize==0)
  312.     printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
  313. else
  314.     do_not_open=false;
  315. if(do_not_open){
  316.     if(!listonly) printf(in_Italia?"Questo tipo di file non puÿ essere aperto da suntar\n":
  317.         "This file type can\'t be opened by suntar\n");
  318.     return;
  319.     }
  320.  
  321. /* Open the file only now, and don't open files with empty data fork:
  322. Disk Doubler extracts the resource fork of compressed files if I do that,
  323. but that's time consuming and useless */
  324.  
  325. if(apri_file("rb",&inputFile))
  326.     return;
  327.  
  328. inf_is_open=true;
  329. file_aperto=ff_tarbar;
  330. file_current_s=-1;
  331.  
  332. if(forza_formato==ff_packit || forza_formato==0 && fpb.ioFlFndrInfo.fdType=='PIT '){
  333.     /* don't examine the creator, there is at least one program (unpit)
  334.     which creates PackIt files with another creator ('UPIT') */
  335.     if(listonly)
  336.         printf(in_Italia?"Archivio PackIt\n":"PackIt archive\n");
  337.     else{
  338.         select_directory();
  339.         if(reply.good){
  340.             file_date= -1;
  341.             one_empty_line();
  342.             printf(in_Italia?"Estrazione da archivio PackIt %s\n":
  343.                 "Unpacking PackIt archive %s\n", tarh.name);
  344.             my_unpit();
  345.             printf(in_Italia?FINITO:DONE);
  346.             fine_lavoro();
  347.             }
  348.         chiudi_archivio();
  349.         }
  350.     }
  351. else if(!forza_formato&&is_hqx_name()||forza_formato==ff_binhex){
  352.     macbinh.cdate=fpb.ioFlCrDat;
  353.     macbinh.mdate=fpb.ioFlMdDat;
  354. /*    dopo di che non deve essere chiamato chkmacbin, che scarabocchia su macbinh...*/
  355.  
  356.     file_aperto=ff_binhex;
  357.     fase=reading_disk;
  358.  
  359.     if(listonly)
  360.         untar_file(filesize);
  361.     else{
  362.         select_directory();
  363.         if(reply.good){
  364.             one_empty_line();
  365.             untar_file(filesize);
  366.             printf(in_Italia?FINITO:DONE);
  367.             fine_lavoro();
  368.             }
  369.         chiudi_archivio();
  370.         }
  371.     }
  372. else if((forza_formato==0 || forza_formato==ff_macbin||forza_formato==ff_c_macbin) &&
  373.         chkmacbin (filesize,forza_formato)){
  374.     file_aperto=ff_macbin;
  375.     fase=reading_disk;
  376.  
  377.     copia_ultimo_header(&tarh,(sector_t)0);
  378.     if(listonly)
  379.         untar_file(filesize);
  380.     else{
  381.         select_directory();    /* per la veritê, salvando un solo file potrei usare uno
  382.                         standard put, ma significherebbe fare modifiche pi¥
  383.                         pesanti di quanto non voglia
  384.                         --having only one file to save I could use SFPutFile, but
  385.                         the existing routines don't expect more than a destination 
  386.                         folder, and suntar was NOT meant as a file format converter,
  387.                         even if it can convert file formats, hence these commands
  388.                         are implemented according to the principle of "do that in
  389.                         the fewest statements with the fewest changes to existing
  390.                         routines"
  391.                         */
  392.         if(reply.good){
  393.             one_empty_line();
  394.             untar_file(filesize);
  395.             printf(in_Italia?FINITO:DONE);
  396.             fine_lavoro();
  397.             }
  398.         chiudi_archivio();
  399.         }
  400.     }
  401. else if(forza_formato==ff_macbin||forza_formato==ff_c_macbin)
  402.     error_message(in_Italia?"Formato non MacBinary\n":"Not a Macbinary file\n");
  403. else if(forza_formato==ff_ASCII||!forza_formato && isASCII(filesize,&nLF)>0  ){
  404.     file_aperto=ff_ASCII;
  405.     fase=reading_disk;
  406.  
  407.     if(listonly){
  408.         printf(in_Italia ?"Contenente testo ASCII":"Containing ASCII text");
  409.         if(nLF>0) printf(in_Italia?" con LF":" using LF");
  410.         printf("\n");
  411.         }
  412.     else if(nLF==0){
  413.         printf(in_Italia?"Testo ASCII in formato Macintosh, nessuna conversione\n":
  414.             "ASCII text in Macintosh format, no conversion\n");
  415.         chiudi_archivio();
  416.         }
  417.     else{
  418.         if(reply.fName[0]>63-4) reply.fName[0]=63-4;
  419.         pStrcat(reply.fName,"\p.out");
  420.         my_SF_Put(in_Italia?"\pSalva testo Mac col nome:":"\pSave Mac text as:",reply.fName);
  421.         if(reply.good){
  422.             register int i,j;
  423.             if(new_text_file(&info_file)==0){
  424.                 printf(in_Italia?"Converto %s in %p\n":"Converting %s to %p\n",tarh.name,reply.fName);
  425.                 info_file_open=1;
  426.                 while(filesize>0){
  427.                     if(filesize>=512L) i=512; else i= (int)filesize;
  428.                     filesize -= i;
  429.                     if(readblock(disk_buffer,i)!=0)
  430.                         error_message_1("Disk read error %d\n",err_code);
  431.                     for(j=0;j<512;j++)
  432.                         if(disk_buffer[j]==LF) disk_buffer[j]=CR;
  433.                     if(mac_fwrite(disk_buffer,i,info_file)<0)
  434.                         error_message("File write error!\n");
  435.                     }
  436.                 FSClose(info_file);
  437.                 info_file_open=0;
  438.                 }
  439.             else
  440.                 error_message(in_Italia?"Errore nell\'apertura del file\n":"Error opening file\n");
  441.             printf(in_Italia?FINITO:DONE);
  442.             fine_lavoro();
  443.             }
  444.         chiudi_archivio();
  445.         }
  446.     }
  447. else{    /* the file is opened as a tar/bar archive */
  448.     if(!listonly){
  449.         one_empty_line();
  450.         printf(in_Italia?"Apertura file %s\n":
  451.             "Opening file %s\n", tarh.name);
  452.         (void)identify_format();
  453.         /*printf("\n");*/
  454.         }
  455.     else
  456.         (void)identify_format();
  457.     }
  458. if(listonly){
  459.     chiudi_archivio();
  460.     /*printf("\n");*/
  461.     }
  462. }
  463.  
  464. void chiudi_archivio()
  465. {
  466. inf_is_open=false;
  467. file_aperto=0;
  468. FSClose(inputFile);
  469. }
  470.  
  471. /***************** copia da disco a file ******************/
  472.  
  473. void copia_da_disco_a_file()            /* copy a disk archive to a file archive */
  474. /* trasferisce quello che vede in un file tar, senza estrarre i singoli files */
  475. {
  476. sector_t more_sectors;
  477. short inPlace;
  478. Boolean fine;
  479. long length;
  480. int outputFile;
  481. static unsigned char nome_ita[]="\parchivio",  eng_name[]="\parchive";
  482.  
  483. listonly=0;    /* ad uso di floppy swap, le altre routines non le chiamo */
  484.  
  485. if(setjmp(main_loop)<0) {
  486.     FSClose(outputFile);    /* non lo metto in raise_error... */
  487.     return;
  488.     }
  489.  
  490. if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
  491.     "\pInsert the disk in UNIX format") || di.is_not_initialized){
  492.         FSClose(outputFile);
  493.         return;
  494.         }
  495.  
  496.  
  497. more_sectors=0;
  498.  
  499. fase=reading_disk;
  500. bar_archive= identify_format()==bar_format;
  501.  
  502. if(bar_archive){
  503.     if( my_atoi(((barh_type*)disk_buffer)->volume_num,&floppy_n)) floppy_n = -1;
  504.     if(floppy_n!=1) error_message(in_Italia?"Questo non Å il primo disco\n":
  505.         "That\'s not the first disk\n");
  506.     }
  507.  
  508. pStrcpy(disk_buffer,in_Italia?nome_ita:eng_name);
  509. pStrcat(disk_buffer,bar_archive?"\p.bar":"\p.tar");
  510.  
  511. my_SF_Put(in_Italia?"\pSalva col nome:":"\pSave as:",disk_buffer);
  512. if(!reply.good) return;
  513.  
  514. if(apri_file("wb",&outputFile)) return;
  515.  
  516. one_empty_line();
  517. printf(in_Italia?"Inizio lettura\n":START_READ);
  518.  
  519. if(!bar_archive)
  520.     tar_check_floppy_swap(1);    /* ci sono delle inizializzazioni */
  521. else{
  522.     leggi_settore(0,&disk_buffer);
  523.     if(check_error()) raise_error();
  524.     if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
  525.         beep_in_foreground();
  526.         error_message("Write error\n");
  527.         }
  528.     bar_check_floppy_swap(1);
  529.     }
  530.  
  531. leggi_settore(sect_n,&disk_buffer);
  532. if(check_error()) raise_error();
  533.  
  534. do{
  535.     if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
  536.         beep_in_foreground();
  537.         error_message("Write error\n");
  538.         }
  539.     check_events();
  540.     fine = more_sectors==0;        /* fine del file corrente 
  541.                                 -- end of current file ? */
  542.     if(fine){
  543.         fine= check_all_zero(disk_buffer);    /* fine dell'intero archivio
  544.                                         -- end of the archive ? */
  545.         if(!fine){
  546.             unsigned char linkflag = get_linkflag(&length);
  547.             last_offset=0;
  548.             copia_ultimo_header(disk_buffer,sect_n+1);    /* gli devo passare il numero del
  549.                         settore successivo all'header, da qui il +1 */
  550.             if(length<0)
  551.                 fine=true;
  552.             else{
  553.                 print_info(bar_archive?((barh_type*)disk_buffer)->name:disk_buffer,length);
  554.                 more_sectors=(length+511)/512;
  555.                 }
  556.             }
  557.         }
  558.     else
  559.         more_sectors--;
  560.  
  561.     if(!fine){
  562.         sect_n++;
  563.         if(bar_archive)
  564.             bar_check_floppy_swap(more_sectors==0?-1:0);
  565.         else
  566.             tar_check_floppy_swap(more_sectors==0?-1:0);
  567.         leggi_settore(sect_n,&disk_buffer);
  568.         if(check_error()) raise_error();
  569.         }
  570.     }
  571. while(!fine);
  572.  
  573. one_empty_line();
  574. printf(in_Italia ? "Lettura completata\n" : "Read completed\n");
  575. diskEject();
  576. FSClose(outputFile);
  577. fine_lavoro();
  578. }
  579.  
  580. /***************** estrai da floppy ******************/
  581.  
  582. void estrai_da_floppy()        /* extract or list */
  583. {
  584. enum formats fmt;
  585.  
  586. if(setjmp(main_loop)<0) {
  587.     return;
  588.     }
  589.  
  590. if(!listonly){
  591.     select_directory();
  592.     if(!reply.good) return;
  593.     }
  594.  
  595. if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
  596.     "\pInsert the disk in UNIX format") ||di.is_not_initialized) return;
  597. one_empty_line();
  598. printf(in_Italia?"Inizio lettura\n":START_READ);
  599.  
  600. disco_espulso=!listonly;    /* per un extract non mi interessa impedire di espellere... */
  601. fase=reading_disk;
  602.  
  603. fmt=identify_format();
  604. if(fmt==tar_format)
  605.     my_untar();
  606. else if(fmt==bar_format)
  607.     my_unbar();
  608.  
  609. if(disco_espulso) diskEject();
  610. fine_lavoro();
  611. }
  612.  
  613.  
  614. /************ scrivi su floppy ******************/
  615.  
  616.  
  617. void scrivi_su_floppy()        /* handling of the Write menu */
  618. {
  619. Boolean ok_to_proceed;
  620.  
  621. if(setjmp(main_loop)<0) {
  622.     return;
  623.     }
  624.  
  625. ok_to_proceed=false;
  626. do{
  627.     if(aspetta_inserzione(in_Italia?"\pInserisci il disco su cui scrivere":
  628.         "\pInsert the disk to be written")) return;
  629.  
  630.     if(is_wrprot()){
  631.         printf_protetto();
  632.         SysBeep(5);
  633.         return;
  634.         }
  635.  
  636.     if(di.is_not_initialized){
  637.         disk_format(false);
  638.         if(drive_number==0 && append_mode) return;
  639.         }
  640.     else
  641.         ok_to_proceed=true;
  642.     }
  643. while(!ok_to_proceed);
  644.  
  645. warning_400_800();
  646.  
  647. leggi_settore(0,&disk_buffer);    /* serve come controllo di errore, e poi non so,
  648.                             potrebbe essere utile per la faccenda del TagBuffer */
  649. if(check_error())return;
  650.  
  651. fase=reading_disk;
  652.  
  653. reset_sector_count();
  654. one_empty_line();
  655. if(append_mode){
  656.     cerca_fine();
  657.     }
  658. else
  659.     printf(in_Italia?"Nuovo archivio %car\n":"New %car archive\n",bar_archive?'b':'t');
  660.  
  661. for(;;){
  662.     unsigned char itemname[32];
  663.     fase=in_writing;
  664.     print_ready();
  665.     settori_passati=0;
  666.     EnableItem(writeMenu, 0);
  667.     GetIndString (itemname,128,bar_archive?2:1);
  668.     SetItem (writeMenu,wmWriteTar,itemname);
  669.  
  670.     DrawMenuBar();
  671.     close_all_open_WD();
  672.     check_ev_timing=120;
  673.     flush_buffers();
  674.     last_selection=0;
  675.     while(last_selection==0)
  676.         MainEvent();
  677.     DisableItem(writeMenu, 0);
  678.     DrawMenuBar();
  679.  
  680.     if(last_selection==menuItemMess(fileID,fmAbort)||
  681.        last_selection==menuItemMess(writeID,wmEndWrite)||
  682.        last_selection==menuItemMess(fileID,fmEject) ){
  683.         if(last_selection!=menuItemMess(writeID,wmEndWrite)) diskEject();
  684.         return;
  685.         }
  686.     else if(hiword(last_selection)==writeID){
  687.         my_tar(loword(last_selection));
  688.         fine_lavoro();
  689.         }
  690.     /* non ci sono altri men¥ attivi: in principio pensavo di lasciare il List 
  691.     (senza espellere!) ma non serve, man mano che scrivo files sulla console
  692.     vengono scritti i nomi ! */
  693.     }
  694. }
  695.  
  696.  
  697. void disk_initialize()
  698. {
  699. short inPlace;
  700. int i;
  701.  
  702. fase=initializing;
  703.  
  704. i=aspetta_inserzione(in_Italia ? "\pInserisci il disco da inizializzare":
  705.     "\pInsert the disk to be initialized");
  706.  
  707. i=testa_stato(&inPlace,0);
  708. if(i!=0 || !inPlace){
  709.     diskEject();
  710.     return;
  711.     }
  712. if(is_wrprot()){
  713.     printf_protetto();
  714.     SysBeep(5);
  715.     return;
  716.     }
  717. if(warning_first_write(1)<0){
  718.     diskEject();
  719.     return;
  720.     }
  721.  
  722. disk_format(crea_mac_dir);
  723. if(drive_number){
  724.     if(testa_stato(&inPlace,1)){
  725.         diskEject();
  726.         }
  727.     }
  728. }
  729.  
  730.  
  731. /*************************************************/
  732.  
  733. enum formats identify_format()
  734. /* asks to the device driver about the current disk, than examines the
  735. first sectors to see whether it's a tar or bar archive */
  736. {
  737. int i;
  738. sector_t j;
  739. #define SUPERDRIVE    4
  740.  
  741. leggi_settore(0,disk_buffer);
  742. if(err_code<0){
  743.     SysBeep(5);
  744.     if(file_aperto){
  745.         if(err_code==eofErr)
  746.             printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
  747.         else
  748.             printf("File access error %d\n",err_code);
  749.         }
  750.     else if( drive_number<=4 && (i=drive_type[drive_number-1]&0x0F)!= SUPERDRIVE &&
  751.         i!= SUPERDRIVE+1){
  752.         printf(in_Italia ? "Disco non inizializzato o in formato 720/1440K\n" : 
  753.             "The disk is either uninitialized or 720/1440K\n");
  754.         printf(in_Italia ? "Prova a inserirlo in un Superdrive" :
  755.             "Try to insert it in a SuperDrive");
  756.         if(n_superdrives==0)
  757.             printf(in_Italia?" (su un Macintosh che ce l\'abbia)":
  758.             " (on a Macintosh which has one)");
  759.         printf("\n");
  760.         }
  761.     else if(di.is_not_initialized)
  762.         printf(in_Italia ? "Disco non inizializzato\n" :
  763.             "The disk is not initialized\n");
  764.     else
  765.         printf(in_Italia ? "Disco illeggibile\n" :
  766.             "The disk is unreadable\n");
  767.  
  768.     return unreadable_disk;
  769.     }
  770. previousFormat=tar_unknown;
  771. i = tar_check_settore0(false);
  772. if(i>=0){
  773.     if(previousFormat==tar_GNU)
  774.         printf(in_Italia ? "Archivio in formato GNU tar\n" : "GNU tar archive\n");
  775.     else
  776.         printf(in_Italia ? "Archivio in formato tar\n" : "Tar archive\n");
  777.     return tar_format;
  778.     }
  779. i= bar_check_settore0(&j,false);
  780. if(i>=0){
  781.     printf(in_Italia ? "Archivio in formato bar\n" : "Bar archive\n");
  782.     return bar_format;
  783.     }
  784. else{
  785. /* I controlli fatti da quelle routines sono rigorosi, basta che il checksum 
  786. sia sbagliato...  non vorrei solo per quello perdere ogni
  787. possibilitê di esaminare il disco, la vecchia versione non Å affatto rigida in
  788. proposito e neanche la nuova lo Å per gli altri header, quindi faccio una 
  789. discriminazione molto pi¥ approssimativa, tanto my_untar e my_unbar poi hanno
  790. dei controlli di errore */
  791.  
  792.     if(((barh_type*)disk_buffer)->bar_magic[0]== 'V' && 
  793.         untar_number(((barh_type*)disk_buffer)->volume_num,-1)!=-1){
  794.         printf(in_Italia ? "Archivio in probabile formato bar\n" : "It looks like a bar archive\n");
  795.            return bar_format;
  796.            }
  797.     else if(untar_number(((tarh_type*)disk_buffer)->size,-1)!=-1 && 
  798.         untar_number(((tarh_type*)disk_buffer)->mtime,-1)!=-1){
  799.         printf(in_Italia ? "Archivio in probabile formato tar\n" : "It looks like a tar archive\n");
  800.          return tar_format;
  801.          }
  802.     else{
  803.         if(fase!=hack_listing){
  804.             SysBeep(5);
  805.             disable_autoflush();
  806.             if(file_aperto)
  807.                 printf(in_Italia ? "Il file" : "The file");
  808.             else
  809.                 printf(in_Italia ? "Il disco" : "The disk");
  810.             printf(in_Italia ? " non Å in formato tar nÄ bar" : 
  811.                 " format is neither tar nor bar");
  812.             if(!file_aperto&&tar_version==tar_AIX)
  813.                 printf(in_Italia?" (ma potrebbe essere un disco tar oltre il primo)":
  814.                     " (but it could be a tar disk following the first one)");
  815.             printf("\n");
  816.             enable_autoflush();
  817.             }
  818.         return unknown_format;
  819.         }
  820.     }
  821. }
  822.  
  823.  
  824. /***************** apri file *********************/
  825.  
  826. short apri_file(modo,who)        /* opens a file */
  827. char *modo;
  828. int *who;
  829. {
  830. int io;
  831.  
  832. reply.fName[reply.fName[0]+1]='\0';    /* per il caso debba fare una printf...*/
  833. /* SetVol(NULL,reply.vRefNum);  setta la directory: inutile */
  834.  
  835. if(modo[0]=='r')
  836.     io=FSOpen (reply.fName, reply.vRefNum, who);
  837. else if(modo[0]=='w')
  838.     if(bar_archive)
  839.         io=create_overwrite(bar_creator, bar_type, who);
  840.     else
  841.         io=create_overwrite(tar_creator, 'TARF', who);
  842. if(io!=noErr) {
  843.     start_of_line();
  844.     printf("failure opening %p\n",reply.fName);
  845.     return -1;
  846.     }
  847. return 0;
  848. }
  849.  
  850. OSErr new_text_file(outputFile)        /* creates and opens a text file */
  851. int *outputFile;
  852. {
  853. int io;
  854. /* SetVol(NULL,reply.vRefNum); setta la directory: inutile e pericoloso */
  855.  
  856. return create_overwrite(text_creator, 'TEXT',outputFile);
  857. }
  858.  
  859. OSErr create_overwrite(c,t,who)
  860. OSType t,c;
  861. int *who;
  862. {
  863. OSErr io;
  864. io=Create(reply.fName, reply.vRefNum, c, t);
  865. if (io==noErr)
  866.     io = FSOpen( reply.fName, reply.vRefNum, who );
  867. else if(io==dupFNErr){
  868.     io = open_overwrite( reply.fName, reply.vRefNum, who );
  869.     if(io==noErr){
  870. /* settare tipo e creatore: certo se il file esiste giê dovrebbero
  871. essere gli stessi, ma meglio non fidarsi !
  872. -- type and creator must be modified
  873. */
  874.         FileParam fpb;
  875.         fpb.ioFVersNum = 0;
  876.         fpb.ioFDirIndex = 0;
  877.         fpb.ioVRefNum=reply.vRefNum;
  878.         fpb.ioNamePtr= &reply.fName;
  879.         if (PBGetFInfoSync(&fpb)==noErr){
  880.             fpb.ioFlFndrInfo.fdType=t;
  881.             fpb.ioFlFndrInfo.fdCreator=c;
  882.             PBSetFInfoSync(&fpb);
  883.             }
  884.         }
  885.     }
  886. return io;
  887. }
  888.  
  889. int mac_fread(buff,nbytes,refNum)
  890. char *buff;
  891. {
  892. long count = nbytes;
  893. if( (err_code=FSRead( refNum, &count, buff )) != noErr){
  894.     if(err_code==eofErr && count!=0){
  895.         fillmem(&buff[count],0,512-(int)count);
  896.         err_code=noErr;
  897.         }
  898.     else
  899.         return -1;
  900.     }
  901. return (int) count;
  902. }
  903.  
  904. int mac_fwrite(buff,nbytes,refNum)
  905. char *buff;
  906. {
  907. long count=nbytes;
  908. if( FSWrite( refNum, &count, buff ) != noErr )
  909.     return -1;
  910. return (int)count;
  911. }
  912.  
  913. OSErr open_overwrite (fileName,vRefNum,refnum)
  914. /* apre la data fork del file, tagliando a zero bytes sia questa sia la
  915. resource fork
  916. -- opens the file data fork, truncating it and the resource fork to zero length
  917. */
  918. char *fileName;
  919. int *refnum;
  920. {
  921. short i = FSOpen(fileName,vRefNum, refnum);
  922. if(i==noErr){
  923.     SetEOF(*refnum,0L);
  924.     if( OpenRF (fileName,vRefNum,&i)==noErr){
  925.         SetEOF(i,0L);
  926.         FSClose(i);
  927.         }
  928.     i=noErr;
  929.     }
  930. return i;
  931. }
  932.  
  933. /**************** gestione eventi durante le operazioni ************/
  934.  
  935. Boolean my_disk_is_in()
  936. {
  937. /* Called before exiting from a pause: checks whether the disk is where is
  938. expected, and if there are some obvious reasons to believe it's not the
  939. expected disk
  940. */
  941. static char s1[]="Disco cambiato !\n",
  942.     s2[]="Changed disk !\n";
  943.     {
  944.     short inPlace;
  945.     sector_t old_s=sectors_on_floppy;
  946.     if (testa_stato(&inPlace,0) || !inPlace){
  947.         printf(in_Italia?"Disco assente !\n" : "Missing disk !\n");
  948.         return false;
  949.         }
  950.     if(sectors_on_floppy!=old_s){
  951.         sectors_on_floppy=old_s;
  952.         printf(in_Italia?s1:s2);
  953.         return false;
  954.         }
  955.     sectors_on_floppy=old_s;
  956.     }
  957.     {
  958.     char buffer[512];
  959.     int refnum;
  960.     long space;
  961.     enum os_type i;
  962.     if( GetVInfo (drive_number, buffer, &refnum,&space) == nsvErr ) return true;
  963.          /* no such volume: a non-Mac disk is not mounted hence...*/
  964.     read_one_sector(2,buffer,drive_number);
  965.     if(!err_code) i=riconosci_disco_mac(buffer);
  966.     if(err_code || i!=mac_HFS&&i!=mac_MFS){
  967.         UnmountVol (NULL,drive_number);    /* however, 
  968.              in some cases (see comments to de_Mac_ize) it's mounted, at least if
  969.              suntar is not in foreground */;
  970.         return true;
  971.         }
  972.     printf(in_Italia?s1:s2);
  973.     return false;
  974.     }
  975. }
  976.  
  977. void handle_pause()
  978. {
  979.     enum tipo_fase old=fase;
  980.     extern DialogPtr ListDialog;
  981.     fase=paused;
  982.     last_selection=0;
  983.  
  984.     if(my_windows[0].used) SetWTitle (&my_windows[0],in_Italia?"\p<< in pausa >>":"\p<< paused >>");
  985.     {unsigned char itemname[32];
  986.     GetIndString(itemname,129,4);
  987.     SetItem (myMenus[fileM], fmPause, itemname);
  988.     }
  989.     if(dirty_buffers()) flush_buffers();
  990.  
  991.     while(last_selection!=menuItemMess(fileID,fmPause) && 
  992.           last_selection!=menuItemMess(fileID,fmAbort)){
  993.         MainEvent();    /* be', non tutti
  994.             i filtri ha senso chiamarli anche durante un pause, ma in realtê
  995.             il pause non Å attivo durante i filtri che "lavorano" come
  996.             quello del disk insertion, restano solo quelli dei dialoghi che
  997.             vanno chiamati perchÄ gestiscono gli update
  998.             --not all filters must continue to be called during a pause,
  999.             but when pause is enabled some filters are not used, and the
  1000.             filters of semimodal and of the selection dialog must be called
  1001.             during pauses
  1002.             */
  1003.         if(last_selection==menuItemMess(fileID,fmPause) && drive_number && !my_disk_is_in() ){
  1004.             last_selection=0;
  1005.             }
  1006.         }
  1007.     if(last_selection==menuItemMess(fileID,fmPause)) last_selection=0;
  1008.     {unsigned char itemname[32];
  1009.     GetIndString(itemname,129,3);
  1010.     SetItem (myMenus[fileM], fmPause, itemname);
  1011.     }
  1012.     if(my_windows[0].used) SetWTitle (&my_windows[0],window_title);
  1013.     fase=old;
  1014. }
  1015.  
  1016. Boolean check_filter(EventRecord *);
  1017. static Boolean check_filter(theEvent)
  1018. /* event filter used while suntar is working: most events are ignored
  1019. without being handled
  1020. */
  1021. EventRecord *theEvent;
  1022. {
  1023. switch(theEvent->what){
  1024. case keyDown:
  1025.     if(theEvent->modifiers&cmdKey) break;    /* se accetta la selezione men¥ deve
  1026.                                             accettare anche i command-tasto */
  1027.     /* else prosegui in sequenza 
  1028.     -- else, since there is no break, continue with the following instruction */
  1029. case autoKey:
  1030.     return false;    /* the event must not be handled */
  1031.     break;
  1032. case mouseDown:
  1033.     {
  1034.     WindowPtr        whichWindow;
  1035.     int code=FindWindow( theEvent->where, &whichWindow );
  1036.     if(code!=inMenuBar && code!=inSysWindow && code!=inDrag &&
  1037.         code!=inGrow && whichWindow==FrontWindow())
  1038.         return false;
  1039.     else
  1040.         SetCursor(&arrow);
  1041.     }
  1042.     break;
  1043. }
  1044. return true;
  1045. }
  1046.  
  1047.  
  1048. void check_events()
  1049. /* handle the events which are allowed while suntar is working, including
  1050. the Pause command
  1051. */
  1052. {
  1053. EventRecord        myEvent;
  1054.  
  1055. /* We've discovered that, in typical file extractions, check_events occupied up
  1056. to 35% of processing time, even if no event was pending. Hence, events must be
  1057. checked less often, but with care, otherwise suntar would lose its feel (it's
  1058. good to be able to change preferences on the fly, and while it's working in
  1059. background one does not like to notice a huge speed difference in the foreground
  1060. application) */
  1061.  
  1062. ++check_ev_timing;
  1063. if( check_ev_timing< (gInBackground?back_prio:(fase!=reading_disk&&fase!=hack_listing||
  1064.     !listonly)?18:3) ){
  1065.     EventRecord        myEvent;
  1066.     if((check_ev_timing&1) || !OSEventAvail(everyEvent,&myEvent))
  1067.         return;
  1068.     }
  1069. check_ev_timing=0;
  1070.  
  1071. if(last_selection!=menuItemMess(fileID,fmPause)){
  1072.     sto_lavorando=true;
  1073.  
  1074.     /* what follows is the body of MainEvent, with an extra call in order to ignore
  1075.     all the events which are not urgent */
  1076.  
  1077.     if(get_event(&myEvent)){
  1078.         if(check_filter(&myEvent)){
  1079.             if(my_event_filter!=NULL) (*my_event_filter)(&myEvent);
  1080.             handle_event(&myEvent);
  1081.             }
  1082.         }
  1083.     sto_lavorando=false;
  1084.     }
  1085. if(last_selection==menuItemMess(fileID,fmPause))
  1086.     handle_pause();
  1087. accept_abort_command();
  1088. }
  1089.  
  1090. short check_error_and_events()
  1091. {
  1092. /* in theory it's:
  1093. if(check_error()) return -1;
  1094. check_events();
  1095. return 0;
  1096. in practice, it was extended to transform a "missing disk" error to a pause,
  1097. so you (and we) won't lose your work for an unwanted eject (it happened to us
  1098. for a 4Megabytes file, filling 3 disks, and we had to start again after
  1099. half an hour of work in background). But the caller must read the sector again,
  1100. hence a new return code of 1
  1101. */
  1102. if(err_code!=-65){
  1103.     if(check_error()) return -1;
  1104.     check_events();
  1105.     return 0;
  1106.     }
  1107. else{
  1108.     beep_in_foreground();
  1109.     start_of_line();
  1110.     printf(in_Italia?"Disco assente, pausa forzata\n":"Missing disk, a pause was forced\n");
  1111.     last_selection=menuItemMess(fileID,fmPause);
  1112.     check_events();
  1113.     return 1;
  1114.     }
  1115. }
  1116.  
  1117. void accept_abort_command()
  1118. {
  1119. if(last_selection == menuItemMess(fileID,fmAbort)){
  1120.     one_empty_line();
  1121.     error_message(in_Italia?"Comando abortito\n":"Command aborted\n");
  1122.     }
  1123. }
  1124.  
  1125. Boolean is_abort_command()
  1126. /* external routines must not know how I receive the Abort command,
  1127. but they must be able to know when they must abort themselves */
  1128. {
  1129. return last_selection == menuItemMess(fileID,fmAbort);
  1130. }
  1131.  
  1132. Boolean is_pause_command()
  1133. {
  1134. return last_selection == menuItemMess(fileID,fmPause);
  1135. }
  1136.  
  1137. /****************** gestione dialogo di inserzione *********/
  1138.  
  1139. int filter_insert(EventRecord*);
  1140. static int filter_insert(theEvent)
  1141. EventRecord*theEvent;
  1142. {
  1143. if(theEvent->what==diskEvt){
  1144.     drive_number=loword(theEvent->message);
  1145.  
  1146.     if(drive_number<=last_drive){
  1147.         /*FlushVol (PNS,drive_number);*/
  1148.         UnmountVol (NULL,drive_number); /* smonta qualunque 
  1149.         cosa si trovasse in precedenza in quel drive, e il disco stesso se Å stato
  1150.         montato: inutile guardare al codice di errore ritornato
  1151.         -- the Finder often mounts even a tar archive, if it was formatted on a Mac
  1152.         (see de_Mac_ize in tar.c): anyway, it must not be mounted if I want to use 
  1153.         it without being disturbed by the Finder; the returned error code may be 
  1154.         ignored, I don't worry to call this only when it was mounted...
  1155.         */
  1156.         }
  1157.     return -1;
  1158.     }
  1159. else if(drive_number)    /* the user may call the about_box, but about_box does
  1160.     not delay the handling of disk insertions (as options_box does), hence it's
  1161.     possible that the disk insertion event was handled by unexpected_disk_insertion */
  1162.     return -1;
  1163. return 0;
  1164. }
  1165.  
  1166. /************* aspetta inserzione **************/
  1167.  
  1168. short aspetta_inserzione(message)
  1169. /* if a file or disk is already open, return immediately; otherwise,
  1170. present the disk insertion dialog and update all the status informations
  1171. about the current disk
  1172. */
  1173. char*message;
  1174. {
  1175. int inPlace;
  1176.  
  1177. if(drive_number!=0){
  1178.     if(testa_stato(&inPlace,0)==0){
  1179.         if(inPlace){
  1180.             if(di.is_not_initialized)
  1181.                 printf(in_Italia?"Disco non inizializzato\n":"This disk is not initialized\n");
  1182.             return 0;
  1183.             }
  1184.         }
  1185.     else
  1186.         drive_number=0;
  1187.     }
  1188. else if(file_aperto){
  1189.     di.is_write_protected=false;
  1190.     di.is_not_initialized=false;
  1191.     di.os=unknown_os;
  1192.     di.disk_code=noMacDskErr;
  1193.     return 0;
  1194.     }
  1195.  
  1196. if(preferred_drive){
  1197. /* if there only one disk drive, or only one is a SuperDrive, eject anything
  1198. was currently in that drive, since it's the only place where the user may insert
  1199. the requested disk. But don't do that if a disk insertion on that drive has just
  1200. happened
  1201. */
  1202.     EventRecord event;
  1203.  
  1204.     drive_number=preferred_drive;
  1205.  
  1206.     if ( !OSEventAvail(diskMask,&event) || drive_number!=loword(event.message)){
  1207.         /*FlushVol (PNS,drive_number);*/
  1208.         UnmountVol (NULL,drive_number);    /* inutile guardare al codice di errore ritornato */
  1209.         diskEject();
  1210.         }
  1211.     }
  1212.  
  1213. {static Point wPos={-1,-1};
  1214. char*p="\pAnnulla";
  1215.  
  1216. if(semimodalDialog(138,&wPos,filter_insert,&p,1,
  1217.     message,in_Italia?"\p\r\rin un disk drive":"\p\r\rin a floppy disk drive",NULL,
  1218.     teJustCenter,fase==ricevuto_comando||fase==initializing)==-1){
  1219.     if(testa_stato(&inPlace,1)){
  1220.         if(fase==initializing) return 0;
  1221.         diskEject();
  1222.         return -1;
  1223.         }
  1224.     return 0;    /* disco inserito OK */
  1225.     }
  1226.  
  1227. return -1;
  1228. }
  1229. }
  1230. /*************************************************/
  1231.  
  1232. void check_foreground()
  1233. {
  1234. /* to be called before interacting with the user when I could be 
  1235. running in background: if I am, call the Notification Manager to alert
  1236. the user and wait for him/her to bring this application to foreground
  1237. */
  1238.  
  1239. if(gInBackground){
  1240.     NMRec my_notif_rec;
  1241.  
  1242.     my_notif_rec.qType=8;
  1243.     my_notif_rec.nmMark=1;
  1244. #if 1
  1245.     my_notif_rec.nmSIcon=GetResource ('SICN',128);
  1246. #else
  1247.     /* with another version of header files, it's */
  1248.     my_notif_rec.nmIcon=GetResource ('SICN',128);
  1249. #endif
  1250.     my_notif_rec.nmSound=(void*)-1;
  1251.     my_notif_rec.nmStr=NULL;
  1252.     my_notif_rec.nmResp=NULL;
  1253.     NMInstall(&my_notif_rec);
  1254.     while(gInBackground)
  1255.         MainEvent();
  1256.     NMRemove(&my_notif_rec);
  1257. #if 1
  1258.     ReleaseResource(my_notif_rec.nmSIcon);
  1259. #else
  1260.     ReleaseResource(my_notif_rec.nmIcon);
  1261. #endif
  1262.     }
  1263. settori_passati=0;
  1264.  
  1265. }
  1266.  
  1267. void beep_in_foreground()
  1268. {
  1269. if(gInBackground)
  1270.     check_foreground();        /* which does a beep */
  1271. else
  1272.     SysBeep(5);
  1273. }
  1274.  
  1275.  
  1276. /***********************/
  1277.  
  1278. void update_about_box(EventRecord*);
  1279. static void update_about_box(theEvent)
  1280. EventRecord *theEvent;
  1281. {
  1282. WindowPtr theWindow=(WindowPtr)theEvent->message;
  1283. static Rect
  1284.     boundsR1={10,105,30,475},
  1285.     boundsR2={40,130,140,475},
  1286.     boundsR3={148,5,285,300},
  1287.     dstRect1={5,5,129,129},
  1288.     dstRect2={148,288,258,476};
  1289. Handle h;
  1290. GrafPtr    savePort;
  1291. char*p;
  1292.  
  1293. GetPort( &savePort );
  1294. SetPort(theWindow);
  1295. BeginUpdate( theWindow );
  1296.  
  1297. TextFont(3);
  1298. TextSize(12);
  1299. p="suntar 1.3";
  1300.  
  1301. TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
  1302. TextFont(4);
  1303. TextSize(9);
  1304.  
  1305. if(in_Italia) p=
  1306. "Suntar Å il mezzo pi¥ semplice ed economico di comunicare\r\
  1307. dati tra un Macintosh (dotato di SuperDrive) e un sistema\r\
  1308. UNIX (con un drive per floppy disk da 3,5 pollici):\r\
  1309. legge e scrive dischetti in formato tar UNIX, convertendo\r\
  1310. automaticamente i files di testo e i formati MacBinary e\r\
  1311. BinHex 4.0, usati negli archivi di pubblico dominio per\r\
  1312. immagazzinare files Macintosh in files UNIX.\r\
  1313. Sotto System 7, puoi usare gli aiuti a fumetti.";
  1314. else
  1315. p=
  1316. "Suntar is the simplest and cheapest way to communicate\r\
  1317. data between a Macintosh (with a SuperDrive) and a UNIX\r\
  1318. machine (with a 3.5 inch floppy disk drive): it reads\r\
  1319. and writes disks in the UNIX tar format, automatically\r\
  1320. converting plain text files and the MacBinary and\r\
  1321. BinHex 4.0 formats, used in public domain archives to\r\
  1322. store Macintosh files in UNIX files.\r\
  1323. Under System 7, help balloons are available.";
  1324.  
  1325. TextBox(p,(long)strlen(p),&boundsR2,teJustRight);
  1326.  
  1327. if(in_Italia) p=
  1328. "suntar Å un programma freeware\r\
  1329. ⌐ 1991-92 Sauro e Gabriele Speranza\r\
  1330. Indirizzo: Sauro Speranza via Cappuccini 18\r\
  1331.            40026 Imola (Bo)\r\
  1332. E-mail: speranza@cirfid.unibo.it\r\
  1333. oppure: speranza@cs.unibo.it\r\
  1334. Porzioni del programma sono ⌐ Gail Zacharias,\r\
  1335. Symantec, Apple Computer, Allan Weber.\r\
  1336. Scritto in Think C 4.0.5 (⌐ 1989-91\r\
  1337.      Symantec Corporation)";
  1338. else p=
  1339. "suntar is a freeware program\r\
  1340. ⌐ 1991-92 Sauro and Gabriele Speranza\r\
  1341. Address: Sauro Speranza via Cappuccini 18\r\
  1342.          40026 Imola Italy\r\
  1343. E-mail: speranza@cirfid.unibo.it\r\
  1344.     or: speranza@cs.unibo.it\r\
  1345. Portions of suntar are ⌐ Gail Zacharias,\r\
  1346. Symantec, Apple Computer, Allan Weber.\r\
  1347. Written in Think C 4.0.5 (⌐ 1989-91\r\
  1348.      Symantec Corporation)";
  1349.  
  1350. TextBox(p,(long)strlen(p),&boundsR3,teJustLeft);
  1351.  
  1352. h=GetResource ('PICT',128);
  1353. HLock(h);
  1354. DrawPicture (h, &dstRect1);
  1355. ReleaseResource(h);
  1356. h=GetResource ('PICT',129);
  1357. HLock(h);
  1358. DrawPicture (h, &dstRect2);
  1359. ReleaseResource(h);
  1360.  
  1361. EndUpdate( theWindow );
  1362. SetPort (savePort);
  1363.  
  1364. }
  1365.  
  1366. void about_box()
  1367. {
  1368. static Rect
  1369.     winRect={0,0,265,480};
  1370. WindowPtr theWindow;
  1371. short stato=0;
  1372. EventRecord        myEvent;
  1373. enum tipo_fase old_fase=fase;
  1374.  
  1375. if(dirty_buffers()) flush_buffers();
  1376. PositionDialog(&winRect);
  1377. theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, -1L, 0, (long)-1);
  1378. ((WindowPeek)theWindow)->refCon= -3;
  1379.  
  1380. install_handlers(theWindow, update_about_box, NULL);
  1381. while(stato!=2){
  1382.     sto_lavorando=false;    /* cursor shape and delay for WaitNextEvent... */
  1383.     fase=paused;            /* for unexpected_disk_insertion */
  1384.     if(get_event(&myEvent)){
  1385.         if(myEvent.what==diskEvt){
  1386.             int olddrive=drive_number;
  1387.             unexpected_disk_insertion(myEvent.message);
  1388.             if(olddrive!=drive_number) break;
  1389.             }
  1390.         else if(myEvent.what==mouseDown)
  1391.             stato=1;
  1392.         else if(stato==1&&myEvent.what==mouseUp)
  1393.             stato=2;
  1394.         /* all other events are ignored: that's anyway a progress upon the 1.1 version, 
  1395.         which never called GetNextEvent during the about box (background tasks and 
  1396.         even screen savers were disabled...) */
  1397.         }
  1398.     }
  1399.  
  1400. remove_handlers(theWindow);
  1401. DisposeWindow(theWindow);
  1402. fase=old_fase;
  1403. /*Riattiva();*/
  1404. }
  1405.  
  1406.  
  1407. /************* check all zero **********/
  1408.  
  1409. Boolean check_all_zero(buffer)
  1410. char *buffer;
  1411. {
  1412. register int    i=512/sizeof(long);
  1413. register long    n_or=0;
  1414. register long*    p= (long*) &buffer[0];
  1415.  
  1416. while(--i>=0 &&  (n_or|= *p++) ==0L)
  1417.     ;
  1418. return n_or==0L;
  1419. }
  1420.  
  1421. /************************/
  1422.  
  1423. void print_info(name,length)
  1424. char *name;
  1425. long length;
  1426. {
  1427. if(name[strlen(name)-1]=='/')
  1428.     printf("Directory %s\n",name);
  1429. else
  1430.     printf("File %s (%ld bytes)\n",name,length);
  1431. }
  1432.  
  1433. /*****************************/
  1434.  
  1435. void raise_error()
  1436. {
  1437. /* prima di riprendere, chiamo tutte le routine di "cleanup", che ovviamente
  1438. se non c'Å niente da chiudere ritornano senza fare niente
  1439. -- in suntar, all high level routines must use a setjmp to handle
  1440. recovering after an error. All permanent entities (variables, files, windows)
  1441. which need to be closed or restored to the normal state must declare a clean-up 
  1442. routine (which does nothing if no clean-up is needed) and that routine must 
  1443. be called here (beware, there's also a raise_hqx_error, which aborts the
  1444. extraction of the current file but not the command)
  1445. */
  1446. SetCursor(&waitCursor);    /* closing files may flush the disk cache, and that
  1447.             may take several seconds */
  1448. deall_tree();
  1449.  
  1450. if(drive_number && dirty_buffers()){
  1451.     int refnum;
  1452.     long space;
  1453.     if( GetVInfo (drive_number, disk_buffer, &refnum,&space) == nsvErr ){
  1454.         /* no such volume: a non-Mac disk is not mounted hence...*/
  1455.         flush_buffers();
  1456.         }
  1457.     else
  1458.         invalid_buffers();
  1459.     }
  1460.  
  1461. check_and_eject();
  1462. my_event_filter=NULL;
  1463. last_selection=0;
  1464. sto_lavorando=false;
  1465. close_input_files();
  1466. close_or_del_out_file();
  1467. close_info_file();
  1468. enable_autoflush();
  1469. close_semimodal();
  1470. FlushEvents( everyEvent, 0 );
  1471. longjmp(main_loop,-1);
  1472. }
  1473.  
  1474. void error_message(p)
  1475. char *p;
  1476. {
  1477. start_of_line();
  1478. printf(p);
  1479. raise_error();
  1480. }
  1481.  
  1482.  
  1483. void error_message_1(p,n)
  1484. char *p;
  1485. {
  1486. start_of_line();
  1487. printf(p,n);
  1488. raise_error();
  1489. }
  1490.  
  1491. /************************/
  1492. short check_error()
  1493. {
  1494. /* da chiamare esclusivamente dopo leggi_settore
  1495. -- to be called after leggi_settore */
  1496. if(err_code){
  1497. /* e se invece riprovassi a leggere ? Non Å che il disk driver ritenti giê lui? */
  1498.     start_of_line();
  1499.     if(err_code==-39 || file_aperto && err_code==-81)
  1500.         printf(in_Italia?"Fine del file prematura\n":"Error: unexpected end of file\n");
  1501.     else if(err_code==-65)
  1502.         printf(in_Italia?"Errore: disco assente\n" : "Error: missing disk\n");
  1503.     else if(err_code<=-66 && err_code>=-71)
  1504.         printf(in_Italia?"Settore illeggibile (codice err=%d)\n": 
  1505.             "Unreadable sector (err code= %d)\n",err_code);
  1506.     else
  1507.         printf(diskReadErrMsg,err_code);
  1508.     if(!ignore_errors){
  1509.         diskEject();
  1510.         return 1;
  1511.         }
  1512.     }
  1513. return 0;
  1514. }
  1515.  
  1516. /***********************************************************************/
  1517.  
  1518. void hacking(command)
  1519. /* handles all the commands in the Special menu: mainly for historical reasons
  1520. (suntar 1.0 was rather modal) I preferred to loop internally while commands are 
  1521. from this menu rather than returning to the main loop after executing
  1522. the first command
  1523. */
  1524.  
  1525. {
  1526. /* visto che i comandi del men¥ Special sono attivi se e solo se lo sono quelli
  1527. del men¥ file avrebbe senso eseguire un solo comando e ritornare, preferisco 
  1528. ciclare anche qui dentro perchÄ cosô Å pi¥ facile gestire il comando Again */
  1529.  
  1530.  
  1531. short inPlace;
  1532. register int i;
  1533. Boolean sect_n_valid;
  1534. Boolean out_f_open=false;
  1535. sector_t default_sect_n=0;
  1536. int outputFile;
  1537. static unsigned char messIta[]="\pInserisci il disco di prova",
  1538.     messIng[]="\pInsert the test disk",
  1539.     mess_wrprot[]="Write protected disk !\n";
  1540.  
  1541. next_header_for_AIX=-1;
  1542. again_command=0;
  1543. if(setjmp(main_loop)<0){
  1544.     if(out_f_open) FSClose(outputFile);
  1545.     if(again_command!=hmList || !drive_number)
  1546.         return;            /* il disco Å stato espulso, non ha senso restare qui dentro;
  1547.                         non Å detto perÿ, forse a volte non espello ! */
  1548.     command=0;
  1549.     }
  1550.  
  1551. if(aspetta_inserzione(in_Italia?messIta:messIng))
  1552.     return;
  1553.  
  1554. for(;;){
  1555.     if(command==0){
  1556.         fase=non_faccio_nulla;
  1557.         close_all_open_WD();
  1558.         check_ev_timing=120;
  1559.         flush_buffers();
  1560.         last_selection=0;
  1561.         while(last_selection==0){
  1562.             MainEvent();
  1563.             if(!expert_mode) return;
  1564.             }
  1565.         if(again_command==hmView && (loword(last_selection)==hmView ||
  1566.            loword(last_selection)==hmAgain) && default_sect_n<sectors_on_floppy-1) 
  1567.                 default_sect_n++;    /* tipicamente io guardo
  1568.                    il settore prima di farci sopra un clear o read, per cui voglio un
  1569.                    autoincremento solo se il comando resta view
  1570.                    -- I usually view a sector just before clearing or untar-ring, hence
  1571.                    I want auto-increment only if the following command is another View */
  1572.         command=loword(last_selection);
  1573.         fase=ricevuto_comando;
  1574.         if(hiword(last_selection)==fileID)
  1575.             return;        /* non tocca a me gestirlo */
  1576.         last_selection=0;
  1577.         if(sect_n_valid=(command==hmAgain)){
  1578.             command=again_command;
  1579.             if(command==hmList){
  1580.                 diskEject();    /* non avrebbe senso farlo due
  1581.                     volte sullo stesso disco, ma ha senso farlo su pi¥ dischi di fila
  1582.                     -- Do it again used on Expert list means do it on another disk,
  1583.                     hence the current disk must be ejected */
  1584.                 if(aspetta_inserzione(in_Italia?messIta:messIng))
  1585.                     return;
  1586.                 }
  1587.             }
  1588.         again_command=0;
  1589.         }
  1590.     else
  1591.         sect_n_valid=false;
  1592.  
  1593.     switch(command){
  1594.         case hmList:
  1595.             {
  1596.             enum formats fmt;
  1597.             if(drive_number) /* solo su disco, non su file */
  1598.                 again_command=hmList;
  1599.             if(next_header_for_AIX!=-1 && tar_version==tar_AIX)
  1600.                 fase=hack_listing;    /* so identify_format doesn not print
  1601.                         its "unknown format" message */
  1602.             one_empty_line();
  1603.             fmt = identify_format();    /* che legge in disk_buffer il settore 0
  1604.                             -- which leaves a copy of sector 0 in disk_buffer */
  1605.             if(next_header_for_AIX!=-1 && tar_version==tar_AIX && fmt==unknown_format){
  1606.                 /* printf("sn=%ld\n",next_header_for_AIX); */
  1607.                 if(next_header_for_AIX < sectors_on_floppy){
  1608.                     leggi_settore(next_header_for_AIX,&tarh);
  1609.                     if(check_all_zero(&tarh)){
  1610.                         print_sector_n(next_header_for_AIX);
  1611.                         printf("End of Archive (dangerous, can\'t check it\'s the right disk)\n");
  1612.                         break;        /*save the value of next_header_for_AIX */
  1613.                         }
  1614.                     else if(untar_number(tarh.size,-1) != -1 &&
  1615.                             untar_checksum(&tarh,-1,false) != -2)
  1616.                         fmt=tar_format;
  1617.                     else{
  1618.                         printf("Unknown format (maybe wrong disk)\n");
  1619.                         break;
  1620.                         }
  1621.                     }
  1622.                 else{
  1623.                     printf("No file starts here (dangerous, can\'t check it\'s the right disk)\n");
  1624.                     next_header_for_AIX-=sectors_on_floppy;
  1625.                     break;
  1626.                     }
  1627.                 }
  1628.             else
  1629.                 next_header_for_AIX=-1;
  1630.  
  1631.             fase=hack_listing;
  1632.             if(fmt==bar_format){
  1633.                 int n;
  1634.                 one_empty_line();
  1635.                 printf(START_READ);
  1636.                 if(my_atoi(((barh_type*)disk_buffer)->volume_num,&n)!=0)
  1637.                     printf("No sequence number\n");
  1638.                 else
  1639.                     stampa_info_bar(n);
  1640.                 listonly=1;
  1641.                 my_unbar();        /* che in caso di fase==hack_listing si comporta diversamente
  1642.                                 dal solito per il cambio disco, e stampa pi¥ informazioni
  1643.                                 -- which, when fase==hack_listing, behaves differently
  1644.                                 than when called by a List command */
  1645.                 }
  1646.             else if(fmt==tar_format){
  1647.                 one_empty_line();
  1648.                 printf(START_READ);
  1649.                 listonly=1;
  1650.                 my_untar();
  1651.                 }
  1652.             next_header_for_AIX=-1;
  1653.             }
  1654.             break;
  1655.         case hmClear:    /* clear sector */
  1656.         case hmOverwrite:
  1657.             one_empty_line();
  1658.             if(is_wrprot()){
  1659.                 printf(mess_wrprot);
  1660.                 }
  1661.             else{
  1662.                 if(command==hmClear){
  1663.                     printf("Clearing the sector will erase its previous content.\n");
  1664.                     printf(
  1665. "If it was an header, List, Extract and Append will see it as end of the archive\n");
  1666.                     sect_n=default_sect_n;
  1667.                     }
  1668.                 else{
  1669.                     printf("The previous content will be lost\nstart ");
  1670.                     sect_n=0;
  1671.                     } 
  1672.                 fase=reading_sect_n;
  1673.                 if(read_sect_n(§_n)==noErr){
  1674.                     if(command==hmClear){
  1675.                         fillmem(disk_buffer, 0, 512);
  1676.                         scrivi_settore(sect_n,disk_buffer);
  1677.                         if(err_code) printf(diskWriteErrMsg,err_code);
  1678.                         }
  1679.                     else{
  1680.                         overwrite_sectors();
  1681.                         printf(DONE);
  1682.                         }
  1683.                     default_sect_n=sect_n;
  1684.                     }
  1685.                 }
  1686.             break;
  1687.         case hmView:        /* view sector */
  1688.             fase=reading_sect_n;
  1689.             one_empty_line();
  1690.             if(sect_n_valid)
  1691.                 printf("View sector %ld\n",(long)sect_n);
  1692.             else{
  1693.                 sect_n=default_sect_n;
  1694.                 sect_n_valid= read_sect_n(§_n)==0;
  1695.                 }
  1696.             if(sect_n_valid){
  1697.                 fillmem(disk_buffer, 0, 512);
  1698.                 read_sectors(sect_n,&disk_buffer,1);
  1699.                 if(err_code){
  1700.                     beep_in_foreground();
  1701.                     printf(diskReadErrMsg,err_code);
  1702.                     }
  1703.                 stampa_buffer(sect_n,disk_buffer);
  1704.                 again_command=command;
  1705.                 default_sect_n=sect_n;
  1706.                 if(sect_n<sectors_on_floppy-1) sect_n++;
  1707.                 }
  1708.             break;
  1709.         case hmSave:
  1710.             {sector_t sect_finale;
  1711.             my_SF_Put("\pSave as:","\psectors");
  1712.             if(!reply.good) break;
  1713.  
  1714.             i=new_text_file(&outputFile);
  1715.             if(i!=noErr) break;
  1716.             out_f_open=true;
  1717.             sect_n=default_sect_n;
  1718.             fase=reading_sect_n;
  1719.             one_empty_line();
  1720.             if((printf("start "),read_sect_n(§_n)==0) && 
  1721.                (sect_finale=sect_n,printf("end "),read_sect_n(§_finale)==0) ){
  1722.  
  1723.                 fase=reading_disk;
  1724.                 do{
  1725.                     check_events();
  1726.                     leggi_settore(sect_n,&disk_buffer);
  1727.                     if(check_error()) raise_error();
  1728.                     if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
  1729.                         beep_in_foreground();
  1730.                         error_message("Write error\n");
  1731.                         }
  1732.                     sect_n++;
  1733.                     }
  1734.                 while(sect_n<=sect_finale);
  1735.                 }
  1736.             FSClose(outputFile);
  1737.             printf(DONE);
  1738.             out_f_open=false;
  1739.             }
  1740.             break;
  1741.         case hmFind:
  1742.             {int err_n=0;
  1743.             long exp_check;
  1744.             Boolean stampato=false;
  1745.             one_empty_line();
  1746.             fase=reading_disk;
  1747.             listonly=0;        /* full buffering... */
  1748.             for(sect_n=0;sect_n<sectors_on_floppy;sect_n++){
  1749.                 check_events();
  1750.                 leggi_settore(sect_n,&disk_buffer);
  1751.                 if(err_code!=noErr){
  1752.                     printf("sector %ld could not be read\n",(long)sect_n);
  1753.                     if(++err_n>max(20,(int)(sect_n/8))){
  1754.                         beep_in_foreground();
  1755.                         error_message("Too many errors, search aborted\n");
  1756.                         }
  1757.                     }
  1758.                 else if(untar_number(((struct tarh_type*)disk_buffer)->size,-1) != -1 &&
  1759.                         untar_checksum(&disk_buffer,-1,false) == 0){
  1760.                     disk_buffer[99]=0;
  1761.                     disable_autoflush();
  1762.                     printf("tar ");
  1763.                     print_sector_n(sect_n);
  1764.                     if(((struct tarh_type*)disk_buffer)->linkflag=='V')
  1765.                         printf("Volume header: ");
  1766.                     if(((struct tarh_type*)disk_buffer)->linkflag=='M')
  1767.                         printf("Continuation: ");
  1768.                     printf("%s\n",disk_buffer);
  1769.                     enable_autoflush();
  1770.                     stampato=true;
  1771.                     }
  1772.                 else if(sect_n!=0&&untar_number(((barh_type*)disk_buffer)->size,-1) !=-1 &&
  1773.                         unbar_checksum(&disk_buffer,-1,&exp_check) == 0 ){
  1774.                     ((barh_type*)disk_buffer)->name[99]=0;
  1775.                     printf("bar ");
  1776.                     print_sector_n(sect_n);
  1777.                     printf(" %s\n",((barh_type*)disk_buffer)->name);
  1778.                     stampato=true;
  1779.                     }
  1780.                 }
  1781.             if(!stampato) printf("No headers found\n");
  1782.             printf(DONE);
  1783.             }
  1784.             break;
  1785.         case hmUntar:
  1786.         case hmUnbar:
  1787.             fase=reading_sect_n;
  1788.             one_empty_line();
  1789.  
  1790.             if(sect_n_valid)
  1791.                 printf("Un%car at sector %ld\n",((command==hmUntar)?'t':'b'),(long)sect_n);
  1792.             else{
  1793.                 sect_n=default_sect_n;
  1794.                 sect_n_valid= read_sect_n(§_n)==0;    /* come sopra */
  1795.                 }
  1796.             if(sect_n_valid){
  1797.                 leggi_settore(sect_n,&disk_buffer);
  1798.                 if(err_code)
  1799.                     printf(diskReadErrMsg,err_code);
  1800.                 else if(check_all_zero(disk_buffer))
  1801.                     printf("Null header\n");
  1802.                 else{
  1803.                     select_directory();
  1804.                     if(reply.good){
  1805.                         listonly=0;
  1806.                         bar_archive= command==hmUnbar;
  1807.                         fase=hack_reading;        /* per avvertire di non chiedere un disco
  1808.                                                 specifico: forse il settore 0 Å danneggiato
  1809.                                                 o sovrascritto da un altro header bar
  1810.                                                 -- essentially, it's used to remember that
  1811.                                                 the floppy_n variable may be invalid,
  1812.                                                 hence when asking next disk don't rely on it */
  1813.                         if(bar_archive){
  1814.                             unbar();
  1815.                             }
  1816.                         else
  1817.                             untar();
  1818.                         print_sector_n(sect_n);
  1819.                         printf(" Done\n");
  1820.                         }
  1821.                     again_command=command;
  1822.                     default_sect_n=sect_n;
  1823.                     }
  1824.                 }
  1825.             break;
  1826.         case hmMac_ize:
  1827.             if(is_wrprot()){
  1828.                 printf(mess_wrprot);
  1829.                 }
  1830.             else{
  1831.                 i=warning_first_write(1);
  1832.                 if(i>=0){
  1833.                     ioParam pb;
  1834.                     if(i>0){
  1835.                         ParamText(i==1?"\pNon-Mac disk":"\pEmpty Macintosh disk",
  1836.                         "\p\rAny data in this disk will be lost. Continue ?",PNS,PNS);
  1837.                         if( my_modal_dialog(139,NULL,2) == 2) break;
  1838.                         }
  1839.                     printf("Creating directory...\n");
  1840.                     fillmem(disk_buffer, 0xF6, 512);
  1841.                     write_sectors(0,disk_buffer,1);
  1842.                     DIZero (drive_number,"\pUntitled");
  1843.                     pb.ioVRefNum=drive_number;
  1844.                     drive_number=0;
  1845.                     PBMountVol(&pb);
  1846.                     printf(DONE);
  1847.                     invalid_buffers();
  1848.  
  1849.                     return;
  1850.                     }
  1851.                 else{
  1852.                     diskEject();
  1853.                     return;
  1854.                     }
  1855.                 }
  1856.             break;
  1857.         case hmDriveList:
  1858.             DriveList();
  1859.             break;
  1860.         }        /* fine switch */
  1861.         command=0;
  1862.     }
  1863. }
  1864.  
  1865. short read_sect_n(n)
  1866. sector_t *n;
  1867. {
  1868. char buffer[32];
  1869. short i;
  1870. printf("sector number : ");
  1871. /* gets(buffer); */
  1872. my_itoa((long)*n,buffer);
  1873. prompt(buffer,sizeof(buffer)-1);
  1874.  
  1875. #if SECTOR_T_SIZE==4
  1876. i=my_atol(&buffer[0],n);
  1877. #else
  1878. i=my_atoi(&buffer[0],n);
  1879. #endif
  1880. if(i==0 && (*n<0 || *n >= sectors_on_floppy) ){
  1881.     printf("Invalid sector number\n");
  1882.     return -3;
  1883.     }
  1884. else if(i==-2)
  1885.     printf("Invalid digit\n");
  1886. return i;
  1887. }
  1888.  
  1889. short my_atoi(buffer,n)
  1890. register char*buffer;
  1891. register int *n;
  1892. {
  1893. for(;*buffer==' ';buffer++)
  1894.     ;
  1895. if(*buffer>='0'&&*buffer<='9'){
  1896.     *n=0;
  1897.     while(*buffer>='0'&&*buffer<='9')
  1898.             *n= *n * 10 + *buffer++ -'0';
  1899.     return 0;
  1900.     }
  1901. return *buffer? -2 : -1;
  1902. }
  1903.  
  1904. short my_atol(buffer,n)
  1905. register char*buffer;
  1906. register long *n;
  1907. {
  1908. for(;*buffer==' ';buffer++)
  1909.     ;
  1910. if(*buffer>='0'&&*buffer<='9'){
  1911.     *n=0;
  1912.     while(*buffer>='0'&&*buffer<='9')
  1913.             *n= *n * 10 + *buffer++ -'0';
  1914.     return 0;
  1915.     }
  1916. return *buffer? -2 : -1;
  1917. }
  1918.  
  1919.  
  1920. void overwrite_sectors()
  1921. {
  1922. SFTypeList    myTypes;
  1923. short charsRead;
  1924.  
  1925.     my_SF_Get(-1,myTypes);
  1926.     if(!reply.good)return;
  1927.  
  1928.     if(apri_file("rb",&inputFile))
  1929.         return;
  1930.     inf_is_open=true;
  1931.     fase=writing_disk;
  1932.  
  1933.     while( (charsRead = mac_fread(disk_buffer, 512, inputFile)) >0 ){
  1934.         if(sect_n>=sectors_on_floppy){
  1935.             printf("End of disk reached\n");
  1936.             break;
  1937.             }
  1938.         scrivi_settore(sect_n,disk_buffer);
  1939.         check_wr_err();
  1940.         sect_n++;
  1941.         check_events();
  1942.         }
  1943.  
  1944.     FSClose(inputFile);
  1945.     inf_is_open=false;
  1946. }
  1947.  
  1948.  
  1949. void print_sector_n(sector_n)
  1950. sector_t sector_n;
  1951. {
  1952. /* well, I use a printf which does not accept a %4d descriptor... !!! */
  1953.     printf("[sector %s%ld] ",sector_n>=1000?"":sector_n>=100?" ":sector_n>=10?"  ":"   ",
  1954.         (long)sector_n);
  1955. }
  1956.  
  1957. void stampa_info_bar(n)    /* print informations from a bar volume header */
  1958. {
  1959. char buffer[16];
  1960. register int i,j;
  1961. printf("Disk number %d ", n);
  1962. for(i=j=0;i<10;i+=2,j+=3){
  1963.     buffer[j]=((barh_type*)disk_buffer)->cdate[i];
  1964.     buffer[j+1]=((barh_type*)disk_buffer)->cdate[i+1];
  1965.     }
  1966. buffer[2]=buffer[5]='/';
  1967. buffer[8]=' ';
  1968. buffer[11]=':';
  1969. buffer[14]='\0';
  1970. printf("created %s",buffer);
  1971. if(((barh_type*)disk_buffer)->name[0])
  1972.     print_if_string("; archive name is ",((barh_type*)disk_buffer)->name,100);
  1973. printf("\n");
  1974. }
  1975.  
  1976.  
  1977. /*********************************************/
  1978.  
  1979.  
  1980. int going_to_background()
  1981. /* to write on a disk in background is very dangerous, since suntar 
  1982. uses very low level calls and can't realize that a disk was replaced 
  1983. by a Mac disk containing precious files. Hence, the user must be
  1984. alerted, and since at the next GetNextEvent I'll lose the right to get
  1985. CPU time, I can't present a standard alert
  1986. */
  1987. {
  1988.  
  1989. if(fase==writing_disk && sto_lavorando){
  1990.     static Rect winRect={0,0,80,300},
  1991.         boundsR1={15,0,80,300};
  1992.     WindowPtr theWindow;
  1993.     GrafPtr    savePort;
  1994.     char *p;
  1995.     unsigned long time;
  1996.  
  1997.     PositionDialog(&winRect);
  1998.     theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, -1L, 0, (long)-1);
  1999.     GetPort( &savePort );
  2000.     SetPort(theWindow);
  2001.     p= in_Italia ?
  2002. "suntar continuerê a scrivere in background\rsu qualunque cosa si trovi nel drive\r\
  2003. non espellere il disco ! ! !":
  2004. "suntar will write in background\ron anything is in the disk drive\r\
  2005. please don\'t eject this disk";
  2006.  
  2007.     TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
  2008.     
  2009.     /* while(!Button()) ;
  2010.     while( Button()) ;
  2011.     FlushEvents( mDownMask|mUpMask, 0 ); */
  2012.     time=Ticks+delay_back;        /* 5 secondi (nella risorsa), ma un clic del mouse riduce l'attesa 
  2013.                         purchÄ siano almeno 1.5 */
  2014.     while (time >Ticks)
  2015.         if(time-delay_back+90 < Ticks && Button()){
  2016.             /*FlushEvents( mDownMask, 0 );*/    /* inutile, in pratica, l'evento va al
  2017.                             processo successivo... 
  2018.                             -- a mouse click aborts the delay loop: however, I can't
  2019.                             tell the Finder that that mouse click was already served,
  2020.                             since that event is anyway passed to the application
  2021.                             which is going to foreground, I can't flush it
  2022.                             */
  2023.             break;
  2024.             }
  2025.     SetPort (savePort);
  2026.     DisposeWindow(theWindow);
  2027.     return 1;
  2028.     }
  2029. return 0;
  2030. }
  2031.  
  2032. void DriveList()
  2033. {
  2034. int i;
  2035.     disable_autoflush();
  2036.     one_empty_line();
  2037.     for(i=0;i<max_drive;i++){
  2038.         if(drive_type[i]){
  2039.             printf("Drive %d: ",i+1);
  2040.             switch(drive_type[i]&0xF){
  2041.             case 7:
  2042.                 printf("Hard disk 20 ");
  2043.                 break;
  2044.             case 2:
  2045.                 printf("Single sided (GCR 400k) ");
  2046.                 break;
  2047.             case 3:
  2048.                 printf("Double sided (GCR 800k) ");
  2049.                 break;
  2050.             case 4:
  2051.                 printf("SuperDrive (GCR 800k-MFM 720/1440k) ");
  2052.                 break;
  2053.             case 5:
  2054.                 {Handle h=GetResource('STR ',200);
  2055.                 if(h){
  2056.                     HLock(h);
  2057.                     printf("%p ",*h);
  2058.                     HUnlock(h);
  2059.                     break;
  2060.                     }
  2061.                 }
  2062.                 /* else unknown type */
  2063.             default:
  2064.                 printf("Unknown drive type ");
  2065.             }
  2066.             if(drive_type[i]>0){    /* that bit is set/cleared by suntar */
  2067.                 printf((drive_type[i]&0x100) ?"external":"internal");
  2068.                 if(drive_type[i]&0x200) printf("(SCSI)");
  2069.                 printf((drive_type[i]&0x400) ?", fixed (suntar can\'t open it)":", removable");
  2070.                 }
  2071.             printf("\n");
  2072.             }
  2073.         }
  2074.     printf("\n");
  2075.     enable_autoflush();
  2076. }
  2077.  
  2078. void fine_lavoro()
  2079. {
  2080. if(gInBackground)
  2081.     check_foreground();
  2082. else if(settori_passati>min_to_beep)
  2083.     SysBeep(5);
  2084. }
  2085.  
  2086. void unexpected_disk_insertion(message)
  2087. /* called when a disk is inserted and suntar does not expect a disk insertion:
  2088. obviously, that disk could be a Mac disk to be passed to the Finder, but it
  2089. could be a tar disk, or it could be in the disk drive where suntar believes
  2090. there was still the disk it has opened and on which it was working
  2091. */
  2092. long message;
  2093. {
  2094. extern Point badmount_point;
  2095. extern char *titoli[];
  2096. extern Boolean finestra_sm_aperta;
  2097. jmp_buf savebuf;
  2098. short inPlace;
  2099. Boolean andata_male;
  2100.  
  2101. sector_t old_s=sectors_on_floppy;
  2102. short old_drive_n=drive_number;
  2103. struct disk_info old_di=di;
  2104.  
  2105. mcopy(&savebuf,&main_loop,sizeof(jmp_buf));
  2106.  
  2107. andata_male=false;
  2108. drive_number=loword(message);
  2109.  
  2110. if(setjmp(main_loop)<0) {    /* at least identify_format may do a raise_error, and
  2111.     raise_error causes a bad crash if no currently running function has performed
  2112.     a setjmp, and I don't know what's the current situation */
  2113.     andata_male=true;
  2114.     }
  2115. if(andata_male || testa_stato(&inPlace,0)){
  2116.     diskEject();
  2117.     mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
  2118.     sectors_on_floppy=old_s;
  2119.     drive_number=old_drive_n;
  2120.     di=old_di;
  2121.     return;
  2122.     }
  2123.  
  2124. if( (di.os==mac_HFS||di.os==mac_MFS) && (drive_number!=old_drive_n || !dirty_buffers()) ){
  2125.         /* il disco non mi riguarda, lo lascio passare
  2126.         -- that disk is of no interest to suntar; do what GetNextEvent would do,
  2127.         then what Apple suggests to do when receiving a disk insertion event */
  2128.     ParamBlockRec param;
  2129.     param.volumeParam.ioVRefNum=loword(message);
  2130.     if( (hiword(message)=PBMountVol (¶m)) != noErr ){
  2131.         DIBadMount(badmount_point, message);
  2132.         invalid_buffers();
  2133.         }
  2134.     mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
  2135.     sectors_on_floppy=old_s;
  2136.     drive_number=old_drive_n;
  2137.     di=old_di;
  2138.     return;
  2139.     }
  2140.  
  2141. if(fase==non_faccio_nulla && old_drive_n==loword(message)){
  2142.     old_drive_n=0;        /* there is no reason to ask the disk back if I was
  2143.                         not working on it, simply close the old one */
  2144.     invalid_buffers();
  2145.     }
  2146.  
  2147. if( old_drive_n!=0 || file_aperto){
  2148.     if((fase==paused || fase==in_writing || fase==reading_sect_n || finestra_sm_aperta) &&
  2149.        loword(message)==old_drive_n){ /* il disco 
  2150.             era dentro, probabilmente Å stato estratto a tradimento e poi reinserito 
  2151.             -- the tar disk was in that drive, probably it was ejected (without using
  2152.             suntar's eject) and inserted in back */
  2153.         if (sectors_on_floppy!=old_s ){
  2154.             if(dirty_buffers())
  2155.                 diskEject();
  2156.             else{
  2157.                 ParamBlockRec param;
  2158.                 param.volumeParam.ioVRefNum=loword(message);
  2159.                 if (di.os==unknown_os || (hiword(message)=PBMountVol (¶m)) != noErr)
  2160.                     DIBadMount(badmount_point, message);
  2161.                 }
  2162.             }
  2163.         else{
  2164.             short item;
  2165.  
  2166.             ParamText(in_Italia?"\pQuesto Å il disco su cui stavo lavorando ?":
  2167.                 "\pIs this the disk I was working on ?",PNS,PNS,PNS);
  2168.             item=my_modal_dialog(139,titoli,2);
  2169.             if(item==2){
  2170.                 /*FlushVol (PNS,drive_number);*/
  2171.                 UnmountVol(NULL,drive_number);
  2172.                 diskEject();
  2173.                 }
  2174.             }
  2175.         }
  2176.     else{
  2177. /* non accetto altri dischi
  2178. -- suntar has something open and since it can't open more than one thing it can't
  2179. open that disk, do something which looks like the standard behaviour
  2180. for non-Mac or non-initialized disks
  2181. */
  2182.         if(dirty_buffers())
  2183.             diskEject();
  2184.         else if(di.os==msdos){        /* AccessPC or DOS Mounter could be installed... */
  2185.             ParamBlockRec param;
  2186.             param.volumeParam.ioVRefNum=loword(message);
  2187.             if( (hiword(message)=PBMountVol (¶m)) != noErr ){
  2188.                 DIBadMount(badmount_point, message);
  2189.                 }
  2190.             }
  2191.         else{
  2192.             diskEject();
  2193.             ParamText(in_Italia?"\pNon si possono aprire due archivi":
  2194.                 "\pCannot open more than one archive",PNS,PNS,PNS);
  2195.             my_alert();
  2196.             }
  2197.         }
  2198.     sectors_on_floppy=old_s;
  2199.     di=old_di;
  2200.     drive_number=old_drive_n;    /* diskEject lo azzera */
  2201.     }
  2202.  
  2203. else{    /* open it ! */
  2204.     if(testa_stato(&inPlace,true))        /* must call it again, for the "verbose" parameter */
  2205.         diskEject();
  2206.     else{
  2207.         if(drive_number<=last_drive && fase!=initializing){
  2208.             /*FlushVol (PNS,drive_number);*/
  2209.             /*i=*/ UnmountVol (NULL,drive_number);
  2210.             }
  2211.         if(di.os==msdos){
  2212.             ParamBlockRec param;
  2213.             param.volumeParam.ioVRefNum=drive_number;
  2214.             if( (hiword(message)=PBMountVol (¶m)) != noErr ){
  2215.                 diskEject();
  2216.                 ParamText(in_Italia?
  2217.                 "\pDisco MS-DOS, per usarlo scegli un comando \"Create╔\"":
  2218.                 "\pMS-DOS disk, to open it select a \"Create╔\" command",PNS,PNS,PNS);
  2219.                 my_alert();
  2220.                 }
  2221.             drive_number=0;
  2222.             }
  2223.         else if(!di.is_not_initialized)
  2224.             (void)identify_format();
  2225.         }
  2226.     }
  2227. mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
  2228. }
  2229.  
  2230. /************** gestione men¥ ****************/
  2231.  
  2232. void EnableDisableItem(MenuHandle,short,Boolean);
  2233. static void EnableDisableItem(menu, item, flag)
  2234. MenuHandle menu;
  2235. short item;
  2236. Boolean flag;
  2237. {
  2238. if(flag)
  2239.     EnableItem(menu, item);
  2240. else
  2241.     DisableItem(menu, item);
  2242. }
  2243.  
  2244. void MaintainApplSpecificMenus()
  2245. /* it's an idea borrowed from TEsample: rather than enabling and disabling
  2246. items when the situation changes, be sure that some global variables always
  2247. tell what the situation is and adjust all the menu items when receiving a 
  2248. keyDown event with the Command key or a MouseDown event in the menu bar.
  2249.  That's the most reasonable way to do things in a program which has an abort
  2250. command and does not quit at the first error.
  2251. */
  2252. extern Boolean finestra_sm_aperta;
  2253. extern DialogPtr ListDialog;
  2254.  
  2255. Boolean b;
  2256. b= fase==non_faccio_nulla;
  2257. if(b){
  2258.     EnableDisableItem(myMenus[fileM], fmGetInfo, !file_aperto&&drive_number==0);
  2259.     EnableDisableItem(myMenus[fileM], fmCopy, !file_aperto);
  2260.     EnableItem(myMenus[fileM], fmList);
  2261.     EnableItem(myMenus[fileM], fmExtract);
  2262.     EnableDisableItem(myMenus[fileM], fmWriteTar, !file_aperto);
  2263.     EnableDisableItem(myMenus[fileM], fmWriteBar, !file_aperto);
  2264.     EnableDisableItem(myMenus[fileM], fmAppend, !file_aperto);
  2265.     EnableDisableItem(myMenus[fileM], fmFormat, !file_aperto);
  2266.     EnableItem(myMenus[fileM], fmSelect);
  2267.     }
  2268. else{
  2269.     DisableItem(myMenus[fileM], fmGetInfo);
  2270.     DisableItem(myMenus[fileM], fmCopy);
  2271.     DisableItem(myMenus[fileM], fmList);
  2272.     DisableItem(myMenus[fileM], fmExtract);
  2273.     DisableItem(myMenus[fileM], fmWriteTar);
  2274.     DisableItem(myMenus[fileM], fmWriteBar);
  2275.     DisableItem(myMenus[fileM], fmAppend);
  2276.     DisableItem(myMenus[fileM], fmFormat);
  2277.     EnableDisableItem(myMenus[fileM], fmSelect, ListDialog&&FrontWindow()!=ListDialog);
  2278.     }
  2279. /* il Think C marker non accetta macro su due righe, e non voglio perdere i suoi servizi ! */
  2280. #define abort_mask    ( (1<<writing_disk) | (1<<reading_disk) | (1<<reading_sect_n) | (1<<hack_reading) | (1<<hack_listing) | (1<<paused) | (1<<in_writing) | (1<<selected_reading) )
  2281.  
  2282. EnableDisableItem(myMenus[fileM], fmPause, sto_lavorando || fase==paused /* nel secondo
  2283.             caso, l'item Å diventato resume */ || finestra_sm_aperta&&((abort_mask>>fase)&1));
  2284. EnableDisableItem(myMenus[fileM], fmOpen, fase==non_faccio_nulla&&drive_number==0&&!file_aperto);
  2285.  
  2286. #ifdef V_122
  2287. EnableDisableItem(myMenus[fileM], fmEject, drive_number!=0 &&( fase==non_faccio_nulla || fase==in_writing
  2288.     /* || fase==paused || finestra_sm_aperta*/) );        /* sarebbe sensato averlo attivo
  2289.                 anche allora, ma non passo dal main per gestirlo ! */
  2290. EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla&&file_aperto);
  2291. #else
  2292. /* in the 1.3 version, they share the same item */
  2293. {
  2294. unsigned char itemname[32];
  2295. int i=2;
  2296. if(!file_aperto&&drive_number==0)
  2297.     DisableItem(myMenus[fileM], fmEject);
  2298. else{
  2299.     if(file_aperto)
  2300.         i=1;
  2301.     EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla || fase==in_writing);
  2302.     }
  2303. GetIndString (itemname,129,i);
  2304. SetItem (myMenus[fileM],fmClose,itemname);
  2305. }
  2306. #endif
  2307.  
  2308.  
  2309. /*EnableDisableItem(myMenus[fileM], fmAbort, fase==writing_disk ||fase==reading_disk ||
  2310.     fase==reading_sect_n || fase==hack_reading || fase==hack_listing || fase==paused) || 
  2311.     fase==in_writing || fase==selected_reading; */
  2312. EnableDisableItem(myMenus[fileM], fmAbort, (abort_mask>>fase)&1 );
  2313.  
  2314. if(expert_mode){
  2315.     if(b){
  2316.         EnableItem(hackersMenu, hmView);
  2317.         EnableDisableItem(hackersMenu, hmClear,!file_aperto);
  2318.         EnableDisableItem(hackersMenu, hmMac_ize,!file_aperto);
  2319.         EnableDisableItem(hackersMenu, hmOverwrite,!file_aperto);
  2320.         EnableItem(hackersMenu, hmSave);
  2321.         EnableItem(hackersMenu, hmFind);
  2322.         EnableItem(hackersMenu, hmUntar);
  2323.         EnableItem(hackersMenu, hmUnbar);
  2324.         EnableItem(hackersMenu, hmList);
  2325.         EnableItem(hackersMenu, hmDriveList);
  2326.         EnableDisableItem(hackersMenu, hmAgain, again_command!=0);
  2327.         }
  2328.     else{
  2329.         DisableItem(hackersMenu, hmView);
  2330.         DisableItem(hackersMenu, hmClear);
  2331.         DisableItem(hackersMenu, hmMac_ize);
  2332.         DisableItem(hackersMenu, hmOverwrite);
  2333.         DisableItem(hackersMenu, hmSave);
  2334.         DisableItem(hackersMenu, hmFind);
  2335.         DisableItem(hackersMenu, hmUntar);
  2336.         DisableItem(hackersMenu, hmUnbar);
  2337.         DisableItem(hackersMenu, hmList);
  2338.         DisableItem(hackersMenu, hmDriveList);
  2339.         DisableItem(hackersMenu, hmAgain);
  2340.         }
  2341.     }
  2342. }
  2343.  
  2344.  
  2345. void set_skip_all(n)
  2346. {
  2347. /* il confirm saves ha tre stati: 
  2348.     non selezionato (confirm_saves=0,saveskip_all=0)
  2349.     selezionato     (confirm_saves=1,saveskip_all=0)
  2350.     posto in corsivo da una skip all o save all (confirm_saves=0,saveskip_all=1)
  2351. questa routine gestisce i passaggi tra i tre stati:
  2352.  
  2353. n= 0 -> se Å in corsivo torna sel, se no resta immutato;
  2354. n= 1 -> da sel commuta a posto in corsivo (e da non sel resta immutato !)
  2355. n=-1 -> da chiamare quando seleziono l'entry del men¥: se Å in corsivo torna selezionato,
  2356.         se no inverte lo stato attuale
  2357.  
  2358. -- the confirm saves menu item has three states:
  2359.     non-selected (confirm_saves=0,saveskip_all=0)
  2360.     selected     (confirm_saves=1,saveskip_all=0)
  2361.     italicized by a skip all or save all (confirm_saves=0,saveskip_all=1)
  2362. this routine handles all its status changes:
  2363. n=0 => I'm in the main loop, if it's italicized then make it selected
  2364.   1 => the save all or skip all was clicked (caution, the confirm saves could 
  2365.         have been disabled after the window appeared, and the button may still
  2366.         be clicked)
  2367.  -1 => the confirm saves menu item was selected: if italicized return normal,
  2368.         otherwise invert its current state
  2369.  
  2370. */
  2371. static Boolean saveskip_all=false;
  2372.  
  2373. if(!n || (n<0&&saveskip_all) ){
  2374.     if(saveskip_all){
  2375.         saveskip_all=false;
  2376.         SetItemStyle(myMenus[prefM],pmConfirm,0);
  2377.         confirm_saves=true;
  2378.         }
  2379.     }
  2380. else if (n>0){
  2381.     if(confirm_saves||saveskip_all){    /* puÿ capitare che non sia cosô se 
  2382.             deseleziono durante il dialogo e poi clicco su un bottone...*/
  2383.         saveskip_all=true;
  2384.         SetItemStyle(myMenus[prefM],pmConfirm, 2);    /* corsivo */
  2385.         confirm_saves=false;
  2386.         }
  2387.     }
  2388. else{    /* n=-1, saveskip_all=0 */
  2389.     CheckItem(myMenus[prefM],pmConfirm,confirm_saves^=1);
  2390.     }
  2391. }
  2392.  
  2393. void load_OSType(short,OSType *);
  2394. static void load_OSType(id,dest)
  2395. short id;
  2396. OSType *dest;
  2397. {
  2398. Handle h;
  2399. if((h=GetResource ('STR ',id))==NULL)
  2400.     *dest='????';
  2401. else{
  2402.     HLock(h);
  2403.     mcopy((char*)dest,(char*)*h+1,4);
  2404.     ReleaseResource(h);
  2405.     /* *dest = (((long)*(unsigned char*)(*h+1))<<24) +
  2406.                   (((long)*(unsigned char*)(*h+2))<<16) +
  2407.                   (((long)*(unsigned char*)(*h+3))<<8) +
  2408.                   ((long)*(unsigned char*)(*h+4));    */
  2409.     }
  2410. }
  2411.  
  2412. long load_number(short,int);
  2413. static long load_number(id,deflt)
  2414. short id;
  2415. int deflt;
  2416. {
  2417. Handle h;
  2418. if((h=GetResource ('STR ',id))==NULL)
  2419.     return deflt;
  2420. else{
  2421.     long temp;
  2422.     HLock(h);
  2423.     temp=pstrtoi(*h);
  2424.     ReleaseResource(h);
  2425.     return temp;
  2426.     }
  2427. }
  2428.  
  2429. void prefs_da_risorsa()
  2430. /* read all the preference settings which depend on a resource, including
  2431. the INTL 0 resorce which is in the System file and contains the code
  2432. for the nation, and compute the centered locations for those dialogs which
  2433. are difficultly moved after their creation
  2434. */
  2435. {
  2436. Handle h;
  2437. int i;
  2438. static Rect bmr={0,0,96,300};
  2439. static short SF_IDs[]={199,200,-3999,-4000,1043,400,399};
  2440. extern long my_uid,my_gid;
  2441. extern char *uname,*gname;
  2442. extern Boolean gHasCustomPutFile,SB3_compatibility;
  2443. #define verItSwiss 36
  2444.  
  2445. load_OSType(129,&tar_creator);
  2446. load_OSType(136,&bar_creator);
  2447. load_OSType(137,&bar_type);
  2448.  
  2449. max_hqx_header=load_number(134,10240);
  2450.  
  2451. my_uid=load_number(130,0);
  2452. my_gid=load_number(131,0);
  2453. uname=gname="";
  2454. ResrvMem ((Size)64);
  2455. h=GetResource ('STR ',132);
  2456. if(h){
  2457.     HLock(h);
  2458.     uname=p2cstr(*h);
  2459.     }
  2460. h=GetResource ('STR ',133);
  2461. if(h){
  2462.     HLock(h);
  2463.     gname=p2cstr(*h);
  2464.     }
  2465.  
  2466. if((h=GetResource ('STR ',135))!=NULL ){
  2467.     if(**h){
  2468.         char c= *(*h+1)&~0x20;
  2469.         if(c=='I')
  2470.             in_Italia=true;
  2471.         else if(c=='E')
  2472.             in_Italia=false;
  2473.         else
  2474.             h=NULL;
  2475.         }
  2476.     else
  2477.         h=NULL;
  2478.     }
  2479.  
  2480. if(h==NULL){
  2481.     h=IUGetIntl (0);
  2482.     if(h!=NULL){
  2483.         in_Italia=(((Intl0Rec*)*h)->Intl0Vers>>8)==verItaly || 
  2484.             (((Intl0Rec*)*h)->Intl0Vers>>8)==verItSwiss;
  2485.         ReleaseResource(h);
  2486.         CheckItem(myMenus[prefM],pmEnglish,!in_Italia);
  2487.         }
  2488.     }
  2489.  
  2490. h=GetResource ('STR ',141);
  2491. if(h && **h && ((*h)[1] | 0x20)!='n') SB3_compatibility=true;
  2492.  
  2493. floppy_buffer_size =load_number(138,18);
  2494. hd_buffer_size = load_number(139,20)<<9;
  2495. back_prio = load_number(140,4);
  2496.  
  2497. load_options();
  2498.  
  2499. /* compute the centered position for the the disk initialization dialog */
  2500. PositionDialog(&bmr);        /* finestra usata da DIBadMount, uso dimensioni fisse 
  2501.             che perÿ sono quelle della finestra personalizzata e dovrebbero coincidere
  2502.             con quelle di sistema */
  2503. *(long*)&badmount_point=*(long*)&bmr;
  2504. /* sotto il System 7 passare {0,0} allo standard file provoca un dialogo 
  2505. centrato, ma purtroppo col system 6 non Å cosô... */
  2506.  
  2507. /* and the positions for the standard file dialogs */
  2508. for(i=0;i<sizeof(SF_IDs)/sizeof(short);i++){
  2509.     AlertTHndl    alertHandle = (AlertTHndl)GetResource('DLOG',SF_IDs[i]);
  2510.     if(alertHandle){
  2511.         PositionDialog( &((**alertHandle).boundsRect));
  2512.         where[i]=*(Point*)&((**alertHandle).boundsRect);
  2513.         }
  2514.     else{
  2515.         static Point    def_where={80,80};
  2516.         where[i]=def_where;
  2517.         }
  2518.     }
  2519. }
  2520.  
  2521. void load_options()
  2522. {
  2523. static OSType gif_default='QGif';
  2524. Handle h;
  2525. if((h=GetResource ('OPTs',128))==NULL){
  2526.     /* create the options resource if it doesn't exist: probably that will not
  2527.     be useful to the user, we'll make suntar 1.2 and 1.3 available with an OPTs
  2528.     resource (otherwise, a file which grows could make somebody think about
  2529.     viruses) but during the development of the program it was useful,
  2530.     each time we changed the format of the resource, deleting the old one
  2531.     one obtains the creation of the new one */
  2532.     h=NewHandle(sizeof(options));
  2533.     fillmem(&options,0,sizeof(options));
  2534.     text_creator='EDIT';
  2535.     gif_creator=gif_default;
  2536.     resolve_aliases=useSys7_SF=true;
  2537.     non_text_ASCII=1;
  2538.     smallFilesAreASCII=1;
  2539.     delay_back=300;
  2540.     min_to_beep=500;
  2541.     mcopy(*h,&options,sizeof(options));
  2542.     AddResource (h, 'OPTs',128,PNS);
  2543.     WriteResource(h);
  2544.     }
  2545. else{
  2546.     Size s=GetHandleSize(h);
  2547.     if(s<sizeof(options)){        /* somebody is using the old format of the OPTs
  2548.                                 resource, convert it to the new format:
  2549.                                 it's always wise to support old formats for
  2550.                                 anything */
  2551.         SetHandleSize (h,(Size)sizeof(options));
  2552.         fillmem(*h+(&options.opt_bytes[12]-(char*)&options),0,8);
  2553.         *(char*)(*h+(&options.opt_bytes[12]-(char*)&options)) = 1;
  2554.         mcopy(*h+((char*)&options.gif_cr-(char*)&options),&gif_default,4);
  2555.         *( *h+(&options.opt_bytes[0]-(char*)&options) ) <<= 1;    /* it's no more a Boolean... */
  2556.         ChangedResource(h);
  2557.         WriteResource(h);
  2558.         }
  2559.     mcopy(&options,*h,sizeof(options));
  2560.     }
  2561. ReleaseResource(h);
  2562. }
  2563.  
  2564. void save_options()
  2565. {
  2566. Handle h;
  2567. h=GetResource ('OPTs',128);
  2568. mcopy(*h,&options,sizeof(options));
  2569. ChangedResource(h);
  2570. WriteResource(h);
  2571. ReleaseResource(h);
  2572. }
  2573.  
  2574. void add_expert_menu(void);
  2575. static void add_expert_menu()
  2576. {
  2577. unsigned char itemname[48];
  2578.     GetIndString(itemname,130,1);
  2579.     AppendMenu(myMenus[prefM],itemname);
  2580.     GetIndString(itemname,130,2);
  2581.     AppendMenu(myMenus[prefM],itemname);
  2582.     InsertMenu(hackersMenu = GetMenu(hackID),0);
  2583. }
  2584.  
  2585.  
  2586. static void add_menu()    /* create application specific menus */
  2587. {
  2588. int markChar;
  2589.  
  2590.     CheckItem(myMenus[prefM],pmAutowrap,false);
  2591.     CheckItem(myMenus[prefM],pmConfirm,false);
  2592.     GetItemMark (hqxM,bmDisable,&markChar);
  2593.     disable_binhex = markChar==checkMark;
  2594.     GetItemMark (hqxM,bmShowExtr,&markChar);
  2595.     if(markChar==checkMark) disable_binhex |=2;
  2596.     GetItemMark (hqxM,bmSaveInfo,&markChar);
  2597.     if(markChar==checkMark) disable_binhex |=8;
  2598.     GetItemMark (hqxM,bmShowList,&markChar);
  2599.     if(markChar==checkMark) disable_binhex |=4;
  2600.  
  2601. #ifdef V_122
  2602.     GetItemMark (myMenus[prefM],pmSmallText,&markChar);
  2603.     smallFilesAreASCII= markChar==checkMark;
  2604. #endif
  2605.     GetItemMark (myMenus[prefM],pmExpert,&markChar);
  2606.     expert_mode= markChar==checkMark;
  2607.     InsertMenu(writeMenu = GetMenu(writeID), 0);
  2608.     DisableItem(writeMenu, 0);
  2609.     if(expert_mode) add_expert_menu();    /* always un-checked... */
  2610.     tarPopupMenu = GetMenu(tarPopupID);
  2611.     ntAPopupMenu = GetMenu(ntAPopupID);
  2612.  
  2613. }
  2614.  
  2615. static void handle_menus(choice)    /* handle application specific menus */
  2616. long choice;
  2617. {
  2618. if(hiword(choice)==appleID)
  2619.     about_box();
  2620. else if(hiword(choice)==prefID)
  2621.     switch(loword(choice)) {
  2622.     case pmOptions:
  2623.         if(dirty_buffers()) flush_buffers();
  2624.         options_box();
  2625.         break;
  2626.     case pmEnglish:{
  2627.         int markChar;
  2628.         in_Italia^=1;
  2629.         GetItemMark (myMenus[prefM],pmEnglish,&markChar);
  2630.         CheckItem(myMenus[prefM],pmEnglish,!markChar);
  2631.         }
  2632.         break;
  2633.     case pmConfirm:
  2634.         set_skip_all(-1);
  2635.         break;
  2636. #ifdef V_122
  2637.     case pmSmallText:
  2638.         CheckItem(myMenus[prefM],pmSmallText, smallFilesAreASCII^=1);
  2639.         preferences_changed=true;
  2640.         break;
  2641. #endif
  2642.     case pmExpert:
  2643.         CheckItem(myMenus[prefM],pmExpert,expert_mode ^=1);
  2644.         if(expert_mode){
  2645.             add_expert_menu();
  2646.             }
  2647.         else{
  2648.             DelMenuItem (myMenus[prefM], pmNoConvers);
  2649.             DelMenuItem (myMenus[prefM], pmIgnore);
  2650.             DeleteMenu (hackID);
  2651.             ignore_errors=non_convertire=false;
  2652.             }
  2653.         DrawMenuBar();
  2654.         preferences_changed=true;
  2655.         break;
  2656.     case pmIgnore:
  2657.         CheckItem(myMenus[prefM],pmIgnore,ignore_errors^=1);
  2658.         break;
  2659.     case pmNoConvers:
  2660.         CheckItem(myMenus[prefM],pmNoConvers,non_convertire^=1);
  2661.         break;
  2662.     }
  2663. else if(hiword(choice)==hqxID){
  2664.     preferences_changed=true;
  2665.     switch(loword(choice)){
  2666.     case bmDisable:
  2667.         CheckItem(hqxM,bmDisable,(disable_binhex^=1)&1);
  2668.         break;
  2669.     case bmShowExtr:
  2670.         CheckItem(hqxM,bmShowExtr,((disable_binhex^=2)&2)!=0);
  2671.         break;
  2672.     case bmSaveInfo:
  2673.         CheckItem(hqxM,bmSaveInfo,((disable_binhex^=8)&8)!=0);
  2674.         break;
  2675.     case bmShowList:
  2676.         CheckItem(hqxM,bmShowList,((disable_binhex^=4)&4)!=0);
  2677.         break;
  2678.     }
  2679.     }
  2680. else{    /* fileID o writeID oppure hackID, tanto non sono mai abilitati insieme, 
  2681.         e comunque non butto via l'informazione
  2682.         -- I don't serve the command, rather I remember that it was selected.
  2683.         That's a matter of program hierarchy: MainEvent is a slave, it's not the
  2684.         master, hence important operations are not executed under it, and
  2685.         this routine is called from it.
  2686.         */
  2687.  
  2688.     if(choice==menuItemMess(fileID,fmSelect)&&ListDialog&&
  2689.         ListDialog != FrontWindow() ){
  2690.         SelectWindow(ListDialog);
  2691.         }
  2692.     else
  2693.         last_selection= choice;
  2694.     }
  2695. }
  2696.  
  2697.  
  2698. static int my_quit_handler()
  2699. {
  2700.  
  2701. if(((abort_mask>>fase)&1) && fase!=in_writing){    /* it's the condition used for the abort menu item */
  2702.     ParamText(in_Italia?"\pVuoi interrompere il comando in corso ?":
  2703.         "\pDo you want to abort the current command and quit ?",PNS,PNS,PNS);
  2704.     beep_in_foreground();
  2705.     if(my_modal_dialog(139,titoli,2)==2) return 0;
  2706.     }
  2707.  
  2708. check_and_eject();    /* ejects the disk and, if writing, truncates... */
  2709.  
  2710. if(!preferences_changed) return 1;
  2711.  
  2712. /* save the preferences settings */
  2713. if(expert_mode){
  2714.     DelMenuItem (myMenus[prefM], pmNoConvers);
  2715.     DelMenuItem (myMenus[prefM], pmIgnore);
  2716.     }
  2717. (**myMenus[prefM]).menuProc=NULL;    /* without it, horrible things happen */
  2718. ChangedResource(myMenus[prefM]);
  2719. WriteResource(myMenus[prefM]);
  2720.  
  2721. (**hqxM).menuProc=NULL;
  2722. ChangedResource(hqxM);
  2723. WriteResource(hqxM);
  2724. return 1;
  2725. }
  2726.