home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Zodiac Super OZ
/
MEDIADEPOT.ISO
/
FILES
/
16
/
RAWED1_1.ZIP
/
RAWEDIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-08
|
83KB
|
2,945 lines
/* -- rawedit.c View/edit a file in hex/ascii -- */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <errno.h>
#include "rawedit.h"
/* --------------------- **
** M A C R O S **
** --------------------- */
#define HEX_SIDE 0
#define ASCII_SIDE 1
#define STARTROW 3
#define MAXROW 24
#define BYTES_PER_ROW 24
#define BYTES_PER_PAGE ((MAXROW - STARTROW + 1) * BYTES_PER_ROW)
#define HEX_COL_START 1
#define ASCII_COL_START 56
#define ASCII_LEN (BYTES_PER_ROW)
#define HEX_LEN ( (BYTES_PER_ROW * 2) + 6 )
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE -1
#endif
/* -------------------------------- **
** G L O B A L V A R I A B L E S **
** -------------------------------- */
FILE *file;
char *filename = (char *)0;
short curx = 1, cury = 1;
long filelen = 0L, filepos = 0L;
char orig_buffer[ BYTES_PER_PAGE + 3 ];
long orig_filepos = -1L;
char buffer[ BYTES_PER_PAGE + 3 ];
short bufpos=0, buflen=0;
short nibblestate = 0;
short tabstate = HEX_SIDE;
char search_direction = 'F'; /* F = forward, B = backward */
char search_type = 'A'; /* H = hex, A = ascii */
char search_string[200];
short search_string_len = 0;
long last_srch_pos = 0;
short read_only = 0;
char *cursor_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT v1.1 By: Ken Martin | ",
" | C U R S O R K E Y S | ",
" | | ",
" | Up ............... UP-ARROW, CTRL-U | ",
" | Down ............. DOWN-ARROW, CTRL-D | ",
" | Previous Page .... PAGE-UP, CTRL-P | ",
" | Next Page ........ PAGE-DOWN, CTRL-N | ",
" | Left ............. LEFT-ARROW, CTRL-L | ",
" | Right ............ RIGHT-ARROW, CTRL-R | ",
" | Beginning of file. HOME, CTRL-H | ",
" | End of file ...... END, CTRL-E | ",
" | Jump ............. TAB, CTRL-I | ",
" | Menu ............. ENTER, CTRL-M | ",
" | Exit ............. ESCAPE, CTRL-C | ",
" | Help (in menu) ... ? | ",
" | | ",
" | Hit any key to continue... | ",
" |_____________________________________________| ",
" ",
" ",
"\0"
};
char *main_menu_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Main Menu | ",
" | | ",
" | Exit ............ Leave the RAWEDIT program | ",
" | Goto ............ Goto an offset# in file | ",
" | Search ...... ... Search for a string | ",
" | Repeat_search ... Repeat search using | ",
" | previous search parameters| ",
" | re-Draw_screen .. Redisplay entire screen | ",
" | Help ............ Show cursor keys | ",
" | ? ............... Show this help screen. | ",
" | | ",
" | Access any menu option by pressing the | ",
" | corresponding capitalized letter. For | ",
" | example, to exit RAWEDIT, press 'E'. | ",
" | | ",
" | Hit a key to continue... | ",
" | | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *offset_num_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Offset Number | ",
" | | ",
" | The offset # should be from 0 to file | ",
" | length (shown at the top of the screen). | ",
" | | ",
" | Offset # may be an integer (base 10), or | ",
" | hexadecimal. For hexadecimal, prefix with | ",
" | '0x'. | ",
" | | ",
" | Examples: | ",
" | Enter offset# to go: 1234 | ",
" | Enter offset# to go: 0xF1C4 | ",
" | | ",
" | Hit a key to continue... | ",
" | | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *search_direction_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Search Direction | ",
" | | ",
" | To Type | ",
" | ----------------------------------- ------- | ",
" | Search forward from current offset F | ",
" | Search backward from current offset B | ",
" | Return to previous menu [ENTER] | ",
" | Show this help screen ? | ",
" | | ",
" | | ",
" | Hit a key to continue... | ",
" | | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *search_type_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Search Type | ",
" | | ",
" | To Type | ",
" | ----------------------------------- ------- | ",
" | Search using hexadecimal numbers H | ",
" | Search using normal ASCII text A | ",
" | Return to previous menu [ENTER] | ",
" | Show this help screen ? | ",
" | | ",
" | | ",
" | Hit a key to continue... | ",
" | | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *search_string_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Search String | ",
" | | ",
" | Enter the ASCII text string to be used for | ",
" | searching. RAWEDIT will then go to the | ",
" | first matching position in the file. | ",
" | A failure a match will return to the | ",
" | current offset position. | ",
" | | ",
" | Hit a key to continue... | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *search_hex_nums_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Search Hex Nums | ",
" | | ",
" | Enter the hexadecimal numbers to be used for| ",
" | searching. RAWEDIT will then go to the | ",
" | first matching position in the file. | ",
" | A failure a match will return to the | ",
" | current offset position. | ",
" | | ",
" | Examples: | ",
" | search hex nums: A1C4010004 | ",
" | search hex nums: 00 01 39 CF | ",
" | search hex nums: 0xF00F 0xC1 0x001A03 | ",
" | | ",
" | Hit a key to continue... | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *write_changes_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Write changes | ",
" | | ",
" | Yes ...... Save changes made to this screen | ",
" | | ",
" | No ....... Discard changes, this page will | ",
" | not be altered. | ",
" | | ",
" | | ",
" | Hit a key to continue... | ",
" |_____________________________________________| ",
" ",
"\0"
};
char *util_help[] = {
" _____________________________________________ ",
" | | ",
" | RAWEDIT HELP: Utilities | ",
" | | ",
" | Expand_file.... Increase size of current | ",
" | file | ",
" | Save_chunk..... Save a portion of this file | ",
" | to a new file | ",
" | Hex_conv....... Convert hex to dec, hex to | ",
" | bin, dec to bin, dec to | ",
" | hex, bin to hex, bin to dec | ",
" | Calc........... Simple scientific calculator| ",
" | | ",
" | Hit a key to continue... | ",
" |_____________________________________________| ",
" ",
"\0"
};
/* -------------------------------- **
** P R O T O T Y P E S **
** ---------------------------------*/
int rawedit( char *fname );
void display_header( void );
void refresh_screen( short firstrow, short lastrow );
void flush_buffer( void );
int get_buffer( void );
void compute_xy( short *x, short *y );
char *get_hex( char ch );
void print_filename( void );
void update_position_display( void );
void do_page_up( long newbufpos );
void do_page_down( long newbufpos );
void do_right( void );
int do_menu( void );
void do_goto_offset( void );
void do_help( char *help_text[] );
void strip( char *s );
int hex_to_long( char *s, unsigned long *ret_val );
char hex_to_nibble( char c );
void message( char *msg );
void do_search( void );
void do_search_direction( void );
void do_search_type( void );
void do_repeat_search( void );
void do_utilities( void );
void do_setfilesize( void );
void do_savechunk( void );
void do_hexconv( void );
void calc(short col, short row);
int calc_error( char * action );
void search_file( long start_pos );
int copy_files( FILE *source, FILE *dest, long offset1, long offset2,
char append);
void get_file_length( void );
char *long_to_hex( long l );
char *hex_to_bytes( char *hex, long *b_len);
short input_line( char *editstr, short col, short row, short len,
short startpos, int *exitlist, char *options );
void lstrip( char * );
void rstrip( char * );
char valid_char( char a );
int files_are_same( char *file1, char *file2 );
char *long_to_bin( long l );
/* -------------------- **
** M A I N **
** ---------------------*/
int main(int argc, char *argv[])
{
long i;
if ( argc < 2 )
{
printf(
"\n RAWEDIT - View a file in hex/ascii "
"\n"
"\n Syntax: rawedit -r <filename1> {<filename2> ...}"
"\n"
"\n where: -r Read-only mode. No file changes allowed."
"\n <filename> The file to view/modify."
"\n"
);
exit(1);
}
io_init();
display_header();
/* --- Check for switch --- */
for (i = 1; i < argc; i++ )
{
if ( strcmp( argv[i], "-r" ) == 0 )
{
read_only = 1;
}
}
for (i = 1; i < argc; i++ )
{
if ( strcmp( argv[i], "-r" ) == 0 ) continue;
io_gotoxy(1,2);
io_printf("%80s", " ");
if ( !rawedit ( argv[i] ) )
{
io_refresh();
io_end();
exit(1);
}
}
io_end();
return 0;
}
/* ----------------------------------- **
** R A W E D I T F U N C T I O N S **
** ----------------------------------- */
void display_header( void )
{
io_clrscr();
io_gotoxy( 26, 1 ); io_puts( "Len:" );
io_gotoxy( 41, 1 ); io_puts( "File Offset:" );
io_gotoxy( 1, 2 ); io_puts( "[ENTER]=Menu" );
io_refresh();
}
int rawedit( char *fname )
{
char tmp[100];
short keyhit;
short tmpx, tmpy;
filename = fname;
print_filename();
/* ------------------------------- **
** Open filename **
** ------------------------------- */
if ( read_only )
{
file = fopen( filename, "rb" );
}
else
{
file = fopen( filename, "r+b" );
}
if ( file == (FILE *)0 )
{
io_clrscr();
sprintf( tmp, "Unable to open %s. Hit a key...", filename );
message( tmp );
return 1;
}
/* ------------------------------- **
** Display initial file info **
** ------------------------------- */
get_file_length();
fseek( file, 0L, SEEK_SET ); /* Reset to beginning */
if ( get_buffer() ) return 1;
io_gotoxy( 1, 2 );
io_printf("[ENTER]=Menu %65.65s", " " );
refresh_screen( STARTROW, MAXROW );
/* ------------------------------- **
** Get keystroke and process **
** --------------------------------*/
while( 1 )
{
update_position_display();
compute_xy( &curx, &cury );
io_gotoxy( curx, cury );
io_refresh();
keyhit = io_inchar();
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C )
{
break;
}
else if ( keyhit == io_TAB || keyhit == io_CTRL_I ) /* Jump */
{
tabstate = 1 - tabstate;
nibblestate = 0;
}
else if ( keyhit == io_PAGEUP || keyhit == io_CTRL_P )
{
do_page_up( bufpos );
}
else if ( keyhit == io_PAGEDOWN || keyhit == io_CTRL_N )
{
do_page_down( bufpos );
}
else if ( keyhit == io_UP || keyhit == io_CTRL_U )
{
if ( bufpos - BYTES_PER_ROW >= 0 )
{
bufpos -= BYTES_PER_ROW;
}
else
{
if ( filepos > 0L )
{
if ( filepos < BYTES_PER_PAGE )
{
do_page_up( filepos - BYTES_PER_ROW );
}
else
{
do_page_up( BYTES_PER_PAGE - BYTES_PER_ROW + bufpos );
}
}
}
}
else if ( keyhit == io_DOWN || keyhit == io_CTRL_D )
{
if ( bufpos + BYTES_PER_ROW < buflen )
{
bufpos += BYTES_PER_ROW;
}
else
{
do_page_down( bufpos - BYTES_PER_PAGE + BYTES_PER_ROW );
}
}
else if ( keyhit == io_LEFT || keyhit == io_CTRL_L )
{
if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
{
if ( bufpos > 0 )
bufpos--;
else
{
if ( filepos < BYTES_PER_PAGE )
{
do_page_up( filepos - 1L );
}
else
{
do_page_up( BYTES_PER_PAGE );
}
}
}
else /* --- Hex text area --- */
{
if ( nibblestate )
{
nibblestate = 0;
}
else
{
if ( bufpos > 0 )
{
bufpos--;
nibblestate = 1;
}
else
{
if ( filepos > 0L )
{
if ( filepos < BYTES_PER_PAGE )
{
do_page_up( filepos - 1L );
}
else
{
do_page_up( BYTES_PER_PAGE );
}
}
}
}
}
}
else if ( keyhit == io_RIGHT || keyhit == io_CTRL_R )
{
do_right();
}
/* --- Beginning of file --- */
else if ( keyhit == io_HOME || keyhit == io_CTRL_H )
{
filepos = 0L;
bufpos = 0;
if ( get_buffer() ) return 1;
refresh_screen( STARTROW, MAXROW );
}
/* --- End of file --- */
else if ( keyhit == io_END || keyhit == io_CTRL_E )
{
get_file_length( );
filepos = filelen - BYTES_PER_PAGE + BYTES_PER_ROW;
if ( filepos >= filelen ) filepos = filelen - 1L;
if ( filepos < 0L ) filepos = 0L;
bufpos = filelen - filepos - 1L;
if ( get_buffer() ) return 1;
refresh_screen( STARTROW, MAXROW );
}
/* ----- Activate Menu ----- */
else if ( keyhit == io_ENTER || keyhit == io_CTRL_M )
{
if ( do_menu() ) break;
io_gotoxy( 1, 2 );
io_printf("[ENTER]=Menu %65.65s", " " );
}
/* --- Modify the buffer --- */
else if ( !read_only && keyhit >=(short)32 && keyhit <= (short)io_MAX_VALID_CHARACTER )
{
if ( tabstate == HEX_SIDE )
{ /* --- Hex side, allow only hex characters --- */
keyhit = (short)toupper( (int)keyhit );
if ( (keyhit >= (short)'0' && keyhit <= (short)'9') ||
(keyhit >= (short)'A' && keyhit <= (short)'F')
)
{
if ( nibblestate == 0 ) /* --- Upper nibble --- */
{
buffer[bufpos] =
( buffer[bufpos] & 0x0F ) |
( hex_to_nibble( (char)keyhit ) << 4 );
}
else /* --- Lower nibble --- */
{
buffer[bufpos] =
( buffer[bufpos] & 0xF0 ) |
hex_to_nibble( (char)keyhit );
}
/* --- update other side --- */
tabstate = ASCII_SIDE;
compute_xy( &tmpx, &tmpy );
io_gotoxy( tmpx, tmpy );
io_putc( valid_char(buffer[bufpos]) );
tabstate = HEX_SIDE;
io_gotoxy( curx, cury );
io_putc( keyhit );
do_right();
}
}
else /* --- Ascii side, allow regular characters --- */
{
buffer[bufpos] = (char)keyhit;
/* --- Update other side --- */
tabstate = HEX_SIDE;
compute_xy( &tmpx, &tmpy );
io_gotoxy( tmpx, tmpy );
io_printf( "%02s", get_hex( (char)keyhit ) );
tabstate = ASCII_SIDE;
io_gotoxy( curx, cury );
io_putc( valid_char((char)keyhit) );
do_right();
}
}
else
{
;
}
}
flush_buffer();
fclose( file );
return 1;
}
void refresh_screen( short firstrow, short lastrow )
{
short y, i, j, k;
char hex_text[81] = " "
" ";
char ascii_text[81] = " "
" ";
short bufidx = 0;
char ch;
hex_text[HEX_LEN+1] = '\0';
ascii_text[ASCII_LEN] = '\0';
for( y = firstrow, bufidx = (firstrow-STARTROW)*BYTES_PER_ROW;
y <= lastrow; y++, bufidx+=BYTES_PER_ROW )
{
/* --- build hex/ascii -number text for display --- */
for ( i = bufidx, j=0, k=0;
i < bufidx + BYTES_PER_ROW && i < buflen; i++, j++, k+=2 )
{
ch = buffer[i];
/* --- hex number --- */
strncpy(&hex_text[k], get_hex(ch), 2 );
if ( (i+1) % 4 == 0 )
{
hex_text[k+2] = ' ';
k++;
}
/* --- ascii number --- */
ascii_text[j] = valid_char( ch );
}
if ( hex_text[0] != ' ')
for ( i = k; i < HEX_LEN; i++ ) hex_text[i] = ' ';
for ( i = j; i < ASCII_LEN; i++ ) ascii_text[i] = ' ';
/* --- Display the row --- */
io_gotoxy( HEX_COL_START, y );
io_puts( hex_text );
io_puts( ascii_text );
}
}
void flush_buffer( void )
{
char tmp[100];
short keyhit;
short status;
/* --- Check for changes to buffer --- */
if ( !read_only && orig_filepos >= 0L &&
memcmp( orig_buffer, buffer, buflen ) != 0 )
{
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Write changes?: Yes No " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( keyhit == 'Y' || keyhit == 'y' )
{
/* --- write changes to the file --- */
fseek( file, orig_filepos, SEEK_SET );
status = fwrite( buffer, (size_t)buflen, (size_t)1, file );
if ( !status )
{
message( "Unable to write changes. Hit a key..." );
memcpy( buffer, orig_buffer, buflen );
}
break;
}
else if ( keyhit == 'N' || keyhit == 'n' )
{
break;
}
else if ( keyhit == '?' )
{
do_help( write_changes_help );
}
else
{
;
}
} /* End while loop */
io_gotoxy( 1, 2 );
io_printf("[ENTER]=Menu %65.65s", " " );
}
}
int get_buffer( void )
{
short status;
flush_buffer();
/* -- Always get end-of-file in case file length changes while editing -*/
get_file_length();
if ( filelen < 1 )
{
message("Nothing in file! Hit a key...");
return (-1);
}
if ( filepos >= filelen )
filepos = filelen-1L;
if ( filepos < 0L ) filepos = 0L;
if ( BYTES_PER_PAGE < filelen - filepos )
buflen = BYTES_PER_PAGE;
else
buflen = filelen - filepos;
/* -- Clear out keyboard buffer before performing a disk read -- */
io_flush_keyboard();
fseek( file, filepos, SEEK_SET );
status = fread( buffer, 1, buflen, file );
if ( !status )
{
message( "Unable to read file. Hit a key..." );
memset( buffer, '\0', buflen );
filepos = 0L;
return (-1);
}
if ( !read_only )
{
memcpy( orig_buffer, buffer, buflen );
orig_filepos = filepos;
}
return 0;
}
void compute_xy( short *x, short *y )
{
/* tabstate 0 means hex area
** tabstate other means ascii area
*/
short ascii_col_start = 56;
short hex_col_start = 1;
short col_adder = 0;
if ( bufpos > buflen ) bufpos = buflen;
if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
{
*y = (bufpos / ASCII_LEN);
*x = (bufpos - (*y * BYTES_PER_ROW ) ) + ascii_col_start;
*y = *y + STARTROW;
}
else /* --- Hex area --- */
{
*y = (bufpos / ASCII_LEN);
*x = (bufpos - (*y * BYTES_PER_ROW ) );
*y = *y + STARTROW;
col_adder = *x / 4;
*x = (*x * 2) + col_adder + nibblestate + hex_col_start;
}
}
void print_filename( void )
{
char *ptr;
/* ------------------------------- **
** Print filename on header **
** ------------------------------- */
io_gotoxy( 1, 1 );
ptr = strrchr( filename, '/' );
if ( ptr == (char *)0 )
{
ptr = strrchr( filename, '\\' );
}
if ( ptr == (char *)0 )
{
io_printf( "%-24.24s", filename );
}
else
{
io_printf( "%-24.24s", &ptr[1] );
}
}
void update_position_display( void )
{
char tmp[30];
long offset;
offset = filepos + bufpos;
io_gotoxy( 54, 1 );
sprintf( tmp, "%ld, 0x%s", offset, long_to_hex( offset ) );
io_printf( "%-24s", tmp );
}
void do_page_up( long newbufpos )
{
if ( newbufpos < 0L ) newbufpos = 0L;
filepos -= BYTES_PER_PAGE;
if (filepos < 0L) filepos = 0L;
bufpos = 0L;
get_buffer();
refresh_screen( STARTROW, MAXROW );
if ( (newbufpos) > buflen - 1L )
bufpos = buflen - 1L;
else
bufpos = (newbufpos);
if ( bufpos < 0L ) bufpos = 0L;
}
void do_page_down( long newbufpos )
{
if ( filepos + BYTES_PER_PAGE < filelen )
{
filepos += BYTES_PER_PAGE;
if ( filepos > filelen ) filepos = filelen;
bufpos = 0L;
get_buffer();
refresh_screen( STARTROW, MAXROW );
if ( (newbufpos) > buflen - 1L )
bufpos = buflen - 1L;
else
bufpos = (newbufpos);
}
}
void do_right( void )
{
if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
{
if ( bufpos < buflen - 1 )
bufpos++;
else
do_page_down( 0 );
}
else /* --- Hex text area --- */
{
if ( nibblestate == 0)
{
nibblestate = 1;
}
else
{
if ( bufpos < buflen - 1 )
{
bufpos++;
nibblestate = 0;
}
else
do_page_down( 0 );
}
}
}
/* --------------------------------- **
** M E N U F U N C T I O N S **
** --------------------------------- */
int do_menu( void )
{
/* -- RETURN STATUS: 0 = continue normally, 1 = exit program --- */
short keyhit;
char tmp[82];
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Exit Goto Search Repeat_search Util re-Draw_screen Help " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( keyhit == 'E' || keyhit == 'e' ) /* -- Exit -- */
{
return 1;
}
else if ( keyhit == 'G' || keyhit == 'g' ) /* -- Goto -- */
{
do_goto_offset();
return 0;
}
else if ( keyhit == 'S' || keyhit == 's' ) /* -- Search -- */
{
do_search();
return 0;
}
else if ( keyhit == 'R' || keyhit == 'r' ) /* -- Repeat search -- */
{
do_repeat_search();
return 0;
}
else if ( keyhit == 'U' || keyhit == 'u' ) /* -- Utilities -- */
{
do_utilities();
return 0;
}
else if ( keyhit == 'D' || keyhit == 'd' ) /* -- re-draw screen -- */
{
/* --- Redraw screen -- */
display_header();
update_position_display();
print_filename();
get_file_length();
refresh_screen( STARTROW, MAXROW );
return 0;
}
else if ( keyhit == 'H' || keyhit == 'h' ) /* -- Help -- */
{
do_help( cursor_help );
return 0;
}
else if ( keyhit == '?' )
{
do_help( main_menu_help );
}
else if ( keyhit == io_ESCAPE || keyhit == io_ENTER ||
keyhit == io_CTRL_M || keyhit == io_CTRL_C )
{
return 0;
}
else
{
;
}
} /* End while loop */
}
void do_goto_offset( void )
{
short keyhit;
char tmp[100];
char tmp2[20];
unsigned long offset;
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Enter offset# to go: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
tmp2[0] = (char)0;
keyhit = input_line( tmp2, strlen( tmp ), 2, 15, 1, (int *)0, "" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) ) continue;
rstrip(tmp2);
if ( strcmp( tmp2, "" ) == 0 ) return;
if ( strcmp( tmp2, "?" ) == 0 )
{
do_help( offset_num_help );
continue;
}
strip(tmp2);
if ( strcmp( tmp2, "" ) == 0 ) return;
if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
/* -- Hex value entered -- */
{
if ( hex_to_long( &tmp2[2], &offset ) == FALSE ) continue;
}
else /* -- Numeric value entered -- */
{
offset = atol( tmp2 );
if ( offset == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
}
break;
}
filepos = offset;
bufpos = 0;
get_file_length();
if ( filepos >= filelen )
{
filepos = filelen - BYTES_PER_PAGE + BYTES_PER_ROW;
bufpos = filelen - filepos -1L;
}
if ( filepos < 0L )
{
filepos = 0L;
bufpos = 0L;
}
get_buffer();
refresh_screen( STARTROW, MAXROW );
}
void do_search( void )
{
short keyhit;
char tmp[82];
char tmp2[82];
char *ptr;
short tmp_hex_len, i, j;
/* ---- Get search direction ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "search direction: Forward Backward " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( keyhit == 'F' || keyhit == 'f' )
{
search_direction = 'F';
break;
}
else if ( keyhit == 'B' | keyhit == 'b' )
{
search_direction = 'B';
break;
}
else if ( keyhit == '?' )
{
do_help( search_direction_help );
}
else if ( keyhit == io_ESCAPE || keyhit == io_ENTER ||
keyhit == io_CTRL_M || keyhit == io_CTRL_C )
{
return;
}
else
{
;
}
} /* End while loop */
/* ---- Get search type ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "search type: Hex Ascii_text " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( keyhit == 'H' || keyhit == 'h' )
{
search_type = 'H';
break;
}
else if ( keyhit == 'A' | keyhit == 'a' )
{
search_type = 'A';
break;
}
else if ( keyhit == '?' )
{
do_help( search_type_help );
}
else if ( keyhit == io_ESCAPE || keyhit == io_ENTER ||
keyhit == io_CTRL_M || keyhit == io_CTRL_C )
{
return;
}
else
{
;
}
} /* End while loop */
/* --- Get search data --- */
while( 1 )
{
switch ( search_type )
{
case 'A':
io_gotoxy( 1, 2 );
sprintf( tmp, "search string: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
search_string[0] = (char)0;
keyhit = input_line( search_string, strlen( tmp ), 2,
80 - strlen( tmp ), 1, (int *)0, "" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) ) continue;
lstrip( search_string );
rstrip( search_string );
if ( strcmp( search_string, "" ) == 0 ) return;
if ( strcmp( search_string, "?" ) == 0 )
{
do_help( search_string_help );
continue;
}
search_string_len = strlen( search_string );
break;
case 'H':
io_gotoxy( 1, 2 );
sprintf( tmp, "search hex nums: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
tmp2[0] = (char)0;
keyhit = input_line( tmp2, strlen( tmp ), 2, 80 - strlen( tmp ),
1, (int *)0, "" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) ) continue;
if ( strcmp( tmp2, "" ) == 0 ) return;
if ( strcmp( tmp2, "?" ) == 0 )
{
do_help( search_hex_nums_help );
continue;
}
/* --- convert this input to the search_string --- */
strip( tmp2 );
strcpy( search_string, "" );
/* --- Strip off any leading 0x prefix --- */
while(1)
{
ptr = strstr( tmp2, "0X" );
if ( ptr == (char *)0 ) break;
ptr[0] = ' ';
ptr[1] = ' ';
}
strip( tmp2 );
ptr = &tmp2[0];
tmp_hex_len = strlen( ptr );
if ( tmp_hex_len % 2 != 0 )
{
message( "Must enter an even number of hex values. "
"Hit a key..." );
continue;
}
search_string_len = tmp_hex_len / 2;
/* --- Cycle through list of hex values --- */
for ( i = 0, j=0; i < tmp_hex_len; i += 2, j++ )
{
search_string[j] = ( hex_to_nibble( ptr[i] ) << 4 ) |
hex_to_nibble( ptr[i+1] );
}
break;
default:
return;
} /* -- End switch -- */
break;
} /* -- End while loop -- */
/* --- Perform actual search --- */
search_file( filepos + bufpos );
}
void do_repeat_search( void )
{
/* --- Perform actual search --- */
if ( search_direction == 'F' )
search_file( filepos + bufpos + 1L);
else
search_file( filepos + bufpos - 1L);
}
void do_utilities( void )
{
short keyhit;
char tmp[82];
char tmp2[82];
char *ptr;
short tmp_hex_len, i, j;
/* ---- Utility Menu ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "util: Expand_file Save_chunk Hex_conv Calc " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( toupper(keyhit) == 'E' ) /* -- expand file size -- */
{
do_setfilesize();
break;
}
else if ( toupper(keyhit) == 'S' ) /* copy from this file to another */
{
do_savechunk();
break;
}
else if ( toupper(keyhit) == 'H' ) /* --- Hex conversion stuff --- */
{
do_hexconv();
}
else if ( toupper(keyhit) == 'C' ) /* --- Calculator --- */
{
calc(4, 4);
refresh_screen( 4, 16 );
}
else if ( keyhit == '?' )
{
do_help( util_help );
}
else if ( keyhit == io_ESCAPE || keyhit == io_ENTER ||
keyhit == io_CTRL_M || keyhit == io_CTRL_C )
{
return;
}
else
{
;
}
} /* End while loop */
}
void do_setfilesize()
{
short keyhit;
char tmp[82];
char z_newsize[80];
unsigned long l_newsize;
int status;
/* ---- Get new filesize number ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Enter new filesize, [ENTER] to cancel: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
z_newsize[0] = (char)0;
keyhit = input_line( z_newsize, strlen( tmp ), 2,
80 - strlen( tmp ), 1, (int *)0, ".NUMERIC" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
lstrip( z_newsize );
rstrip( z_newsize );
if ( strlen( z_newsize ) == 0 ) return;
l_newsize = atol( z_newsize );
if ( l_newsize <= filelen )
{
message( "New size must be larger than current size. Hit a key...");
continue;
}
fseek( file, l_newsize-1U, SEEK_SET );
status = fwrite( "\0", (size_t)1, (size_t)1, file );
if ( !status )
{
message( "Unable to expand file. Hit a key...");
break;
}
fseek( file, filepos, SEEK_SET );
get_buffer();
refresh_screen( STARTROW, MAXROW );
break;
}
return;
}
void do_savechunk( void )
{
short keyhit;
char tmp[82];
char tmp2[80];
char new_filename[200];
unsigned long offset1, offset2;
int status;
FILE *newfile;
char append = 'N';
/* ---- Get starting offset# ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Enter start offset number, [ENTER] to cancel: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
tmp2[0] = (char)0;
keyhit = input_line( tmp2, strlen( tmp ), 2,
80 - strlen( tmp ), 1, (int *)0, "" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
strip( tmp2 );
if ( strcmp( tmp2, "" ) == 0 ) return;
if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
/* -- Hex value entered -- */
{
if ( hex_to_long( &tmp2[2], &offset1 ) == FALSE ) continue;
}
else /* -- Numeric value entered -- */
{
offset1 = atol( tmp2 );
if ( offset1 == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
}
if ( offset1 >= filelen )
{
message( "Offset number must be less than file length. Hit a key...");
continue;
}
break;
}
/* ---- Get ending offset# ---- */
while( 1 )
{
io_gotoxy( 1, 2 );
sprintf( tmp, "Enter ending offset number, [ENTER] to cancel: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
tmp2[0] = (char)0;
keyhit = input_line( tmp2, strlen( tmp ), 2,
80 - strlen( tmp ), 1, (int *)0, ".NUMERIC" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
strip( tmp2 );
if ( strcmp( tmp2, "" ) == 0 ) return;
if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
/* -- Hex value entered -- */
{
if ( hex_to_long( &tmp2[2], &offset2 ) == FALSE) continue;
}
else /* -- Numeric value entered -- */
{
offset2 = atol( tmp2 );
if ( offset2 == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
}
if ( offset2 >= filelen )
{
message( "Offset number must be less than file length. Hit a key...");
continue;
}
if ( offset2 < offset1 )
{
message( "Ending offset # can't be less than starting #. Hit a key...");
continue;
}
break;
}
/* ---- Get new filename ---- */
while( 1 )
{
append = 'N';
io_gotoxy( 1, 2 );
sprintf( tmp, "Enter new file name, [ENTER] to cancel: " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
new_filename[0] = (char)0;
keyhit = input_line( new_filename, strlen( tmp ), 2,
80 - strlen( tmp ), 1, (int *)0, "" );
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
if ( keyhit != io_ENTER && ( keyhit < 32 ||
keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
lstrip( new_filename );
rstrip( new_filename );
if ( strlen( new_filename ) == 0 ) return;
if ( files_are_same( new_filename, filename ) )
{
message("New and current filenames should be different."
" Hit a key...");
continue;
}
newfile = fopen(new_filename,"rb");
if ( newfile != (FILE *)0 )
{
fclose(newfile);
io_gotoxy( 1, 2 );
sprintf( tmp, "File exists: Overwrite Append Cancel " );
io_printf( "%-79.79s", tmp );
io_gotoxy( strlen( tmp ), 2 );
io_refresh();
keyhit = io_inchar( );
if ( toupper(keyhit) == 'O')
{
append = 'N';
io_unlink(new_filename);
newfile = fopen(new_filename, "w+b");
}
else if ( toupper(keyhit) == 'A' )
{
append = 'Y';
newfile = fopen(new_filename, "r+b");
}
else
{
continue;
}
}
else
{
newfile = fopen(new_filename, "w+b");
}
if ( newfile == (FILE *)0 )
{
sprintf( tmp, "Can't update \"%1.30s\". Hit a key...", new_filename );
message( tmp );
continue;
}
/* Copy from "filename" to "newfile" starting from offset1 and
** ending at offset2
*/
if ( copy_files( file, newfile, offset1, offset2, append ) == FALSE )
{
message("File-save aborted. Hit a key...");
}
fclose(newfile);
break;
}
return;
}
void do_hexconv( void )
{
char *hexscreen[] = {
" ________________________________________ ",
" | | ",
" | HEX ........ | ",
" | DEC .......... | ",
" | BIN ................................ | ",
" | ASC .... | ",
" | ASC# ... ... ... ... <-ENTER=next byte | ",
" | | ",
" | TAB=Next Field ESC=Cancel | ",
" |________________________________________| ",
" ",
"\0"
} ;
char hex_str[9] = "";
char dec_str[11] = "";
char bin_str[33] = "";
char asc_str[5] = "";
char ascnum_str[4][4] = { "", "", "", "" };
short i = 0;
short oldi = 0;
short field_num = 0;
short col, row;
long byte_len;
long bitset;
unsigned long dec = 0;
char *options;
short len;
short ascpos = 0;
int keyhit = 0;
/* --- Display window --- */
while( strcmp( hexscreen[i], "\0" ) != 0 )
{
io_gotoxy( 11, STARTROW + i );
io_printf( "%s", hexscreen[i] );
i++;
}
io_refresh();
col = 20;
/* --- Prompt for value loop --- */
while(1)
{
row = STARTROW + 2 + field_num;
switch (field_num)
{
case 0: /* --- Hexadecimal --- */
options = ".HEX .ZAP";
len = 8;
keyhit = input_line( hex_str, col, row, len, 1, (int *)0, options );
hex_to_long( hex_str, &dec );
break;
case 1: /* --- Decimal --- */
options = ".DEC .ZAP";
len = 10;
keyhit = input_line( dec_str, col, row, len, 1, (int *)0, options );
dec = atol( dec_str );
break;
case 2: /* --- Binary --- */
options = ".BIN .ZAP";
len = 32;
keyhit = input_line( bin_str, col, row, len, 1, (int *)0, options );
/* -- convert binary string to a long (dec variable) -- */
dec = 0L;
bitset = 1L;
for ( i = strlen(bin_str) - 1; i >= 0; i--)
{
if ( bin_str[i] == '1' )
{
dec = dec | bitset;
}
else
if ( bin_str[i] != '0' ) break;
bitset = bitset << 1;
}
break;
case 3: /* --- ASCII --- */
options = ".ZAP .PRE_VALIDATE";
len = 4;
keyhit = input_line( asc_str, col, row, len, 1, (int *)0, options );
strcpy(hex_str,"");
byte_len = strlen(asc_str);
for ( i = 0; i < byte_len; i++)
{
strcat(hex_str, get_hex(asc_str[i]) );
}
hex_to_long(hex_str, &dec);
break;
case 4: /* --- ASCII # --- */
options = ".NUMERIC .ZAP";
len = 3;
keyhit = input_line( &ascnum_str[ascpos][0],
col+(4*ascpos), row, len, 1, (int *)0, options );
/* --- push everything over to left and clean up --- */
for ( i = 0, oldi = 0; i <= 3; i++ )
{
strip(ascnum_str[i]);
if ( strcmp( ascnum_str[i], "" ) == 0 ||
atoi(ascnum_str[i]) > 255 ||
atoi(ascnum_str[i]) < 0 )
{
continue;
}
if ( i == oldi )
{
oldi++;
continue;
}
strcpy(ascnum_str[oldi], ascnum_str[i]);
oldi++;
}
for ( i = oldi; i <= 3; i++ )
{
strcpy( ascnum_str[i], "" );
}
/*
**io_gotoxy( col+(4*ascpos), row );
**io_printf( "%3s", ascnum_str[ascpos]);
*/
/* --- Advance ascnum postion pointer --- */
if ( keyhit == io_ENTER || keyhit == io_CTRL_M )
{
if ( ascpos < 3 )
ascpos++;
else
ascpos = 0;
}
dec = 0L;
/* --- Build long-integer dec --- */
for ( i = 0; i <= 3; i++)
{
if ( strcmp( ascnum_str[i], "" ) == 0 ) break;
if ( i != 0 ) dec = dec << 8;
dec |= atol(ascnum_str[i]);
}
break;
default:
break;
}
if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) break;
/* --- Update all fields --- */
/* dec must be set first */
io_gotoxy(col, STARTROW+2);
strcpy(hex_str,long_to_hex(dec));
lstrip(hex_str);
rstrip(hex_str);
io_printf("%-10s", hex_str);
io_gotoxy(col, STARTROW+2+1);
sprintf(dec_str, "%-10lu", dec);
io_puts(dec_str);
io_gotoxy(col, STARTROW+2+2);
strcpy( bin_str, long_to_bin(dec) );
io_printf("%-32.32s", bin_str);
io_gotoxy(col, STARTROW+2+3);
io_printf( "....");
io_gotoxy(col, STARTROW+2+4);
io_printf( "... ... ... ...");
strcpy( asc_str, hex_to_bytes(hex_str, &byte_len) );
for ( i = 0; i < byte_len; i++)
{
io_gotoxy( col+i, STARTROW+2+3 );
io_putc( valid_char( asc_str[i] ) );
io_gotoxy( col+(i*4), STARTROW+2+4 );
sprintf( ascnum_str[i], "%3hu", (unsigned short)asc_str[i] & 0x00FF );
io_puts( ascnum_str[i] );
}
/* --- Check keystrokes --- */
if ( keyhit == io_TAB || keyhit == io_CTRL_I || keyhit == io_DOWN
|| keyhit == io_CTRL_D )
{
if ( field_num < 4 )
field_num++;
else
field_num = 0;
}
else if ( keyhit == io_UP || keyhit == io_CTRL_U )
{
if ( field_num > 0 )
field_num--;
else
field_num = 4;
}
} /* End of while loop */
/* --- Done, refresh screen and exit --- */
refresh_screen( STARTROW, STARTROW + 10 );
}
void do_help( char *help_text[] )
{
short i = 0;
while( strcmp( help_text[i], "\0" ) != 0 )
{
io_gotoxy( 11, STARTROW + i );
io_printf( "%s", help_text[i] );
i++;
}
io_refresh();
(void)io_inchar();
refresh_screen( STARTROW, STARTROW + i - 1 );
}
void search_file( long start_pos )
{
long old_file_pos, i, j;
short old_buf_pos, match, count;
old_file_pos = filepos;
old_buf_pos = bufpos;
/* --- last_search_pos hold current filepos --- */
if ( start_pos > filelen )
{
message( "* End of file. Hit a key.." );
return;
}
filepos = start_pos; /* Set to current cursor location */
bufpos = 0L;
count = 0;
switch ( search_direction )
{
case 'F': /* Forward */
while( filepos < filelen )
{
io_gotoxy(60,2);
if( count > 60 )
{
io_printf("filepos: %10ld", filepos );
count = 0;
}
else
{
count++;
}
io_refresh();
get_buffer();
/* --- Go through each position in the buffer --- */
for ( i = 0; i < buflen; i++ )
{
/* --- Compare string with current string in buffer --- */
match = 1;
for ( j = 0; j < search_string_len; j++ )
{
if ( buffer[i+j] != search_string[j] )
{
match = 0;
break;
}
}
if ( match )
{
filepos += i;
bufpos = 0;
get_buffer();
refresh_screen( STARTROW, MAXROW );
/* message( "Match found. Hit a key..." ); */
refresh_screen( STARTROW, MAXROW );
return;
}
}
filepos += ( BYTES_PER_PAGE - search_string_len );
} /* --- End of while loop -- */
message( "No match found. Hit a key..." );
filepos = old_file_pos;
bufpos = old_buf_pos;
get_buffer();
refresh_screen( STARTROW, MAXROW );
break;
case 'B': /* Backward */
while( filepos > 0L )
{
if ( filepos >= BYTES_PER_PAGE )
{
bufpos = BYTES_PER_PAGE;
filepos -= (BYTES_PER_PAGE - search_string_len);
}
else
{
bufpos = filepos;
filepos = 0L;
}
io_gotoxy(60,2);
io_printf("filepos: %10ld", filepos );
io_refresh();
get_buffer();
/* --- Go through each position in the buffer --- */
for ( i = buflen-1; i >= 0; i-- )
{
/* --- Compare string with current string in buffer --- */
match = 1;
for ( j = 0; j < search_string_len; j++ )
{
if ( buffer[i+j] != search_string[j] )
{
match = 0;
break;
}
}
if ( match )
{
filepos += i;
bufpos = 0;
get_buffer();
refresh_screen( STARTROW, MAXROW );
/* message( "Match found. Hit a key..." ); */
refresh_screen( STARTROW, MAXROW );
return;
}
}
} /* --- End of while loop -- */
message( "No match found. Hit a key..." );
filepos = old_file_pos;
bufpos = old_buf_pos;
get_buffer();
refresh_screen( STARTROW, MAXROW );
break;
default:
;
}
}
void calc(short col, short row)
{
/* --- Calculator variables -- */
static char editstr[30] = "";
char *sptr;
short keyhit = 0, i = 0;
char operator = ' ';
char cur_oper = 1;
long double max_num;
short max_places = 18;
short degrees = 1;
short radians = 2;
short grads = 3;
short start = 0;
short deg_rad_grad = 1;
long double pi = 3.141592653589793238462643383279;
int exitlist[] = {
io_LEFT, io_RIGHT, '-', '+', '*',
'/', '^', ' ', '=', io_ENTER, io_CTRL_M, io_CTRL_L, io_CTRL_R,
'Q', 'q', 'A', 'a', 'Z', 'z', 'W', 'w', 'S', 's',
'X', 'x', 'E', 'e', 'D', 'd', 'C', 'c', 'R', 'r',
'F', 'f', 'V', 'v', 'T', 't', 'G', 'g', 'B', 'b',
'Y', 'y', 'H', 'h', 'N', 'n',
0
};
char status;
long double operand[3];
char *calc_screen[] = {
" ___________________________________________ ",
" | | ",
" | | ",
" | ------------------ | ",
" | | ",
" | Q:Clr W:sin E:asin R:1/x T:n! Y:DRG | ",
" | A:ClrE S:cos D:acos F:log10 G:10^x H:pi | ",
" | Z:+/- X:tan C:atan V:ln B:e^x | ",
" | | ",
" | Digits 0-9, Operators +-*/^= | ",
" | ESC:Exit ENTER:Equals | ",
" |___________________________________________| ",
" ",
"\0"
};
max_num = (long double)pow(10, max_places);
for ( i = 0; i < 3; i++) operand[i] = 0;
status = ' ';
(void)calc_error("CLEAR");
/* --- Begin calc code --- */
io_flush_keyboard();
/* -- Begin displaying the calculator -- */
i = 0;
while ( strcmp( calc_screen[i], "" ) != 0 )
{
io_gotoxy( col, row + i );
io_puts( calc_screen[i] );
i++;
}
while(1)
{
if ( calc_error("") == 1 ) status = 'E';
/* --- Update screen --- */
io_gotoxy(2+col, 2+row);
io_printf("%c", status );
io_gotoxy(2+max_places+4+col, 2+row);
io_printf("%c", operator );
io_gotoxy(2+max_places+4+3+col, 2+row);
if ( degrees == deg_rad_grad )
io_printf("DEG ");
else if ( radians == deg_rad_grad )
io_printf("RAD ");
else if ( grads == deg_rad_grad )
io_printf("GRAD");
else
;
/* Strip off trailing spaces */
sptr = strchr( editstr, ' ');
if ( sptr != (char *)0 ) sptr[0] = (char)0;
if ( (long)strlen(editstr) >= (long)max_places )
start = max_places;
else
start = strlen(editstr) + 1;
io_refresh();
/* --- Get keystroke --- */
keyhit = input_line(editstr,
4+col, /* Column */
2+row, /* Row */
max_places, /* Length */
start, /* startpos */
exitlist, /* exitlist */
".NUMERIC .ZAP" /* options */
);
operand[cur_oper] = (long double)atof(editstr);
if ( keyhit == io_ESCAPE )
{
break;
}
else if( keyhit == 'Q' || keyhit == 'q' ) /* Clear all */
{
for ( i = 0; i < 3; i++) operand[i] = (long double)0;
status = ' ';
cur_oper = 1;
operator = ' ';
strcpy(editstr,"");
(void)calc_error("CLEAR");
continue;
}
else if( keyhit == 'A' || keyhit == 'a' ) /* Clear entry */
{
operand[cur_oper] = (long double)0;
strcpy(editstr,"");
status = ' ';
(void)calc_error("CLEAR");
continue;
}
else if(status == 'E' ) /* Error entry */
{
; /* -- Will fall through to bottom -- */
}
else if( keyhit == 'Z' || keyhit == 'z' ) /* +/- */
{
operand[cur_oper] = operand[cur_oper] * (long double)-1;
}
else if( keyhit == 'W' || keyhit == 'w' ) /* sine */
{
if ( degrees == deg_rad_grad )
operand[cur_oper] = (long double)sin(operand[cur_oper] * pi / 180);
else if ( radians == deg_rad_grad )
operand[cur_oper] = (long double)sin(operand[cur_oper]);
else if ( grads == deg_rad_grad )
operand[cur_oper] = (long double)sin(operand[cur_oper] * pi / 200);
else
;
}
else if( keyhit == 'S' || keyhit == 's' ) /* cosine */
{
if ( degrees == deg_rad_grad )
operand[cur_oper] = (long double)cos(operand[cur_oper] * pi / 180);
else if ( radians == deg_rad_grad )
operand[cur_oper] = (long double)cos(operand[cur_oper]);
else if ( grads == deg_rad_grad )
operand[cur_oper] = (long double)cos(operand[cur_oper] * pi / 200);
else
;
}
else if( keyhit == 'X' || keyhit == 'x' ) /* tangent */
{
if ( degrees == deg_rad_grad )
operand[cur_oper] = (long double)tan(operand[cur_oper] * pi / 180);
else if ( radians == deg_rad_grad )
operand[cur_oper] = (long double)tan(operand[cur_oper]);
else if ( grads == deg_rad_grad )
operand[cur_oper] = (long double)tan(operand[cur_oper] * pi / 200);
else
;
}
else if( keyhit == 'E' || keyhit == 'e' ) /* arcsine */
{
if ( fabs(operand[cur_oper]) > 1 )
{
status = 'E';
}
else if ( deg_rad_grad == degrees )
{
operand[cur_oper] = (long double)asin(operand[cur_oper]) *
180 / pi;
}
else if ( deg_rad_grad == radians )
{
operand[cur_oper] = (long double)asin(operand[cur_oper]);
}
else if ( deg_rad_grad == grads )
{
operand[cur_oper] = (long double)asin(operand[cur_oper]) *
200 / pi;
}
else
{ ; }
}
else if( keyhit == 'D' || keyhit == 'd' ) /* arccosine */
{
if ( fabs(operand[cur_oper]) > 1 )
{
status = 'E';
}
else if ( deg_rad_grad == degrees )
{
operand[cur_oper] = (long double)acos(operand[cur_oper]) *
180 / pi;
}
else if ( deg_rad_grad == radians )
{
operand[cur_oper] = (long double)acos(operand[cur_oper]);
}
else if ( deg_rad_grad == grads )
{
operand[cur_oper] = (long double)acos(operand[cur_oper]) *
200 / pi;
}
else
{
;
}
}
else if ( keyhit == 'C' || keyhit == 'c' ) /* arctangent */
{
if ( deg_rad_grad == degrees )
{
operand[cur_oper] = (long double)atan(operand[cur_oper]) *
180 / pi;
}
else if ( deg_rad_grad == radians )
{
operand[cur_oper] = (long double)atan(operand[cur_oper]);
}
else if ( deg_rad_grad == grads )
{
operand[cur_oper] = (long double)atan(operand[cur_oper]) *
200 / pi;
}
else
{
;
}
}
else if ( keyhit == 'R' || keyhit == 'r' ) /* 1/x */
{
if ( operand[cur_oper] == (long double)0 )
status = 'E';
else
operand[cur_oper] = (long double)1 / operand[cur_oper];
}
else if( keyhit == 'F' || keyhit == 'f' ) /* log10 */
{
if ( operand[cur_oper] == (long double)0 )
status = 'E';
else
operand[cur_oper] = (long double)log10(operand[cur_oper]);
}
else if ( keyhit == 'V' || keyhit == 'v' ) /* natural log */
{
if ( operand[cur_oper] == (long double)0 )
status = 'E';
else
operand[cur_oper] = (long double)log(operand[cur_oper]);
}
else if ( keyhit == 'T' || keyhit == 't' ) /* factorial! */
{
long double i = 0; long double sum = 1; long start = 0;
start = operand[cur_oper];
if ( start < 0 ) start = start * (long double)-1;
start = floor(start);
for ( i = start; i > 1; i-- )
{
sum = sum * i;
if ( sum > max_num ) break;
}
operand[cur_oper] = sum;
}
else if ( keyhit == 'G' || keyhit == 'g' ) /* 10 ^ x */
{
operand[cur_oper] = (long double)pow(10, operand[cur_oper]);
}
else if( keyhit == 'B' || keyhit == 'b' ) /* e ^ x */
{
operand[cur_oper] = (long double)exp(operand[cur_oper]);
}
else if ( keyhit == 'Y' || keyhit == 'y' ) /* Degrees, Radians, Grads */
{
if ( deg_rad_grad < 3 )
deg_rad_grad++;
else
deg_rad_grad = 1;
}
else if ( keyhit == 'H' || keyhit == 'h' ) /* pi */
{
operand[cur_oper] = pi;
}
else if ( keyhit == 'N' || keyhit == 'n' ) /* */
{
;
}
/* ---- OPERATORS ---- */
else if ( keyhit == '+' || keyhit == '-' || keyhit == '*' ||
keyhit == '/' || keyhit == '^' || keyhit == '=' ||
keyhit == io_ENTER
)
{
if ( cur_oper == 2 ) /* --- Assign result to operand[1] --- */
{
switch (operator)
{
case '+':
operand[1] = operand[1] + operand[2];
break;
case '-':
operand[1] = operand[1] - operand[2];
break;
case '*':
operand[1] = operand[1] * operand[2];
break;
case '/':
if ( operand[2] == 0 )
{
operand[1] = 0;
status = 'E';
}
else
{
operand[1] = operand[1] / operand[2];
}
break;
case '^':
operand[1] = (long double)pow(operand[1], operand[2]);
break;
default:
;
}
}
if ( keyhit == '+' || keyhit == '-' || keyhit == '*' ||
keyhit == '/' || keyhit == '^'
)
{
operand[2] = operand[1];
operator = (char)keyhit;
cur_oper = 2;
}
else
{
operator = ' ';
cur_oper = 1;
}
}
else
{
continue;
}
/* --- Update the edit string --- */
if ( fabs(operand[cur_oper]) >= max_num )
{
status = 'E';
sprintf(editstr,"");
}
else
{
char *ptr = (char *)0;
char *ptr2 = (char *)0;
char *ptr3 = (char *)0;
/* -- Compensate for rounding errors -- */
if (operand[cur_oper] < 0)
{
;
}
else
{
operand[cur_oper] = operand[cur_oper] +
( ((long double)1) / (long double)pow(10, max_places) );
}
/* -- Format number into string -- */
sprintf(editstr,"%*.*Lf", max_places, max_places, operand[cur_oper]);
editstr[max_places] = (char)0;
/* -- strip off trailing zeros past the decimal place. -- */
ptr = strchr(editstr,'.');
ptr2 = strchr(editstr, '\0');
if ( ptr != (char *)0 && ptr2 != (char *)0)
{
for ( ptr3 = ptr2-1; ptr3 != ptr; ptr3-- )
{
if ( ptr3[0] != '0' ) break;
}
if ( ptr3 == ptr )
{
ptr[0] = (char)0; /* --- Get rid of decimal point if nothing
is to its right --- */
}
else
{
ptr3[1] = (char)0;
}
}
}
}
}
int matherr(struct exception *x)
{
(void)calc_error( "SET" );
return 1; /* To prevent display of built-in error message */
}
int calc_error( char * action )
{
static int math_error = 0;
if ( strcmp(action, "SET") == 0 ) math_error = 1;
if ( strcmp(action, "CLEAR") == 0 ) math_error = 0;
return math_error;
}
/* ----------------------------------- **
** U T I L I T Y F U N C T I O N S **
** ----------------------------------- */
int copy_files( FILE *source, FILE *dest, long offset1, long offset2,
char append )
{
/*
** Returns: FALSE if copy failed
** TRUE if copy succeeded
**
** append: 'Y' means append to end of destination, otherwise overwrite
*/
char *copy_buffer = (char *)0;
unsigned long buffer_size = 0UL;
unsigned long max_buffer_size = 100000UL;
unsigned long copy_filepos = 0UL;
int status = TRUE;
unsigned long adder = 0UL;
if ( offset2 - offset1 + 1L < 100000L )
{
max_buffer_size = offset2 - offset1 + 1UL;
}
while(1)
{
copy_buffer = (char *)malloc((size_t)max_buffer_size);
if ( copy_buffer == ( char * )0 )
{
max_buffer_size /= 2L;
if ( max_buffer_size < 10L ) return FALSE;
}
else
{
break;
}
}
buffer_size = max_buffer_size;
if ( append == 'Y' )
{
fseek( dest, 0L, SEEK_END );
adder = ftell( dest ); /* Get file length */
}
for ( copy_filepos = offset1;
copy_filepos <= offset2;
copy_filepos += max_buffer_size
)
{
if ( copy_filepos + max_buffer_size > offset2 )
{
buffer_size = offset2 - copy_filepos + 1UL;
}
errno = 0;
status = (int)fseek( source, copy_filepos, SEEK_SET );
if ( status == -1 && errno )
{
status = FALSE;
break;
}
errno = 0;
status = (int)fseek( dest, copy_filepos - offset1 + adder, SEEK_SET );
if ( status == -1 && errno)
{
status = FALSE;
break;
}
status = fread( copy_buffer, (size_t)1, (size_t)buffer_size, source );
if ( !status ) break;
status = fwrite( copy_buffer, (size_t)1, (size_t)buffer_size, dest );
if ( !status ) break;
}
fseek( file, filepos, SEEK_SET );
free(copy_buffer);
return status;
}
char *get_hex( char ch )
{
/*
** Return the hex value in the form of a string
*/
static char tmp[3] = {0,0,0};
char lo, hi;
lo = ch & 0x0F;
hi = (ch >> 4) & 0x0F;
if ( lo < 10 )
tmp[1] = lo + (char)'0';
else
tmp[1] = lo + (char)'A' - 10;
if ( hi < 10 )
tmp[0] = hi + (char)'0';
else
tmp[0] = hi + (char)'A' - 10;
return tmp;
}
void strip( char *s )
{
long source=0, target=0, len=0;
len = strlen( s );
if ( len == 0 ) return;
while( source < len )
{
if ( s[source] >= 'a' && s[source] <= 'z' )
{
s[source] = (char)toupper( s[source] );
}
if ( ( s[source] >= '0' && s[source] <= '9' ) ||
( s[source] >= 'A' && s[source] <= 'Z' )
)
{
if ( source != target )
{
s[target] = s[source];
}
target++;
}
source++;
}
s[target] = (char)0;
}
int hex_to_long( char *s, unsigned long *ret_val )
{
/*
** Convert a hexadecimal number from string to long int
** Return value: FALSE = function failed
** TRUE = function worked
*/
long len, i;
char ch;
*ret_val = (unsigned long)0;
len = strlen( s );
if ( len > 8 ) return FALSE;
for (i = 0; i < len; i++ )
{
ch = s[i];
ch = (char)toupper( ch );
if ( ch >= '0' && ch <= '9' )
{
*ret_val = ( *ret_val << 4 ) | (unsigned long)( ch - '0' );
}
else if ( ch >= 'A' && ch <= 'F' )
{
*ret_val = ( *ret_val << 4 ) | (unsigned long)( ch - 'A' + 10 );
}
else
{
return FALSE;
}
}
return TRUE;
}
/* -- Converts written hex digit to nibble -- */
char hex_to_nibble( char c )
{
char ch;
ch = (char)toupper( c );
if ( ch >= '0' && ch <= '9' )
{
return (char)( ch - '0' );
}
else if ( ch >= 'A' && ch <= 'F' )
{
return (char)( ch - 'A' + 10 );
}
else /* --- Failure --- */
{
return 0xFF;
}
}
char *hex_to_bytes( char *hex, long *b_len)
{
static char *s = (char *)0;
char * hex_ptr;
long hex_len, byte_len, i, j;
if ( s != (char *)0 ) free (s);
hex_len = strlen(hex);
if ( hex_len > 1 )
{
if ( hex[0] == '0' && hex[1] == 'x' )
{
hex_ptr = &hex[2];
hex_len = strlen(hex_ptr);
}
else
{
hex_ptr = hex;
}
}
else
{
hex_ptr = hex;
}
byte_len = (hex_len / 2) + (hex_len % 2);
s = (char *)malloc((size_t)(byte_len+1L));
if ( s == (char *)0 ) return s;
memset(s, '\0', (size_t)(byte_len + 1L));
for ( i = byte_len-1, j = hex_len-1; i >= 0; i--, j-=2 )
{
s[i] = hex_to_nibble(hex_ptr[j]);
if ( j > 0 ) s[i] = s[i] + (hex_to_nibble(hex_ptr[j-1]) << 4);
}
*b_len = byte_len;
return s;
}
char *long_to_hex( long l )
{
static char s[10];
long source=0, target=0, len=0;
short flag=0;
strcpy( s,"" );
strcat( s, get_hex( (char)(l >> 24) ) );
strcat( s, get_hex( (char)((l >> 16) & 0x000000FF) ) );
strcat( s, get_hex( (char)((l >> 8) & 0x000000FF) ) );
strcat( s, get_hex( (char)(l & 0x000000FF) ) );
/* --- clean off leading zeros --- */
len = strlen( s );
if ( len == 0 ) return (char *)0;
while( source < len )
{
if ( flag )
{
if ( source != target )
{
s[target] = s[source];
}
target++;
}
else
{
if ( s[source] != '0' )
{
flag = 1;
source--;
}
}
source++;
}
s[target] = (char)0;
return s;
}
char *long_to_bin( long l )
{
static char s[33];
short i;
s[32]=(char)0;
for ( i = 1; i <= 32; i++)
{
if ( l & 0x0001 )
s[32-i] = '1';
else
s[32-i] = '0';
l = l >> 1;
}
/* --- Replace leading 0's with spaces --- */
for ( i = 0; i < 32; i++)
{
if ( s[i] == '1' ) break;
s[i] = ' ';
}
lstrip(s);
return s;
}
void message( char *msg )
{
io_gotoxy( 1, 2 );
io_printf( "%-79.79s", msg );
io_gotoxy( strlen( msg ), 2 );
io_refresh();
(void)io_inchar( );
}
void get_file_length( void )
{
static old_file_length = -1;
/* -- Always get end-of-file in case file length changes while editing -*/
fseek( file, 0L, SEEK_END );
filelen = ftell( file ); /* Get file length */
/* --- Update display to screen of file length --- */
if ( filelen != old_file_length )
{
io_gotoxy( 31, 1 );
io_printf( "%-10ld", filelen );
old_file_length = filelen;
}
}
void rstrip( char *s )
{
long i;
for( i = strlen(s)-1; i >= 0; i--)
{
if ( s[i] == ' ' || s[i] == '\t' || s[i] == '\n')
s[i] = 0;
else
break;
}
}
void lstrip( char *s )
{
long i;
long len;
long ptr=0;
len = strlen(s);
/* -- find first non-blank -- */
for (i = 0; i < len; i++)
{
if ( s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
{
ptr = i;
break;
}
}
if ( ptr == 0 ) return; /* -- Nothing to strip -- */
/* -- Copy elements over -- */
for (i = 0; ptr < len; i++, ptr++)
{
s[i] = s[ptr];
}
s[i] = 0;
}
char valid_char( char a )
{
short s;
s = (short)a & 0x00FF;
if ( s < (short)io_MIN_VALID_CHARACTER ||
s > (short)io_MAX_VALID_CHARACTER )
{
return (char)'.';
}
else
{
return a;
}
}
int files_are_same( char *file1, char *file2)
{
/*
** Return value: 1 = files are same
** 0 = files are not same
*/
char *ptr1;
char *ptr2;
long i = 0;
ptr1 = strrchr( file1, '/' );
if ( ptr1 == (char *)0 )
{
ptr1 = strrchr( file1, '\\' );
}
else
{
ptr1++;
}
if ( ptr1 == (char *)0 )
{
ptr1 = file1;
}
else
{
ptr1++;
}
ptr2 = strrchr( file2, '/' );
if ( ptr2 == (char *)0 )
{
ptr2 = strrchr( file2, '\\' );
}
else
{
ptr2++;
}
if ( ptr2 == (char *)0 )
{
ptr2 = file2;
}
else
{
ptr2++;
}
if ( io_MIXED_CASE_FILENAMES )
{
do
{
if ( ptr1[i] != ptr2[i] ) return 0;
i++;
}
while( ptr1[i-1] != (char)0 && ptr2[i-1] != (char)0 );
}
else
{
do
{
if ( toupper(ptr1[i]) != toupper(ptr2[i]) ) return 0;
i++;
}
while ( ptr1[i-1] != (char)0 && ptr2[i-1] != (char)0 );
}
return 1;
}
short input_line( char *str, short col, short row, short len,
short startpos, int *exitlist, char *options )
{
short i;
short break_flag;
short curpos;
short keyhit = 0;
int null_flag;
char *numeric = (char *)0;
char *hex = (char *)0;
char *binary = (char *)0;
char *instant_exit = (char *)0;
char *zap = (char *)0;
char *exit_left = (char *)0;
char *exit_right = (char *)0;
char *pre_validate = (char *)0;
numeric = strstr(options, ".NUMERIC");
hex = strstr(options, ".HEX");
binary = strstr(options, ".BINARY");
instant_exit = strstr(options, ".INSTANT_EXIT");
zap = strstr(options, ".ZAP");
exit_left = strstr(options, ".EXIT_LEFT");
exit_right = strstr(options, ".EXIT_RIGHT");
pre_validate = strstr(options, ".PRE_VALIDATE");
curpos = startpos;
if ( pre_validate != (char *)0 )
{
for ( i = 0; i < len; i++ )
{
if ( str[i] == (char)0 ) break;
str[i] = valid_char(str[i]);
}
}
/*----------------------------------------------
Process keystrokes
*----------------------------------------------*/
io_gotoxy(col, row);
io_printf("%-*.*s", len, len, str);
do /* Beginning of key-processing block */
{
io_gotoxy(col+curpos-1,row);
io_refresh();
keyhit = io_inchar();
if ( exitlist != (int *)0 )
{
break_flag = 0;
for ( i = 0; exitlist[i] != (int)0 && break_flag == 0; i++)
{
if (keyhit == exitlist[i]) break_flag = 1;
}
if ( break_flag ) break;
}
if ( keyhit == io_BACKSPACE || keyhit == io_CTRL_H )
{
zap = (char *)0;
if (curpos > 1) curpos--;
if (curpos <= len) str[curpos-1] = ' ';
io_gotoxy(col+curpos-1,row);
io_printf(" ");
}
else if ( keyhit == io_LEFT || keyhit == io_CTRL_L )
{
zap = (char *)0;
if (curpos > 1)
curpos--;
else
{
if ( exit_left ) break;
}
}
else if ( keyhit == io_RIGHT || keyhit == io_CTRL_R )
{
zap = (char *)0;
if (curpos < len)
curpos++;
else
{
if ( exit_right ) break;
}
}
else
{
if (keyhit >= 32 && keyhit <= io_MAX_VALID_CHARACTER )
{
if ( numeric != (char *)0 &&
strchr("0123456789", (char)keyhit) == (char *)0 ) continue;
if ( hex != (char *)0 && strchr("0123456789ABCDEFabcdef",
(char)keyhit) == (char *)0 ) continue;
if ( binary != (char *)0 &&
strchr("01", (char)keyhit) == (char *)0 ) continue;
if ( hex && strchr("abcdef", keyhit) ) keyhit = toupper(keyhit);
if ( zap )
{
curpos = 1;
sprintf( str, "%*s", len, " " );
io_gotoxy(col,row);
io_puts(str);
io_gotoxy(col+curpos-1,row);
zap = (char *)0;
}
/* --- Regular character entered -- */
if ( curpos > len ) curpos = len;
io_putc( keyhit );
/* --- Pad with spaces if needed -- */
for (i = 0, null_flag = FALSE; i < curpos; i++)
{
if (null_flag == TRUE)
{
str[i] = ' ';
continue;
}
if ( str[i] == (char)0 ) null_flag = TRUE;
}
if ( null_flag == TRUE ) str[curpos] = (char)0;
str[curpos-1]=(char)keyhit;
if (curpos < len ) curpos++;
}
else
{
break;
}
}
}while( !instant_exit ); /* End of do-while loop */
return keyhit;
}