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

629 lines
16 KiB
Plaintext

/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
#include "dialog.h"
#include "win_ctrl.h"
/*
** help.cb:
**
** This macro contains the BRIEF help system. Display of menus and the like
** is handled by the BRIEF dialog manager.
*/
#define FIRST_MENU_LINE 3
#define FIRST_MENU_COL 20
int _user_kbd;
string prev_func; // name of the previous menu action function
int process_help_menu (string buf_name, string file_name, ~int height, ~int width);
int _help_add_button (~string buffer_name);
void to_top (void);
string search_path (string path, string name);
int display_help (string topic, ~string help_file);
void mouse_help(int event, int modifier, int parm2, int parm3);
void mouse_help_menu(int event, int modifier, int parm2, int parm3);
void _help_down();
void _help_up();
void _help_exit ();
/*
** help:
**
** This macro is used as the main help command. It's called when
** the user presses Alt-h.
*/
void help ()
{
_user_kbd = inq_keyboard ();
process_help_menu ("Help Menu", "help.mnu");
}
/*
** _context_help:
**
** This macro is used as the "help" registered macro. It is called
** when a prompt is displayed on the status line and the user presses
** Alt-h. Write a replacement macro if you want your own help to be
** be available for your own commands. The macro should check if the
** last command is one of your macros, and if so call display_help
** with the name of your help file; if not, just call _context_help
** (so that all replacement macros are eventually called).
*/
void _context_help ()
{
_user_kbd = inq_keyboard ();
display_help (inq_command ());
}
/*
** process_help_menu:
**
** This macro takes four parameters: the buffer name, file name,
** height and width of the menu. It sets things up and calls the
** dialog manager to deal with the actual display and manipulation of
** the menus. (If height & width are omitted, menu is sized
** automatically based on the contents of the menu buffer.)
*/
int process_help_menu (string buf_name, string file_name, ~int height, ~int width)
{
int startline,
startcol;
/*
** Successive menus are offset by a constant amount from the
** first one. The dialog manager automatically keeps track of
** the current menu level. Note that if height and width are
** omitted, height == startline and width == startcol.
*/
height += startline = FIRST_MENU_LINE + _dialog_level;
width += startcol = FIRST_MENU_COL + _dialog_level * 2;
/*
** Here we call the dialog manager to create the help menu.
** Whenever an interesting event occurs, the dialog manager will
** call process_help_event.
**
** Note that process_help_event function may call this
** routine to display an additional menu.
*/
_process_menu (startcol, height, width, startline, buf_name, "Select a Category", file_name, NULL, "process_help_event", TRUE);
returns (TRUE);
}
/*
** process_help_event:
**
** Action macro called by the dialog manager. Used to add buttons
** to the menu or handle picking from the menu.
*/
int process_help_event (int key, ...)
{
string action;
/*
** If a menu button was picked, we parse the action off
** the menu button and execute it.
*/
if (key == DIALOG_INIT)
{
/*
** Setup a mouse event handler to allow button 2 click to
** exit the current menu and Ctrl+ button 2 click to exit help
*/
prev_func = inq_mouse_action();
set_mouse_action( "mouse_help_menu" );
}
else if (key == DIALOG_PICK_MENU)
{
get_parm (2, action);
execute_macro (substr (action, index (action, ";") + 1));
}
else if (key == DIALOG_CREATE_MENU)
{
get_parm (2, action);
_help_add_button (action);
}
returns (TRUE);
}
/*
** display_help:
**
** display_help takes a help keyword and displays the appropriate
** help information in an overlapping window. It uses the global
** variable _dialog_level to tie the grey - and Esc keystrokes in
** with the rest of the menu package (grey - will remove the window,
** and Esc will remove windows until the _dialog_level is 0).
**
** The optional second parameter is the name of the help file.
*/
int display_help (string, ~string)
{
int displayed_help,
orig_buffer,
file_buffer;
string commands = "help.txt";
get_parm (1, commands);
if (file_buffer = create_buffer ("Help File", search_path (_dialog_dir, commands), 1))
{
string topic;
get_parm (0, topic);
message ("Locating help text...");
orig_buffer = set_buffer (file_buffer);
tabs (3);
if (search_fwd (("\xc" + topic) + "\xc") || search_back (("\xc" + topic) + "\xc"))
{
int loc;
message ("Help display for %s.", topic);
if (loc = index (commands = read (), "\xc\""))
commands = substr (commands, loc + 1, strlen (commands) - (loc + 2));
else
commands = "";
beginning_of_line ();
down ();
/*
** hide the zoom button and horizontial scroll bars for the help
** information windows
*/
set_ctrl_state( ZOOM_BTN, HIDE_CTRL ); // dont display a zoom button
set_ctrl_state( HORZ_SCROLL, HIDE_CTRL ); // dont display a horizontial scroll bar
if (inq_called () == "_context_help") {
create_window (2, 21, 76, 2, "<Alt-h> for assignment, <Esc> or <Keypad-minus> to exit help");
} else {
create_window (2, 21, 76, 2, "<Keypad-minus> for menu, <Alt-h> for assignment, <Esc> to exit help");
}
attach_buffer (file_buffer);
keyboard_push ();
assign_to_key ("<Keypad-minus>", "_exit");
assign_to_key ("<Esc>", "_help_exit");
assign_to_key ("<PgUp>", "_help_up");
assign_to_key ("<PgDn>", "_help_down");
assign_to_key ("<Alt-h>", "_help_assignment " + commands);
/* establish the mouse action handler for help */
set_mouse_action( "mouse_help" );
refresh ();
process ();
keyboard_pop ();
delete_window ();
search_back (("\xc" + topic) + "\xc");
beginning_of_line ();
displayed_help++;
/*
** allow display of zoom button and horizontial scroll bar
** for subsequent window creation
*/
set_ctrl_state( ZOOM_BTN, SHOW_CTRL ); // display a zoom button
set_ctrl_state( HORZ_SCROLL, SHOW_CTRL ); // display a horizontial scroll bar
}
else
error ("No help available for %s.", topic);
set_buffer (orig_buffer);
}
else
error ("Help file not found.");
returns (displayed_help);
}
/*
** mouse_help
**
** Handle all the mouse events of interest for help text windows
**
** Mouse assignments
** BTN1_CLICK - display key assignment i.e. <Alt-h>
** BTN2_CLICK - to previous screen i.e. <Keypad-minus>
** BTN2_CLICK + CTRL - exit help i.e. <Esc>
** SET_WIN outside text window - close the window
**
*/
void mouse_help ( int event, // the event code
int modifier, // modifier keys
int parm2, // line or scroll bar code
int parm3 ) // column or thumb position
{
/* handle the events of interest */
switch ( event ){
case BTN1_CLICK: // display key assignment
execute_macro( inq_assignment( "<Alt-h>" ));
case CLOSE_WIN: // close the window
case BTN2_CLICK: // to previous screen
switch ( modifier ){
case 0: // to previous screen
exit();
case KB_CTRL: // exit the help system
_help_exit();
}
case SET_WIN: // click outside window is close window
if ( parm2 != inq_window() ) exit();
case VSCROLL: // vertical scroll bar event
switch ( parm2 ){
case SB_BOTTOM: // end of this help text
{
int old_line, line;
inq_position (old_line); // save current position
search_fwd ("\xc"); // look for next topic in help file
inq_position (line); // get its position
if (line - old_line <= 18) {
/* current topic is only one "page", go to original position */
move_abs (old_line);
} else {
/* current topic is more than one "page" go to last page */
move_abs ( line - 18 );
}
}
case SB_TOP: // top of this help text
{
int old_line, line;
inq_position (old_line); // save current position
search_back ("\xc"); // look for next topic in help file
inq_position (line); // get its position
if (old_line - line <= 18) {
/* current topic is only one "page", go to original position */
move_abs (old_line);
} else {
/* current topic is more than one "page" go to first page */
move_abs ( line+1 );
}
}
case SB_LINEDOWN:
case SB_PAGEDOWN: // page down request
_help_down();
case SB_LINEUP:
case SB_PAGEUP: // page up request
_help_up();
}
}
}
/*
** _help_down:
**
** _help_down is called when the PgDn key is pressed: it ensures that
** the user does not go past the end of the help file. Since the command
** name begins with an underscore, the current command is not reassigned.
*/
void _help_down ()
{
int line,
col,
old_line,
old_col;
inq_position (old_line, old_col);
search_fwd ("\xc");
inq_position (line, col);
move_abs (old_line, old_col);
page_down ();
if (line - old_line <= 18)
move_abs (old_line, old_col);
}
/*
** _help_up:
**
** Goes up a page in the help file. Since the command name begins
** with an underscore, the current command is not reassigned.
*/
void _help_up ()
{
int line,
col,
old_line,
old_col;
inq_position (old_line, old_col);
search_back ("\xc");
inq_position (line, col);
move_abs (old_line, old_col);
page_up ();
if (old_line - line <= 18)
move_abs (old_line, old_col);
}
/*
** key_specific_help:
**
** Gets help for the user using the keys, not the menus.
*/
void key_specific_help ()
{
int saved_level = _dialog_level,
key_value;
string sequence,
assignment;
/*
** The dialog level is saved and restored when we enter and exit
** key-specific help. During execution, we set the _dialog_level to
** 0; a press of Esc will then only remove the help screen.
**
** If this wasn't done, extra "exit" calls would be done, and
** the next time a window came up it would be removed immediately.
*/
_dialog_level = 0;
keyboard_push (_user_kbd);
message ("Press the key you want help on, <Esc> to exit.");
while (key_value != key_to_int ("<Esc>"))
{
while ((key_value = read_char ()) == -1);
sprintf (sequence, "#%u", key_value);
/*
** If the key assignment we have obtained is ambiguous, we keep
** appending additional key assignments to it until we find a
** command (or fail).
*/
while ((assignment = inq_assignment (sequence)) == "ambiguous")
{
message ("Press next key in sequence, <Esc> to exit.");
while ((key_value = read_char ()) == -1);
if (key_value == key_to_int ("<Esc>"))
break;
sprintf (sequence, "%s#%u", sequence, key_value);
}
if (key_value == key_to_int ("<Esc>"))
break;
if (display_help (assignment))
message ("Press the key you want help on, <Esc> to exit.");
}
_dialog_level = saved_level;
keyboard_pop (1);
message ("");
}
/*
** _help_assignment:
**
** This macro takes a command name as a parameter, creates a window
** and displays the keys assigned to that command.
*/
_help_assignment (string commands)
{
string this_command,
keys;
int old_buf,
key_buf,
loc,
comma_loc,
semi_loc,
key_read,
have_assignment;
keyboard_push (_user_kbd);
old_buf = set_buffer (key_buf = create_buffer ("Keys", NULL, 1));
tabs (4);
while (strlen (commands))
{
if (semi_loc && (semi_loc < comma_loc || !comma_loc))
insert ("\n\nSee also:\n");
comma_loc = index (commands, ",");
semi_loc = index (commands, ";");
if (semi_loc && (semi_loc < comma_loc || !comma_loc))
loc = semi_loc;
else
loc = comma_loc;
if (loc)
{
this_command = substr (commands, 1, loc - 1);
commands = substr (commands, loc + 1);
}
else
{
this_command = commands;
commands = "";
}
if (this_command != "")
{
++have_assignment;
if ((keys = inq_assignment (this_command, 1)) == "")
keys = inq_assignment ("execute_macro", 1) + "<-and> " + this_command;
insert ("\n \"" + this_command + "\" is assigned to:\n\t\t");
while (loc = index (keys, "<-"))
{
insert (substr (keys, 1, loc - 1));
keys = substr (keys, loc);
switch (substr (keys, 1, index (keys, ">")))
{
case "<-and>":
keys = substr (keys, 7);
case "<-also>":
{
insert ("\n\t\t");
keys = substr (keys, 8);
}
default:
{
keys = "";
/*
** Note: this breaks from the loop, not the switch.
*/
break;
}
}
}
insert (keys + "\n");
}
}
/*
** If any assignments were found, we display them in a window.
*/
if (have_assignment)
{
keyboard_push ();
assign_to_key ("<Esc>", "_exit");
assign_to_key ("<Keypad-minus>", "_exit");
assign_to_key ("<PgUp>", "_assign_up");
assign_to_key ("<PgDn>", "_assign_down");
top_of_buffer ();
create_window (6, 15, 72, 4, "<Esc> or <Keypad-minus> to exit, <PgUp> or <PgDn> to scroll");
attach_buffer (key_buf);
/* establish the mouse action handler for this help window */
set_mouse_action( "mouse_help" );
refresh ();
process ();
keyboard_pop ();
delete_window ();
}
if (!have_assignment)
beep ();
delete_buffer (key_buf);
set_buffer (old_buf);
keyboard_pop (1);
}
void _assign_up ()
{
page_up ();
}
void _assign_down ()
{
page_down ();
move_rel (inq_position () * -1);
}
/*
** _help_exit:
**
** Exits from the help system; calls exit to remove the help
** window, and pushes back an <Esc> if the dialog manager is active
** to remove the other (menu) windows.
*/
void _help_exit ()
{
if (_dialog_level)
push_back (key_to_int ("<Esc>"));
exit ();
}
/*
** _help_add_button:
**
** Used to add buttons to existing menus. This macro does nothing,
** but you can write a replacement macro for it that checks the only
** parameter (the buffer name) and adds buttons. When your replacement
** macro is called, the menu buffer will be current and the menu will
** be unformatted (just as it is on disk).
** Make sure your replacement calls _help_add_button so that all
** other replacement macros eventually get called.
*/
int _help_add_button (~string)
{
returns (TRUE);
}
/*
** mouse_help_menu
**
** Sub-class the default menu handler for the help system
**
** Mouse action assignments:
** default menu actions plus
** Click 2 - exit this menu
** Dbl Click 2 - exit the help system
**
*/
void mouse_help_menu(int event, // the event code
int modifier, // modifier keys
int parm2, // line or scroll bar code
int parm3 ) // column or thumb position
{
/* handle the events of interest */
switch ( event ){
case BTN2_CLICK: // to previous screen
switch ( modifier ){
case 0: // exit this menu
exit();
case KB_CTRL: // exit the help system
_help_exit();
}
default:
/* let the previous event handler for menus process the event */
execute_macro( prev_func, event, modifier, parm2, parm3 );
}
}