Files
CydandClaude Fable 5 db7745fcd0 sda4: commit the Glaze developer hard-drive dump
Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:41:15 -05:00

780 lines
19 KiB
Plaintext

/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** keys.cb:
**
** This macro allows basic reconfiguration of the key assignments
** for the commands provided with BRIEF. It displays a menu containing
** a list of commands, and an adjacent window containing the key
** assignment(s) for the currently highlighted command. By selecting
** a command, the user can move into the window, and add or delete
** key assignments with Ins and Del.
**
** The macro uses the Dialog Manager for the menu it displays. The
** key assignments are changed by modifying and/or adding assign_to_key
** calls to keyboard.h. If no keyboard.h can be found, the macro can
** be used as an online quick reference card, to find the key sequence
** associated with each command. If a non-zero parameter is supplied,
** the macro inserts the key assignments into the current buffer, instead
** of keyboard.h.
*/
#include "dialog.h"
#include "win_ctrl.h"
int menu_buf,
key_buf,
include_buf,
menu_win,
key_win,
orig_keyboard,
key_parm;
string search_text,
bpath,
include_file,
button_text,
assign_text;
string default_mouse_handler; // default left side menu handler for mouse.
string add_to_path (string path, string file);
void _keys_message ();
void _keys_menu_message ();
string _get_command_str ();
string search_path (string pathvar, string filename);
void mouse_keys_left();
void mouse_keys_right();
void _dialog_menu_pick();
void mouse_menu(int, int, int, int);
/*
** keys:
**
** This macro sets up the buffers needed: one for the command menu,
** one for the key assignment display, and one for keyboard.h. It then
** calls the Dialog Manager to process commands, and when the user
** finishes, it writes keyboard.h and registers a macro to recompile
** startup, if necessary.
*/
void keys ()
{
int old_buffer = inq_buffer ();
string message_str;
orig_keyboard = inq_keyboard ();
include_file = add_to_path (_dialog_dir, "commands.mnu");
if (!exist (include_file))
{
error ("Unable to locate help files (commands.mnu).");
return;
}
menu_buf = create_buffer ("Commands", include_file, 1);
set_buffer (menu_buf);
search_text = read ();
bpath = inq_environment ("BPATH");
if (substr (bpath, 1, 1) == ";")
bpath = substr (bpath, 2);
if (substr (bpath, 1, 1) == ".")
bpath = substr (bpath, index (bpath, ";") + 1);
if (bpath == "")
bpath = "/brief/macros";
include_file = search_path (bpath, "keyboard.h");
key_parm = 0;
get_parm (0, key_parm);
if (!key_parm)
include_buf = include_file == "" ? 0 : create_buffer ("Macro", include_file, 1);
else
{
key_parm = old_buffer;
include_buf = 0;
}
key_buf = create_buffer ("Assignments", NULL, 1);
set_ctrl_state( ZOOM_BTN, HIDE_CTRL); // hide the zoom button for this window
set_ctrl_state( HORZ_SCROLL, HIDE_CTRL); // hide the horz scroll bar for this window
set_ctrl_state( CLOSE_BTN, HIDE_CTRL); // hide the close button for this window
create_window (41, 21, 72, 1, include_buf || key_parm ? ", Del to delete, Ins to add" : "Current Key Assignments");
set_ctrl_state( ZOOM_BTN, SHOW_CTRL); // show the zoom button
set_ctrl_state( HORZ_SCROLL, SHOW_CTRL); // show the horz scroll bar
set_ctrl_state( CLOSE_BTN, SHOW_CTRL); // show the close button for this window
key_win = inq_window ();
attach_buffer (key_buf);
set_buffer (key_buf);
refresh ();
if (include_buf || key_parm)
sprintf (message_str, ", , %c, Enter, Ins, or Esc", 26);
else
message_str = ", , Enter, or Esc";
_process_menu (7, 1, 38, 1, NULL, message_str, NULL, menu_buf, "_keys_menu", 1);
set_window (key_win);
delete_window ();
if (include_buf)
{
set_buffer (include_buf);
if (inq_modified ())
{
if (get_parm (NULL, message_str, "Save changes permanently [yn]? ", 1) && index ("nN", message_str))
message ("Changes only effective for this editing session.");
else
{
message (""); // Clear cancelled message if there.
register_macro (5, "_keys_exit");
write_buffer ();
message ("Changes saved.");
}
}
if (old_buffer != include_buf)
delete_buffer (include_buf);
}
set_buffer (old_buffer);
delete_buffer (menu_buf);
delete_buffer (key_buf);
call_registered_macro (1);
}
/*
** _keys_menu:
**
** This macro is the action routine for the command menu. It handles
** initialization, changing the menu selection, choosing a menu item,
** and terminating the menu. All other menu events are irrelevant.
*/
int _keys_menu (int event_type, ~, string)
{
int text_found,
old_keyboard;
switch (event_type)
{
case DIALOG_INIT:
{
menu_win = inq_window ();
get_parm (2, button_text);
_keys_menu_message ();
button_text = substr (button_text, index (button_text, ";") + 1);
sprintf (search_text, "assign_to_key (\"%%s\", \"%s\"", button_text);
set_buffer (key_buf);
old_keyboard = inq_keyboard ();
keyboard_push (orig_keyboard);
assign_text = inq_assignment (button_text, 1);
if (assign_text == "")
assign_text = _get_command_str () + button_text;
while (!inq_position ())
delete_line ();
insert (assign_text);
top_of_buffer ();
translate ("\\<-also\\>", "\n", 1);
translate ("{\\<-and\\>}|{\\<-or\\>\\<*\\>}", "", 1);
set_buffer (menu_buf);
keyboard_pop (1);
assign_to_key ("<Right>", "_dialog_menu_pick");
if (include_buf || key_parm)
{
assign_to_key ("<Ins>", "_keys_insert");
if (key_parm)
assign_to_key ("<Enter>", "_keys_insert");
}
if (include_buf)
message ("Select item with Enter, add assignment with Ins.");
else
message (" and  to view key assignments.");
/* sub-class the mouse event handler for the menu */
default_mouse_handler = inq_mouse_action(); // save current one
set_mouse_action( "mouse_keys_left" ); // establich new one
}
case DIALOG_ALTER_MENU: {
_keys_menu_message ();
get_parm (2, button_text);
button_text = substr (button_text, index (button_text, ";") + 1);
sprintf (search_text, "assign_to_key (\"%%s\", \"%s\"", button_text);
set_buffer (key_buf);
old_keyboard = inq_keyboard ();
keyboard_push (orig_keyboard);
assign_text = inq_assignment (button_text, 1);
if (assign_text == "")
assign_text = _get_command_str () + button_text;
while (!inq_position ())
delete_line ();
insert (assign_text);
top_of_buffer ();
translate ("\\<-also\\>", "\n", 1);
translate ("{\\<-and\\>}|{\\<-or\\>\\<*\\>}", "", 1);
set_buffer (menu_buf);
keyboard_pop (1);
}
case DIALOG_PICK_MENU: {
if (!include_buf)
{
error ("Unable to find macro source; can't reconfigure.");
return (1);
}
set_window (key_win);
keyboard_push ();
if (strlen (ltrim (read ())))
drop_anchor (3);
_keys_message ();
assign_to_key ("<Up>", "_keys_up");
assign_to_key ("<Down>", "_keys_down");
assign_to_key ("<Ins>", "_keys_insert");
assign_to_key ("<Del>", "_keys_delete");
assign_to_key ("<Alt-d>", "_keys_delete");
assign_to_key ("<Esc>", "exit");
assign_to_key ("<F10>", "exit");
assign_to_key ("<Left>", "exit");
refresh ();
/* specify the mouse event handler for the right-hand window */
set_mouse_action( "mouse_keys_right" );
process ();
keyboard_pop ();
/* If the window has not yet been reset, need to raise the
** anchor
*/
if (inq_window() != menu_win)
raise_anchor ();
set_window (menu_win);
_keys_menu_message ();
}
case DIALOG_TERM: {
message ("Returning to editing session...");
assign_to_key ("<Ins>", "nothing");
assign_to_key ("<Right>", "nothing");
assign_to_key ("<Enter>", "_dialog_menu_pick");
}
}
return (1);
}
/*
** _keys_up:
**
** When the user presses the up arrow in the Assignments window,
** this macro is called. If the user isn't at the top of the buffer,
** it moves the mark up one line.
*/
void _keys_up ()
{
int line;
inq_position (line);
if (line > 1)
{
move_rel (-1, 0);
raise_anchor ();
drop_anchor (3);
}
}
/*
** _keys_down:
**
** Likewise, when the user presses the down arrow in the Assignments
** window, this macro is called. If the user isn't at the bottom of the
** buffer, it moves the mark down one line.
*/
void _keys_down ()
{
move_rel (1, 0);
if (!inq_position ())
{
raise_anchor ();
drop_anchor (3);
}
else
move_rel (-1, 0);
}
/*
** _keys_insert:
**
** This one does all the work. If the user wants to add a key
** assignment, it asks for the new assignment, gets rid of the old
** assignment (both in the Assignment window and in the keyboard.h
** file), and inserts the new assign_to_key statement at the bottom
** of the first macro in keyboard.h (the keyboard macro), or in the
** current buffer, depending on the parameter passed to keys.
*/
void _keys_insert ()
{
int key_value,
old_win = inq_window (),
old_buffer,
found,
i,
abort_insert;
string key_string,
insert_string,
cur_key;
old_buffer = inq_buffer ();
set_window (key_win);
message ("Type the key sequence; press Enter to end.");
while ((key_value = read_char ()) == -1);
insert ("\n");
up ();
while (key_value != key_to_int ("<Enter>"))
{
cur_key = int_to_key (key_value);
error ("cur_key is %s", cur_key);
insert (cur_key);
key_string += cur_key;
message ("Continue; press Enter to end, Esc to cancel.", key_string);
if (++i == 5)
break;
while ((key_value = read_char ()) == -1);
if (key_value == key_to_int ("<Esc>"))
{
abort_insert = 1;
break;
}
}
delete_line ();
beginning_of_line ();
if (abort_insert)
message ("Keystroke cancelled.");
else
{
if (key_string == "")
key_string = "<Enter>";
message ("Processing assignment...");
keyboard_push (orig_keyboard);
assign_to_key (key_string, button_text);
keyboard_pop (1);
save_position ();
top_of_buffer ();
found = search_fwd (key_string, 0, NULL, 0);
restore_position ();
set_buffer (old_buffer);
if (found)
error ("Key sequence already assigned.");
else
{
sprintf (insert_string, "assign_to_key (\"%s\",", key_string);
if (include_buf)
{
set_buffer (include_buf);
top_of_buffer ();
if (search_fwd (insert_string, 0))
{
delete_line ();
beginning_of_line ();
}
}
insert_string += " \"";
insert_string += button_text;
if (include_buf)
{
if (search_fwd ("<\\c\\}"))
{
insert ("\t\t" + insert_string + "\");\n");
up ();
sprintf (insert_string, "Assigned %s to %%s.", button_text);
message (insert_string, key_string);
}
else
error ("Unable to locate end of macro.");
}
else
{
if (key_parm)
{
set_buffer (key_parm);
insert (insert_string + "\");\n");
}
message ("String inserted in current buffer.");
}
set_buffer (key_buf);
insert (key_string + "\n");
raise_anchor ();
if (read () == "\n")
delete_line ();
up ();
drop_anchor (3);
}
}
set_buffer (old_buffer);
set_window (old_win);
}
/*
** _keys_delete:
**
** This macro is called when the user deletes a key assignment.
** It assigns the key sequence to "nothing" in the original keyboard,
** and deletes the text from the Assignments window and the keyboard.h
** file (if it is there).
*/
void _keys_delete ()
{
string key_string,
search_str,
command_str;
key_string = trim (read ());
command_str = _get_command_str ();
if (substr (key_string, 1, strlen (command_str)) != command_str)
{
keyboard_push (orig_keyboard);
assign_to_key (key_string, "nothing");
set_buffer (include_buf);
message ("Locating old assignment...");
top_of_buffer ();
sprintf (search_str, search_text, key_string);
if (search_fwd (search_str, 0, 0))
{
delete_line ();
beginning_of_line ();
}
else if (search_fwd ("<\\c[ \t]+)\n)"))
{
sprintf (search_str, "\t\tassign_to_key (\"%s\", \"nothing\");\n", key_string);
insert (search_str);
up ();
}
else
error ("Unable to locate end of macro.");
set_buffer (key_buf);
set_window (key_win);
delete_block ();
if (inq_position ())
up ();
if (strlen (ltrim (read ())))
drop_anchor (3);
keyboard_pop (1);
_keys_message ();
}
}
/*
** _keys_exit:
**
** This macro is called when the user exits, if there have been
** any modifications to keyboard.h. It recompiles the startup macro,
** so the assignments will be in effect next time BRIEF is run.
*/
void _keys_exit (...)
{
int old_buffer = inq_buffer ();
string command_string;
if (include_buf = create_buffer ("Macros", include_file, 1))
{
set_buffer (include_buf);
message ("Recompiling startup macro...");
if (inq_modified ())
write_buffer ();
sprintf (command_string, "cb %s >&temp.$b$", search_path (bpath, "startup.cb"));
if (dos (command_string))
{
int old_pause_on_error = pause_on_error (1);
error ("Compile failed; run \"cb startup\". Press a key.");
pause_on_error (old_pause_on_error);
}
else
message ("Reconfiguration complete.");
del ("temp.$b$");
}
else
error ("Unable to locate %s.", include_file);
set_buffer (old_buffer);
}
/*
** _keys_message, _keys_menu_message:
**
** These macros simply display the appropriate message when
** they are called.
*/
void _keys_message ()
{
message ("Press Ins to add assignment, Del to delete.");
}
void _keys_menu_message ()
{
if (include_buf)
message ("Select item with Enter, add assignment with Ins.");
else
message (" and  to view key assignments.");
}
/*
** _get_command_str:
**
** Gets the key sequence that is used for the execute_macro
** primitive. If multiple assignments exist, only the first one
** is used.
*/
string _get_command_str ()
{
string command_str;
int command_len;
keyboard_push (orig_keyboard);
command_str = inq_assignment ("execute_macro", 1);
keyboard_pop (1);
if (command_len = index (command_str, "<-and>"))
command_str = substr (command_str, 1, command_len - 1);
if (command_len = index (command_str, "<-also>"))
command_str = substr (command_str, 1, command_len - 1);
returns (command_str + " ");
}
/*
** mouse_keys_right
**
** Handle all the mouse events of interest for the right-hand
** window of the keys macro
**
** Mouse action assignments:
** default menu assignments plus
** Click 2 - insert new entry - like paste
** Ctrl+ Click 2 - delete entry - like cut
** If the user clicks in the other left-hand menu switch processing
** to that menu. Click outside any window exits.
**
** int event, the event code
** int modifier modifier keys
** int parm2 line or scroll bar code
** int parm3 column or thumb position
**
*/
void mouse_keys_right(int event, int modifier, int parm2, int parm3 )
{
/* handle the events of interest */
switch ( event ){
case BTN1_DOWN: // highlite a menu entry
case BTN1_UP: // highlite a menu entry
case BTN1_MOVE: // highlite a menu entry
case BTN1_CLICK: // pick a menu choice
{
int lines;
if ( modifier == 0 ) // make sure no modifiers present
{
/* determine the number of lines in the buffer */
save_position();
end_of_buffer(); // position to the end of the buffer
inq_position( lines );
restore_position();
if ( 0 < parm2 && parm2 <= lines )
{
inq_position(lines);
if (lines != parm2) // did the mouse move to a new entry?
{
raise_anchor(); // erase current highlight
move_abs( parm2, 0 ); // position to choice that was clicked on
drop_anchor(3); // highlight the menu choice
}
}
}
}
case BTN2_CLICK: // insert or delete a key assignment
switch ( modifier )
{
case KB_CTRL:
_keys_delete();
case 0:
_keys_insert();
}
case SET_WIN: // the user clicked in another window
/* was the left-hand menu selected?? */
if ( parm2 == menu_win )
{
/*
** YES - exit this mouse event handler and let the menu event handler
** for the left menu take over. Before exiting this process loop
** via the exit(), set the new current window to the left
** menu to allow the mouse events for the window to come thru.
** Specifically the BTN1_DOWN & BTN1_UP that follow the SET_WIN
** event.
*/
raise_anchor ();
set_window( parm2 );
/*
** Switch the action handler to the left menu because the
** button down event will come thru here before Brief switches
** out of this process loop. We will figure out some way
** so this does not need to be done in the future.
*/
set_mouse_action( "mouse_keys_left" );
exit();
}
else
{
/* a click outside both windows says to exit keys */
exit();
/* send the event to the left menu handler */
set_window( menu_win );
execute_macro( "mouse_keys_left", event, modifier, parm2, parm3 );
}
/*
** Since there is no close button on the right window, see if the
** user clicked on the close button of the left window. If so
** exit keys.
*/
case CLOSE_WIN:
if ( parm2 == menu_win )
{
exit();
/* send the event to the left menu handler */
set_window( menu_win );
execute_macro( "mouse_keys_left", event, modifier, parm2, parm3 );
}
}
}
/*
** mouse_keys_left
**
** Sub-class the default menu handler for the left menu
**
** int event, the event code
** int modifier modifier keys
** int parm2 line or scroll bar code
** int parm3 column or thumb position
**
*/
void mouse_keys_left(int event, int modifier, int parm2, int parm3)
{
/* handle the events of interest */
switch ( event )
{
case SET_WIN: // if the user clicked in the right menu
/* Jam an Enter to bring us to the right window
*/
if ( parm2 == key_win )
push_back(key_to_int("<Enter>"));
/* let the previous event handler for menus process the event
*/
else
execute_macro( default_mouse_handler, event, modifier, parm2, parm3 );
default:
/* let the previous event handler for menus process the event
*/
execute_macro( default_mouse_handler, event, modifier, parm2, parm3 );
}
}