/* Standard TOS funktionen bekannt machen: */ #include #include #include #include #include #include #include #include #include "gfx.h" #include "gui.h" #include "editor.h" #include "script.h" #include "keys.h" #include "sets.h" #include "ezxml/ezxml.h" #include "main.h" #ifdef __AHCC__ void vq_chcell( int handle, int *rows, int *columns ); #define vq_chcells vq_chcell #endif #define DEC_VERSION 0.3 #define INFO "HELP=HELP, RETURN=TOGGLE, Q=QUIT, Fx=SELECT SET, SHIFT+Fx=SAVE SET" char * filtermask[] = {"*.PR*", "*.AC*", "*.CP*"}; #define PRG_FILTER 0 #define ACC_FILTER 1 #define CPX_FILTER 2 /*#define DEBUG 1 */ #define COL_LEN 14 #ifndef WITHOUT_GFX /* Grahical boot manager? */ #define LIST_START 4 #else #define LIST_START 2 #endif /* quit variable, program exits */ /* when quit == 1 */ short quit; /* Current filter for directory listing */ char filter = PRG_FILTER; /* list of files for each filter: */ #define FLIST_MAX 127 char filelist[3][FLIST_MAX+1][14]; short cursor = -1; short numfiles[3] = {0,0,0}; long timeout = 3; char * basepath[3] = {"C:\\AUTO", "C:", "C:"}; char resort[3]; /* id, name and handle of current loaded set: */ short currentset = -1; char currentscript[SCRIPT_MAX_LEN+1]; const char * setname = NULL; ezxml_t set=NULL; ezxml_t cfgitem; ezxml_t ezxmlh; char * default_config_str = "" "" "C:\\AUTO" "C:" "C:" "3" "" ""; char * examplescript = "" " #initial script for set: %s\n" " #supported commands:\n" " #parameters marked with * are optional\n" " #pause *message - waits for any keypress\n" " #echo *message - prints message to screen or just newline\n" " #set echo off - turn on/off verbose command output\n" " #copy src dst - copy file from source to destination\n" " #rewrite file match replace - replace all matching strings in file\n" ""; char * cfg_titles[] = {"AUTO Path", "ACC Path", "CPX Path", "Boot Timeout"}; char * cfg_items[] = {"prgpath", "accpath", "cpxpath", "timeout"}; void dbg(char * str) { Cconws( str ); Cconws( "\r\n" ); getch(); } void die( char * str ) { Cconws( str ); Cconws("\n"); Cconws("Press any key...\n"); getch(); exit( 1 ); } void draw_list_header( void ) { #ifdef WITHOUT_GFX fillspace(0, 1, c_cols, 0); #endif textxy( 2, LIST_START, (filter==PRG_FILTER) ? 1 : 0, "PRG:" ); textxy( 2+COL_LEN, LIST_START, (filter==ACC_FILTER) ? 1 : 0, "ACC:" ); textxy( 2+COL_LEN*2, LIST_START, (filter==CPX_FILTER) ? 1 : 0, "CPX:" ); } void draw_list_item( int _filter, int idx ) { short inv = ( _filter == filter && idx == cursor ) ? 1 : 0; int y = idx + LIST_START + 1; if( (idx >= numfiles[_filter]) || (idx < 0) ){ return; } if( y >= c_rows-3 ) y=c_rows-3; textxy( 2+(_filter*COL_LEN), y, inv, " "); textxy( 2+(_filter*COL_LEN), y, inv, filelist[_filter][idx] ); } void draw_list( short _filter ) { short i; for( i=0; i n) n = numfiles[i]; } for( i=LIST_START; i<=n+2; i++ ){ fillspace(0, i, c_cols, 0); } textxy( 1, line++, 1, "Mainscreen Keys: "); textxy( 1, line++, 0, " "); textxy( 1, line++, 0, "Help: Show this screen."); textxy( 1, line++, 0, "Enter: Toogle active/inactive"); textxy( 1, line++, 0, "ESC/Q/q: Continue boot / save changes."); textxy( 1, line++, 0, "Shift+A: Move file up."); textxy( 1, line++, 0, "Shift+Y: Move file down."); textxy( 1, line++, 0, "Shift+F1-F10: Save Set 1-10."); textxy( 1, line++, 0, "F1-F10: Load Set 1-10."); textxy( 1, line++, 0, "C: Configuration."); textxy( 1, line++, 0, "D: Delete current set."); textxy( 1, line++, 0, "E: Edit Script for current set."); textxy( 1, line++, 0, "L: List available sets."); textxy( 1, line++, 0, "S: Save without exit."); Cconin(); draw_main(); } char * cfg_str( const char * name, char * def) { char * ret = def; ezxml_t item; if( ezxmlh == NULL || name == NULL ) return(""); item = ezxml_child(ezxmlh, name); if( item != NULL ){ ret = item->txt; } if( ret == NULL ) ret = def; return( ret ); } void init_config_vars( void ) { FILE * fp; char drive; static char def_prg[128]; static char def_misc[128]; if( ezxmlh == NULL ) { ezxmlh = ezxml_parse_file("SBOOT.XML"); } if( ezxmlh == NULL ){ fp = fopen("SBOOT.XML", "w"); if( fp ){ fwrite( default_config_str, strlen(default_config_str), 1, fp ); fclose( fp ); ezxmlh = ezxml_parse_file( "SBOOT.XML" ); } } if( ezxmlh != NULL ) { drive = 'A'+Dgetdrv(); sprintf( def_prg, "%c:\\AUTO", drive ); basepath[0] = cfg_str( "prgpath", def_prg ); sprintf( def_misc, "%c:", drive ); basepath[1] = cfg_str( "accpath", def_misc ); basepath[2] = cfg_str( "cpxpath", def_misc ); timeout = atoi( cfg_str("timeout", "3") ); strncpy( currentscript, cfg_str("lastscript", ""), SCRIPT_MAX_LEN ); } } /* draw the global configuration */ void draw_config(void){ short line=LIST_START, inv; int i,n=0; char spare[200]; char * cfgstr = NULL; for( i=0; i<3; i++){ if(numfiles[i] > n) n = numfiles[i]; } for( i=LIST_START; i<=n+2; i++ ){ fillspace(0, i, c_cols, 0); } textxy( 1, line++, 1, "Configuration: "); textxy( 1, line++, 0, " "); for( i=0; i(sizeof(cfg_items)/4)-1 ) return; cfgstr = cfg_str( cfg_items[n], ""); inv = (cursor == n) ? 1 : 0; sprintf( (char*)&spare, "%12s: %s", cfg_titles[n], cfgstr ); textxy( 1, LIST_START+2+n, inv, (char*)&spare ); } const char * ask_for_string( char * query, const char * current, short max ) { static char buf[200]; int i; if( max > 199 ) max = 199; if( current == NULL ){ sprintf( (char*)&buf, "%s:", query ); textxy( 0, c_rows-2, 1, buf ); } else { sprintf( (char*)&buf, "%s (%s):", query, current ); textxy( 0, c_rows-2, 1, buf ); } Rev_on(); scanf("%s", &buf); buf[max]=0; i = 0; while( buf[i] != 0){ if( buf[i] == 10 || buf[i] == 13 ){ buf[i] = 0; break; } i++; } Rev_off(); fillspace( 0, c_rows-2, c_cols, 0); if( strlen((char*)&buf) < 1 ) return( current ); return( (char*)&buf ); } /* move file from / to - this is not an simple rename */ long move_file( char * src, char * dst) { long err, count; short srcf, dstf; static buf[8192]; srcf = Fopen( src, 0 ); dstf = Fcreate( dst, 0 ); if( srcf < 0 || dstf < 0 ){ printf("Error open file\r\n"); if( srcf > 0) Fclose( srcf ); if( dstf > 0 ) Fclose( srcf ); return( -2 ); } count = Fread( srcf, 8192, &buf ); if( count > 0 ){ do{ Fwrite(dstf, count, &buf ); count = Fread( srcf, 8192, &buf); }while( count > 0 ); } Fclose(dstf); Fclose(srcf); err = Fdelete( src ); if( err != 0 ) return( err ); return( 0 ); } /* sort files matching _filter mask on disk */ void sort_files(char _filter) { short i; char * anim[] = {"|", "/", "-", "\\"}; long err; char buf[256]; char buf2[256]; sprintf(buf, "%s\\SBOOTTMP", basepath[_filter] ); if( Dcreate(buf) < 0 ){ draw_info("Error creating temp. Dir!"); sleep(1); } for( i=0; i= numfiles[filter] ) { index = 0; } /* bzw. wenn erster ueberschritten, dann auf letzten*/ if( index < 0 ) { index = numfiles[filter] - 1; } /* wenn der cursor schonmal gezeichnet wurde, */ /* dann alte ausgabe mit leerzeichen ueberschreiben:*/ cursor = index; if( old >= 0 ) { /*textxy( 0+(filter*COL_LEN), cursor + LIST_START, 0, " "); */ draw_list_item( oldfilter, old ); } /* index neu setzen und bildschirmpos. berechnen */ y = cursor + LIST_START+1; /* markierung ausgeben: */ /*textxy( 0+(filter*COL_LEN), y, 0, ">");*/ draw_list_item( filter, cursor ); /* und den alpha cursor um eins nach links */ /* da sonst der buchstabe des aktuellen eintrags */ /* vom cursor ueberdeckt ist: */ Goto_pos( y, 0+(filter*COL_LEN) ); } void fill_list( char * path) { int err; struct ffblk blk; numfiles[filter] = 0; err = findfirst( path, &blk, 0xff); while( err == 0 && numfiles[filter] <=FLIST_MAX ){ strncpy( filelist[filter][numfiles[filter]], blk.ff_name, 14 ); numfiles[filter]++; err = findnext( &blk ); } } void set_filter( char _filter ) { char * base = basepath[_filter]; char path[255]; memset( &path, 0, 255 ); filter = _filter; sprintf(path, "%s\\%s", base, filtermask[filter] ); fill_list( path ); } void move_cur( signed char direction ) { char prevfile[14]; short bak; if( cursor+direction < 0 ) return; if( cursor+direction >= numfiles[filter] ) return; bak = cursor; set_active( cursor+direction, filter ); cursor = bak; strcpy(prevfile, filelist[filter][cursor+direction]); strcpy(filelist[filter][cursor+direction], filelist[filter][cursor]); strcpy(filelist[filter][cursor], prevfile); cursor += direction; draw_list_item( filter, bak ); draw_list_item( filter, cursor ); resort[filter] = 1; } void toggle_cur( void ) { long n; char fullpath[255]; char newpath[255]; char * base = basepath[ filter ]; char * curfile = filelist[filter][cursor]; char end = 'G'; char oldend = ' '; if( numfiles[filter] <= 0 ) { return; } if( (strlen(curfile) + strlen(base) + 2) < 255 ) { sprintf( fullpath, "%s\\%s", base, curfile ); n = strlen(curfile); oldend = curfile[n-1]; /* Programm auf inaktiv geschaltet? */ if( (curfile[n-1] == 'X' && filter != CPX_FILTER ) || (curfile[n-1] == 'Z' && filter == CPX_FILTER ) ){ if( filter == ACC_FILTER ) end = 'C'; if( filter == CPX_FILTER ) end = 'X'; curfile[n-1] = end; } else { /* Programm deaktivieren */ if( filter == CPX_FILTER ){ curfile[n-1] = 'Z'; } else { curfile[n-1] = 'X'; } } sprintf( newpath, "%s\\%s", base, curfile ); if( Frename( 0, (const char*)&fullpath, (char*)&newpath ) != 0 ) { /* Datei konnte nicht umbennant werden, */ /* liste wiederherstellen */ curfile[n-1] = oldend; } else { draw_list_item( filter, cursor ); } } } void delete_set( short index ) { const char * attr; const char * yesno; char query[255]; ezxml_t lset = NULL; for( lset = ezxml_child(ezxmlh, "set"); lset; lset = lset->next){ attr = ezxml_attr(lset, "pos" ); if( attr != NULL ){ if( atoi(attr) == index ){ sprintf(query, "Delete Set %s? (yes/no)", ezxml_attr(lset, "name") ); yesno = ask_for_string( query, NULL, 3 ); if(strncmp("yes", yesno, 3) == 0 ){ ezxml_remove( lset ); } } } } draw_title( NULL ); draw_info( INFO ); /* set default filter and draw list: */ set_filter( CPX_FILTER ); set_filter( ACC_FILTER ); set_filter( PRG_FILTER ); draw_main(); } void write_set( short index, short create ) { int i,x; size_t l; const char * attr; ezxml_t lset = NULL, item = NULL; static char spare[255]; char * settag[4] = {"prg", "acc", "cpx", "custom"}; char * query = "Enter new Set name"; char removed = 0; char * script=NULL; item = NULL; if( create != 0 ) { setname = NULL; } for( lset = ezxml_child(ezxmlh, "set"); lset; lset = lset->next){ attr = ezxml_attr(lset, "pos" ); if( attr != NULL ){ if( atoi(attr) == index ){ if( removed == 0 && create != 0 ) { setname = ask_for_string( query, ezxml_attr(lset, "name"), 12 ); } ezxml_remove( lset ); removed++; } } } if( setname == NULL ) { if( create == 0 ) return; setname = ask_for_string( query, NULL, 12 ); if( setname == NULL ){ setname = spare; sprintf((char*)setname, "SET%d", index ); } } set = ezxml_add_child(ezxmlh, "set", 0); currentset = index; sprintf( spare, "%d", index); ezxml_set_attr_d(set, "pos", spare ); ezxml_set_attr_d(set, "name", setname ); item = ezxml_add_child(set, "script", 0); printf("removed: %ld\n"); if( removed > 0 ){ ezxml_set_txt_d(item, currentscript ); } else{ ezxml_set_txt_d(item, "" ); } for( i=0; i<4; i++ ){ if( i <= CPX_FILTER ){ for( x=0; xnext){ attr = ezxml_attr( set, "pos" ); if( attr != NULL ){ if( atoi(attr) == index ){ setname = ezxml_attr( set, "name" ); currentset = index; item = ezxml_child( set, "script" ); strncpy(currentscript, ezxml_txt( item ), SCRIPT_MAX_LEN ); currentscript[SCRIPT_MAX_LEN]=0; break; } } } if( set == NULL ){ draw_info("Set not found!"); currentset = -1; setname = NULL; return ( set ); } /* set lastscript, so that no load of set is required when booting */ if( strlen(currentscript) > 0 ) { item = ezxml_child(ezxmlh, "lastscript"); if( item == NULL ) { item = ezxml_add_child(ezxmlh, "lastscript", 0); } ezxml_set_txt_d(item, currentscript ); } for( i=0; i<=CPX_FILTER; i++ ){ sprintf( path1, "%s\\%s", basepath[i], filtermask[i]); err = findfirst( path1, &blk, 0xff); while( err == 0 ){ found = 0; for( item = ezxml_child(set, settag[i]); item; item=item->next){ enabled = ezxml_txt( item ); if( strcmp((char*)&blk.ff_name, (char*)enabled) == 0 ){ /* found file as enabled */ found = 1; break; } strcpy(disabled, enabled); l = strlen((char*)&disabled)-1; if( i == CPX_FILTER ) disabled[l] = 'Z'; else disabled[l] = 'X'; if( strcmp( (char*)&blk.ff_name, (char*)&disabled) == 0 ){ /* found file as disabled */ found = 1; sprintf(path3, "%s\\%s", basepath[i], enabled ); sprintf(path2, "%s\\%s", basepath[i], &blk.ff_name ); Frename( 0, path2, path3 ); } } if( found == 0 ) { /* file not found in xml, so disable it... */ strcpy( (char*)&disabled, (char*)&blk.ff_name ); l = strlen((char*)&disabled)-1; if( i == CPX_FILTER ) disabled[l] = 'Z'; else disabled[l] = 'X'; if( strcmp((char*)&disabled, (char*)&blk.ff_name) != 0 ){ sprintf( path2, "%s\\%s", basepath[i], (char*)&blk.ff_name ); sprintf( path3, "%s\\%s", basepath[i], (char*)&disabled ); Frename( 0, path2, path3 ); } } err = findnext( &blk ); } } set_filter( CPX_FILTER ); set_filter( ACC_FILTER ); set_filter( PRG_FILTER ); draw_main(); if( setname == NULL ) sprintf(path1, "Loaded set F%d.", index+1 ); else sprintf(path1, "Loaded set %s.", setname ); draw_info(path1); return( set ); } void config( void ) { short prevcursor; char ascii,sh; short code, key; char ig=0; short exit = 0; const char * input; char changed = 0; ezxml_t item; cursor = 0; draw_config(); draw_info("ESC/Q=Leave, ENTER=Edit item."); do{ ig = 0; key = getkey(&sh, &code, &ascii); switch( code ){ case CURS_DOWN: prevcursor = cursor; cursor = ((cursor + 1) % (sizeof(cfg_items)/4)); draw_config_item( prevcursor ); draw_config_item( cursor ); ig=1; break; case CURS_UP: prevcursor = cursor; cursor = ((cursor - 1) % (sizeof(cfg_items)/4)); if( cursor < 0 ){ cursor = (sizeof(cfg_items)/4)-1; } draw_config_item( prevcursor ); draw_config_item( cursor ); ig = 1; break; case ESC: exit = 1; break; default: /* printf("Code: 0x%x, key: 0x%x, ascii: 0x%x\n",code, key, ascii ); */ break; } if( ig != 1 && exit != 1){ switch( key ){ case 'Q': case 'q': exit = 1; break; case 10: case 13: input = cfg_str( cfg_items[cursor], "NULL" ); input = ask_for_string( "New Value", input, 12); if( (input != NULL) && (strlen(input) > 0) && (ezxmlh != NULL) ) { item = ezxml_child(ezxmlh, cfg_items[cursor]); if( item ){ ezxml_set_txt_d( item, input ); init_config_vars(); fillspace(0, cursor, c_cols, 0); draw_config(); changed = 1; } } break; default: break; } } } while ( exit != 1 ); if( changed == 1 ) { set_filter( CPX_FILTER ); set_filter( ACC_FILTER ); set_filter( PRG_FILTER ); } cursor = prevcursor; draw_info( INFO ); draw_main(); } void input( void ) { char ascii,sh; short code, key, old; char spare[255]; char ig=0; char * tmp; key = getkey(&sh, &code, &ascii); /* sprintf(&spare, "cook: %04x, sh: %02x, code: %04x, ascii: %0x2", key, sh, code, ascii ); textxy(1, 1, 0, &spare ); */ switch( code ){ case CURS_DOWN: set_active( cursor + 1, filter ); ig=1; break; case CURS_UP: set_active( cursor - 1, filter ); ig = 1; break; case HELP: help(); draw_main(); ig = 1; break; case F11_BASE: case F11_BASE+1*0x100: case F11_BASE+2*0x100: case F11_BASE+3*0x100: case F11_BASE+4*0x100: case F11_BASE+5*0x100: case F11_BASE+6*0x100: case F11_BASE+7*0x100: case F11_BASE+8*0x100: case F11_BASE+9*0x100: write_set( (short)(code - F11_BASE)/0x100, 1 ); ig = 1; break; case F1_BASE: case F1_BASE+1*0x100: case F1_BASE+2*0x100: case F1_BASE+3*0x100: case F1_BASE+4*0x100: case F1_BASE+5*0x100: case F1_BASE+6*0x100: case F1_BASE+7*0x100: case F1_BASE+8*0x100: case F1_BASE+9*0x100: load_set( (short)(code - F1_BASE)/0x100 ); ig = 1; break; case CURS_LEFT: if( filter > 0 ){ old = filter; set_filter( (filter-1) % 3 ); draw_list_item( old, cursor ); cursor = (cursor <= (numfiles[filter]-1)) ? cursor : (numfiles[filter]-1); draw_list_header(); set_active( cursor, old ); } ig = 1; break; case CURS_RIGHT: old = filter; set_filter( (filter+1) % 3 ); draw_list_item( old, cursor ); cursor = (cursor <= (numfiles[filter]-1)) ? cursor : 0 ; draw_list_header(); set_active( cursor, old ); ig = 1; break; case ESC: ig = 1; quit = 1; break; case CTRL_S: if( ascii == 19 ){ save_settings(); ig = 1; } break; } if( ig == 1 ) return; switch( key ) { case 'q': case 'Q': quit = 1; break; case '\n': case '\r': case ' ': toggle_cur(); break; case 'A': move_cur( -1 ); break; case 'Y': move_cur( 1 ); break; case 'C': case 'c': config(); break; case 'l': case 'L': list_sets(); break; case 'S': save_settings(); break; case 'D': if( set != NULL ) delete_set(currentset); break; case 'E': case 'e': if( set != NULL ) { if( ezxml_attr(set, "script") != NULL ){ sprintf(currentscript, "%s", ezxml_attr(set, "script") ); } if( strlen(currentscript) < 1 ){ sprintf(currentscript, examplescript, setname ); } sprintf( spare, "Edit script for Set: %s", setname); tmp = edit_text(spare , currentscript ); if ( tmp ) { strncpy( currentscript, tmp, SCRIPT_MAX_LEN ); currentscript[SCRIPT_MAX_LEN] = 0; write_set(currentset, 0); } else { if( ezxml_attr(set, "script") != NULL ){ sprintf(currentscript, "%s", ezxml_attr(set, "script") ); } } end_edit_text(); clear_workarea(); draw_title( NULL ); draw_info( INFO ); /* set default filter and draw list: */ set_filter( CPX_FILTER ); set_filter( ACC_FILTER ); set_filter( PRG_FILTER ); draw_main(); } else { draw_info("You must load a set before editing it's script!"); } break; default: break; } } int main(void) { long avail = 0; long prev=0, cur; char spare[255]; init(); draw_title( NULL ); draw_info( INFO ); /* set default filter and draw list: */ set_filter( CPX_FILTER ); set_filter( ACC_FILTER ); set_filter( PRG_FILTER ); draw_main(); sprintf((char*)&spare, "%d", (short)timeout); textxy( c_cols-1, c_rows-1, 0, spare); /* wait for character, or timeout */ prev = cur = clock()/CLK_TCK; while( timeout >= 0 ) { avail = Cconis(); if( avail != 0 ) break; cur = (long)(clock()/CLK_TCK); if( cur > prev ){ prev = (long)cur; timeout--; if( timeout >= 0 ){ sprintf(spare, "%d", (short)timeout); textxy( c_cols-1, c_rows-1, 0, (char*)&spare); } } } if( avail == 0 ) { goto end; } /* clear the last time output: */ textxy( c_cols-1, c_rows-1, 1, " "); /* screen = Physbase(); *(long*)(screen) = 0xFF0000; */ /* handle user input: */ while ( quit != 1 ) { input(); } save_settings(); end: Clear_home(); if( strlen( currentscript ) > 1 ){ execute_script( currentscript ); } if( vdivh != 0 ) v_clsvwk( vdivh ); if( vdiph != 0 ) v_clswk( vdiph ); if( ezxmlh ) ezxml_free( ezxmlh ); return( 0 ); }