Files
TeslaRel410/sda4/BRIEF/MACROS/SEARCH.CB
T
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

919 lines
20 KiB
Plaintext

/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** search.cb:
**
** This file contains all of the standard BRIEF macros for search
** and translate.
*/
/*
** search:
**
** This macro defines the global variables needed by the search and
** translate macros.
*/
#define FORWARD 1 // Value used to search FORWARD.
#define BACKWARD 0 // Value used to search BACKWARD.
#define TRUE 1 // Standard definitions of TRUE & FALSE.
#define FALSE 0
#define MARKSRCH_TIMEOUT 5 // Timeout for marked location.
extern int _dir, // Current/last search direction.
_t_dir, // Current/last translate direction.
_reg_exp, // Regular expressions on/off.
_block_search, // Block search on/off.
_package_buf; // Parsed language package information.
extern string _s_pat, // Current/last search pattern.
_t_pat, // Current/last translate pattern.
_r_pat; // Current/last replacement pattern.
string _nw_macro, // Current next_word macro.
_pw_macro, // Current previous_word macro.
_ew_macro, // Current begin_word macro.
_bw_macro; // Current end_word macro.
string _evaluate_package (string extension, string macro_name);
void _marksrch (int match_length, ~string);
int _marksrch_active; // Flag to tell _invalid_key we're active.
/*
** _on:
**
** This simple generic package resets the _nw_macro and _pw_macro variables
** when we switch buffers and BPACKAGE parsing is active.
*/
string _on ()
{
returns (_nw_macro = _pw_macro = _ew_macro = _bw_macro = "");
}
/*
** next_word, _next_word:
**
** Locates the next word in the file using a regular expression. If
** there are no following words in the file, the cursor does not move.
*/
int next_word ()
{
if (_nw_macro != "")
returns (execute_macro (_nw_macro));
else
{
string extension;
inq_names (NULL, extension);
if (!_package_buf)
{
extension = "." + extension + "_next_word";
returns (execute_macro (inq_macro (extension) ? extension : "_next_word"));
}
else
returns (execute_macro (_nw_macro = _evaluate_package (extension, "_next_word")));
}
}
int _next_word ()
{
returns (search_fwd ("[ \t\x0c\n]\\c[~ \t\x0c\n]"));
}
/*
** previous_word, _previous_word:
**
** Locates the previous word in the file using a regular expression. If
** there are no preceding words in the file, the cursor does not move.
*/
int previous_word ()
{
if (_pw_macro != "")
returns (execute_macro (_pw_macro));
else
{
string extension;
inq_names (NULL, extension);
if (!_package_buf)
{
extension = "." + extension + "_previous_word";
returns (execute_macro (inq_macro (extension) ? extension : "_previous_word"));
}
else
returns (execute_macro (_pw_macro = _evaluate_package (extension, "_previous_word")));
}
}
int _previous_word ()
{
if (prev_char ())
returns (search_back ("{[~ \t\x0c\n]+}|{[ \t\x0c\n]+}[ \t\x0c\n]@", -2));
else
returns (0);
}
/*
** .c_next_word, .c_previous_word, .cb_next_word, .cb_previous_word,
** .h_next_word, .h_previous_word, .inc_next_word, .inc_previous_word,
** .m_next_word, .m_previous_word, .asm_next_word, .asm_previous_word:
**
** These definitions are used as "language sensitive" word patterns
** for C, Assembler and the BRIEF macro languages.
*/
int .c_next_word ()
{
int length;
save_position ();
if (length = search_fwd ("{[a-zA-Z0-9_]+}|{[~ \t\x0c\na-zA-Z0-9_]+}|{[ \t\x0c\n]+}[ \t\x0c\n]@", -2))
{
int at_end_of_line;
next_char (--length);
at_end_of_line = (read (1) == "\n");
restore_position (at_end_of_line);
returns (!at_end_of_line);
}
else
{
restore_position ();
returns (0);
}
}
int .c_previous_word ()
{
if (prev_char ())
returns (search_back ("{[a-zA-Z0-9_]+}|{[~ \t\x0c\na-zA-Z0-9_]+}[ \t\x0c\n]@", -2));
else
returns (0);
}
int .cb_next_word ()
{
returns (.c_next_word ());
}
int .cb_previous_word ()
{
returns (.c_previous_word ());
}
int .h_next_word ()
{
returns (.c_next_word ());
}
int .h_previous_word ()
{
returns (.c_previous_word ());
}
int .inc_next_word ()
{
returns (.c_next_word ());
}
int .inc_previous_word ()
{
returns (.c_previous_word ());
}
int .m_next_word ()
{
returns (.c_next_word ());
}
int .m_previous_word ()
{
returns (.c_previous_word ());
}
int .asm_next_word ()
{
returns (.c_next_word ());
}
int .asm_previous_word ()
{
returns (.c_previous_word ());
}
/*
** search_fwd:
**
** This macro is used to search forward in the buffer from the
** keyboard level. If there is a previously defined pattern, it is
** displayed on the command line. Typing any character makes this pattern
** vanish and the new one will take its place. If Esc is typed, the old
** pattern is retained.
*/
replacement int search_fwd (~string, ~int, ~int, ~int)
{
/*
** If we're not being called from the keyboard, we don't want
** to extend the search command at all.
*/
if (inq_called () != "")
returns (search_fwd ());
else
{
/*
** We set the message level to 0 so that the user can see
** the messages that the search command displays.
*/
int old_msg_level = set_msg_level (0),
ret_code;
string prompt;
/*
** It's nice to be able to see the setting of the regular
** expression toggle in the search string. We check to see
** what it is, and change the search prompt accordingly.
*/
sprintf (prompt, " Search %sfor: ", _reg_exp ? "" : "(RE off) ");
if (get_parm (0, _s_pat, prompt, NULL, _s_pat))
{
_dir = FORWARD;
/*
** Finally, we search for the specified pattern, using
** the current regular expression setting. Since we've
** given the pattern in the function call, the user is
** not prompted.
*/
if ((ret_code = search_fwd (_s_pat, _reg_exp, NULL, _block_search)) > 0)
_marksrch (ret_code, "search_fwd");
}
else
ret_code = -1;
set_msg_level (old_msg_level);
returns (ret_code);
}
}
/*
** search_back:
**
** This macro is used to search backward in the buffer from the
** keyboard level. If there is a previously defined pattern, it is
** displayed on the command line. Typing any character makes this pattern
** vanish and the new one will take its place. If Esc is typed, the old
** pattern is retained.
*/
replacement int search_back (~string, ~int, ~int, ~int)
{
/*
** If we're not being called from the keyboard, we don't want
** to extend the search command at all.
*/
if (inq_called () != "")
returns (search_back ());
else
{
/*
** We set the message level to 0 so that the user can see
** the messages that the search command displays.
*/
int old_msg_level = set_msg_level (0),
ret_code;
string prompt;
/*
** It's nice to be able to see the setting of the regular
** expression toggle in the search string. We check to see
** what it is, and change the search prompt accordingly.
*/
sprintf (prompt, " Search %sfor: ", _reg_exp ? "" : "(RE off) ");
/*
** Here we retrieve the search pattern for the user. Note
** that we pass the previous search pattern (which is stored in
** the global variable _s_pat) to _get_default as a default prompt
** response.
*/
if (get_parm (0, _s_pat, prompt, NULL, _s_pat))
{
_dir = BACKWARD;
/*
** Finally, we search for the specified pattern, using
** the current regular expression setting. Since we've
** given the pattern in the function call, the user is
** not prompted.
*/
if ((ret_code = search_back (_s_pat, _reg_exp, NULL, _block_search)) > 0)
_marksrch (ret_code, "search_back");
}
else
ret_code = -1;
set_msg_level (old_msg_level);
returns (ret_code);
}
}
/*
** search_again:
**
** This macro uses the information provided by search_fwd and search_back
** to search for the same pattern again, in the same direction.
*/
int search_again ()
{
/*
** We set the message level to 0 so that the user can see
** the messages that the search commands display.
*/
int ret_code,
old_msg_level = set_msg_level (0);
/*
** We check to see if there is a previous search pattern --
** if not, we can't search for it.
*/
if (strlen (_s_pat))
{
/*
** We're searching again, so we have to move before
** we call the appropriate search routine. We do this
** to ensure we don't find the same pattern a second
** time. The current cursor location is saved on the
** position stack because of this: if the search fails,
** we want to put the cursor back where it was before the
** movement.
*/
save_position ();
if (_dir == BACKWARD && prev_char ())
ret_code = search_back (_s_pat, _reg_exp, NULL, _block_search);
else if (_dir == FORWARD && next_char ())
ret_code = search_fwd (_s_pat, _reg_exp, NULL, _block_search);
else
message ("Pattern not found.");
if (ret_code > 0)
_marksrch (ret_code, "search_again");
/*
** Restore the cursor position if the search failed.
*/
restore_position (!ret_code);
}
else
{
error ("No previous search pattern.");
beep ();
}
set_msg_level (old_msg_level);
returns (ret_code);
}
/* Define a mouse event handler to exit from the process if a mouse
** event occurs. Save the parameters to pass on to the current handler
** after the process exits.
*/
void idle_mouse();
int do_mouse_event,
parm1,
parm2,
parm3,
parm4;
/*
** _marksrch:
**
** This routine accepts the return code from the search routines and
** does marking based on that return code. It can be replaced by the
** user to modify the marking action.
*/
void _marksrch (int match_length, ~string)
{
if (!inq_kbd_char ())
{
drop_anchor ();
next_char (match_length - 1 - (match_length != 1));
swap_anchor ();
keyboard_push ();
_marksrch_active++;
refresh ();
set_mouse_action( "idle_mouse" );
do_mouse_event = 0;
register_macro (4, "_marksrch_idle");
process ();
unregister_macro (4, "_marksrch_idle");
_marksrch_active--;
keyboard_pop ();
raise_anchor ();
if (do_mouse_event)
{
string mse_handler;
sprintf(mse_handler, "%s %d %d %d %d", inq_mouse_action(), parm1, parm2, parm3, parm4);
execute_macro(mse_handler);
}
}
}
/* This function is called if a mouse event occurs while a pattern is
** marked after a search.
*/
void idle_mouse(int p1, int p2, int p3, int p4)
{
parm1 = p1;
parm2 = p2;
parm3 = p3;
parm4 = p4;
do_mouse_event = 1;
exit();
}
void _marksrch_idle ()
{
if (MARKSRCH_TIMEOUT != 0 && inq_idle_time () >= MARKSRCH_TIMEOUT)
exit ();
}
/*
** _invalid_key:
**
** This routine is called when an "invalid" key is pressed during normal
** macro processing. If the _marksrch_active variable isn't set, we just
** call down to the default _invalid_key handler. Otherwise, we exit the
** shell process we're in, and allow the keystroke to be processed again.
*/
void _invalid_key (void)
{
if (_marksrch_active)
exit ();
else
_invalid_key ();
}
/*
** translate_back:
**
** This routine handles calls to translate back from the keyboard level.
*/
int translate_back (~string, ~string, ~int, ~int, ~int, ~int, ~int)
{
returns (translate ());
}
/*
** translate:
**
** This routine handles calls to translate from the keyboard level,
** making sure that the call heeds the value of the regular expression
** toggle. As a special bonus, BRIEF will use the value of the last
** thing searched for as the translation pattern if no pattern is
** entered. Once a translate pattern is specified, the search and
** translate patterns separate -- a pattern is maintained for each
** operation.
*/
replacement int translate (~string, ~string, ~int, ~int, ~int, ~int, ~int)
{
int old_msg_level,
ret_code,
dir;
string pattern,
default_pat,
prompt;
/*
** If we're not being called from the keyboard, we don't want
** to extend the search command at all.
*/
if (inq_called () != "")
if (inq_called () != "translate_back")
return (translate ());
else
dir = BACKWARD;
else
dir = FORWARD;
old_msg_level = set_msg_level (0);
/*
** It's nice to be able to see the setting of the regular
** expression toggle in the search string. We check to see
** what it is, and change the translate prompt accordingly.
*/
sprintf (prompt, "%c Pattern%s: ", dir ? '' : '', _reg_exp ? "" : " (RE off)");
/*
** If there haven't been any previous translate patterns,
** we use the last search pattern as the default response to
** the Pattern: prompt. Otherwise, we use the previous
** translate pattern.
*/
if (!strlen (_t_pat))
default_pat = _s_pat;
else
default_pat = _t_pat;
if (get_parm (0, pattern, prompt, NULL, default_pat)
&& get_parm (1, _r_pat, "Replacement: ", NULL, _r_pat))
{
_t_pat = pattern;
_t_dir = dir;
ret_code = translate (_t_pat, _r_pat, NULL, _reg_exp, NULL, inq_marked (), _t_dir);
}
else
ret_code = -1;
set_msg_level (old_msg_level);
returns (ret_code);
}
/*
** translate_again:
**
** This call implements the translate_again command -- it uses the values
** of the various global translate variables to perform the translation.
*/
int translate_again ()
{
int ret_code,
old_msg_level = set_msg_level (0);
if (strlen (_t_pat) || strlen (_r_pat))
ret_code = translate (_t_pat, _r_pat, NULL, _reg_exp, NULL, inq_marked (), _t_dir);
else
{
error ("No previous translate pattern.");
beep ();
}
set_msg_level (old_msg_level);
returns (ret_code);
}
/*
** toggle_re:
**
** This macro toggles the state of the regular expression global
** variable, which controls whether regular expressions are used during
** search and translate.
*/
int toggle_re (~int)
{
int ret_code,
previous_value = _reg_exp;
if (!(ret_code = get_parm (0, _reg_exp)))
_reg_exp = !_reg_exp;
if (!ret_code || inq_called () == "")
/*
** This displays a message on the status line showing the
** new regular expression setting. Note the use of (if) --
** this is the equivalent of the C ?: operator. If the
** expression is true, the statement evaluates to "off";
** otherwise, it evaluates to "on".
**
** Also note that the message is not displayed unless
** the macro is called from the keyboard or the command is
** used as a toggle.
*/
message ("Regular expressions %s.", _reg_exp ? "on" : "off");
returns (previous_value);
}
/*
** block_search:
**
** This macro toggles the state of block searching.
*/
int block_search (~int)
{
int ret_code,
previous_value = _block_search;
if (!(ret_code = get_parm (0, _block_search)))
_block_search = !_block_search;
if (!ret_code || inq_called () == "")
message ("Block searching %s.", _block_search ? "on" : "off");
returns (previous_value);
}
/*
** i_search:
**
** This macro implements a simple incremental search. It does not
** allow regular expressions to be specified. The Esc key terminates
** the search.
**
** The backspace key moves you to the previously matched pattern.
*/
void i_search ()
{
int char,
level;
string pattern,
character,
assignment;
/*
** We use the save_position/restore_position commands to keep
** track of the previously matched location. Searching back for
** the identical pattern would not work, since it would match the
** current occurrence. In addition, prev_char then search_back
** would not match if the current occurrence were the correct one.
*/
save_position ();
while (TRUE)
{
/*
** Since we want the cursor to remain on the screen in the
** proper place, we create a "pseudo-cursor" with an IBM
** graphics character.
*/
message ("I-search for: %s", pattern);
while ((char = read_char ()) == -1);
if (char == key_to_int ("<Esc>"))
break;
sprintf (character, "%s#%d", character, char);
assignment = inq_assignment (character);
if (assignment == "self_insert" || assignment == "nothing")
{
if (char == key_to_int ("<Backspace>"))
{
if (strlen (pattern) > 1)
pattern = substr (pattern, 1, strlen (pattern) - 1);
else
pattern = "";
restore_position ();
if (!--level)
{
save_position ();
level = 1;
}
}
else
{
/*
** Now we have a character that we can search for.
** We add it to the string of characters, and use
** the search_fwd command to locate it. While we're
** searching, we place an ellipsis after the
** string, so the user know's we're doing something.
*/
sprintf (character, "%c", char & 0xff);
pattern += character;
save_position ();
message ("I-search for: %s...", pattern);
if (!search_fwd (pattern, FALSE))
{
beep ();
restore_position ();
pattern = substr (pattern, 1, strlen (pattern) - 1);
}
else
++level;
}
refresh ();
character = "";
}
else if (assignment != "ambiguous")
{
character = "";
if (assignment == "search_again")
{
message ("I-search for: %s...", pattern);
save_position ();
next_char ();
if (!search_fwd (pattern, FALSE))
{
beep ();
restore_position ();
}
else
{
refresh ();
restore_position (FALSE);
}
}
else
beep ();
}
}
/*
** When finished, we pop all of the saved positions off the
** stack. Note the use of the "pop, don't move" parameter with
**
*/
while (--level >= 0)
restore_position (FALSE);
message ("I-search ended.");
}
/*
** end_word:
** _end_word:
**
** Locates the end of the current word in the files using a regular
** expression. If there is no current word in the file, the cursor does not
** move.
*/
int end_word ()
{
if (_ew_macro != "")
returns (execute_macro (_ew_macro));
else
{
string extension;
inq_names (NULL, extension);
if (!_package_buf)
{
extension = "." + extension + "_end_word";
returns (execute_macro (inq_macro (extension) ? extension : "_end_word"));
}
else
returns (execute_macro (_ew_macro = _evaluate_package (extension, "_end_word")));
}
}
int _end_word ()
{
returns (search_fwd ("{[~ \t\x0c\n]\\c[ \t\x0c\n]}|>"));
}
/*
** begin_word:
** _begin_word:
**
** Locates the beginning of the current word.
*/
int begin_word ()
{
if (_bw_macro != "")
returns (execute_macro (_bw_macro));
else
{
string extension;
inq_names (NULL, extension);
if (!_package_buf)
{
extension = "." + extension + "_begin_word";
returns (execute_macro (inq_macro (extension) ? extension : "_begin_word"));
}
else
returns (execute_macro (_bw_macro = _evaluate_package (extension, "_begin_word")));
}
}
int _begin_word ()
{
returns (search_back ("{[ \t\x0c]}|<[ \t\x0c]@\\c[~ \t\x0c]"));
}
/*
** .c_end_word, .c_begin_word, .cb_end_word, .cb_begin_word,
** .h_end_word, .h_begin_word, .inc_end_word, .inc_begin_word,
** .m_end_word, .m_begin_word, .asm_end_word, .asm_begin_word:
**
** These definitions are used as "language sensitive" word patterns
** for C, Assembler and the BRIEF macro languages.
*/
int .c_end_word ()
{
returns( search_fwd ("{[a-zA-Z0-9_]+}|{[~ \t\x0c\na-zA-Z0-9_]+}|{[ \t\x0c\n]+>}\\c", -2) );
}
int .c_begin_word ()
{
returns (search_back ("{[a-zA-Z0-9_]+}|{[~ \t\x0c\na-zA-Z0-9_]+}", -2));
}
int .cb_end_word ()
{
returns (.c_end_word ());
}
int .cb_begin_word ()
{
returns (.c_begin_word ());
}
int .h_end_word ()
{
returns (.c_end_word ());
}
int .h_begin_word ()
{
returns (.c_begin_word ());
}
int .inc_end_word ()
{
returns (.c_end_word ());
}
int .inc_begin_word ()
{
returns (.c_begin_word ());
}
int .m_end_word ()
{
returns (.c_end_word ());
}
int .m_begin_word ()
{
returns (.c_begin_word ());
}
int .asm_end_word ()
{
returns (.c_end_word ());
}
int .asm_begin_word ()
{
returns (.c_begin_word ());
}