home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************\
-
- main module
-
- suntar 1.3, ⌐1991-92 Sauro & Gabriele Speranza
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
-
- #include "PB_sync.h"
- #include "antiglue.h"
-
- /*#include <EventMgr.h>
- #include <QuickDraw.h>
- #include <StdFilePkg.h>
- */
- #include <IntlPkg.h>
- /*
-
- #include <DiskDvr.h>
- #include <DeviceMgr.h>
- */
-
- #include <string.h>
-
- #include "windows.h"
- #include "suntar.h"
-
- #define dp printf /* use it for debug, so it's easy to */
- /* find&delete all the extra print instructions */
-
-
- MenuHandle writeMenu,hackersMenu,tarPopupMenu,ntAPopupMenu;
-
- int err_code;
- short drive_number=0;
-
- options_type options;
- long last_selection=0;
- short again_command=0;
- sector_t sectors_on_floppy;
- OSType tar_creator,bar_creator,bar_type;
- static Boolean append_mode;
- Boolean in_Italia=false;
- Boolean ignore_errors=false;
- Boolean confirm_saves=false;
- Boolean expert_mode=false;
- Boolean non_convertire=false;
- Boolean disco_espulso; /* was my disk ejected ? */
- Boolean sto_lavorando=false; /* non usarlo se non per lo scopo attuale, dire al calcolo del
- tempo di sleep per WaitNextEvent di ritornare sempre 0, e sapere
- se devo abilitare il comando Pause
- -- consider it as a read only variable !*/
- unsigned char file_aperto=0;
- static unsigned char check_ev_timing;
- #ifdef V_122
- Boolean smallFilesAreASCII;
- #endif
- short disable_binhex; /* bit 0: disable conversion
- bit 1: show info in extract
- bit 2: show info in list
- bit 3: save .info */
-
- short last_drive,preferred_drive;
- short back_prio;
-
- struct disk_info di;
-
- static Boolean preferences_changed=0; /* Apple (TN 188) discourages to call
- ChangedResource if it's not followed immediately by WriteResource,
- and I want to modify the file only once, and not to modify it if nothing
- changed */
- sector_t settori_passati;
-
- enum tipo_fase fase;
- short n_superdrives;
- sector_t file_current_s;
- short drive_type[max_drive];
- extern sector_t next_header_for_AIX;
- unsigned char window_title[]="\psuntar 1.3 - console";
- short default_flags =READONLY|CONSOLE|NOCLOSEBOX;
- extern short floppy_buffer_size;
- extern unsigned int hd_buffer_size;
-
- void handle_menus(long);
- void add_menu(void);
- int my_quit_handler(void);
-
-
- static char diskReadErrMsg[]="Disk read error %d\n",
- diskReadErrIta[]="Errore di lettura ní %d\n";
- static char diskWriteErrMsg[]="Disk write error %d\n";
- char DONE[]="Done\n",FINITO[]="Finito\n";
- char START_READ[]="Start reading\n";
-
-
- /***************** main ******************/
-
-
- /*
- suntar use an architecture which is unusual, at least in the Mac world:
- it has not a main event loop.
- When you have passed the first wave of horror and astonishment, I'll
- tell you how it works.
- The MainEvent routine calls GetNextEvent and serves the event, but:
- 1) it returns to the caller, it does not loop internally
- 2) it does not know how to serve all events, since it's part of the
- windows module and does not know anything about the tar/untar modules:
- you must enlarge its capabilities by providing an event filter and an
- "application specific menus handler", and maybe some "updaters" and
- "activaters" for windows (e.g. other filters)
- 3) some menu items are handled immediately, but others only set the
- "last_selection" variable which the caller then examines and handles.
- That is, MainEvent is a relatively low-level routine, which is not allowed to
- take important decisions.
- So, suntar has several event loops, which call MainEvent, usually after installing
- different event filters. Furthermore, MainEvent is called periodically
- while suntar is working, with one further event filter which disables all the
- events which are not essential. This architecture may easily emulate
- a typical Mac behaviour, but it's more flexible and powerful.
- Finally, MainEvent was broken into two parts, and sometimes one calls
- the two parts, doing its own event handling between the two calls, so reducing the
- need for a lot of filters.
- */
-
- void main()
- {
- int command;
-
- /* install the handlers for events which the window module doesn't know how
- to handle */
- my_handle_menus=handle_menus;
- my_add_menus=add_menu;
-
- /* initialize everything */
- /* l'ordine Å importante perchÄ a) ci sono delle dipendenze da variabili
- inizializzate da un'altra di esse, e b) determina dove sono caricate le
- risorse di codice e quindi la frammentazione della memoria */
- init_hqx_tab();
- InitConsole();
- prefs_da_risorsa();
- init_hd_buffering();
- init_buffering();
-
- /* look at what disk drives and device driver are available */
- identifica_hardware();
-
- /* install the Quit handler */
- my_at_exit= my_quit_handler;
-
- /* main loop */
-
- /* debugging: open a second window so debugging prints don't mix with the
- normal outputs * /
- printf("inizio\n");
- pStrcpy(window_title,"\pDebug");
- new_window();
- / * */
-
- for(;;){
- fase=non_faccio_nulla;
- set_skip_all(0);
- close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
-
- last_selection=0;
- while(last_selection==0)
- MainEvent();
- fase=ricevuto_comando;
- settori_passati=0;
-
- /* sono possibili solo i men¥ Special e File, perchÄ Preferences ed Edit sono gestiti
- subito e Write non Å abilitato */
- if(hiword(last_selection)==hackID){
- if(loword(last_selection)==hmDriveList)
- DriveList(); /* it's the only command which needs no disk...*/
- else
- hacking(loword(last_selection));
- }
- /* non faccio else perchÄ si puÿ uscire dall'hacking anche con un comando
- del men¥ File, che va eseguito
- -- don't do 'else': I can exit from hacking with a File menu command which must be
- executed */
-
- command=loword(last_selection);
-
- if(hiword(last_selection)==fileID){
- again_command=0;
- last_selection=0;
- if(command==fmGetInfo){
- listonly=2;
- apri_archivio();
- }
- else if(command==fmOpen){
- listonly=0;
- apri_archivio();
- }
- else if(command==fmClose){
- if(file_aperto)
- chiudi_archivio();
- else
- diskEject();
- }
- else if(command ==fmCopy)
- copia_da_disco_a_file();
- else if(command==fmList){
- listonly=1;
- estrai_da_floppy();
- }
- else if(command==fmExtract){ /* extract, con de-macBinarizzazione e conversione LF->CR */
- listonly=0;
- estrai_da_floppy();
- }
- else if(command==fmSelect)
- select_and_extract();
- else if(command==fmWriteTar||command==fmWriteBar||command==fmAppend){
- bar_archive= command==fmWriteBar; /* non valido nel caso di append */
- append_mode= command==fmAppend;
- scrivi_su_floppy();
- }
- else if(command==fmFormat){
- disk_initialize();
- }
- }
- }
- }
-
- /**************** apri/chiudi archivio su file ***********/
-
- void apri_archivio() /* open a file archive */
- {
- long filesize;
- int nLF,forza_formato;
- FileParam fpb;
- Boolean not_ask_type,do_not_open;
- extern long file_date;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- if(listonly){
- SFTypeList myTypes;
- my_SF_Get(-1,myTypes);
- if(!reply.good) return;
- not_ask_type=true;
- }
- else{
- if(! get_file_with_checkbox(¬_ask_type)) return;
- }
-
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
- fpb.ioVRefNum=reply.vRefNum;
- fpb.ioNamePtr=reply.fName;
- if (PBGetFInfoSync(&fpb)) pbsyserr(&fpb);
- filesize=fpb.ioFlLgLen;
- sectors_on_floppy= (filesize+511)>>9;
-
- if(listonly){
- disable_autoflush();
- one_empty_line();
- printf("File %p ",reply.fName);
- printf("(data %ld+res %ld bytes)",fpb.ioFlLgLen,fpb.ioFlRLgLen);
- #if 0
- #define ALIAS_BIT 0x8000
- if(fpb.ioFlFndrInfo.fdFlags & ALIAS_BIT) printf(" alias"); /* currently
- that's useless, I'm using a non-custom standard file, which resolves aliases ! */
- #endif
- printf("\n");
- print_one_date(fpb.ioFlCrDat,in_Italia?"creato ":"created ");
- printf("\n");
- print_one_date(fpb.ioFlMdDat,in_Italia?"modificato ":"modified ");
- printf("\n");
- print_type_creator(fpb.ioFlFndrInfo.fdType,fpb.ioFlFndrInfo.fdCreator);
- printf("\n");
- enable_autoflush();
- }
- else
- one_empty_line();
-
- pStrcpy(tarh.name,reply.fName);
- p2cstr(tarh.name); /* these statements are useful only if the file is not */
- bar_archive=0; /* a tar/bar archive */
-
- /* tarh.mtime is examined later, nothing bad happens if it contains garbage
- but that's not good programming style */
- strcpy(tarh.mtime,"0");
- sect_n=0;
- end_of_file(); /* forse non necessario, ma prudente */
- copia_ultimo_header(&tarh,(sector_t)0); /* gli devo passare il numero del
- settore successivo all'header */
-
- if(filesize!=0 && !not_ask_type)
- forza_formato=dialogo_tipo_file();
- else
- forza_formato=0;
-
- do_not_open=true;
- if(!forza_formato && fpb.ioFlFndrInfo.fdType=='APPL')
- printf(in_Italia?"Applicazione\n":"Application\n");
- else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='INIT')
- printf(in_Italia?"Estensione\n":"Extension\n");
- else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='cdev')
- printf(in_Italia?"Pannello di controllo\n":"Control panel\n");
- else if(!forza_formato && (fpb.ioFlFndrInfo.fdType=='DFIL'||fpb.ioFlFndrInfo.fdType=='dfil'))
- printf(in_Italia?"Accessorio di scrivania\n":"Desk Accessory\n");
- else if(filesize==0)
- printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
- else
- do_not_open=false;
- if(do_not_open){
- if(!listonly) printf(in_Italia?"Questo tipo di file non puÿ essere aperto da suntar\n":
- "This file type can\'t be opened by suntar\n");
- return;
- }
-
- /* Open the file only now, and don't open files with empty data fork:
- Disk Doubler extracts the resource fork of compressed files if I do that,
- but that's time consuming and useless */
-
- if(apri_file("rb",&inputFile))
- return;
-
- inf_is_open=true;
- file_aperto=ff_tarbar;
- file_current_s=-1;
-
- if(forza_formato==ff_packit || forza_formato==0 && fpb.ioFlFndrInfo.fdType=='PIT '){
- /* don't examine the creator, there is at least one program (unpit)
- which creates PackIt files with another creator ('UPIT') */
- if(listonly)
- printf(in_Italia?"Archivio PackIt\n":"PackIt archive\n");
- else{
- select_directory();
- if(reply.good){
- file_date= -1;
- one_empty_line();
- printf(in_Italia?"Estrazione da archivio PackIt %s\n":
- "Unpacking PackIt archive %s\n", tarh.name);
- my_unpit();
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if(!forza_formato&&is_hqx_name()||forza_formato==ff_binhex){
- macbinh.cdate=fpb.ioFlCrDat;
- macbinh.mdate=fpb.ioFlMdDat;
- /* dopo di che non deve essere chiamato chkmacbin, che scarabocchia su macbinh...*/
-
- file_aperto=ff_binhex;
- fase=reading_disk;
-
- if(listonly)
- untar_file(filesize);
- else{
- select_directory();
- if(reply.good){
- one_empty_line();
- untar_file(filesize);
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if((forza_formato==0 || forza_formato==ff_macbin||forza_formato==ff_c_macbin) &&
- chkmacbin (filesize,forza_formato)){
- file_aperto=ff_macbin;
- fase=reading_disk;
-
- copia_ultimo_header(&tarh,(sector_t)0);
- if(listonly)
- untar_file(filesize);
- else{
- select_directory(); /* per la veritê, salvando un solo file potrei usare uno
- standard put, ma significherebbe fare modifiche pi¥
- pesanti di quanto non voglia
- --having only one file to save I could use SFPutFile, but
- the existing routines don't expect more than a destination
- folder, and suntar was NOT meant as a file format converter,
- even if it can convert file formats, hence these commands
- are implemented according to the principle of "do that in
- the fewest statements with the fewest changes to existing
- routines"
- */
- if(reply.good){
- one_empty_line();
- untar_file(filesize);
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if(forza_formato==ff_macbin||forza_formato==ff_c_macbin)
- error_message(in_Italia?"Formato non MacBinary\n":"Not a Macbinary file\n");
- else if(forza_formato==ff_ASCII||!forza_formato && isASCII(filesize,&nLF)>0 ){
- file_aperto=ff_ASCII;
- fase=reading_disk;
-
- if(listonly){
- printf(in_Italia ?"Contenente testo ASCII":"Containing ASCII text");
- if(nLF>0) printf(in_Italia?" con LF":" using LF");
- printf("\n");
- }
- else if(nLF==0){
- printf(in_Italia?"Testo ASCII in formato Macintosh, nessuna conversione\n":
- "ASCII text in Macintosh format, no conversion\n");
- chiudi_archivio();
- }
- else{
- if(reply.fName[0]>63-4) reply.fName[0]=63-4;
- pStrcat(reply.fName,"\p.out");
- my_SF_Put(in_Italia?"\pSalva testo Mac col nome:":"\pSave Mac text as:",reply.fName);
- if(reply.good){
- register int i,j;
- if(new_text_file(&info_file)==0){
- printf(in_Italia?"Converto %s in %p\n":"Converting %s to %p\n",tarh.name,reply.fName);
- info_file_open=1;
- while(filesize>0){
- if(filesize>=512L) i=512; else i= (int)filesize;
- filesize -= i;
- if(readblock(disk_buffer,i)!=0)
- error_message_1("Disk read error %d\n",err_code);
- for(j=0;j<512;j++)
- if(disk_buffer[j]==LF) disk_buffer[j]=CR;
- if(mac_fwrite(disk_buffer,i,info_file)<0)
- error_message("File write error!\n");
- }
- FSClose(info_file);
- info_file_open=0;
- }
- else
- error_message(in_Italia?"Errore nell\'apertura del file\n":"Error opening file\n");
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else{ /* the file is opened as a tar/bar archive */
- if(!listonly){
- one_empty_line();
- printf(in_Italia?"Apertura file %s\n":
- "Opening file %s\n", tarh.name);
- (void)identify_format();
- /*printf("\n");*/
- }
- else
- (void)identify_format();
- }
- if(listonly){
- chiudi_archivio();
- /*printf("\n");*/
- }
- }
-
- void chiudi_archivio()
- {
- inf_is_open=false;
- file_aperto=0;
- FSClose(inputFile);
- }
-
- /***************** copia da disco a file ******************/
-
- void copia_da_disco_a_file() /* copy a disk archive to a file archive */
- /* trasferisce quello che vede in un file tar, senza estrarre i singoli files */
- {
- sector_t more_sectors;
- short inPlace;
- Boolean fine;
- long length;
- int outputFile;
- static unsigned char nome_ita[]="\parchivio", eng_name[]="\parchive";
-
- listonly=0; /* ad uso di floppy swap, le altre routines non le chiamo */
-
- if(setjmp(main_loop)<0) {
- FSClose(outputFile); /* non lo metto in raise_error... */
- return;
- }
-
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
- "\pInsert the disk in UNIX format") || di.is_not_initialized){
- FSClose(outputFile);
- return;
- }
-
-
- more_sectors=0;
-
- fase=reading_disk;
- bar_archive= identify_format()==bar_format;
-
- if(bar_archive){
- if( my_atoi(((barh_type*)disk_buffer)->volume_num,&floppy_n)) floppy_n = -1;
- if(floppy_n!=1) error_message(in_Italia?"Questo non Å il primo disco\n":
- "That\'s not the first disk\n");
- }
-
- pStrcpy(disk_buffer,in_Italia?nome_ita:eng_name);
- pStrcat(disk_buffer,bar_archive?"\p.bar":"\p.tar");
-
- my_SF_Put(in_Italia?"\pSalva col nome:":"\pSave as:",disk_buffer);
- if(!reply.good) return;
-
- if(apri_file("wb",&outputFile)) return;
-
- one_empty_line();
- printf(in_Italia?"Inizio lettura\n":START_READ);
-
- if(!bar_archive)
- tar_check_floppy_swap(1); /* ci sono delle inizializzazioni */
- else{
- leggi_settore(0,&disk_buffer);
- if(check_error()) raise_error();
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- error_message("Write error\n");
- }
- bar_check_floppy_swap(1);
- }
-
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
-
- do{
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- error_message("Write error\n");
- }
- check_events();
- fine = more_sectors==0; /* fine del file corrente
- -- end of current file ? */
- if(fine){
- fine= check_all_zero(disk_buffer); /* fine dell'intero archivio
- -- end of the archive ? */
- if(!fine){
- unsigned char linkflag = get_linkflag(&length);
- last_offset=0;
- copia_ultimo_header(disk_buffer,sect_n+1); /* gli devo passare il numero del
- settore successivo all'header, da qui il +1 */
- if(length<0)
- fine=true;
- else{
- print_info(bar_archive?((barh_type*)disk_buffer)->name:disk_buffer,length);
- more_sectors=(length+511)/512;
- }
- }
- }
- else
- more_sectors--;
-
- if(!fine){
- sect_n++;
- if(bar_archive)
- bar_check_floppy_swap(more_sectors==0?-1:0);
- else
- tar_check_floppy_swap(more_sectors==0?-1:0);
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- }
- }
- while(!fine);
-
- one_empty_line();
- printf(in_Italia ? "Lettura completata\n" : "Read completed\n");
- diskEject();
- FSClose(outputFile);
- fine_lavoro();
- }
-
- /***************** estrai da floppy ******************/
-
- void estrai_da_floppy() /* extract or list */
- {
- enum formats fmt;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- if(!listonly){
- select_directory();
- if(!reply.good) return;
- }
-
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
- "\pInsert the disk in UNIX format") ||di.is_not_initialized) return;
- one_empty_line();
- printf(in_Italia?"Inizio lettura\n":START_READ);
-
- disco_espulso=!listonly; /* per un extract non mi interessa impedire di espellere... */
- fase=reading_disk;
-
- fmt=identify_format();
- if(fmt==tar_format)
- my_untar();
- else if(fmt==bar_format)
- my_unbar();
-
- if(disco_espulso) diskEject();
- fine_lavoro();
- }
-
-
- /************ scrivi su floppy ******************/
-
-
- void scrivi_su_floppy() /* handling of the Write menu */
- {
- Boolean ok_to_proceed;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- ok_to_proceed=false;
- do{
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco su cui scrivere":
- "\pInsert the disk to be written")) return;
-
- if(is_wrprot()){
- printf_protetto();
- SysBeep(5);
- return;
- }
-
- if(di.is_not_initialized){
- disk_format(false);
- if(drive_number==0 && append_mode) return;
- }
- else
- ok_to_proceed=true;
- }
- while(!ok_to_proceed);
-
- warning_400_800();
-
- leggi_settore(0,&disk_buffer); /* serve come controllo di errore, e poi non so,
- potrebbe essere utile per la faccenda del TagBuffer */
- if(check_error())return;
-
- fase=reading_disk;
-
- reset_sector_count();
- one_empty_line();
- if(append_mode){
- cerca_fine();
- }
- else
- printf(in_Italia?"Nuovo archivio %car\n":"New %car archive\n",bar_archive?'b':'t');
-
- for(;;){
- unsigned char itemname[32];
- fase=in_writing;
- print_ready();
- settori_passati=0;
- EnableItem(writeMenu, 0);
- GetIndString (itemname,128,bar_archive?2:1);
- SetItem (writeMenu,wmWriteTar,itemname);
-
- DrawMenuBar();
- close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
- last_selection=0;
- while(last_selection==0)
- MainEvent();
- DisableItem(writeMenu, 0);
- DrawMenuBar();
-
- if(last_selection==menuItemMess(fileID,fmAbort)||
- last_selection==menuItemMess(writeID,wmEndWrite)||
- last_selection==menuItemMess(fileID,fmEject) ){
- if(last_selection!=menuItemMess(writeID,wmEndWrite)) diskEject();
- return;
- }
- else if(hiword(last_selection)==writeID){
- my_tar(loword(last_selection));
- fine_lavoro();
- }
- /* non ci sono altri men¥ attivi: in principio pensavo di lasciare il List
- (senza espellere!) ma non serve, man mano che scrivo files sulla console
- vengono scritti i nomi ! */
- }
- }
-
-
- void disk_initialize()
- {
- short inPlace;
- int i;
-
- fase=initializing;
-
- i=aspetta_inserzione(in_Italia ? "\pInserisci il disco da inizializzare":
- "\pInsert the disk to be initialized");
-
- i=testa_stato(&inPlace,0);
- if(i!=0 || !inPlace){
- diskEject();
- return;
- }
- if(is_wrprot()){
- printf_protetto();
- SysBeep(5);
- return;
- }
- if(warning_first_write(1)<0){
- diskEject();
- return;
- }
-
- disk_format(crea_mac_dir);
- if(drive_number){
- if(testa_stato(&inPlace,1)){
- diskEject();
- }
- }
- }
-
-
- /*************************************************/
-
- enum formats identify_format()
- /* asks to the device driver about the current disk, than examines the
- first sectors to see whether it's a tar or bar archive */
- {
- int i;
- sector_t j;
- #define SUPERDRIVE 4
-
- leggi_settore(0,disk_buffer);
- if(err_code<0){
- SysBeep(5);
- if(file_aperto){
- if(err_code==eofErr)
- printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
- else
- printf("File access error %d\n",err_code);
- }
- else if( drive_number<=4 && (i=drive_type[drive_number-1]&0x0F)!= SUPERDRIVE &&
- i!= SUPERDRIVE+1){
- printf(in_Italia ? "Disco non inizializzato o in formato 720/1440K\n" :
- "The disk is either uninitialized or 720/1440K\n");
- printf(in_Italia ? "Prova a inserirlo in un Superdrive" :
- "Try to insert it in a SuperDrive");
- if(n_superdrives==0)
- printf(in_Italia?" (su un Macintosh che ce l\'abbia)":
- " (on a Macintosh which has one)");
- printf("\n");
- }
- else if(di.is_not_initialized)
- printf(in_Italia ? "Disco non inizializzato\n" :
- "The disk is not initialized\n");
- else
- printf(in_Italia ? "Disco illeggibile\n" :
- "The disk is unreadable\n");
-
- return unreadable_disk;
- }
- previousFormat=tar_unknown;
- i = tar_check_settore0(false);
- if(i>=0){
- if(previousFormat==tar_GNU)
- printf(in_Italia ? "Archivio in formato GNU tar\n" : "GNU tar archive\n");
- else
- printf(in_Italia ? "Archivio in formato tar\n" : "Tar archive\n");
- return tar_format;
- }
- i= bar_check_settore0(&j,false);
- if(i>=0){
- printf(in_Italia ? "Archivio in formato bar\n" : "Bar archive\n");
- return bar_format;
- }
- else{
- /* I controlli fatti da quelle routines sono rigorosi, basta che il checksum
- sia sbagliato... non vorrei solo per quello perdere ogni
- possibilitê di esaminare il disco, la vecchia versione non Å affatto rigida in
- proposito e neanche la nuova lo Å per gli altri header, quindi faccio una
- discriminazione molto pi¥ approssimativa, tanto my_untar e my_unbar poi hanno
- dei controlli di errore */
-
- if(((barh_type*)disk_buffer)->bar_magic[0]== 'V' &&
- untar_number(((barh_type*)disk_buffer)->volume_num,-1)!=-1){
- printf(in_Italia ? "Archivio in probabile formato bar\n" : "It looks like a bar archive\n");
- return bar_format;
- }
- else if(untar_number(((tarh_type*)disk_buffer)->size,-1)!=-1 &&
- untar_number(((tarh_type*)disk_buffer)->mtime,-1)!=-1){
- printf(in_Italia ? "Archivio in probabile formato tar\n" : "It looks like a tar archive\n");
- return tar_format;
- }
- else{
- if(fase!=hack_listing){
- SysBeep(5);
- disable_autoflush();
- if(file_aperto)
- printf(in_Italia ? "Il file" : "The file");
- else
- printf(in_Italia ? "Il disco" : "The disk");
- printf(in_Italia ? " non Å in formato tar nÄ bar" :
- " format is neither tar nor bar");
- if(!file_aperto&&tar_version==tar_AIX)
- printf(in_Italia?" (ma potrebbe essere un disco tar oltre il primo)":
- " (but it could be a tar disk following the first one)");
- printf("\n");
- enable_autoflush();
- }
- return unknown_format;
- }
- }
- }
-
-
- /***************** apri file *********************/
-
- short apri_file(modo,who) /* opens a file */
- char *modo;
- int *who;
- {
- int io;
-
- reply.fName[reply.fName[0]+1]='\0'; /* per il caso debba fare una printf...*/
- /* SetVol(NULL,reply.vRefNum); setta la directory: inutile */
-
- if(modo[0]=='r')
- io=FSOpen (reply.fName, reply.vRefNum, who);
- else if(modo[0]=='w')
- if(bar_archive)
- io=create_overwrite(bar_creator, bar_type, who);
- else
- io=create_overwrite(tar_creator, 'TARF', who);
- if(io!=noErr) {
- start_of_line();
- printf("failure opening %p\n",reply.fName);
- return -1;
- }
- return 0;
- }
-
- OSErr new_text_file(outputFile) /* creates and opens a text file */
- int *outputFile;
- {
- int io;
- /* SetVol(NULL,reply.vRefNum); setta la directory: inutile e pericoloso */
-
- return create_overwrite(text_creator, 'TEXT',outputFile);
- }
-
- OSErr create_overwrite(c,t,who)
- OSType t,c;
- int *who;
- {
- OSErr io;
- io=Create(reply.fName, reply.vRefNum, c, t);
- if (io==noErr)
- io = FSOpen( reply.fName, reply.vRefNum, who );
- else if(io==dupFNErr){
- io = open_overwrite( reply.fName, reply.vRefNum, who );
- if(io==noErr){
- /* settare tipo e creatore: certo se il file esiste giê dovrebbero
- essere gli stessi, ma meglio non fidarsi !
- -- type and creator must be modified
- */
- FileParam fpb;
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
- fpb.ioVRefNum=reply.vRefNum;
- fpb.ioNamePtr= &reply.fName;
- if (PBGetFInfoSync(&fpb)==noErr){
- fpb.ioFlFndrInfo.fdType=t;
- fpb.ioFlFndrInfo.fdCreator=c;
- PBSetFInfoSync(&fpb);
- }
- }
- }
- return io;
- }
-
- int mac_fread(buff,nbytes,refNum)
- char *buff;
- {
- long count = nbytes;
- if( (err_code=FSRead( refNum, &count, buff )) != noErr){
- if(err_code==eofErr && count!=0){
- fillmem(&buff[count],0,512-(int)count);
- err_code=noErr;
- }
- else
- return -1;
- }
- return (int) count;
- }
-
- int mac_fwrite(buff,nbytes,refNum)
- char *buff;
- {
- long count=nbytes;
- if( FSWrite( refNum, &count, buff ) != noErr )
- return -1;
- return (int)count;
- }
-
- OSErr open_overwrite (fileName,vRefNum,refnum)
- /* apre la data fork del file, tagliando a zero bytes sia questa sia la
- resource fork
- -- opens the file data fork, truncating it and the resource fork to zero length
- */
- char *fileName;
- int *refnum;
- {
- short i = FSOpen(fileName,vRefNum, refnum);
- if(i==noErr){
- SetEOF(*refnum,0L);
- if( OpenRF (fileName,vRefNum,&i)==noErr){
- SetEOF(i,0L);
- FSClose(i);
- }
- i=noErr;
- }
- return i;
- }
-
- /**************** gestione eventi durante le operazioni ************/
-
- Boolean my_disk_is_in()
- {
- /* Called before exiting from a pause: checks whether the disk is where is
- expected, and if there are some obvious reasons to believe it's not the
- expected disk
- */
- static char s1[]="Disco cambiato !\n",
- s2[]="Changed disk !\n";
- {
- short inPlace;
- sector_t old_s=sectors_on_floppy;
- if (testa_stato(&inPlace,0) || !inPlace){
- printf(in_Italia?"Disco assente !\n" : "Missing disk !\n");
- return false;
- }
- if(sectors_on_floppy!=old_s){
- sectors_on_floppy=old_s;
- printf(in_Italia?s1:s2);
- return false;
- }
- sectors_on_floppy=old_s;
- }
- {
- char buffer[512];
- int refnum;
- long space;
- enum os_type i;
- if( GetVInfo (drive_number, buffer, &refnum,&space) == nsvErr ) return true;
- /* no such volume: a non-Mac disk is not mounted hence...*/
- read_one_sector(2,buffer,drive_number);
- if(!err_code) i=riconosci_disco_mac(buffer);
- if(err_code || i!=mac_HFS&&i!=mac_MFS){
- UnmountVol (NULL,drive_number); /* however,
- in some cases (see comments to de_Mac_ize) it's mounted, at least if
- suntar is not in foreground */;
- return true;
- }
- printf(in_Italia?s1:s2);
- return false;
- }
- }
-
- void handle_pause()
- {
- enum tipo_fase old=fase;
- extern DialogPtr ListDialog;
- fase=paused;
- last_selection=0;
-
- if(my_windows[0].used) SetWTitle (&my_windows[0],in_Italia?"\p<< in pausa >>":"\p<< paused >>");
- {unsigned char itemname[32];
- GetIndString(itemname,129,4);
- SetItem (myMenus[fileM], fmPause, itemname);
- }
- if(dirty_buffers()) flush_buffers();
-
- while(last_selection!=menuItemMess(fileID,fmPause) &&
- last_selection!=menuItemMess(fileID,fmAbort)){
- MainEvent(); /* be', non tutti
- i filtri ha senso chiamarli anche durante un pause, ma in realtê
- il pause non Å attivo durante i filtri che "lavorano" come
- quello del disk insertion, restano solo quelli dei dialoghi che
- vanno chiamati perchÄ gestiscono gli update
- --not all filters must continue to be called during a pause,
- but when pause is enabled some filters are not used, and the
- filters of semimodal and of the selection dialog must be called
- during pauses
- */
- if(last_selection==menuItemMess(fileID,fmPause) && drive_number && !my_disk_is_in() ){
- last_selection=0;
- }
- }
- if(last_selection==menuItemMess(fileID,fmPause)) last_selection=0;
- {unsigned char itemname[32];
- GetIndString(itemname,129,3);
- SetItem (myMenus[fileM], fmPause, itemname);
- }
- if(my_windows[0].used) SetWTitle (&my_windows[0],window_title);
- fase=old;
- }
-
- Boolean check_filter(EventRecord *);
- static Boolean check_filter(theEvent)
- /* event filter used while suntar is working: most events are ignored
- without being handled
- */
- EventRecord *theEvent;
- {
- switch(theEvent->what){
- case keyDown:
- if(theEvent->modifiers&cmdKey) break; /* se accetta la selezione men¥ deve
- accettare anche i command-tasto */
- /* else prosegui in sequenza
- -- else, since there is no break, continue with the following instruction */
- case autoKey:
- return false; /* the event must not be handled */
- break;
- case mouseDown:
- {
- WindowPtr whichWindow;
- int code=FindWindow( theEvent->where, &whichWindow );
- if(code!=inMenuBar && code!=inSysWindow && code!=inDrag &&
- code!=inGrow && whichWindow==FrontWindow())
- return false;
- else
- SetCursor(&arrow);
- }
- break;
- }
- return true;
- }
-
-
- void check_events()
- /* handle the events which are allowed while suntar is working, including
- the Pause command
- */
- {
- EventRecord myEvent;
-
- /* We've discovered that, in typical file extractions, check_events occupied up
- to 35% of processing time, even if no event was pending. Hence, events must be
- checked less often, but with care, otherwise suntar would lose its feel (it's
- good to be able to change preferences on the fly, and while it's working in
- background one does not like to notice a huge speed difference in the foreground
- application) */
-
- ++check_ev_timing;
- if( check_ev_timing< (gInBackground?back_prio:(fase!=reading_disk&&fase!=hack_listing||
- !listonly)?18:3) ){
- EventRecord myEvent;
- if((check_ev_timing&1) || !OSEventAvail(everyEvent,&myEvent))
- return;
- }
- check_ev_timing=0;
-
- if(last_selection!=menuItemMess(fileID,fmPause)){
- sto_lavorando=true;
-
- /* what follows is the body of MainEvent, with an extra call in order to ignore
- all the events which are not urgent */
-
- if(get_event(&myEvent)){
- if(check_filter(&myEvent)){
- if(my_event_filter!=NULL) (*my_event_filter)(&myEvent);
- handle_event(&myEvent);
- }
- }
- sto_lavorando=false;
- }
- if(last_selection==menuItemMess(fileID,fmPause))
- handle_pause();
- accept_abort_command();
- }
-
- short check_error_and_events()
- {
- /* in theory it's:
- if(check_error()) return -1;
- check_events();
- return 0;
- in practice, it was extended to transform a "missing disk" error to a pause,
- so you (and we) won't lose your work for an unwanted eject (it happened to us
- for a 4Megabytes file, filling 3 disks, and we had to start again after
- half an hour of work in background). But the caller must read the sector again,
- hence a new return code of 1
- */
- if(err_code!=-65){
- if(check_error()) return -1;
- check_events();
- return 0;
- }
- else{
- beep_in_foreground();
- start_of_line();
- printf(in_Italia?"Disco assente, pausa forzata\n":"Missing disk, a pause was forced\n");
- last_selection=menuItemMess(fileID,fmPause);
- check_events();
- return 1;
- }
- }
-
- void accept_abort_command()
- {
- if(last_selection == menuItemMess(fileID,fmAbort)){
- one_empty_line();
- error_message(in_Italia?"Comando abortito\n":"Command aborted\n");
- }
- }
-
- Boolean is_abort_command()
- /* external routines must not know how I receive the Abort command,
- but they must be able to know when they must abort themselves */
- {
- return last_selection == menuItemMess(fileID,fmAbort);
- }
-
- Boolean is_pause_command()
- {
- return last_selection == menuItemMess(fileID,fmPause);
- }
-
- /****************** gestione dialogo di inserzione *********/
-
- int filter_insert(EventRecord*);
- static int filter_insert(theEvent)
- EventRecord*theEvent;
- {
- if(theEvent->what==diskEvt){
- drive_number=loword(theEvent->message);
-
- if(drive_number<=last_drive){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol (NULL,drive_number); /* smonta qualunque
- cosa si trovasse in precedenza in quel drive, e il disco stesso se Å stato
- montato: inutile guardare al codice di errore ritornato
- -- the Finder often mounts even a tar archive, if it was formatted on a Mac
- (see de_Mac_ize in tar.c): anyway, it must not be mounted if I want to use
- it without being disturbed by the Finder; the returned error code may be
- ignored, I don't worry to call this only when it was mounted...
- */
- }
- return -1;
- }
- else if(drive_number) /* the user may call the about_box, but about_box does
- not delay the handling of disk insertions (as options_box does), hence it's
- possible that the disk insertion event was handled by unexpected_disk_insertion */
- return -1;
- return 0;
- }
-
- /************* aspetta inserzione **************/
-
- short aspetta_inserzione(message)
- /* if a file or disk is already open, return immediately; otherwise,
- present the disk insertion dialog and update all the status informations
- about the current disk
- */
- char*message;
- {
- int inPlace;
-
- if(drive_number!=0){
- if(testa_stato(&inPlace,0)==0){
- if(inPlace){
- if(di.is_not_initialized)
- printf(in_Italia?"Disco non inizializzato\n":"This disk is not initialized\n");
- return 0;
- }
- }
- else
- drive_number=0;
- }
- else if(file_aperto){
- di.is_write_protected=false;
- di.is_not_initialized=false;
- di.os=unknown_os;
- di.disk_code=noMacDskErr;
- return 0;
- }
-
- if(preferred_drive){
- /* if there only one disk drive, or only one is a SuperDrive, eject anything
- was currently in that drive, since it's the only place where the user may insert
- the requested disk. But don't do that if a disk insertion on that drive has just
- happened
- */
- EventRecord event;
-
- drive_number=preferred_drive;
-
- if ( !OSEventAvail(diskMask,&event) || drive_number!=loword(event.message)){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol (NULL,drive_number); /* inutile guardare al codice di errore ritornato */
- diskEject();
- }
- }
-
- {static Point wPos={-1,-1};
- char*p="\pAnnulla";
-
- if(semimodalDialog(138,&wPos,filter_insert,&p,1,
- message,in_Italia?"\p\r\rin un disk drive":"\p\r\rin a floppy disk drive",NULL,
- teJustCenter,fase==ricevuto_comando||fase==initializing)==-1){
- if(testa_stato(&inPlace,1)){
- if(fase==initializing) return 0;
- diskEject();
- return -1;
- }
- return 0; /* disco inserito OK */
- }
-
- return -1;
- }
- }
- /*************************************************/
-
- void check_foreground()
- {
- /* to be called before interacting with the user when I could be
- running in background: if I am, call the Notification Manager to alert
- the user and wait for him/her to bring this application to foreground
- */
-
- if(gInBackground){
- NMRec my_notif_rec;
-
- my_notif_rec.qType=8;
- my_notif_rec.nmMark=1;
- #if 1
- my_notif_rec.nmSIcon=GetResource ('SICN',128);
- #else
- /* with another version of header files, it's */
- my_notif_rec.nmIcon=GetResource ('SICN',128);
- #endif
- my_notif_rec.nmSound=(void*)-1;
- my_notif_rec.nmStr=NULL;
- my_notif_rec.nmResp=NULL;
- NMInstall(&my_notif_rec);
- while(gInBackground)
- MainEvent();
- NMRemove(&my_notif_rec);
- #if 1
- ReleaseResource(my_notif_rec.nmSIcon);
- #else
- ReleaseResource(my_notif_rec.nmIcon);
- #endif
- }
- settori_passati=0;
-
- }
-
- void beep_in_foreground()
- {
- if(gInBackground)
- check_foreground(); /* which does a beep */
- else
- SysBeep(5);
- }
-
-
- /***********************/
-
- void update_about_box(EventRecord*);
- static void update_about_box(theEvent)
- EventRecord *theEvent;
- {
- WindowPtr theWindow=(WindowPtr)theEvent->message;
- static Rect
- boundsR1={10,105,30,475},
- boundsR2={40,130,140,475},
- boundsR3={148,5,285,300},
- dstRect1={5,5,129,129},
- dstRect2={148,288,258,476};
- Handle h;
- GrafPtr savePort;
- char*p;
-
- GetPort( &savePort );
- SetPort(theWindow);
- BeginUpdate( theWindow );
-
- TextFont(3);
- TextSize(12);
- p="suntar 1.3";
-
- TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
- TextFont(4);
- TextSize(9);
-
- if(in_Italia) p=
- "Suntar Å il mezzo pi¥ semplice ed economico di comunicare\r\
- dati tra un Macintosh (dotato di SuperDrive) e un sistema\r\
- UNIX (con un drive per floppy disk da 3,5 pollici):\r\
- legge e scrive dischetti in formato tar UNIX, convertendo\r\
- automaticamente i files di testo e i formati MacBinary e\r\
- BinHex 4.0, usati negli archivi di pubblico dominio per\r\
- immagazzinare files Macintosh in files UNIX.\r\
- Sotto System 7, puoi usare gli aiuti a fumetti.";
- else
- p=
- "Suntar is the simplest and cheapest way to communicate\r\
- data between a Macintosh (with a SuperDrive) and a UNIX\r\
- machine (with a 3.5 inch floppy disk drive): it reads\r\
- and writes disks in the UNIX tar format, automatically\r\
- converting plain text files and the MacBinary and\r\
- BinHex 4.0 formats, used in public domain archives to\r\
- store Macintosh files in UNIX files.\r\
- Under System 7, help balloons are available.";
-
- TextBox(p,(long)strlen(p),&boundsR2,teJustRight);
-
- if(in_Italia) p=
- "suntar Å un programma freeware\r\
- ⌐ 1991-92 Sauro e Gabriele Speranza\r\
- Indirizzo: Sauro Speranza via Cappuccini 18\r\
- 40026 Imola (Bo)\r\
- E-mail: speranza@cirfid.unibo.it\r\
- oppure: speranza@cs.unibo.it\r\
- Porzioni del programma sono ⌐ Gail Zacharias,\r\
- Symantec, Apple Computer, Allan Weber.\r\
- Scritto in Think C 4.0.5 (⌐ 1989-91\r\
- Symantec Corporation)";
- else p=
- "suntar is a freeware program\r\
- ⌐ 1991-92 Sauro and Gabriele Speranza\r\
- Address: Sauro Speranza via Cappuccini 18\r\
- 40026 Imola Italy\r\
- E-mail: speranza@cirfid.unibo.it\r\
- or: speranza@cs.unibo.it\r\
- Portions of suntar are ⌐ Gail Zacharias,\r\
- Symantec, Apple Computer, Allan Weber.\r\
- Written in Think C 4.0.5 (⌐ 1989-91\r\
- Symantec Corporation)";
-
- TextBox(p,(long)strlen(p),&boundsR3,teJustLeft);
-
- h=GetResource ('PICT',128);
- HLock(h);
- DrawPicture (h, &dstRect1);
- ReleaseResource(h);
- h=GetResource ('PICT',129);
- HLock(h);
- DrawPicture (h, &dstRect2);
- ReleaseResource(h);
-
- EndUpdate( theWindow );
- SetPort (savePort);
-
- }
-
- void about_box()
- {
- static Rect
- winRect={0,0,265,480};
- WindowPtr theWindow;
- short stato=0;
- EventRecord myEvent;
- enum tipo_fase old_fase=fase;
-
- if(dirty_buffers()) flush_buffers();
- PositionDialog(&winRect);
- theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, -1L, 0, (long)-1);
- ((WindowPeek)theWindow)->refCon= -3;
-
- install_handlers(theWindow, update_about_box, NULL);
- while(stato!=2){
- sto_lavorando=false; /* cursor shape and delay for WaitNextEvent... */
- fase=paused; /* for unexpected_disk_insertion */
- if(get_event(&myEvent)){
- if(myEvent.what==diskEvt){
- int olddrive=drive_number;
- unexpected_disk_insertion(myEvent.message);
- if(olddrive!=drive_number) break;
- }
- else if(myEvent.what==mouseDown)
- stato=1;
- else if(stato==1&&myEvent.what==mouseUp)
- stato=2;
- /* all other events are ignored: that's anyway a progress upon the 1.1 version,
- which never called GetNextEvent during the about box (background tasks and
- even screen savers were disabled...) */
- }
- }
-
- remove_handlers(theWindow);
- DisposeWindow(theWindow);
- fase=old_fase;
- /*Riattiva();*/
- }
-
-
- /************* check all zero **********/
-
- Boolean check_all_zero(buffer)
- char *buffer;
- {
- register int i=512/sizeof(long);
- register long n_or=0;
- register long* p= (long*) &buffer[0];
-
- while(--i>=0 && (n_or|= *p++) ==0L)
- ;
- return n_or==0L;
- }
-
- /************************/
-
- void print_info(name,length)
- char *name;
- long length;
- {
- if(name[strlen(name)-1]=='/')
- printf("Directory %s\n",name);
- else
- printf("File %s (%ld bytes)\n",name,length);
- }
-
- /*****************************/
-
- void raise_error()
- {
- /* prima di riprendere, chiamo tutte le routine di "cleanup", che ovviamente
- se non c'Å niente da chiudere ritornano senza fare niente
- -- in suntar, all high level routines must use a setjmp to handle
- recovering after an error. All permanent entities (variables, files, windows)
- which need to be closed or restored to the normal state must declare a clean-up
- routine (which does nothing if no clean-up is needed) and that routine must
- be called here (beware, there's also a raise_hqx_error, which aborts the
- extraction of the current file but not the command)
- */
- SetCursor(&waitCursor); /* closing files may flush the disk cache, and that
- may take several seconds */
- deall_tree();
-
- if(drive_number && dirty_buffers()){
- int refnum;
- long space;
- if( GetVInfo (drive_number, disk_buffer, &refnum,&space) == nsvErr ){
- /* no such volume: a non-Mac disk is not mounted hence...*/
- flush_buffers();
- }
- else
- invalid_buffers();
- }
-
- check_and_eject();
- my_event_filter=NULL;
- last_selection=0;
- sto_lavorando=false;
- close_input_files();
- close_or_del_out_file();
- close_info_file();
- enable_autoflush();
- close_semimodal();
- FlushEvents( everyEvent, 0 );
- longjmp(main_loop,-1);
- }
-
- void error_message(p)
- char *p;
- {
- start_of_line();
- printf(p);
- raise_error();
- }
-
-
- void error_message_1(p,n)
- char *p;
- {
- start_of_line();
- printf(p,n);
- raise_error();
- }
-
- /************************/
- short check_error()
- {
- /* da chiamare esclusivamente dopo leggi_settore
- -- to be called after leggi_settore */
- if(err_code){
- /* e se invece riprovassi a leggere ? Non Å che il disk driver ritenti giê lui? */
- start_of_line();
- if(err_code==-39 || file_aperto && err_code==-81)
- printf(in_Italia?"Fine del file prematura\n":"Error: unexpected end of file\n");
- else if(err_code==-65)
- printf(in_Italia?"Errore: disco assente\n" : "Error: missing disk\n");
- else if(err_code<=-66 && err_code>=-71)
- printf(in_Italia?"Settore illeggibile (codice err=%d)\n":
- "Unreadable sector (err code= %d)\n",err_code);
- else
- printf(diskReadErrMsg,err_code);
- if(!ignore_errors){
- diskEject();
- return 1;
- }
- }
- return 0;
- }
-
- /***********************************************************************/
-
- void hacking(command)
- /* handles all the commands in the Special menu: mainly for historical reasons
- (suntar 1.0 was rather modal) I preferred to loop internally while commands are
- from this menu rather than returning to the main loop after executing
- the first command
- */
-
- {
- /* visto che i comandi del men¥ Special sono attivi se e solo se lo sono quelli
- del men¥ file avrebbe senso eseguire un solo comando e ritornare, preferisco
- ciclare anche qui dentro perchÄ cosô Å pi¥ facile gestire il comando Again */
-
-
- short inPlace;
- register int i;
- Boolean sect_n_valid;
- Boolean out_f_open=false;
- sector_t default_sect_n=0;
- int outputFile;
- static unsigned char messIta[]="\pInserisci il disco di prova",
- messIng[]="\pInsert the test disk",
- mess_wrprot[]="Write protected disk !\n";
-
- next_header_for_AIX=-1;
- again_command=0;
- if(setjmp(main_loop)<0){
- if(out_f_open) FSClose(outputFile);
- if(again_command!=hmList || !drive_number)
- return; /* il disco Å stato espulso, non ha senso restare qui dentro;
- non Å detto perÿ, forse a volte non espello ! */
- command=0;
- }
-
- if(aspetta_inserzione(in_Italia?messIta:messIng))
- return;
-
- for(;;){
- if(command==0){
- fase=non_faccio_nulla;
- close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
- last_selection=0;
- while(last_selection==0){
- MainEvent();
- if(!expert_mode) return;
- }
- if(again_command==hmView && (loword(last_selection)==hmView ||
- loword(last_selection)==hmAgain) && default_sect_n<sectors_on_floppy-1)
- default_sect_n++; /* tipicamente io guardo
- il settore prima di farci sopra un clear o read, per cui voglio un
- autoincremento solo se il comando resta view
- -- I usually view a sector just before clearing or untar-ring, hence
- I want auto-increment only if the following command is another View */
- command=loword(last_selection);
- fase=ricevuto_comando;
- if(hiword(last_selection)==fileID)
- return; /* non tocca a me gestirlo */
- last_selection=0;
- if(sect_n_valid=(command==hmAgain)){
- command=again_command;
- if(command==hmList){
- diskEject(); /* non avrebbe senso farlo due
- volte sullo stesso disco, ma ha senso farlo su pi¥ dischi di fila
- -- Do it again used on Expert list means do it on another disk,
- hence the current disk must be ejected */
- if(aspetta_inserzione(in_Italia?messIta:messIng))
- return;
- }
- }
- again_command=0;
- }
- else
- sect_n_valid=false;
-
- switch(command){
- case hmList:
- {
- enum formats fmt;
- if(drive_number) /* solo su disco, non su file */
- again_command=hmList;
- if(next_header_for_AIX!=-1 && tar_version==tar_AIX)
- fase=hack_listing; /* so identify_format doesn not print
- its "unknown format" message */
- one_empty_line();
- fmt = identify_format(); /* che legge in disk_buffer il settore 0
- -- which leaves a copy of sector 0 in disk_buffer */
- if(next_header_for_AIX!=-1 && tar_version==tar_AIX && fmt==unknown_format){
- /* printf("sn=%ld\n",next_header_for_AIX); */
- if(next_header_for_AIX < sectors_on_floppy){
- leggi_settore(next_header_for_AIX,&tarh);
- if(check_all_zero(&tarh)){
- print_sector_n(next_header_for_AIX);
- printf("End of Archive (dangerous, can\'t check it\'s the right disk)\n");
- break; /*save the value of next_header_for_AIX */
- }
- else if(untar_number(tarh.size,-1) != -1 &&
- untar_checksum(&tarh,-1,false) != -2)
- fmt=tar_format;
- else{
- printf("Unknown format (maybe wrong disk)\n");
- break;
- }
- }
- else{
- printf("No file starts here (dangerous, can\'t check it\'s the right disk)\n");
- next_header_for_AIX-=sectors_on_floppy;
- break;
- }
- }
- else
- next_header_for_AIX=-1;
-
- fase=hack_listing;
- if(fmt==bar_format){
- int n;
- one_empty_line();
- printf(START_READ);
- if(my_atoi(((barh_type*)disk_buffer)->volume_num,&n)!=0)
- printf("No sequence number\n");
- else
- stampa_info_bar(n);
- listonly=1;
- my_unbar(); /* che in caso di fase==hack_listing si comporta diversamente
- dal solito per il cambio disco, e stampa pi¥ informazioni
- -- which, when fase==hack_listing, behaves differently
- than when called by a List command */
- }
- else if(fmt==tar_format){
- one_empty_line();
- printf(START_READ);
- listonly=1;
- my_untar();
- }
- next_header_for_AIX=-1;
- }
- break;
- case hmClear: /* clear sector */
- case hmOverwrite:
- one_empty_line();
- if(is_wrprot()){
- printf(mess_wrprot);
- }
- else{
- if(command==hmClear){
- printf("Clearing the sector will erase its previous content.\n");
- printf(
- "If it was an header, List, Extract and Append will see it as end of the archive\n");
- sect_n=default_sect_n;
- }
- else{
- printf("The previous content will be lost\nstart ");
- sect_n=0;
- }
- fase=reading_sect_n;
- if(read_sect_n(§_n)==noErr){
- if(command==hmClear){
- fillmem(disk_buffer, 0, 512);
- scrivi_settore(sect_n,disk_buffer);
- if(err_code) printf(diskWriteErrMsg,err_code);
- }
- else{
- overwrite_sectors();
- printf(DONE);
- }
- default_sect_n=sect_n;
- }
- }
- break;
- case hmView: /* view sector */
- fase=reading_sect_n;
- one_empty_line();
- if(sect_n_valid)
- printf("View sector %ld\n",(long)sect_n);
- else{
- sect_n=default_sect_n;
- sect_n_valid= read_sect_n(§_n)==0;
- }
- if(sect_n_valid){
- fillmem(disk_buffer, 0, 512);
- read_sectors(sect_n,&disk_buffer,1);
- if(err_code){
- beep_in_foreground();
- printf(diskReadErrMsg,err_code);
- }
- stampa_buffer(sect_n,disk_buffer);
- again_command=command;
- default_sect_n=sect_n;
- if(sect_n<sectors_on_floppy-1) sect_n++;
- }
- break;
- case hmSave:
- {sector_t sect_finale;
- my_SF_Put("\pSave as:","\psectors");
- if(!reply.good) break;
-
- i=new_text_file(&outputFile);
- if(i!=noErr) break;
- out_f_open=true;
- sect_n=default_sect_n;
- fase=reading_sect_n;
- one_empty_line();
- if((printf("start "),read_sect_n(§_n)==0) &&
- (sect_finale=sect_n,printf("end "),read_sect_n(§_finale)==0) ){
-
- fase=reading_disk;
- do{
- check_events();
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- error_message("Write error\n");
- }
- sect_n++;
- }
- while(sect_n<=sect_finale);
- }
- FSClose(outputFile);
- printf(DONE);
- out_f_open=false;
- }
- break;
- case hmFind:
- {int err_n=0;
- long exp_check;
- Boolean stampato=false;
- one_empty_line();
- fase=reading_disk;
- listonly=0; /* full buffering... */
- for(sect_n=0;sect_n<sectors_on_floppy;sect_n++){
- check_events();
- leggi_settore(sect_n,&disk_buffer);
- if(err_code!=noErr){
- printf("sector %ld could not be read\n",(long)sect_n);
- if(++err_n>max(20,(int)(sect_n/8))){
- beep_in_foreground();
- error_message("Too many errors, search aborted\n");
- }
- }
- else if(untar_number(((struct tarh_type*)disk_buffer)->size,-1) != -1 &&
- untar_checksum(&disk_buffer,-1,false) == 0){
- disk_buffer[99]=0;
- disable_autoflush();
- printf("tar ");
- print_sector_n(sect_n);
- if(((struct tarh_type*)disk_buffer)->linkflag=='V')
- printf("Volume header: ");
- if(((struct tarh_type*)disk_buffer)->linkflag=='M')
- printf("Continuation: ");
- printf("%s\n",disk_buffer);
- enable_autoflush();
- stampato=true;
- }
- else if(sect_n!=0&&untar_number(((barh_type*)disk_buffer)->size,-1) !=-1 &&
- unbar_checksum(&disk_buffer,-1,&exp_check) == 0 ){
- ((barh_type*)disk_buffer)->name[99]=0;
- printf("bar ");
- print_sector_n(sect_n);
- printf(" %s\n",((barh_type*)disk_buffer)->name);
- stampato=true;
- }
- }
- if(!stampato) printf("No headers found\n");
- printf(DONE);
- }
- break;
- case hmUntar:
- case hmUnbar:
- fase=reading_sect_n;
- one_empty_line();
-
- if(sect_n_valid)
- printf("Un%car at sector %ld\n",((command==hmUntar)?'t':'b'),(long)sect_n);
- else{
- sect_n=default_sect_n;
- sect_n_valid= read_sect_n(§_n)==0; /* come sopra */
- }
- if(sect_n_valid){
- leggi_settore(sect_n,&disk_buffer);
- if(err_code)
- printf(diskReadErrMsg,err_code);
- else if(check_all_zero(disk_buffer))
- printf("Null header\n");
- else{
- select_directory();
- if(reply.good){
- listonly=0;
- bar_archive= command==hmUnbar;
- fase=hack_reading; /* per avvertire di non chiedere un disco
- specifico: forse il settore 0 Å danneggiato
- o sovrascritto da un altro header bar
- -- essentially, it's used to remember that
- the floppy_n variable may be invalid,
- hence when asking next disk don't rely on it */
- if(bar_archive){
- unbar();
- }
- else
- untar();
- print_sector_n(sect_n);
- printf(" Done\n");
- }
- again_command=command;
- default_sect_n=sect_n;
- }
- }
- break;
- case hmMac_ize:
- if(is_wrprot()){
- printf(mess_wrprot);
- }
- else{
- i=warning_first_write(1);
- if(i>=0){
- ioParam pb;
- if(i>0){
- ParamText(i==1?"\pNon-Mac disk":"\pEmpty Macintosh disk",
- "\p\rAny data in this disk will be lost. Continue ?",PNS,PNS);
- if( my_modal_dialog(139,NULL,2) == 2) break;
- }
- printf("Creating directory...\n");
- fillmem(disk_buffer, 0xF6, 512);
- write_sectors(0,disk_buffer,1);
- DIZero (drive_number,"\pUntitled");
- pb.ioVRefNum=drive_number;
- drive_number=0;
- PBMountVol(&pb);
- printf(DONE);
- invalid_buffers();
-
- return;
- }
- else{
- diskEject();
- return;
- }
- }
- break;
- case hmDriveList:
- DriveList();
- break;
- } /* fine switch */
- command=0;
- }
- }
-
- short read_sect_n(n)
- sector_t *n;
- {
- char buffer[32];
- short i;
- printf("sector number : ");
- /* gets(buffer); */
- my_itoa((long)*n,buffer);
- prompt(buffer,sizeof(buffer)-1);
-
- #if SECTOR_T_SIZE==4
- i=my_atol(&buffer[0],n);
- #else
- i=my_atoi(&buffer[0],n);
- #endif
- if(i==0 && (*n<0 || *n >= sectors_on_floppy) ){
- printf("Invalid sector number\n");
- return -3;
- }
- else if(i==-2)
- printf("Invalid digit\n");
- return i;
- }
-
- short my_atoi(buffer,n)
- register char*buffer;
- register int *n;
- {
- for(;*buffer==' ';buffer++)
- ;
- if(*buffer>='0'&&*buffer<='9'){
- *n=0;
- while(*buffer>='0'&&*buffer<='9')
- *n= *n * 10 + *buffer++ -'0';
- return 0;
- }
- return *buffer? -2 : -1;
- }
-
- short my_atol(buffer,n)
- register char*buffer;
- register long *n;
- {
- for(;*buffer==' ';buffer++)
- ;
- if(*buffer>='0'&&*buffer<='9'){
- *n=0;
- while(*buffer>='0'&&*buffer<='9')
- *n= *n * 10 + *buffer++ -'0';
- return 0;
- }
- return *buffer? -2 : -1;
- }
-
-
- void overwrite_sectors()
- {
- SFTypeList myTypes;
- short charsRead;
-
- my_SF_Get(-1,myTypes);
- if(!reply.good)return;
-
- if(apri_file("rb",&inputFile))
- return;
- inf_is_open=true;
- fase=writing_disk;
-
- while( (charsRead = mac_fread(disk_buffer, 512, inputFile)) >0 ){
- if(sect_n>=sectors_on_floppy){
- printf("End of disk reached\n");
- break;
- }
- scrivi_settore(sect_n,disk_buffer);
- check_wr_err();
- sect_n++;
- check_events();
- }
-
- FSClose(inputFile);
- inf_is_open=false;
- }
-
-
- void print_sector_n(sector_n)
- sector_t sector_n;
- {
- /* well, I use a printf which does not accept a %4d descriptor... !!! */
- printf("[sector %s%ld] ",sector_n>=1000?"":sector_n>=100?" ":sector_n>=10?" ":" ",
- (long)sector_n);
- }
-
- void stampa_info_bar(n) /* print informations from a bar volume header */
- {
- char buffer[16];
- register int i,j;
- printf("Disk number %d ", n);
- for(i=j=0;i<10;i+=2,j+=3){
- buffer[j]=((barh_type*)disk_buffer)->cdate[i];
- buffer[j+1]=((barh_type*)disk_buffer)->cdate[i+1];
- }
- buffer[2]=buffer[5]='/';
- buffer[8]=' ';
- buffer[11]=':';
- buffer[14]='\0';
- printf("created %s",buffer);
- if(((barh_type*)disk_buffer)->name[0])
- print_if_string("; archive name is ",((barh_type*)disk_buffer)->name,100);
- printf("\n");
- }
-
-
- /*********************************************/
-
-
- int going_to_background()
- /* to write on a disk in background is very dangerous, since suntar
- uses very low level calls and can't realize that a disk was replaced
- by a Mac disk containing precious files. Hence, the user must be
- alerted, and since at the next GetNextEvent I'll lose the right to get
- CPU time, I can't present a standard alert
- */
- {
-
- if(fase==writing_disk && sto_lavorando){
- static Rect winRect={0,0,80,300},
- boundsR1={15,0,80,300};
- WindowPtr theWindow;
- GrafPtr savePort;
- char *p;
- unsigned long time;
-
- PositionDialog(&winRect);
- theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, -1L, 0, (long)-1);
- GetPort( &savePort );
- SetPort(theWindow);
- p= in_Italia ?
- "suntar continuerê a scrivere in background\rsu qualunque cosa si trovi nel drive\r\
- non espellere il disco ! ! !":
- "suntar will write in background\ron anything is in the disk drive\r\
- please don\'t eject this disk";
-
- TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
-
- /* while(!Button()) ;
- while( Button()) ;
- FlushEvents( mDownMask|mUpMask, 0 ); */
- time=Ticks+delay_back; /* 5 secondi (nella risorsa), ma un clic del mouse riduce l'attesa
- purchÄ siano almeno 1.5 */
- while (time >Ticks)
- if(time-delay_back+90 < Ticks && Button()){
- /*FlushEvents( mDownMask, 0 );*/ /* inutile, in pratica, l'evento va al
- processo successivo...
- -- a mouse click aborts the delay loop: however, I can't
- tell the Finder that that mouse click was already served,
- since that event is anyway passed to the application
- which is going to foreground, I can't flush it
- */
- break;
- }
- SetPort (savePort);
- DisposeWindow(theWindow);
- return 1;
- }
- return 0;
- }
-
- void DriveList()
- {
- int i;
- disable_autoflush();
- one_empty_line();
- for(i=0;i<max_drive;i++){
- if(drive_type[i]){
- printf("Drive %d: ",i+1);
- switch(drive_type[i]&0xF){
- case 7:
- printf("Hard disk 20 ");
- break;
- case 2:
- printf("Single sided (GCR 400k) ");
- break;
- case 3:
- printf("Double sided (GCR 800k) ");
- break;
- case 4:
- printf("SuperDrive (GCR 800k-MFM 720/1440k) ");
- break;
- case 5:
- {Handle h=GetResource('STR ',200);
- if(h){
- HLock(h);
- printf("%p ",*h);
- HUnlock(h);
- break;
- }
- }
- /* else unknown type */
- default:
- printf("Unknown drive type ");
- }
- if(drive_type[i]>0){ /* that bit is set/cleared by suntar */
- printf((drive_type[i]&0x100) ?"external":"internal");
- if(drive_type[i]&0x200) printf("(SCSI)");
- printf((drive_type[i]&0x400) ?", fixed (suntar can\'t open it)":", removable");
- }
- printf("\n");
- }
- }
- printf("\n");
- enable_autoflush();
- }
-
- void fine_lavoro()
- {
- if(gInBackground)
- check_foreground();
- else if(settori_passati>min_to_beep)
- SysBeep(5);
- }
-
- void unexpected_disk_insertion(message)
- /* called when a disk is inserted and suntar does not expect a disk insertion:
- obviously, that disk could be a Mac disk to be passed to the Finder, but it
- could be a tar disk, or it could be in the disk drive where suntar believes
- there was still the disk it has opened and on which it was working
- */
- long message;
- {
- extern Point badmount_point;
- extern char *titoli[];
- extern Boolean finestra_sm_aperta;
- jmp_buf savebuf;
- short inPlace;
- Boolean andata_male;
-
- sector_t old_s=sectors_on_floppy;
- short old_drive_n=drive_number;
- struct disk_info old_di=di;
-
- mcopy(&savebuf,&main_loop,sizeof(jmp_buf));
-
- andata_male=false;
- drive_number=loword(message);
-
- if(setjmp(main_loop)<0) { /* at least identify_format may do a raise_error, and
- raise_error causes a bad crash if no currently running function has performed
- a setjmp, and I don't know what's the current situation */
- andata_male=true;
- }
- if(andata_male || testa_stato(&inPlace,0)){
- diskEject();
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- sectors_on_floppy=old_s;
- drive_number=old_drive_n;
- di=old_di;
- return;
- }
-
- if( (di.os==mac_HFS||di.os==mac_MFS) && (drive_number!=old_drive_n || !dirty_buffers()) ){
- /* il disco non mi riguarda, lo lascio passare
- -- that disk is of no interest to suntar; do what GetNextEvent would do,
- then what Apple suggests to do when receiving a disk insertion event */
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- DIBadMount(badmount_point, message);
- invalid_buffers();
- }
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- sectors_on_floppy=old_s;
- drive_number=old_drive_n;
- di=old_di;
- return;
- }
-
- if(fase==non_faccio_nulla && old_drive_n==loword(message)){
- old_drive_n=0; /* there is no reason to ask the disk back if I was
- not working on it, simply close the old one */
- invalid_buffers();
- }
-
- if( old_drive_n!=0 || file_aperto){
- if((fase==paused || fase==in_writing || fase==reading_sect_n || finestra_sm_aperta) &&
- loword(message)==old_drive_n){ /* il disco
- era dentro, probabilmente Å stato estratto a tradimento e poi reinserito
- -- the tar disk was in that drive, probably it was ejected (without using
- suntar's eject) and inserted in back */
- if (sectors_on_floppy!=old_s ){
- if(dirty_buffers())
- diskEject();
- else{
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if (di.os==unknown_os || (hiword(message)=PBMountVol (¶m)) != noErr)
- DIBadMount(badmount_point, message);
- }
- }
- else{
- short item;
-
- ParamText(in_Italia?"\pQuesto Å il disco su cui stavo lavorando ?":
- "\pIs this the disk I was working on ?",PNS,PNS,PNS);
- item=my_modal_dialog(139,titoli,2);
- if(item==2){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol(NULL,drive_number);
- diskEject();
- }
- }
- }
- else{
- /* non accetto altri dischi
- -- suntar has something open and since it can't open more than one thing it can't
- open that disk, do something which looks like the standard behaviour
- for non-Mac or non-initialized disks
- */
- if(dirty_buffers())
- diskEject();
- else if(di.os==msdos){ /* AccessPC or DOS Mounter could be installed... */
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- DIBadMount(badmount_point, message);
- }
- }
- else{
- diskEject();
- ParamText(in_Italia?"\pNon si possono aprire due archivi":
- "\pCannot open more than one archive",PNS,PNS,PNS);
- my_alert();
- }
- }
- sectors_on_floppy=old_s;
- di=old_di;
- drive_number=old_drive_n; /* diskEject lo azzera */
- }
-
- else{ /* open it ! */
- if(testa_stato(&inPlace,true)) /* must call it again, for the "verbose" parameter */
- diskEject();
- else{
- if(drive_number<=last_drive && fase!=initializing){
- /*FlushVol (PNS,drive_number);*/
- /*i=*/ UnmountVol (NULL,drive_number);
- }
- if(di.os==msdos){
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=drive_number;
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- diskEject();
- ParamText(in_Italia?
- "\pDisco MS-DOS, per usarlo scegli un comando \"Create╔\"":
- "\pMS-DOS disk, to open it select a \"Create╔\" command",PNS,PNS,PNS);
- my_alert();
- }
- drive_number=0;
- }
- else if(!di.is_not_initialized)
- (void)identify_format();
- }
- }
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- }
-
- /************** gestione men¥ ****************/
-
- void EnableDisableItem(MenuHandle,short,Boolean);
- static void EnableDisableItem(menu, item, flag)
- MenuHandle menu;
- short item;
- Boolean flag;
- {
- if(flag)
- EnableItem(menu, item);
- else
- DisableItem(menu, item);
- }
-
- void MaintainApplSpecificMenus()
- /* it's an idea borrowed from TEsample: rather than enabling and disabling
- items when the situation changes, be sure that some global variables always
- tell what the situation is and adjust all the menu items when receiving a
- keyDown event with the Command key or a MouseDown event in the menu bar.
- That's the most reasonable way to do things in a program which has an abort
- command and does not quit at the first error.
- */
- {
- extern Boolean finestra_sm_aperta;
- extern DialogPtr ListDialog;
-
- Boolean b;
- b= fase==non_faccio_nulla;
- if(b){
- EnableDisableItem(myMenus[fileM], fmGetInfo, !file_aperto&&drive_number==0);
- EnableDisableItem(myMenus[fileM], fmCopy, !file_aperto);
- EnableItem(myMenus[fileM], fmList);
- EnableItem(myMenus[fileM], fmExtract);
- EnableDisableItem(myMenus[fileM], fmWriteTar, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmWriteBar, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmAppend, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmFormat, !file_aperto);
- EnableItem(myMenus[fileM], fmSelect);
- }
- else{
- DisableItem(myMenus[fileM], fmGetInfo);
- DisableItem(myMenus[fileM], fmCopy);
- DisableItem(myMenus[fileM], fmList);
- DisableItem(myMenus[fileM], fmExtract);
- DisableItem(myMenus[fileM], fmWriteTar);
- DisableItem(myMenus[fileM], fmWriteBar);
- DisableItem(myMenus[fileM], fmAppend);
- DisableItem(myMenus[fileM], fmFormat);
- EnableDisableItem(myMenus[fileM], fmSelect, ListDialog&&FrontWindow()!=ListDialog);
- }
- /* il Think C marker non accetta macro su due righe, e non voglio perdere i suoi servizi ! */
- #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) )
-
- EnableDisableItem(myMenus[fileM], fmPause, sto_lavorando || fase==paused /* nel secondo
- caso, l'item Å diventato resume */ || finestra_sm_aperta&&((abort_mask>>fase)&1));
- EnableDisableItem(myMenus[fileM], fmOpen, fase==non_faccio_nulla&&drive_number==0&&!file_aperto);
-
- #ifdef V_122
- EnableDisableItem(myMenus[fileM], fmEject, drive_number!=0 &&( fase==non_faccio_nulla || fase==in_writing
- /* || fase==paused || finestra_sm_aperta*/) ); /* sarebbe sensato averlo attivo
- anche allora, ma non passo dal main per gestirlo ! */
- EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla&&file_aperto);
- #else
- /* in the 1.3 version, they share the same item */
- {
- unsigned char itemname[32];
- int i=2;
- if(!file_aperto&&drive_number==0)
- DisableItem(myMenus[fileM], fmEject);
- else{
- if(file_aperto)
- i=1;
- EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla || fase==in_writing);
- }
- GetIndString (itemname,129,i);
- SetItem (myMenus[fileM],fmClose,itemname);
- }
- #endif
-
-
- /*EnableDisableItem(myMenus[fileM], fmAbort, fase==writing_disk ||fase==reading_disk ||
- fase==reading_sect_n || fase==hack_reading || fase==hack_listing || fase==paused) ||
- fase==in_writing || fase==selected_reading; */
- EnableDisableItem(myMenus[fileM], fmAbort, (abort_mask>>fase)&1 );
-
- if(expert_mode){
- if(b){
- EnableItem(hackersMenu, hmView);
- EnableDisableItem(hackersMenu, hmClear,!file_aperto);
- EnableDisableItem(hackersMenu, hmMac_ize,!file_aperto);
- EnableDisableItem(hackersMenu, hmOverwrite,!file_aperto);
- EnableItem(hackersMenu, hmSave);
- EnableItem(hackersMenu, hmFind);
- EnableItem(hackersMenu, hmUntar);
- EnableItem(hackersMenu, hmUnbar);
- EnableItem(hackersMenu, hmList);
- EnableItem(hackersMenu, hmDriveList);
- EnableDisableItem(hackersMenu, hmAgain, again_command!=0);
- }
- else{
- DisableItem(hackersMenu, hmView);
- DisableItem(hackersMenu, hmClear);
- DisableItem(hackersMenu, hmMac_ize);
- DisableItem(hackersMenu, hmOverwrite);
- DisableItem(hackersMenu, hmSave);
- DisableItem(hackersMenu, hmFind);
- DisableItem(hackersMenu, hmUntar);
- DisableItem(hackersMenu, hmUnbar);
- DisableItem(hackersMenu, hmList);
- DisableItem(hackersMenu, hmDriveList);
- DisableItem(hackersMenu, hmAgain);
- }
- }
- }
-
-
- void set_skip_all(n)
- {
- /* il confirm saves ha tre stati:
- non selezionato (confirm_saves=0,saveskip_all=0)
- selezionato (confirm_saves=1,saveskip_all=0)
- posto in corsivo da una skip all o save all (confirm_saves=0,saveskip_all=1)
- questa routine gestisce i passaggi tra i tre stati:
-
- n= 0 -> se Å in corsivo torna sel, se no resta immutato;
- n= 1 -> da sel commuta a posto in corsivo (e da non sel resta immutato !)
- n=-1 -> da chiamare quando seleziono l'entry del men¥: se Å in corsivo torna selezionato,
- se no inverte lo stato attuale
-
- -- the confirm saves menu item has three states:
- non-selected (confirm_saves=0,saveskip_all=0)
- selected (confirm_saves=1,saveskip_all=0)
- italicized by a skip all or save all (confirm_saves=0,saveskip_all=1)
- this routine handles all its status changes:
- n=0 => I'm in the main loop, if it's italicized then make it selected
- 1 => the save all or skip all was clicked (caution, the confirm saves could
- have been disabled after the window appeared, and the button may still
- be clicked)
- -1 => the confirm saves menu item was selected: if italicized return normal,
- otherwise invert its current state
-
- */
- static Boolean saveskip_all=false;
-
- if(!n || (n<0&&saveskip_all) ){
- if(saveskip_all){
- saveskip_all=false;
- SetItemStyle(myMenus[prefM],pmConfirm,0);
- confirm_saves=true;
- }
- }
- else if (n>0){
- if(confirm_saves||saveskip_all){ /* puÿ capitare che non sia cosô se
- deseleziono durante il dialogo e poi clicco su un bottone...*/
- saveskip_all=true;
- SetItemStyle(myMenus[prefM],pmConfirm, 2); /* corsivo */
- confirm_saves=false;
- }
- }
- else{ /* n=-1, saveskip_all=0 */
- CheckItem(myMenus[prefM],pmConfirm,confirm_saves^=1);
- }
- }
-
- void load_OSType(short,OSType *);
- static void load_OSType(id,dest)
- short id;
- OSType *dest;
- {
- Handle h;
- if((h=GetResource ('STR ',id))==NULL)
- *dest='????';
- else{
- HLock(h);
- mcopy((char*)dest,(char*)*h+1,4);
- ReleaseResource(h);
- /* *dest = (((long)*(unsigned char*)(*h+1))<<24) +
- (((long)*(unsigned char*)(*h+2))<<16) +
- (((long)*(unsigned char*)(*h+3))<<8) +
- ((long)*(unsigned char*)(*h+4)); */
- }
- }
-
- long load_number(short,int);
- static long load_number(id,deflt)
- short id;
- int deflt;
- {
- Handle h;
- if((h=GetResource ('STR ',id))==NULL)
- return deflt;
- else{
- long temp;
- HLock(h);
- temp=pstrtoi(*h);
- ReleaseResource(h);
- return temp;
- }
- }
-
- void prefs_da_risorsa()
- /* read all the preference settings which depend on a resource, including
- the INTL 0 resorce which is in the System file and contains the code
- for the nation, and compute the centered locations for those dialogs which
- are difficultly moved after their creation
- */
- {
- Handle h;
- int i;
- static Rect bmr={0,0,96,300};
- static short SF_IDs[]={199,200,-3999,-4000,1043,400,399};
- extern long my_uid,my_gid;
- extern char *uname,*gname;
- extern Boolean gHasCustomPutFile,SB3_compatibility;
- #define verItSwiss 36
-
- load_OSType(129,&tar_creator);
- load_OSType(136,&bar_creator);
- load_OSType(137,&bar_type);
-
- max_hqx_header=load_number(134,10240);
-
- my_uid=load_number(130,0);
- my_gid=load_number(131,0);
- uname=gname="";
- ResrvMem ((Size)64);
- h=GetResource ('STR ',132);
- if(h){
- HLock(h);
- uname=p2cstr(*h);
- }
- h=GetResource ('STR ',133);
- if(h){
- HLock(h);
- gname=p2cstr(*h);
- }
-
- if((h=GetResource ('STR ',135))!=NULL ){
- if(**h){
- char c= *(*h+1)&~0x20;
- if(c=='I')
- in_Italia=true;
- else if(c=='E')
- in_Italia=false;
- else
- h=NULL;
- }
- else
- h=NULL;
- }
-
- if(h==NULL){
- h=IUGetIntl (0);
- if(h!=NULL){
- in_Italia=(((Intl0Rec*)*h)->Intl0Vers>>8)==verItaly ||
- (((Intl0Rec*)*h)->Intl0Vers>>8)==verItSwiss;
- ReleaseResource(h);
- CheckItem(myMenus[prefM],pmEnglish,!in_Italia);
- }
- }
-
- h=GetResource ('STR ',141);
- if(h && **h && ((*h)[1] | 0x20)!='n') SB3_compatibility=true;
-
- floppy_buffer_size =load_number(138,18);
- hd_buffer_size = load_number(139,20)<<9;
- back_prio = load_number(140,4);
-
- load_options();
-
- /* compute the centered position for the the disk initialization dialog */
- PositionDialog(&bmr); /* finestra usata da DIBadMount, uso dimensioni fisse
- che perÿ sono quelle della finestra personalizzata e dovrebbero coincidere
- con quelle di sistema */
- *(long*)&badmount_point=*(long*)&bmr;
- /* sotto il System 7 passare {0,0} allo standard file provoca un dialogo
- centrato, ma purtroppo col system 6 non Å cosô... */
-
- /* and the positions for the standard file dialogs */
- for(i=0;i<sizeof(SF_IDs)/sizeof(short);i++){
- AlertTHndl alertHandle = (AlertTHndl)GetResource('DLOG',SF_IDs[i]);
- if(alertHandle){
- PositionDialog( &((**alertHandle).boundsRect));
- where[i]=*(Point*)&((**alertHandle).boundsRect);
- }
- else{
- static Point def_where={80,80};
- where[i]=def_where;
- }
- }
- }
-
- void load_options()
- {
- static OSType gif_default='QGif';
- Handle h;
- if((h=GetResource ('OPTs',128))==NULL){
- /* create the options resource if it doesn't exist: probably that will not
- be useful to the user, we'll make suntar 1.2 and 1.3 available with an OPTs
- resource (otherwise, a file which grows could make somebody think about
- viruses) but during the development of the program it was useful,
- each time we changed the format of the resource, deleting the old one
- one obtains the creation of the new one */
- h=NewHandle(sizeof(options));
- fillmem(&options,0,sizeof(options));
- text_creator='EDIT';
- gif_creator=gif_default;
- resolve_aliases=useSys7_SF=true;
- non_text_ASCII=1;
- smallFilesAreASCII=1;
- delay_back=300;
- min_to_beep=500;
- mcopy(*h,&options,sizeof(options));
- AddResource (h, 'OPTs',128,PNS);
- WriteResource(h);
- }
- else{
- Size s=GetHandleSize(h);
- if(s<sizeof(options)){ /* somebody is using the old format of the OPTs
- resource, convert it to the new format:
- it's always wise to support old formats for
- anything */
- SetHandleSize (h,(Size)sizeof(options));
- fillmem(*h+(&options.opt_bytes[12]-(char*)&options),0,8);
- *(char*)(*h+(&options.opt_bytes[12]-(char*)&options)) = 1;
- mcopy(*h+((char*)&options.gif_cr-(char*)&options),&gif_default,4);
- *( *h+(&options.opt_bytes[0]-(char*)&options) ) <<= 1; /* it's no more a Boolean... */
- ChangedResource(h);
- WriteResource(h);
- }
- mcopy(&options,*h,sizeof(options));
- }
- ReleaseResource(h);
- }
-
- void save_options()
- {
- Handle h;
- h=GetResource ('OPTs',128);
- mcopy(*h,&options,sizeof(options));
- ChangedResource(h);
- WriteResource(h);
- ReleaseResource(h);
- }
-
- void add_expert_menu(void);
- static void add_expert_menu()
- {
- unsigned char itemname[48];
- GetIndString(itemname,130,1);
- AppendMenu(myMenus[prefM],itemname);
- GetIndString(itemname,130,2);
- AppendMenu(myMenus[prefM],itemname);
- InsertMenu(hackersMenu = GetMenu(hackID),0);
- }
-
-
- static void add_menu() /* create application specific menus */
- {
- int markChar;
-
- CheckItem(myMenus[prefM],pmAutowrap,false);
- CheckItem(myMenus[prefM],pmConfirm,false);
- GetItemMark (hqxM,bmDisable,&markChar);
- disable_binhex = markChar==checkMark;
- GetItemMark (hqxM,bmShowExtr,&markChar);
- if(markChar==checkMark) disable_binhex |=2;
- GetItemMark (hqxM,bmSaveInfo,&markChar);
- if(markChar==checkMark) disable_binhex |=8;
- GetItemMark (hqxM,bmShowList,&markChar);
- if(markChar==checkMark) disable_binhex |=4;
-
- #ifdef V_122
- GetItemMark (myMenus[prefM],pmSmallText,&markChar);
- smallFilesAreASCII= markChar==checkMark;
- #endif
- GetItemMark (myMenus[prefM],pmExpert,&markChar);
- expert_mode= markChar==checkMark;
- InsertMenu(writeMenu = GetMenu(writeID), 0);
- DisableItem(writeMenu, 0);
- if(expert_mode) add_expert_menu(); /* always un-checked... */
- tarPopupMenu = GetMenu(tarPopupID);
- ntAPopupMenu = GetMenu(ntAPopupID);
-
- }
-
- static void handle_menus(choice) /* handle application specific menus */
- long choice;
- {
- if(hiword(choice)==appleID)
- about_box();
- else if(hiword(choice)==prefID)
- switch(loword(choice)) {
- case pmOptions:
- if(dirty_buffers()) flush_buffers();
- options_box();
- break;
- case pmEnglish:{
- int markChar;
- in_Italia^=1;
- GetItemMark (myMenus[prefM],pmEnglish,&markChar);
- CheckItem(myMenus[prefM],pmEnglish,!markChar);
- }
- break;
- case pmConfirm:
- set_skip_all(-1);
- break;
- #ifdef V_122
- case pmSmallText:
- CheckItem(myMenus[prefM],pmSmallText, smallFilesAreASCII^=1);
- preferences_changed=true;
- break;
- #endif
- case pmExpert:
- CheckItem(myMenus[prefM],pmExpert,expert_mode ^=1);
- if(expert_mode){
- add_expert_menu();
- }
- else{
- DelMenuItem (myMenus[prefM], pmNoConvers);
- DelMenuItem (myMenus[prefM], pmIgnore);
- DeleteMenu (hackID);
- ignore_errors=non_convertire=false;
- }
- DrawMenuBar();
- preferences_changed=true;
- break;
- case pmIgnore:
- CheckItem(myMenus[prefM],pmIgnore,ignore_errors^=1);
- break;
- case pmNoConvers:
- CheckItem(myMenus[prefM],pmNoConvers,non_convertire^=1);
- break;
- }
- else if(hiword(choice)==hqxID){
- preferences_changed=true;
- switch(loword(choice)){
- case bmDisable:
- CheckItem(hqxM,bmDisable,(disable_binhex^=1)&1);
- break;
- case bmShowExtr:
- CheckItem(hqxM,bmShowExtr,((disable_binhex^=2)&2)!=0);
- break;
- case bmSaveInfo:
- CheckItem(hqxM,bmSaveInfo,((disable_binhex^=8)&8)!=0);
- break;
- case bmShowList:
- CheckItem(hqxM,bmShowList,((disable_binhex^=4)&4)!=0);
- break;
- }
- }
- else{ /* fileID o writeID oppure hackID, tanto non sono mai abilitati insieme,
- e comunque non butto via l'informazione
- -- I don't serve the command, rather I remember that it was selected.
- That's a matter of program hierarchy: MainEvent is a slave, it's not the
- master, hence important operations are not executed under it, and
- this routine is called from it.
- */
-
- if(choice==menuItemMess(fileID,fmSelect)&&ListDialog&&
- ListDialog != FrontWindow() ){
- SelectWindow(ListDialog);
- }
- else
- last_selection= choice;
- }
- }
-
-
- static int my_quit_handler()
- {
-
- if(((abort_mask>>fase)&1) && fase!=in_writing){ /* it's the condition used for the abort menu item */
- ParamText(in_Italia?"\pVuoi interrompere il comando in corso ?":
- "\pDo you want to abort the current command and quit ?",PNS,PNS,PNS);
- beep_in_foreground();
- if(my_modal_dialog(139,titoli,2)==2) return 0;
- }
-
- check_and_eject(); /* ejects the disk and, if writing, truncates... */
-
- if(!preferences_changed) return 1;
-
- /* save the preferences settings */
- if(expert_mode){
- DelMenuItem (myMenus[prefM], pmNoConvers);
- DelMenuItem (myMenus[prefM], pmIgnore);
- }
- (**myMenus[prefM]).menuProc=NULL; /* without it, horrible things happen */
- ChangedResource(myMenus[prefM]);
- WriteResource(myMenus[prefM]);
-
- (**hqxM).menuProc=NULL;
- ChangedResource(hqxM);
- WriteResource(hqxM);
- return 1;
- }
-