home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
09
/
brief
/
binedit.cb
< prev
next >
Wrap
Text File
|
1991-06-03
|
46KB
|
1,467 lines
/*
** This set of macros and the accompanying executable were written by:
** Jim Rodriguez and Tim Hanna for editing hex and unix files.
** See the binread.me file for loading instructions and macro descriptions.
**
** If you do not want hex support for binary files, comment out the #define HEX
** If you do not want unix file support, comment out the #define UNIX
** If you do not want either, delete this file.
** Revision history:
** 4/17/91 fixed bug in positioning after hex/ascii editing.
** added key assignment for alt-g to go to hex offset
** converted if to while when entering ascii/hex characters
** fixed a bug with keyboard manipulation
**
** 4/18/91 added ability to change position when clicking mouse in ascii window
** fixed a bug in the mouse handling for set_win event with multiple windows
*/
// $lgb$
// April 19 91 1.0 binedit.cb JMR
// April 19 91 1.1 binedit.cb JMR
// April 19 91 1.2 binedit.cb JMR
// April 19 91 1.3 binedit.cb JMR
// April 19 91 1.4 binedit.cb JMR optimized movement macros into one function
// April 19 91 1.5 binedit.cb JMR repositioned mouse action macro to correspond with ifdef
// April 19 91 1.6 binedit.cb JMR
// April 19 91 1.7 binedit.cb JMR modified ascii search prompt
// April 25 91 1.8 binedit.cb JMR modified for 3.0 compatability
// April 25 91 1.9 binedit.cb JMR added alt-d for delete line
// April 25 91 1.10 binedit.cb JMR
// May 6 91 1.11 binedit.cb JMR modified search prompt
// May 7 91 1.12 binedit.cb JMR modified bin_search bug fixed bug in bin_on for non-controlled buffers
// May 7 91 1.13 binedit.cb JMR fixed bug in bin_on not setting buffer and fixed bin_search
// May 7 91 1.14 binedit.cb JMR fixed bugs
// May 10 91 1.15 binedit.cb JMR changed _on to a replacement macro
// May 10 91 1.16 binedit.cb JMR modified _on to use the default _on macro and then superclass it
// May 10 91 1.17 binedit.cb JMR Removed _on macro
// May 15 91 1.18 binedit.cb JMR
// May 20 91 1.19 binedit.cb JMR added add_hex_keys modified write_buffer to use delete_curr_buffer
// May 31 91 1.20 binedit.cb JMR modified _bin_atoh by removing the switch
// May 31 91 1.21 binedit.cb JMR
// June 3 91 1.22 binedit.cb JMR cleaned up
// June 3 91 1.23 binedit.cb JMR
// $lge$
#define HEX
#define UNIX
// This defines the number of iterations of the for loop for highlighting
// The current character in the ascii window.
#define SHOW_DELAY 50
// These are for positioning in the buffer.
#define UP -10
#define DOWN 10
#define LEFT -1
#define RIGHT 1
#define PGUP -21
#define PGDN 21
#define TOP 30
#define BOTTOM -31
#define HOME -40
#define END -41
// Declare the _package_buf extern to access the package information and
// the macros for calling template keyboards as well as the global strings
// used for file extension specific next_word etc.
extern _package_buf,
delete_curr_buffer,
.c_template_first,
.for_template_first,
.ada_template_first,
.mod_template_first,
.prg_smart_first,
_regular_first,
.pas_template_first,
.bas_template_first,
.cob_template_first;
int __unix_files, __hex_files;
#ifdef HEX
int __bin_keyboard, __hex_window, __asc_window;
#endif
Create system buffers for holding filenames.
_init ()
{
system buffer for holding UNIX files
__unix_files = create_buffer ("UNIXFILE", NULL, 1);
system buffer for holding HEX files
__hex_files = create_buffer ("HEXFILES", NULL, 1);
#ifdef UNIX
// Register a macro for trapping files with no CR/LF.
register_macro (6, "_unix_edit");
#endif
#ifdef HEX
// Register a macro for trapping Null chars message.
register_macro (6, "_bin_edit");
// Create the editing keyboard
keyboard_push ();
set_mouse_action("_bin_mouse");
add_hex_keys();
__bin_keyboard = inq_keyboard ();
keyboard_pop (1);
#endif
}
#ifdef HEX
// This macro adds the hex editing keys 0-F and function keys hex buffer
add_hex_keys()
{
string macro_name, key_name;
int loop;
for (loop=48;loop<58;loop++) // Use ascii codes for 0-9
{
sprintf (key_name, "<%c>",loop);
sprintf (macro_name, "_bin_add \"%c\"",loop);
assign_to_key (key_name, macro_name);
}
for (loop=65;loop<71;loop++) // Use ascii codes for a-f A-F
{
sprintf (key_name, "<%c>",loop);
sprintf (macro_name, "_bin_add \"%c\"",loop);
assign_to_key (key_name, macro_name);
assign_to_key (lower(key_name), macro_name);
}
assign_to_key ("<Enter>", "_bin_ascii"); // Type ascii character
assign_to_key ("<Ctrl-Enter>", "_bin_open"); // Add a new line
assign_to_key ("<F10>", "execute_macro"); // Just in case
assign_to_key ("<Alt-n>", "edit_next_buffer");// Next buffer
assign_to_key ("<Alt-d>", "_bin_delete 1"); // Delete a line
assign_to_key ("<Alt-e>", "edit_file"); // Edit file
assign_to_key ("<Alt-g>", "_bin_offset"); // Goto offset
assign_to_key ("<Alt-u>", "undo 1"); // Undo
assign_to_key ("<Ctrl-u>", "redo"); // Redo
assign_to_key ("<Alt-w>", "write_buffer"); // Write buffer and reconvert
assign_to_key ("<Del>", "_bin_delete"); // Delete byte
assign_to_key ("<F5>", "_bin_search"); // Search for bytes
assign_to_key ("<Alt-F5>", "_bin_ascii_search"); // Search the ascii buffer
assign_to_key ("<Alt-x>", "exit"); // Exit Brief
assign_to_key ("<Esc>", "_bin_show_match"); // Show corresponding position
// Sprintf used with #defines for movement keys
sprintf (macro_name, "_bin_move %d", UP);
assign_to_key ("<Up>", macro_name);
sprintf (macro_name, "_bin_move %d", DOWN);
assign_to_key ("<Keypad-Enter>", macro_name);
assign_to_key ("<Down>", macro_name);
sprintf (macro_name, "_bin_move %d", LEFT);
assign_to_key ("<Left>", macro_name);
sprintf (macro_name, "_bin_move %d", RIGHT);
assign_to_key ("<Right>", macro_name);
sprintf (macro_name, "_bin_move %d", PGUP);
assign_to_key ("<PgUp>", macro_name);
sprintf (macro_name, "_bin_move %d", PGDN);
assign_to_key ("<PgDn>", macro_name);
sprintf (macro_name, "_bin_move %d", TOP);
assign_to_key ("<Ctrl-Pgup>", macro_name);
sprintf (macro_name, "_bin_move %d", BOTTOM);
assign_to_key ("<Ctrl-PgDn>", macro_name);
sprintf (macro_name, "_bin_move %d", HOME);
assign_to_key ("<Home>", macro_name);
sprintf (macro_name, "_bin_move %d", END);
assign_to_key ("<End>", macro_name);
}
#endif
/*
** A replacement for write_buffer to check file extension and clean up the
** system buffers. Be aware that the conversion back to binary/UNIX will not
** occur if the buffer has not been modified.
*/
replacement int write_buffer ()
{
int buf_to_edit,
buf_to_delete,
file_is_controlled,
file_was_modified;
string file_name,
ext,
response,
response2,
old_buffer,
write_command;
inq_names (file_name, ext);
// If write_buffer was not called from the keyboard and the extension
// isn't .hex or .unx call write_buffer. Otherwise, get some input and go to work.
if ("" == inq_called () && (ext == "hex" || ext == "unx"))
if (get_parm (0, response, "Convert file? ", 1, "Y"))
if (get_parm (1, response2, "Delete buffer? ", 1, "Y"))
{
int file_is_hex,
msg_lvl;
file_is_hex = 0;
// Get the current buffer id to delete.
buf_to_edit = inq_buffer ();
raise_anchor ();
// If the file is modified set a flag and write the buffer.
if (inq_modified ())
{
msg_lvl = inq_msg_level ();
set_msg_level (0);
returns write_buffer ();
set_msg_level (msg_lvl);
file_was_modified = 1;
}
// Otherwise, we don't need to do the conversion.
else
file_was_modified = 0;
// Parse the file name to remove the extension.
if (index (file_name, "."))
file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
// Remove the line in the system buffer which controls the file.
if (ext == "hex")
{
set_buffer (__hex_files);
file_is_hex = 1;
}
else
set_buffer (__unix_files);
top_of_buffer ();
// Be aware that regular expressions CANNOT be used in the
// search.
if (search_fwd (file_name + ",ext=", 0, 0))
// Parse the line to get the original extension and locate
// the associated system buffer.
{
beginning_of_line ();
ext = trim (read ());
file_is_controlled=1;
// Find the system buffer.
if (file_is_hex)
{
int temp_buffer=inq_buffer();
ext = ltrim (substr (ext, index (ext, "newb=") + 5));
old_buffer = substr (ext, 1, 10);
// Convert to a valid buffer id.
buf_to_delete = atoi (old_buffer, 1);
set_buffer(buf_to_delete);
raise_anchor();
write_buffer();
drop_anchor(2);
set_buffer(temp_buffer);
if (upper (response2) == "Y")
delete_buffer (buf_to_delete);
}
// Find the original extension
ext = trim (substr (ext, rindex (ext, "=") + 1));
beginning_of_line ();
if (upper (response2) == "Y")
// Delete the reference to the file.
delete_line ();
}
// Reset the buffer to the original buffer.
set_buffer (buf_to_edit);
// Create the dos line.
if (file_is_hex)
sprintf (write_command, "bbe HB %s.hex %s.%s>&nul", file_name, file_name, ext);
else
sprintf (write_command, "bbe DU %s.unx %s.%s>&nul", file_name, file_name, ext);
if (file_was_modified && upper (response) == "Y" && file_is_controlled)
// If the modified flag is not set we won't bother doing the
// conversion.
{
message ("%s", write_command);
dos (write_command);
message ("Conversion complete");
}
// Now, delete the current buffer and the converted file.
if (upper (response2) == "Y")
{
if (1 != delete_curr_buffer())
{
file_is_controlled=-1;
delete_buffer(buf_to_edit);
}
if (file_is_hex)
{
sprintf (response, "%s.hex", file_name);
del (response);
sprintf (response, "%s.asc", file_name);
}
else
sprintf (response, "%s.unx", file_name);
del (response);
if (file_is_controlled == -1)
exit("y");
}
else
if (file_is_hex && file_is_controlled)
{
move_rel (0, -1);
drop_anchor ();
move_rel (0, 1);
}
}
else ;
else ;
else
return write_buffer ();
}
#ifdef HEX
// This function accepts a "hex" string and returns an integer.
int _bin_atoh (string to_convert)
{
string str_rev;
int converted,
loop_count,
t_int;
get_parm (0, to_convert);
// Method is to read a character from the end of the string and multiply
// it by the loop count which is multiplied by 16 on each iteration.
while (strlen (trim (to_convert)))
// Start from the end of the string.
{
str_rev = substr (to_convert, strlen (to_convert), 1);
// Convert to an integer and store in a temporary variable.
t_int = index("123456789ABCDEF",upper(str_rev));
// Multiply the loop counter by 16 for the base conversion.
loop_count *= 16;
// If the first time through, start the counter.
if (0 == loop_count)
loop_count = 1;
// Add the temp variable to the sum.
converted += t_int * loop_count;
// Remove the last character from the string.
to_convert = substr (to_convert, 1, strlen (to_convert) - 1);
}
// Return the integer.
return converted;
}
// This macro displays the current file offset in decimal and hex.
void _bin_disp_offset ()
{
int hl,
hc,
offset;
string char;
inq_position (hl, hc);
offset = (hl - 1) * 25;
offset += hc / 2;
move_rel (0, -1);
char = read (2);
move_rel (0, 1);
hl = _bin_atoh (char);
switch (hl)
{
case 0:
{
char = "<NULL>";
message ("Offset: %u decimal, %08x hex, %s ascii", offset, offset, char);
}
case 255:
case 20:
{
char = "<SPACE>";
message ("Offset: %u decimal, %08x hex, %s ascii", offset, offset, char);
}
default:
message ("Offset: %u decimal, %08x hex, %c ascii", offset, offset, hl);
}
}
// This macro associates a system buffer with a hex buffer and modifies the
// package information for .hex files
void _hex_edit (string file_name, int in_memory)
{
int __hex_buffer,
__asc_buffer,
tmp_buf,
current_buffer;
string buffer_name,
file_ext,
buffer_id,
file_path;
global __hex_buffer,
__asc_buffer;
// get the file name
if (get_parm (0, file_name))
{
get_parm (1, in_memory);
// parse the file name into path and extension
if (index (file_name, "."))
{
file_ext = substr (file_name, 1 + rindex (file_name, "."));
file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
}
else
file_ext = "";
// parse off the path for the buffer name
buffer_name = substr (file_name, rindex (file_name, "\\") + 1);
// store the current id to possible deletion
current_buffer = inq_buffer ();
// If the macro was called from the registed macro delete the current
// buffer
if (inq_called () == "_bin_edit")
delete_buffer (current_buffer);
// Try to create the buffer to check for existing buffer id
tmp_buf = create_buffer (buffer_name + ".hex", file_name + ".hex", 0);
// If a valid buffer exists, continue
if (tmp_buf)
// See if the hex file is already being edited
{
set_buffer (__hex_files);
top_of_buffer ();
if (search_fwd (file_name + ",", 0, 0))
// The hex file is being edited called edit_file and return
edit_file (file_name + ".hex");
else
// It's a new conversion delete the validity check buffer
{
delete_buffer (tmp_buf);
// Create the dos string from the file name
sprintf (file_path, "bbe BH %s.%s %s.hex %s.asc>&nul", file_name, file_ext, file_name, file_name);
// Do the hex files already exist?
if (!exist (file_name + ".hex") && !exist (file_name + ".asc"))
// Call dos for the conversion
{
message ("Generating hex file");
dos (file_path);
}
else
message ("Editing existing files.");
// Edit the hex and ascii representation of the file
__hex_buffer = create_buffer (buffer_name + ".hex", file_name + ".hex", 0);
__asc_buffer = create_buffer (buffer_name + ("." + file_ext), file_name + ".asc", 1);
// We now have the buffer ids for both files as well as the filename and
// extension. Save them in the hex_files system buffer for later.
sprintf (buffer_id, "oldb=%10d,newb=%10d,file=%s,ext=%s", __hex_buffer, __asc_buffer, file_name, file_ext);
set_buffer (__hex_files);
beginning_of_line ();
insert (buffer_id + "\n");
// Make the hex file current and highlight the
// first byte.
set_buffer (__hex_buffer);
top_of_buffer ();
drop_anchor ();
move_rel (0, 1);
// Access the package buffer and configure for the hex extension
if (first_time ())
// Make sure the user has the language macro loaded.
{
if (!_package_buf)
load_macro ("language");
// Edit the package buffer
set_buffer (_package_buf);
top_of_buffer ();
// Delete any dribble which may have been erroneously set.
while (search_fwd ("<.hex", 1, 0))
delete_line ();
// Add the correct lines in packages to make this work.
insert (".hex_equivalents\n");
insert (".hex_existing;\n");
insert (".hex_first;.hex_template_first\n");
insert (".hex_on;_on,_bin_on\n");
insert (".hex;=hex,,=hex,,t\n");
top_of_buffer ();
}
// Prepare to edit the hex buffer.
set_buffer (__hex_buffer);
// The registed macros may not have been called if
// called from the keyboard.
if (0 != in_memory)
call_registered_macro (1);
}
}
}
}
// Registered macro for trapping Null files message.
void _bin_edit ()
{
if (inq_message () == "Null characters in file fixed.")
{
string okay;
string file;
inq_names (file);
// See if the conversion is requested.
if (get_parm (0, okay, "Okay to create HEX file to edit? ", 1, "Y"))
if (upper (okay) == "Y")
// Call _hex_edit to do the dirty work.
_hex_edit (file, 0);
// Otherwise, let the user frustrate themselves.
else
message ("You asked for it.");
}
}
// This macro allows editing of a file as a hex file from the keyboard.
void edit_hex_file ()
{
string file_name,
last_message;
int ret_val;
// Get the file name to convert
if (get_parm (0, file_name, "File to convert: "))
{
int msgl;
msgl = inq_msg_level ();
// Set the message level to display all messages
set_msg_level (0);
// Call edit_file to do the filename validation.
ret_val = edit_file (file_name);
set_msg_level (msgl);
last_message = inq_message ();
// Get the full path name and write the buffer before conversion
inq_names (file_name);
if (inq_modified () && 1 == ret_val)
write_buffer ();
// If there were nulls in the file the registered macro should deal
// with it
if (ret_val > 0 && last_message != "Null characters in file fixed.")
// Call the _hex_edit macro with the valid name
{
if (exist (file_name))
_hex_edit (file_name, ret_val);
}
}
}
// This macro gets called for all .hex files. It is required to disassociate
// the local keyboard attached to the .hex buffer.
string .hex_template_first ()
{
use_local_keyboard (0);
returns "";
}
/*
** This macro edits the hex and ascii files in side by side windows by
** creating and moving an edge. It insures the correct local keyboard
** by setting it explicitly. We look in the hex_files buffer for the filename
** and extract the buffer ids. Associate the buffers with windows and return.
*/
string _bin_on ()
{
int i;
string buf_to_find,
exten;
// Get the filename and parse off the extension.
inq_names (buf_to_find, exten);
buf_to_find = substr (buf_to_find, 1, (rindex (buf_to_find, exten) - strlen (exten)) + 1);
i=inq_buffer();
// Edit the system buffer to find buffer id's.
set_buffer (__hex_files);
top_of_buffer ();
// Find the line with the filename.
if (search_fwd (buf_to_find + ",", 0, 0))
// Parse the line to retrieve the buffer id's.
{
keyboard_flush();
use_local_keyboard (0);
keyboard_push (__bin_keyboard);
set_mouse_action("_bin_mouse");
beginning_of_line ();
buf_to_find = trim (read ());
buf_to_find = ltrim (substr (buf_to_find, index (buf_to_find, "oldb=") + 5, 10));
__hex_buffer = atoi (buf_to_find, 1);
beginning_of_line ();
buf_to_find = read ();
buf_to_find = ltrim (substr (buf_to_find, index (buf_to_find, "newb=") + 5, 10));
__asc_buffer = atoi (buf_to_find, 1);
set_buffer (__hex_buffer);
// Unregister the registered macro so a recursive situation does not
// arise from the window manipulations.
unregister_macro (1, "_call_on_packages");
create_edge (3);
__hex_window = inq_window ();
move_edge (1, 12);
change_window (1);
// Attach the associated ascii system buffer to the window.
__asc_window = inq_window ();
attach_buffer (__asc_buffer);
// Highlight the character.
if (!inq_marked ())
drop_anchor (2);
else
refresh ();
refresh ();
change_window (3);
// Reregister the language macro.
register_macro (1, "_call_on_packages");
// Display the file offset.
_bin_disp_offset ();
// Return the off event for the language package.
returns "_bin_off";
}
// Otherwise, something got screwed up return nothing so as not to
// propagate the error.
else
{
set_buffer(i);
returns "";
}
}
// This macro deletes the edge created in the on event. The keyboard is popped
// and recreated.
void _bin_off ()
{
keyboard_flush();
keyboard_pop ();
keyboard_push ();
add_hex_keys();
__bin_keyboard = inq_keyboard ();
delete_edge (1);
keyboard_pop (1);
set_mouse_action("_mouse_action");
}
// This function emulates a goto_line macro using a byte offset.
void _bin_offset()
{
int line,
col,
col2,
line2;
string input;
if (get_parm (NULL, input, "Enter Hex offset: "))
{
line2 = _bin_atoh(input);
line = line2 / 25;
line++;
line2 = line2 % 25;
col = line2 * 2;
save_position();
raise_anchor ();
move_rel(0,-1);
unregister_macro (1, "_call_on_packages");
if (move_abs(line,col))
{
inq_position(line2,col2);
if (line2==line && col2 == col)
{
restore_position(0);
move_rel(0,-1);
set_window (__asc_window);
raise_anchor ();
move_abs(line,col / 2);
drop_anchor (2);
refresh ();
set_window (__hex_window);
}
else
restore_position();
}
else
restore_position();
drop_anchor ();
move_rel (0, 1);
register_macro (1, "_call_on_packages");
refresh ();
_bin_disp_offset ();
}
}
// This macro adds a line to the hex file for insertions.
void _bin_open ()
{
int loop_count;
raise_anchor ();
end_of_line ();
insert ("\n");
for (loop_count = 0; loop_count < 25; loop_count++)
insert ("XX");
beginning_of_line ();
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
end_of_line ();
raise_anchor ();
insert ("\n");
for (loop_count = 0; loop_count < 25; loop_count++)
insert (".");
beginning_of_line ();
drop_anchor (2);
refresh ();
set_window (__hex_window);
drop_anchor ();
move_rel (0, 1);
register_macro (1, "_call_on_packages");
refresh ();
_bin_disp_offset ();
}
// This macro handles simutaneous positioning
void _bin_move (int direction)
{
int col,
line;
get_parm(0,direction);
raise_anchor ();
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
raise_anchor ();
inq_position (line, col);
switch (direction)
{
case LEFT:
case RIGHT:
{
if ((col == 25 && direction == RIGHT)|| (col==1 && direction==LEFT))
{
move_rel (direction,0);
col = (direction == LEFT ? 25 : 1);
move_abs (0,col);
}
else
move_rel (0,direction);
}
case UP:
case DOWN:
{
move_rel (direction / 10,0);
}
case PGUP:
case PGDN:
{
inq_window_size(line);
move_rel ((direction % 20) * line,0);
}
case HOME:
move_abs(0,1);
case END:
move_abs(0,25);
case TOP:
move_abs(1,1);
case BOTTOM:
{
end_of_buffer();
move_abs(0,25);
}
}
while (inq_position (line,col))
move_rel (-1, 0);
drop_anchor (2);
refresh ();
set_window (__hex_window);
move_abs(line,col * 2);
move_rel (0, -1);
drop_anchor ();
move_rel (0, 1);
refresh ();
register_macro (1, "_call_on_packages");
_bin_disp_offset ();
}
// This macro is assigned to the enter key to prompt for an ascii character to
// insert rather than having to edit with hex values.
void _bin_ascii ()
{
string ascii_edit,
ascii_tmp;
int hex_val,
hex_tmp;
// Get the character to replace with.
while (get_parm (0, ascii_edit, "Enter ascii character: ", 1))
// Only replace with a valid character.
{
if (strlen (ascii_edit))
// Convert to HEX.
{
hex_val = atoi (ascii_edit, 0);
// Insure the user didn't enter anything stupid.
switch (hex_val)
{
case 13:
case 9:
ascii_edit = ".";
}
// Create a HEX string.
sprintf (ascii_tmp, "%02x", hex_val);
// Reposition the cursor change windows and insert the
// correct characters in the corresponding buffers and
// rehighlight the current byte.
raise_anchor ();
move_rel (0, -1);
// Unregister the language macro for the window manipulations.
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
insert ("%s", ascii_edit);
raise_anchor ();
// Delete the old character.
delete_char ();
move_rel (0, -1);
drop_anchor (2);
refresh ();
set_window (__hex_window);
insert ("%s", upper (ascii_tmp));
// Delete the old characters.
delete_char (2);
move_rel (0, -1);
move_rel (0, -1);
drop_anchor ();
move_rel (0, 1);
refresh ();
_bin_move(1);
// Reregister the language macro.
register_macro (1, "_call_on_packages");
}
}
_bin_disp_offset ();
}
// This function highlights the current character in the ascii buffer.
void _bin_show_match ()
{
int i;
if (__asc_window != inq_window () && __asc_window)
{
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
for (i = 0; i < SHOW_DELAY; i++)
refresh ();
set_window (__hex_window);
register_macro (1, "_call_on_packages");
_bin_disp_offset ();
}
// Otherwise, the ascii window is current i.e. it was called by the mouse
else
for (i = 0; i < SHOW_DELAY; i++)
refresh ();
}
// This macro overwrites the byte in the hex window. It is assigned to all of
// the valid hex editing keys and uses push_back to get the original key.
void _bin_add (string key_read)
{
string character,
sread;
int hex_val,
temp_hex;
// Get the parameter which is the key pressed and push it back so it
// displays in the prompt as if it were typed.
get_parm (0, key_read);
push_back (key_to_int (key_read));
raise_anchor ();
// Read the text from the buffer to display the old value at the prompt.
move_rel (0, -1);
sread = "Enter new value for ";
if (read (1) != "\n")
sread += read (2);
sread += ": ";
if (get_parm (1, character, sread, 2))
// Convert the "hex" string to an integer.
{
hex_val = _bin_atoh (character);
// Convert the integer to a hex value.
sprintf (character, "%02x", hex_val);
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
// Make sure the value is insertable.
switch (hex_val)
{
case 13:
case 9:
case 0:
sread = ".";
default:
sprintf (sread, "%c", hex_val);
}
// Insert the value in the hex and ascii buffers rehighlight and
// return.
raise_anchor ();
delete_char ();
insert ("%s", sread);
move_rel(0,-1);
drop_anchor (2);
refresh ();
set_window (__hex_window);
delete_char (2);
insert ("%s", upper (character));
}
drop_anchor ();
move_rel (0, 1);
refresh ();
register_macro (1, "_call_on_packages");
refresh ();
execute_macro(inq_assignment("<Right>"));
_bin_disp_offset ();
}
// This macro converts the current byte to XX which will not be process when
// converted.
void _bin_delete (int line)
{
get_parm(0,line);
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
raise_anchor ();
if (line)
{
save_position();
move_abs(0,1);
drop_anchor(3);
translate("?",".",1,1,1,1);
raise_anchor ();
restore_position();
}
else
{
delete_char ();
insert (".");
move_rel (0, -1);
}
drop_anchor (2);
refresh ();
set_window (__hex_window);
raise_anchor ();
if (line)
{
save_position();
move_abs(0,1);
drop_anchor(3);
translate("?","X",1,1,1,1);
raise_anchor ();
restore_position();
move_rel (0, -1);
}
else
{
move_rel (0, 1);
insert ("XX");
move_rel (0, -4);
delete_char (2);
}
drop_anchor ();
move_rel (0, 1);
register_macro (1, "_call_on_packages");
refresh ();
_bin_disp_offset ();
}
// This macro does a search on the ascii file.
void _bin_ascii_search ()
{
string str1,
str2;
if (get_parm (0, str1, "Enter ascii search pattern: "))
// Add the regular expression while parsing the string into characters.
{
while (strlen (str1))
{
str2 += substr (str1, 1, 1);
str2 += "[\n]@";
str1 = substr (str1, 2);
}
// If a string exist, search.
if (strlen (str2))
{
int mark_length;
unregister_macro (1, "_call_on_packages");
// We need to search to ascii file so make it current.
set_window (__asc_window);
if (mark_length = search_fwd (str2, 1, 0, 0))
{
int line, col;
raise_anchor ();
drop_anchor ();
inq_position (line, col);
next_char (mark_length);
refresh ();
// Here we want to wait for a key to show the matched
// text highlighted.
pause_on_error (1);
error ("ASCII search complete - press any key.");
pause_on_error (0);
move_abs (line, col);
drop_anchor (2);
refresh ();
set_window (__hex_window);
raise_anchor ();
move_abs (line, col * 2);
move_rel (0, -1);
drop_anchor ();
move_rel (0, 1);
refresh ();
}
else
message ("Pattern not found");
set_window (__hex_window);
register_macro (1, "_call_on_packages");
refresh ();
}
}
}
/*
** This macro is very similar the the ascii_search macro but it uses a different
** character delimiter regular expression and searches in the hex buffer. Matched
** text is highlighted with pause on error.
*/
void _bin_search ()
{
string str1,
str2;
if (get_parm (0, str1, "Enter hex values: ", inq_line_length () / 8))
{
while (strlen (compress(str1)))
{
str2 += substr (str1, 1, 2);
str2 += "[\n]@";
if (substr(str1,3,1)==" ")
str1 = substr (str1, 4);
else
str1 = substr (str1, 3);
}
if (strlen (str2))
{
int mark_length,
line,
col;
save_position();
while (mark_length = search_fwd (str2, 1, 0, 0))
{
inq_position (line, col);
if ((col % 2) == 0)
{
move_rel(0,1);
continue;
}
else
break;
}
if (! mark_length)
{
message ("Pattern not found");
restore_position();
}
else
{
restore_position(0);
unregister_macro (1, "_call_on_packages");
raise_anchor ();
move_abs (line, col);
drop_anchor ();
next_char (mark_length);
refresh ();
pause_on_error (1);
error ("HEX search complete - press any key.");
pause_on_error (0);
move_abs (line, col);
raise_anchor ();
drop_anchor ();
move_rel (0, 1);
col += 1;
col /= 2;
set_window (__asc_window);
raise_anchor ();
move_abs (line, col);
drop_anchor (2);
refresh ();
set_window (__hex_window);
register_macro (1, "_call_on_packages");
}
}
}
}
#define BTN1_CLICK 10
#define BTN2_CLICK 11
#define BTN1_DBLCLK 13
#define BTN2_DBLCLK 14
#define VSCROLL 17
#define CLOSE_WIN 19
#define SET_WIN 20
#define STATUS_AREA 21
#define SB_LINEUP 0
#define SB_LINEDOWN 1
#define SB_PAGEUP 2
#define SB_PAGEDOWN 3
#define SB_TOP 6
#define SB_BOTTOM 7
#define TITLE_BAR 1
/*
** This is the mouse event handler which acknowledges the following events.
**
** STATUS AREA CLICK - goto offset
** LEFT BUTTON CLICK - position the cursor
** RIGHT BUTTON CLICK - position the cursor
** LEFT BUTTON DOUBLE CLICK - enter ascii value
** RIGHT BUTTON DOUBLE CLICK - open a line
** VERTICAL SCROLL - positioning with clicks
*/
void _bin_mouse(int action, int modifier, int line, int col)
{
if (inq_window()==__asc_window)
col=col*2;
switch (action)
{
case STATUS_AREA:
execute_macro(inq_assignment("<Alt-g>"));
case SET_WIN:
{
if (col!=TITLE_BAR && line == __asc_window)
{
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
}
}
case BTN2_CLICK:
case BTN2_DBLCLK:
case BTN1_CLICK:
case BTN1_DBLCLK:
{
int lines,cols;
if (col % 2)
col++;
if (col>50)
col=50;
unregister_macro (1, "_call_on_packages");
set_window (__hex_window);
inq_position(lines, cols);
raise_anchor ();
move_rel(0,-1);
save_position();
if (move_abs(line,col))
{
if (! inq_position(lines,cols)&& lines==line && cols == col)
{
restore_position(0);
move_rel(0,-1);
set_window (__asc_window);
raise_anchor ();
move_abs(line,col / 2);
drop_anchor (2);
refresh ();
set_window (__hex_window);
}
else
restore_position();
}
else
restore_position();
drop_anchor ();
move_rel (0, 1);
register_macro (1, "_call_on_packages");
refresh ();
switch (action)
{
case BTN2_DBLCLK:
{
execute_macro(inq_assignment("<Ctrl-Enter>"));
}
case BTN1_DBLCLK:
{
string sread,
character;
int hex_val;
raise_anchor ();
// Read the text from the buffer to display the old value at the prompt.
move_rel (0, -1);
sread = "Enter new value for ";
if (read (1) != "\n")
sread += read (2);
sread += ": ";
if (get_parm (NULL, character, sread, 2))
// Convert the "hex" string to an integer.
{
hex_val = _bin_atoh (character);
// Convert the integer to a hex value.
sprintf (character, "%02x", hex_val);
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
// Make sure the value is insertable.
switch (hex_val)
{
case 13:
case 9:
case 0:
sread = ".";
default:
sprintf (sread, "%c", hex_val);
}
// Insert the value in the hex and ascii buffers rehighlight and
// return.
insert ("%s", sread);
raise_anchor ();
delete_char ();
move_rel (0, -1);
drop_anchor (2);
refresh ();
set_window (__hex_window);
insert ("%s", upper (character));
delete_char (2);
move_rel (0, -2);
}
drop_anchor ();
move_rel (0, 1);
refresh ();
register_macro (1, "_call_on_packages");
refresh ();
_bin_disp_offset ();
}
}
}
case VSCROLL:
{
switch (line)
{
case SB_LINEUP:
execute_macro(inq_assignment("<Left>"));
case SB_LINEDOWN:
execute_macro(inq_assignment("<Right>"));
case SB_PAGEUP:
execute_macro(inq_assignment("<PgUp>"));
case SB_PAGEDOWN:
execute_macro(inq_assignment("<PgDn>"));
case SB_TOP:
execute_macro(inq_assignment("<Ctrl-PgUp>"));
case SB_BOTTOM:
execute_macro(inq_assignment("<Ctrl-PgDn>"));
}
}
}
}
#endif
#ifdef UNIX
// This macro associates a system buffer with a unix buffer name.
void _unx_edit (string file_name)
{
int unix_buffer,
tmp_buf,
current_buffer;
string buffer_name,
file_ext,
buffer_id,
file_path;
// Get the file name
if (get_parm (0, file_name))
{
// Parse the file name into path and extension
if (index (file_name, "."))
{
file_ext = substr (file_name, 1 + rindex (file_name, "."));
file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
}
else
file_ext = "";
// Parse off the path for the buffer name
buffer_name = substr (file_name, rindex (file_name, "\\") + 1);
// Store the current id to possible deletion
current_buffer = inq_buffer ();
// Try to create the buffer to check for existing buffer id
tmp_buf = create_buffer (buffer_name + "." + file_ext, file_name + ".unx", 0);
// If a valid buffer exists, continue
if (tmp_buf)
// Delete the current buffer
{
delete_buffer (current_buffer);
// See if the unix file is already being edited
set_buffer (__unix_files);
top_of_buffer ();
if (search_fwd (file_name + ",", 0, 0))
// The unix file is being edited called edit_file and return
edit_file (file_name + ".unx");
else
// It's a new conversion delete the validity check buffer
{
delete_buffer (tmp_buf);
// Create the dos string from the file name
sprintf (file_path, "bbe UD %s.%s %s.unx>&nul", file_name, file_ext, file_name);
// Does the file exist?
if (exist ((file_name + ".") + file_ext))
// Do the .unx files already exist?
{
if (!exist (file_name + ".unx"))
// Call dos for the conversion
{
message ("Generating dos equivalent of %s.%s", file_name,file_ext);
dos (file_path);
}
else
message ("Editing existing files.");
// Edit the converted file
unix_buffer = create_buffer (buffer_name + ("." + file_ext), file_name + ".unx", 0);
// Save the true filename in the unix_files system
// buffer for later.
sprintf (buffer_id, "file=%s,ext=%s", file_name, file_ext);
set_buffer (__unix_files);
beginning_of_line ();
insert (buffer_id + "\n");
set_buffer (unix_buffer);
top_of_buffer ();
switch (file_ext)
{
case "c":
case "cb":
case "cpp":
case "h":
case "hpp":
.c_template_first (1, 1, 0, 1);
case "for":
.for_template_first (0, 2, 1, 1);
case "ada":
.ada_template_first (1, 0);
case "mod":
case "def":
.mod_template_first (1, 0, 0, 1);
case "prg":
case "tem":
case "pre":
.prg_smart_first ();
case "for":
.for_template_first (0, 2, 1);
case "pas":
.pas_template_first (1, 0, 1, 1, 1);
case "bas":
.bas_template_first (1, 0, 0, 1);
case "cob":
case "cbl":
.cob_template_first (0, 0, 1, 1, 1);
default:
_regular_first ();
}
}
else
message ("File %s not found", (file_name + ".") + file_ext);
}
}
}
}
// Registered macro for trapping long lines i.e no CR/LF.
void _unix_edit ()
{
if (inq_message () != "Null characters in file fixed." && inq_message () != "Generating hex file")
{
drop_anchor (3);
if (!search_fwd ("\n", 1, 0, 1))
{
string okay,
file;
int line_no;
raise_anchor ();
inq_names (file);
end_of_buffer ();
inq_position (line_no);
if (2 >= line_no)
// See if the conversion is requested.
if (get_parm (0, okay, "Create file with CR/LF as EOL terminator? ", 1, "Y"))
if (upper (okay) == "Y")
{
top_of_buffer();
// Call _hex_edit to do the dirty work.
_unx_edit (file);
}
// Otherwise, let the user frustrate themselves.
else
message ("You asked for it.");
// Otherwise, return to the top of the buffer
else ;
else
top_of_buffer ();
}
else
beginning_of_line ();
raise_anchor ();
}
}
#endif