home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
09
/
brief.lst
< prev
next >
Wrap
File List
|
1991-08-21
|
24KB
|
648 lines
_A BRIEF MACRO PACKAGE FOR EDITING BINARY FILES_
by James Rodriguez
[LISTING ONE]
/¬ _ini⌠ _hex_edi⌠ _bin_oε _bin_ofµ _bin_mousσ write_buffe≥ */
#define HEX
#define SHOW_DELAY 50
#define UP -11
#define DOWN 11
#define LEFT -1
#define RIGHT 1
#define PGUP -21
#define PGDN 21
#define TOP 30
#define BOTTOM -31
#define HOME -40
#define END -41
extern _package_buf, delete_curr_buffer;
int __hex_files, __bin_keyboard, __hex_window, __asc_window, __unix_files;
_init ()
{ __hex_files = create_buffer ("HEXFILES", NULL, 1); //Binary file database
__unix_files = create_buffer ("UNIXFILE", NULL, 1); //Unix file database
register_macro (6, "_bin_edit");
keyboard_push (); // Create a new keyboard
set_mouse_action("_bin_mouse"); // Define the mouse handler
add_hex_keys(); // Add key assignments
__bin_keyboard = inq_keyboard (); // Store the keyboard identifier
keyboard_pop (1); // Reset the stack
}
// _hex_edit: associates a system buffer with a hex buffer and modifies
// the package information for .HEX files. Called by _bin_edit.
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;
if (get_parm (0, file_name))
{ get_parm (1, in_memory); // Check any flag passed
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 = "";
buffer_name = substr (file_name, rindex (file_name, "\\") + 1);
current_buffer = inq_buffer ();
if (inq_called () == "_bin_edit")
delete_buffer (current_buffer);
// Error check for bad buffer name
tmp_buf = create_buffer (buffer_name + ".hex", file_name + ".hex", 0);
if (tmp_buf)
{ set_buffer (__hex_files);
top_of_buffer ();
if (search_fwd (file_name + ",", 0, 0))
edit_file (file_name + ".hex"); // It's already in a buffer
else
{ delete_buffer (tmp_buf);
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"))
{ message ("Generating hex file");
dos (file_path); // spawn standalone program to convert file
}
else
message ("Editing existing files.");
__hex_buffer = create_buffer (buffer_name + ".hex", file_name +
".hex", 0);
__asc_buffer = create_buffer (buffer_name + ("." + file_ext),
file_name + ".asc", 1);
// Save info in the database 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");
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 ())
{ if (!_package_buf) load_macro ("language");
set_buffer (_package_buf);
top_of_buffer ();
while (search_fwd ("<.hex", 1, 0))
delete_line ();
// Add the correct lines in packages to make this work.
insert (".hex_equivalents\n");
insert (".hex_new;\n");
insert (".hex_existing;\n");
insert (".hex_first;\n");
insert (".hex_on;_on,_bin_on\n"); // Enabled _bin_on
insert (".hex;=hex,,=hex\n");
top_of_buffer ();
}
set_buffer (__hex_buffer);
if (! in_memory)
call_registered_macro (1);
}
}
}
}
// _bin_on: edits the hex and ascii files in side by side windows by creating
// and moving an edge. Insures correct local keyboard by setting it explicitly.
// Looks in hex_files buffer for filename and extract buffer ids. Associate
// buffers with windows and return.
string _bin_on ()
{ int i;
string buf_to_find, exten;
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();
set_buffer (__hex_files); // Edit the system buffer to find buffer id's.
top_of_buffer ();
if (search_fwd (buf_to_find + ",", 0, 0)) // Find the line with filename.
{
keyboard_flush(); // Remove any pending keystrokes
use_local_keyboard (0); // Detach the local keyboard
keyboard_push (__bin_keyboard); // Activate the hex keyboard
set_mouse_action("_bin_mouse"); // Attach the mouse event handler
beginning_of_line ();
buf_to_find = trim (read ()); // Parse out the buffer ids
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);
__asc_window = inq_window ();
attach_buffer (__asc_buffer); // Attach the system buffer to a window
if (!inq_marked ())
drop_anchor (2);
else
refresh ();
refresh ();
change_window (3);
register_macro (1, "_call_on_packages"); // Enable the language macro.
returns "_bin_off"; // Return the off event for the language package.
}
else
{ set_buffer(i); // This is an error check to allow editing
returns ""; // of files with .hex extensions which are not
} // under the binary package control.
}
// _bin_off -- deletes the created window and resets the keyboard.
void _bin_off ()
{ keyboard_flush();
keyboard_pop ();
keyboard_push ();
add_hex_keys();
__bin_keyboard = inq_keyboard ();
delete_edge (1); // Delete the window
keyboard_pop (1);
set_mouse_action("_mouse_action"); // Reset the mouse handler
}
#define BUTTON_1_CLICK 10
#define BUTTON_2_CLICK 11
#define BUTTON_1_DBLCLK 13
#define BUTTON_2_DBLCLK 14
#define VERTICAL_SCROLL 17
#define CLOSE_WINDOW 19
#define SET_WINDOW 20
#define STATUS_AREA 21
#define SCROLLBAR__LINEUP 0
#define SCROLLBAR__LINEDOWN 1
#define SCROLLBAR__PAGEUP 2
#define SCROLLBAR__PAGEDOWN 3
#define SCROLLBAR__TOP 6
#define SCROLLBAR__BOTTOM 7
#define TITLE_BAR 1
void _bin_mouse(int action, int modifier, int line, int col)
{ if (inq_window() == __asc_window)
col = col*2; // Modify the column parameter if clicked in ascii window
switch (action)
{
case STATUS_AREA: // Go to offset on status area click
execute_macro(inq_assignment("<Alt-g>"));
case SET_WINDOW: // A different window was selected
{
if (col!=TITLE_BAR && line == __asc_window) // Disregard mouse action
{ // on the border.
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
}
}
case BUTTON_2_CLICK:
case BUTTON_2_DBLCLK:
case BUTTON_1_CLICK:
case BUTTON_1_DBLCLK:
{ int lines,cols;
if (col % 2) // Modify column parameter to event byte value
col++;
if (col > 50) // If past formatted string length go to the end of
col = 50; // the string.
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 beyond the end of buffer ignore the action
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 BUTTON_2_DBLCLK: // Opens a line (feature not shown)
{ execute_macro(inq_assignment("<Ctrl-Enter>"));
}
case BUTTON_1_DBLCLK: // Double click modifies current byte.
{ string sread, character;
int hex_val;
raise_anchor ();
move_rel (0, -1);
sread = "Enter new value for ";
if (read (1) != "\n")
sread += read (2);
sread += ": ";
if (get_parm (NULL, character, sread, 2))
{ hex_val = _bin_atoh (character);
sprintf (character, "%02x", hex_val); // Convert int to hex
unregister_macro (1, "_call_on_packages");
set_window (__asc_window);
switch (hex_val) // Make sure the value is displayable.
{ case 13:
case 9:
case 0:
sread = ".";
default:
sprintf (sread, "%c", hex_val);
}
/* Insert the value in the hex and ascii buffers
** rehighlight both windows 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 ();
}
}
}
case VERTICAL_SCROLL: // Vertical scroll bar events.
{
switch (line)
{
case SCROLLBAR__LINEUP: // Click on up arrow
execute_macro(inq_assignment("<Left>"));
case SCROLLBAR__LINEDOWN: // Click on down arrow
execute_macro(inq_assignment("<Right>"));
case SCROLLBAR__PAGEUP: // Click above thumb button
execute_macro(inq_assignment("<PgUp>"));
case SCROLLBAR__PAGEDOWN: // Click below thumb button
execute_macro(inq_assignment("<PgDn>"));
case SCROLLBAR__TOP: // Double click on up arrow
execute_macro(inq_assignment("<Ctrl-PgUp>"));
case SCROLLBAR__BOTTOM: // Double click on down arrow
execute_macro(inq_assignment("<Ctrl-PgDn>"));
}
}
}
}
// write_buffer: A replacement for write_buffer. Checks file extension, cleans
// up system buffers. Note: conversion back to binary is not done if 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. */
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;
file_is_hex = 0;
buf_to_edit = inq_buffer (); // Store the current buffer id
raise_anchor (); // Remove the highlight
if (inq_modified ()) // Only write and convert if changed
{
returns write_buffer (); // Preserve the return value
file_was_modified = 1;
}
else
file_was_modified = 0; // if not changed don't reconvert
// Remove the extension.
if (index (file_name, "."))
file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
// Make the system buffer database current
if (ext == "hex")
{
set_buffer (__hex_files);
file_is_hex = 1;
}
else
set_buffer (__unix_files); // Not used in this example
top_of_buffer ();
// Try to find filename record and extract original extension.
if (search_fwd (file_name + ",ext=", 0, 0))
{ beginning_of_line ();
ext = trim (read ());
file_is_controlled=1;
// Find the ascii buffer associated with the hex buffer
if (file_is_hex)
{ int temp_buffer=inq_buffer();
ext = ltrim (substr (ext, index (ext, "newb=") + 5));
old_buffer = substr (ext, 1, 10);
// Retrieve the 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);
}
ext = trim (substr (ext, rindex (ext, "=") + 1));
beginning_of_line ();
if (upper (response2) == "Y")
delete_line (); // Delete the record
}
// Reset the current buffer
set_buffer (buf_to_edit);
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)
{
message ("%s", write_command);
dos (write_command); // Call DOS to execute the conversion
message ("Conversion complete");
}
// Delete the current buffer and the converted file(s).
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) // No other buffers
exit("y");
}
else
if (file_is_hex && file_is_controlled)
{
move_rel (0, -1);
drop_anchor ();
move_rel (0, 1);
}
}
else ;
else ;
else // Call the primitive
return write_buffer ();
}
[LISTING TWO]
/* _bin_add _bin_atoh add_hex_keys _bin_edit _bin_delete */
// _bin_move -- this macro handles synchronized positioning.
void _bin_move (int direction)
{ int col, line;
get_parm(0,direction);
raise_anchor ();
unregister_macro (1, "_call_on_packages"); // Remove the language control
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))
{ // Scrolling is needed
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); // Get the number of lines in the window
move_rel ((direction % 20) * line,0);
}
case HOME:
move_abs(0,1); // Beginning of line
case END:
move_abs(0,25); // End of line
case TOP:
move_abs(1,1); // Top of buffer
case BOTTOM:
{ end_of_buffer();
move_abs(0,25); // End of buffer
}
}
while (inq_position (line,col)) // We might be in virtual space if
move_rel (-1, 0); // so move up until we're not.
drop_anchor (2);
refresh ();
set_window (__hex_window);
move_abs(line,col * 2); // Reposition in the hex buffer
move_rel (0, -1); // Highlight the current byte.
drop_anchor ();
move_rel (0, 1);
refresh ();
register_macro (1, "_call_on_packages");
}
// _bin_add: overwrites the byte in hex window. It is assigned to all of 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 key pressed and push it back on keyboard
// buffer so that it displays in prompt as if it were typed there.
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))
{ // Limit the prompt response to two characters
hex_val = _bin_atoh(character);
sprintf (character, "%02x", hex_val); // Convert the int to hex.
unregister_macro (1, "_call_on_packages"); // Don't disturb the windows.
set_window (__asc_window);
switch (hex_val) // Make sure the value typed is displayable
{ case 13:
case 9:
case 0:
sread = ".";
default:
sprintf (sread, "%c", hex_val);
}
raise_anchor ();
delete_char (); // Remove the old character and insert the new.
insert ("%s", sread);
move_rel(0,-1);
drop_anchor (2);
refresh ();
set_window (__hex_window);
delete_char (2); // Remove the old byte and insert the new.
insert ("%s", upper (character));
}
drop_anchor ();
move_rel (0, 1);
refresh ();
register_macro (1, "_call_on_packages"); // Reenable the language macro
refresh ();
execute_macro(inq_assignment("<Right>")); // Move to the next byte.
}
// _bin_delete: converts the current byte to XX which will be ignored when
// reconverted. Parameter is for deleting a full line.
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); // Change any character to a "."
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); // Change any character to "X"
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_atoh -- 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);
// 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)))
{ str_rev = substr (to_convert, strlen (to_convert), 1);
t_int = index("123456789ABCDEF",upper(str_rev));
loop_count *= 16;
if (0 == loop_count)
loop_count = 1;
converted += t_int * loop_count;
to_convert = substr (to_convert, 1, strlen (to_convert) - 1);
}
return converted;
}
// add_hex_keys -- adds hex editing keys to the keyboard.
add_hex_keys()
{ string macro_name, key_name;
int loop;
for (loop=48; loop<58; loop++) // Assign the numeric keys
{ // to the keyboard
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++) // Assign the a-f Hex keys
{ // to the keyboard
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 ("<Alt-n>", "edit_next_buffer");
assign_to_key ("<Alt-e>", "edit_file");
assign_to_key ("<Alt-w>", "write_buffer");
assign_to_key ("<Alt-x>", "exit");
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);
}
// _bin_edit -- 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")
_hex_edit (file, 0); // Call _hex_edit to do conversion
else // Other wise let the user frustrate themselves.
message ("You asked for it.");
}
}
on_packages"); // Don't disturb the windows.
set_window (__asc_window);