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>
635 lines
16 KiB
Plaintext
635 lines
16 KiB
Plaintext
/*
|
|
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
|
|
**
|
|
** Written by Dave Nanian and Michael Strickman.
|
|
*/
|
|
#include "win_ctrl.h"
|
|
|
|
/*
|
|
** tlib.cb:
|
|
**
|
|
** This macro package makes BRIEF work quite well with TLIB.
|
|
*/
|
|
|
|
#define READ_ONLY 0x01
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
|
|
int _tlib_buf; // Buffer that holds checked out logfile names.
|
|
string default_mouse_handler;
|
|
|
|
int _tlib_run_cmd (string cmd_line);
|
|
string _wp_on (~int margin_val);
|
|
void _wp_off ();
|
|
|
|
/*
|
|
** _tlib_new:
|
|
**
|
|
** This macro creates a workfile from a TLIB logfile if the file
|
|
** does not exist.
|
|
*/
|
|
|
|
string _tlib_new (~int)
|
|
{
|
|
string file_name,
|
|
path,
|
|
old_msg,
|
|
old_path,
|
|
old_drive,
|
|
just_name;
|
|
|
|
int deletesrc,
|
|
curr_buf,
|
|
old_msg_level;
|
|
|
|
/*
|
|
** First, we retrieve the name of the file we're trying to
|
|
** obtain. This name is split into a filename component and
|
|
** a path component. We then change to the drive and directory
|
|
** of this file, since most version control systems need to be
|
|
** run from there to work properly.
|
|
*/
|
|
|
|
if (!get_parm (0, deletesrc))
|
|
deletesrc = TRUE;
|
|
|
|
deletesrc = !!deletesrc;
|
|
|
|
if (deletesrc)
|
|
{
|
|
inq_names (file_name);
|
|
|
|
path = substr (file_name, 1, rindex (file_name, substr (file_name, 3, 1)));
|
|
|
|
if (strlen (path) > 3)
|
|
path = substr (path, 1, strlen (path) - 1);
|
|
|
|
just_name = substr (file_name, rindex (file_name, substr (file_name, 3, 1)) + 1);
|
|
|
|
old_msg_level = inq_msg_level ();
|
|
set_msg_level (0);
|
|
old_msg = inq_message ();
|
|
message ("Retrieving workfile %s...", just_name);
|
|
set_msg_level (old_msg_level);
|
|
|
|
getwd ("", old_drive);
|
|
getwd (path, old_path);
|
|
cd (path);
|
|
cd (substr (path, 1, 2));
|
|
|
|
/*
|
|
** Note that since this file doesn't exist, we get the workfile
|
|
** without closing the original buffer first.
|
|
*/
|
|
|
|
if (_tlib_run_cmd ("tlib e " + just_name) != 0)
|
|
message ("%s", old_msg);
|
|
else
|
|
{
|
|
int size,
|
|
file_date,
|
|
file_time,
|
|
attribute;
|
|
|
|
/*
|
|
** If the file has been successfully retrieved, we put its
|
|
** name in the _tlib_buf along with its current date, time, size
|
|
** and attribute. This information is used later to determine
|
|
** whether or not the file should be checked in.
|
|
*/
|
|
|
|
file_pattern (just_name);
|
|
find_file (NULL, size, file_date, file_time, attribute);
|
|
|
|
if (!_tlib_buf)
|
|
{
|
|
_tlib_buf = create_buffer ("TLIB", NULL, 1);
|
|
register_macro (5, "_tlib_exit");
|
|
}
|
|
curr_buf = set_buffer (_tlib_buf);
|
|
|
|
insert (file_name + "\n");
|
|
insert ("DELETESRC %d %d %d %d\n", size, file_date, file_time, attribute);
|
|
|
|
delete_buffer (curr_buf);
|
|
set_buffer (create_buffer (just_name, file_name));
|
|
message ("");
|
|
}
|
|
cd (old_path);
|
|
cd (substr (old_drive, 1, 2));
|
|
}
|
|
returns ("");
|
|
}
|
|
|
|
/*
|
|
** _tlib_existing:
|
|
**
|
|
** This macro creates a workfile from a TLIB logfile if the file
|
|
** is read only.
|
|
*/
|
|
|
|
string _tlib_existing (~int)
|
|
{
|
|
string file_name,
|
|
path,
|
|
old_msg,
|
|
old_path,
|
|
old_drive,
|
|
just_name;
|
|
|
|
int attribute,
|
|
old_msg_level;
|
|
|
|
/*
|
|
** First, we retrieve the name of the file we're trying to
|
|
** obtain. This name is split into a filename component and
|
|
** a path component. We then change to the drive and directory
|
|
** of this file, since most version control systems need to be
|
|
** run from there to work properly.
|
|
*/
|
|
|
|
inq_names (file_name);
|
|
file_pattern (file_name);
|
|
|
|
/*
|
|
** Note that the file has to exist and be read only before this macro
|
|
** does anything. If it doesn't or isn't, we don't have anything to do.
|
|
*/
|
|
|
|
if (find_file (NULL, NULL, NULL, NULL, attribute) != 0 && (attribute & READ_ONLY))
|
|
{
|
|
path = substr (file_name, 1, rindex (file_name, substr (file_name, 3, 1)));
|
|
|
|
if (strlen (path) > 3)
|
|
path = substr (path, 1, strlen (path) - 1);
|
|
|
|
just_name = substr (file_name, rindex (file_name, substr (file_name, 3, 1)) + 1);
|
|
|
|
old_msg_level = inq_msg_level ();
|
|
set_msg_level (0);
|
|
old_msg = inq_message ();
|
|
message ("Retrieving workfile %s...", just_name);
|
|
set_msg_level (old_msg_level);
|
|
|
|
getwd ("", old_drive);
|
|
getwd (path, old_path);
|
|
cd (path);
|
|
cd (substr (path, 1, 2));
|
|
|
|
/*
|
|
** Note that since the file exists, we must delete the buffer
|
|
** before running tlib. Otherwise, we might get file sharing
|
|
** violations.
|
|
*/
|
|
|
|
delete_buffer (inq_buffer ());
|
|
|
|
if (_tlib_run_cmd ("tlib e " + just_name) != 0)
|
|
message ("%s", old_msg);
|
|
else
|
|
{
|
|
int size,
|
|
file_date,
|
|
file_time;
|
|
|
|
/*
|
|
** If the file has been successfully retrieved, we put its
|
|
** name in the _tlib_buf along with its current date, time, size
|
|
** and attribute. This information is used later to determine
|
|
** whether or not the file should be checked in.
|
|
*/
|
|
|
|
file_pattern (just_name);
|
|
find_file (NULL, size, file_date, file_time, attribute);
|
|
|
|
if (!_tlib_buf)
|
|
{
|
|
_tlib_buf = create_buffer ("TLIB", NULL, 1);
|
|
register_macro (5, "_tlib_exit");
|
|
}
|
|
set_buffer (_tlib_buf);
|
|
|
|
insert (file_name + "\n");
|
|
insert ("NODELETESRC %d %d %d %d\n", size, file_date, file_time, attribute);
|
|
|
|
message ("");
|
|
}
|
|
/*
|
|
** Since we deleted this buffer above, we recreate it here, whether
|
|
** or not we were able to check it out.
|
|
*/
|
|
|
|
set_buffer (create_buffer (just_name, file_name));
|
|
cd (old_path);
|
|
cd (substr (old_drive, 1, 2));
|
|
}
|
|
returns ("");
|
|
}
|
|
|
|
/*
|
|
** _tlib_exit:
|
|
**
|
|
** This macro registers another macro, which must run LAST! This is
|
|
** because it deletes (or can delete) a lot of files that are being
|
|
** edited.
|
|
*/
|
|
|
|
void _tlib_exit ()
|
|
{
|
|
if (_tlib_buf)
|
|
register_macro (5, "__tlib_exit");
|
|
}
|
|
|
|
__tlib_exit ()
|
|
{
|
|
string just_name,
|
|
file_name,
|
|
path,
|
|
old_path,
|
|
cmd_line,
|
|
reply;
|
|
|
|
int deletesrc,
|
|
curr_buf,
|
|
ret_code,
|
|
old_msg_level,
|
|
file_date,
|
|
old_date,
|
|
file_time,
|
|
old_time,
|
|
size,
|
|
old_size,
|
|
attribute,
|
|
old_attribute;
|
|
|
|
set_buffer (_tlib_buf);
|
|
set_buffer (curr_buf = next_buffer (1));
|
|
|
|
/*
|
|
** First, we want to delete all non-system buffers. This ensures
|
|
** that they're all closed and available for modification by TLIB.
|
|
*/
|
|
|
|
pause_on_error (1);
|
|
|
|
while (curr_buf != _tlib_buf)
|
|
{
|
|
if (!inq_system (curr_buf))
|
|
{
|
|
delete_buffer (curr_buf);
|
|
set_buffer (_tlib_buf);
|
|
}
|
|
|
|
set_buffer (curr_buf = next_buffer(1));
|
|
}
|
|
top_of_buffer ();
|
|
|
|
old_msg_level = inq_msg_level ();
|
|
set_msg_level (0);
|
|
|
|
while ((file_name = read ()) != "\n")
|
|
{
|
|
file_name = substr (file_name, 1, strlen (file_name) - 1);
|
|
path = substr (file_name, 1, rindex (file_name, substr (file_name, 3, 1)));
|
|
|
|
if (strlen (path) > 3)
|
|
path = substr (path, 1, strlen (path) - 1);
|
|
|
|
/*
|
|
** We keep around a bunch of information for each file that we
|
|
** checked out of TLIB. In addition to the date, time, size and
|
|
** attribute value, we also have to "command words" that tell us
|
|
** what condition the workfile was in to begin with.
|
|
*/
|
|
|
|
just_name = substr (file_name, rindex (file_name, substr (file_name, 3, 1)) + 1);
|
|
down ();
|
|
file_name = read ();
|
|
deletesrc = (substr (file_name, 1, index (file_name, " ") - 1) == "DELETESRC");
|
|
file_name = substr (file_name, index (file_name, " ") + 1);
|
|
old_size = atoi (file_name);
|
|
file_name = substr (file_name, index (file_name, " ") + 1);
|
|
old_date = atoi (file_name);
|
|
file_name = substr (file_name, index (file_name, " ") + 1);
|
|
old_time = atoi (file_name);
|
|
file_name = substr (file_name, index (file_name, " ") + 1);
|
|
old_attribute = atoi (file_name);
|
|
down ();
|
|
|
|
getwd ("", cmd_line);
|
|
getwd (path, old_path);
|
|
old_path = substr (cmd_line, 1, 1) + substr (old_path, 2);
|
|
cd (path);
|
|
cd (substr (path, 1, 2));
|
|
|
|
file_pattern (just_name);
|
|
find_file (NULL, size, file_date, file_time, attribute);
|
|
|
|
if (old_size != size || old_date != file_date || old_time != file_time || old_attribute != attribute)
|
|
{
|
|
if (reply != "q")
|
|
{
|
|
if (reply != "g" && !get_parm (NULL, reply, ("Check in " + just_name) + " [yngq]? ", 1))
|
|
reply = "q";
|
|
|
|
if (strlen (reply) && index ("yg", lower (reply)))
|
|
{
|
|
int num_lines,
|
|
num_cols,
|
|
comment_buf,
|
|
source_keyboard = inq_keyboard (),
|
|
old_msg_level;
|
|
|
|
/*
|
|
** Note that this variable is initialized every time the
|
|
** macro is called, even though it's global.
|
|
*/
|
|
|
|
global int _tlib_abort_pressed = FALSE;
|
|
|
|
string exit_assignment = inq_assignment ("exit", 1),
|
|
window_msg;
|
|
|
|
/*
|
|
** At this point, we know we're going to check in the
|
|
** TLIB file. So we create a window and center it on the
|
|
** screen, and allow the user to enter a check-in comment.
|
|
** Once they've completed the comment, we send it along to
|
|
** TLIB.
|
|
*/
|
|
|
|
if (exit_assignment == "")
|
|
exit_assignment = "<Alt-x>";
|
|
else if (index (exit_assignment, "<-"))
|
|
exit_assignment = substr (exit_assignment, 1, index (exit_assignment, "<-") - 1);
|
|
|
|
sprintf (window_msg, "Enter comment, %s when finished, <Esc> to abort.", exit_assignment);
|
|
|
|
old_msg_level = set_msg_level (3);
|
|
set_buffer (comment_buf = create_buffer (just_name, "check_in.vcs"));
|
|
set_msg_level (old_msg_level);
|
|
tabs (9);
|
|
|
|
inq_screen_size (num_lines, num_cols);
|
|
num_cols /= 2;
|
|
num_lines /= 2;
|
|
|
|
set_ctrl_state( ZOOM_BTN, HIDE_CTRL); // hide the zoom button for this window
|
|
create_window (num_cols - 38, num_lines + ((num_lines / 2) - 1),
|
|
num_cols + 37, num_lines - (num_lines / 2), window_msg);
|
|
set_ctrl_state( ZOOM_BTN, SHOW_CTRL); // show the zoom button
|
|
|
|
/* save the current mouse event handler */
|
|
default_mouse_handler = inq_mouse_action();
|
|
|
|
/*
|
|
** Here, we copy over assignments that are useful inside
|
|
** the TLIB check-in window. Note that we copy both the
|
|
** assignments to _home and _end and beginning_of_line and
|
|
** end_of_line: this is because some people may have kept
|
|
** the old-style assignments intact.
|
|
*/
|
|
|
|
keyboard_push ();
|
|
keyboard_typeables ();
|
|
|
|
copy_keyboard (source_keyboard, "up",
|
|
"down",
|
|
"left",
|
|
"right",
|
|
"_home",
|
|
"_end",
|
|
"beginning_of_line",
|
|
"end_of_line",
|
|
"page_up",
|
|
"page_down",
|
|
"next_word",
|
|
"previous_word",
|
|
"search_fwd",
|
|
"search_back",
|
|
"search_again",
|
|
"translate",
|
|
"translate_back",
|
|
"translate_again",
|
|
"top_of_buffer",
|
|
"end_of_buffer",
|
|
"cut",
|
|
"copy",
|
|
"paste",
|
|
"delete_char",
|
|
"delete_line",
|
|
"delete_to_eol",
|
|
"delete_previous_word",
|
|
"delete_next_word",
|
|
"read_file",
|
|
"quote",
|
|
"undo",
|
|
"insert_mode",
|
|
"mark",
|
|
"mark 2",
|
|
"mark 3",
|
|
"mark 4",
|
|
"dos",
|
|
"goto_line",
|
|
"reform");
|
|
|
|
assign_to_key (exit_assignment, "exit y");
|
|
assign_to_key ("<Esc>", "_tlib_abort");
|
|
|
|
/*
|
|
** If there aren't already keys assigned to the normal
|
|
** TLIB exit keys, we assign them here. Old habits die
|
|
** hard, and we're trying to make it easier for the user.
|
|
*/
|
|
|
|
if (inq_assignment ("<Ctrl-d>") == "self_insert")
|
|
assign_to_key ("<Ctrl-d>", "exit y");
|
|
|
|
if (inq_assignment ("<Ctrl-z>") == "self_insert")
|
|
assign_to_key ("<Ctrl-z>", "exit y");
|
|
|
|
if (inq_assignment ("<Ctrl-c>") == "self_insert")
|
|
assign_to_key ("<Ctrl-c>", "_tlib_abort");
|
|
|
|
attach_buffer (comment_buf);
|
|
|
|
/* set the mouse handler to the default handler */
|
|
set_mouse_action( "mouse_tlib1" );
|
|
|
|
_wp_on (70);
|
|
refresh ();
|
|
process ();
|
|
_wp_off ();
|
|
delete_window ();
|
|
keyboard_pop ();
|
|
|
|
if (_tlib_abort_pressed == FALSE)
|
|
{
|
|
set_msg_level (3);
|
|
write_buffer ();
|
|
set_msg_level (old_msg_level);
|
|
|
|
set_buffer (_tlib_buf);
|
|
delete_buffer (comment_buf);
|
|
|
|
message ("Checking in " + just_name + "...");
|
|
dos ("tlib u " + just_name + " @check_in.vcs >&nul");
|
|
|
|
del ("check_in.vcs");
|
|
message ("");
|
|
}
|
|
else
|
|
set_buffer (_tlib_buf);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
message ("Cleaning up " + just_name + "...");
|
|
dos ("tlib u " + just_name + " No comment. >&nul");
|
|
message ("");
|
|
}
|
|
cd (substr (old_path, 3));
|
|
cd (substr (old_path, 1, 2));
|
|
}
|
|
delete_buffer (_tlib_buf);
|
|
}
|
|
|
|
/*
|
|
** _tlib_abort:
|
|
**
|
|
** This little routine just tells the main check-in code that the
|
|
** user pressed Esc to abort the comment & check-in.
|
|
*/
|
|
|
|
void _tlib_abort ()
|
|
{
|
|
_tlib_abort_pressed++;
|
|
exit ("y");
|
|
}
|
|
|
|
/*
|
|
** _tlib_run_cmd:
|
|
**
|
|
** This command runs a TLIB get command and checks for common errors.
|
|
** If the file isn't a logfile (etc.), no error box is displayed. Otherwise,
|
|
** we display an error box and let the user see the "disaster in progress."
|
|
*/
|
|
|
|
int _tlib_run_cmd (string cmd_line)
|
|
{
|
|
int ret_code;
|
|
|
|
if (ret_code = dos (cmd_line + " >&bvcs.tmp"))
|
|
{
|
|
if (ret_code > 0)
|
|
{
|
|
int error_buf = create_buffer ("TLIB error", "bvcs.tmp", 1),
|
|
old_buf = set_buffer (error_buf);
|
|
|
|
if (!search_fwd ("{No such}|{ould not}"))
|
|
{
|
|
|
|
/* save the current mouse event handler */
|
|
default_mouse_handler = inq_mouse_action();
|
|
|
|
keyboard_push ();
|
|
assign_to_key ("<PgUp>", "page_up");
|
|
assign_to_key ("<PgDn>", "page_down");
|
|
assign_to_key ("<Esc>", "exit");
|
|
assign_to_key ("<Home>", "top_of_buffer");
|
|
assign_to_key ("<End>", "end_of_buffer");
|
|
assign_to_key ("<Up Arrow>", "up");
|
|
assign_to_key ("<Down>", "down");
|
|
|
|
/* set the mouse handler to the default handler */
|
|
set_mouse_action( "mouse_tlib2" );
|
|
|
|
set_ctrl_state( ZOOM_BTN, HIDE_CTRL); // hide the zoom button for this window
|
|
create_window (2, 22, 78, 2, "TLIB error window -- Esc to exit");
|
|
set_ctrl_state( ZOOM_BTN, SHOW_CTRL); // show the zoom button
|
|
attach_buffer (error_buf);
|
|
refresh ();
|
|
|
|
process ();
|
|
|
|
keyboard_pop ();
|
|
delete_window ();
|
|
}
|
|
delete_buffer (error_buf);
|
|
set_buffer (old_buf);
|
|
}
|
|
}
|
|
del ("bvcs.tmp");
|
|
returns (ret_code);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** mouse_tlib1
|
|
**
|
|
** Handle mouse events for the tlib check in window
|
|
**
|
|
** Mouse actions
|
|
** CLOSE_WIN - abort the check in , same as Esc
|
|
** BTN1_CLICK outside of the window - abort the check in
|
|
**
|
|
** All other events are sent to the previous mouse action handler.
|
|
*/
|
|
void mouse_tlib1 (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 CLOSE_WIN: // abort the check in
|
|
_tlib_abort();
|
|
|
|
case SET_WIN: // click outside the window aborts check in
|
|
if ( parm2 != inq_window() ) _tlib_abort();
|
|
|
|
default:
|
|
/* let the previous event handler take care of the event */
|
|
execute_macro( default_mouse_handler, event, modifier, parm2, parm3 );
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
** mouse_tlib2
|
|
**
|
|
** Handle mouse events for the tlib error window
|
|
**
|
|
** Mouse actions
|
|
** CLOSE_WIN - close the window, same as Esc
|
|
** BTN1_CLICK outside of the window - close the window
|
|
** let the default event handler process all the scrolling events
|
|
** ignore all others.
|
|
**
|
|
** All other events are sent to the previous mouse action handler.
|
|
*/
|
|
void mouse_tlib2 (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 CLOSE_WIN: // abort the check in
|
|
exit();
|
|
|
|
case SET_WIN: // click outside the window aborts check in
|
|
if ( parm2 != inq_window() ) exit();
|
|
|
|
case VSCROLL:
|
|
case HSCROLL:
|
|
/* let the previous event handler take care of the event */
|
|
execute_macro( default_mouse_handler, event, modifier, parm2, parm3 );
|
|
|
|
}
|
|
}
|