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

427 lines
9.5 KiB
Plaintext

/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_menu.cb:
**
** This file contains all BRIEF macros for managing menus provided
** by the dialog manager.
*/
#include "dialog.h"
#include "dlg.h"
#include "win_ctrl.h"
/*
** mouse_menu
**
** Handle all the mouse events of interest for menus
**
** Mouse assignments
** BTN1 DOWN, UP, MOVE - highlight a menu entry
** BTN1_CLICK - pick a menu choice
** BTN2_CLICK - close the menu
*/
void mouse_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 ){
/*
** Note: the double click is ignored because the CLICK message
** comes thru before the double click message so the click causes
** the menu selection.
*/
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
_menu_highlight(); // highlight the menu choice
}
if ( event == BTN1_CLICK ) _dialog_menu_pick();
}
}
}
/*
** Close the menu if the user clicks in the status area.
** If you would like a click in the status area, when a
** menu is up to mean shut down the menu and bring up
** a command prompt, then remove the test for BTN1_CLICK
** and just exit. Then the BTN1_DOWN message will cause
** the menu to exit and the BTN1_CLICK will pass thru to
** the default handler which will bring up the command prompt
*/
case STATUS_AREA:
switch ( parm2 ) {
case BTN1_CLICK:
exit();
}
/* close the menu if the close button clicked on this menu */
case CLOSE_WIN:
if ( inq_window() == parm2 ) exit(); // close this menu
/* close the menu if the user clicked outside of it */
case SET_WIN:
if ( inq_window() != parm2 ) exit(); // close this menu
case VSCROLL: // vertical scroll bar event
switch ( parm2 ){
case SB_BOTTOM: // end of menu request
_dialog_menu_end();
case SB_TOP: // top of menu request
_dialog_menu_home();
case SB_PAGEDOWN: // page down request
_dialog_menu_pgdn();
case SB_PAGEUP: // page up request
_dialog_menu_pgup();
case SB_LINEDOWN: // line down request
_dialog_menu_down();
case SB_LINEUP: // line up request
_dialog_menu_up();
case SB_THUMBTRACK:{ // scroll while tracking the thumb
raise_anchor(); // erase current highlight
/* set the thumb position */
set_ctrl_state(VERT_THUMB, parm3);
/* make sure we're at the left col */
move_abs(0, 1);
_menu_highlight(); // highlight the menu choice
}
}
}
}
/*
** _menu_highlight:
**
** Calls the menu alter event. If it succeeds, highlights the
** current menu line using a line mark.
*/
int _menu_highlight ()
{
int line;
inq_position (line);
if (execute_macro (_dialog_action_func, DIALOG_MOVE_MENU, line, _menu_button ()))
{
raise_anchor ();
drop_anchor (3);
returns (TRUE);
}
else
returns (FALSE);
}
/*
** _dialog_menu_home:
**
** Moves the selection to the first selectable item on the menu.
** Calls the action function with the new line number and menu button
** text.
*/
void _dialog_menu_home ()
{
top_of_buffer ();
while (!_menu_highlight ())
down ();
}
/*
** _dialog_menu_end:
**
** Moves to the last selectable item on the menu. Calls the
** action function with the new line number and menu button text.
*/
void _dialog_menu_end ()
{
end_of_buffer ();
beginning_of_line ();
to_bottom ();
while (!_menu_highlight ())
up ();
}
/*
** _dialog_menu_pgup, _dialog_menu_pgdn:
**
** Pages up or down in a menu.
*/
void _dialog_menu_pgup ()
{
page_up ();
if (!(_menu_highlight () || _dialog_menu_up ()))
_dialog_menu_down ();
}
void _dialog_menu_pgdn ()
{
page_down ();
while (inq_position ())
up ();
if (!(_menu_highlight () || _dialog_menu_down ()))
_dialog_menu_up ();
}
/*
** _dialog_menu_down:
**
** Moves the current selection down, stopping at next selectable
** item; if the bottom of the menu is encountered, returns to the
** previous position. Returns whether or not it succeeded in moving.
** Calls the action function with the new line number and menu
** button text as parameters.
*/
int _dialog_menu_down ()
{
int failed;
save_position ();
while (TRUE)
{
down ();
if (inq_position ())
{
failed++;
break;
}
else if (_menu_highlight ())
break;
}
restore_position (failed);
returns (!failed);
}
/*
** _dialog_menu_up:
**
** Moves the current selection up to the previous selectable
** item, if there are any. Returns TRUE if it succeeded.
*/
int _dialog_menu_up ()
{
int moved;
save_position ();
while (up ())
if (_menu_highlight ())
{
moved++;
break;
}
if (!moved)
set_top_left (1, 1);
restore_position (!moved);
returns (moved);
}
/*
** _menu_go:
**
** Reads a character (that was just inserted; _menu_go is
** called by a type 0 registered macro) from the buffer and deletes
** it, then looks for a matching button before the end of the menu.
** If there is none, looks for one starting with the first item.
** If there is still none, stays put. (If a selectable button is found,
** _menu_go moves to it and highlights it.)
*/
void _menu_go (int key)
{
string pattern;
int end_line,
after_line,
start_line,
start_col,
failed;
/*
** Figure out the time when the key was pressed. This is a
** relative number, measured in tenths of a second, and it is
** used to figure out when a user is typing a multi-key
** sequence.
*/
time (NULL, start_line, start_col, end_line);
end_line = (start_line * 60 + start_col) * 10 + end_line / 10;
after_line = end_line - _dialog_menu_time;
_dialog_menu_time = end_line;
while (after_line < 0)
after_line += 32768;
/*
** If .8 seconds or more elapsed since we last pressed a key in
** this menu, we clear the remembered prefix.
*/
if (after_line >= 8)
_dialog_menu_prefix = "";
/*
** Figure out what key was pressed.
*/
sprintf (pattern, "%c", key);
/*
** If the character is a regular expression character, we make
** sure to put a backslash in front of it.
*/
if (index ("?*@+|\\<>%${}[]~-", pattern))
pattern = "\\" + pattern;
pattern = "<[ \\t]@" + (_dialog_menu_prefix += pattern);
/*
** Find the last line of the window; if the search takes us
** outside it, we want to center the line in the window.
*/
inq_position (start_line, start_col);
end_of_window ();
inq_position (end_line);
move_abs (start_line, start_col);
/*
** If we are searching for a one-character button prefix, we
** search the current line last, not first.
*/
if (strlen (_dialog_menu_prefix) == 1)
down ();
/*
** Search from the current position to EOF, breaking if
** a selectable line is found. If the pattern is not found,
** start searching from the top of the file down.
*/
while (!failed)
{
if (search_fwd (pattern, TRUE, FALSE) <= 0)
{
move_abs (start_line, start_col);
drop_anchor (3);
top_of_buffer ();
while (!failed)
{
if (search_fwd (pattern, TRUE, FALSE, TRUE) <= 0)
++failed;
else if (_menu_highlight ())
{
inq_position (after_line);
if (after_line > end_line)
center_line ();
return;
}
else
down ();
}
/*
** If we can't find the current multi-character prefix in the
** menu, but the last two characters were the same, we throw
** away the second of those and look for the next prefix that
** matches.
*/
if ((failed = strlen (_dialog_menu_prefix)) > 1 && substr (_dialog_menu_prefix, failed, 1) == substr (_dialog_menu_prefix, failed - 1, 1))
{
_dialog_menu_prefix = substr (_dialog_menu_prefix, 1, failed - 1);
pattern = "<[ \\t]@" + _dialog_menu_prefix;
move_abs (start_line, start_col);
down ();
failed = FALSE;
}
else
failed = TRUE;
raise_anchor ();
}
else if (_menu_highlight ())
{
inq_position (after_line);
if (after_line > end_line)
center_line ();
return;
}
else
down ();
}
move_abs (start_line, start_col);
}
/*
** _dialog_menu_pick:
**
** Processes the menu line that is selected when the user presses
** Enter.
*/
void _dialog_menu_pick ()
{
int line;
inq_position (line);
if (execute_macro (_dialog_action_func, DIALOG_PICK_MENU, line, _menu_button ()))
_dialog_picked = line;
}
/*
** _menu_button:
**
** Returns the text of the current menu button, with leading and
** trailing white space removed.
*/
string _menu_button ()
{
returns (trim (ltrim (read ())));
}