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>
363 lines
7.2 KiB
Plaintext
363 lines
7.2 KiB
Plaintext
/*
|
|
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
|
|
**
|
|
** Written by Dave Nanian and Michael Strickman.
|
|
*/
|
|
|
|
/*
|
|
** wp.cb:
|
|
**
|
|
** This file contains a set of macros that can help with very simple word
|
|
** processing applications. The functions supported are word_wrap, centering,
|
|
** and paragraph reformatting, with a flexible right margin. By default,
|
|
** word_wrap is turned on when this package is loaded. The other functions
|
|
** can be invoked as they are needed, or can be assigned to any keys you
|
|
** choose.
|
|
**
|
|
** These functions are NOT intended to replace a full-featured word processor.
|
|
** They are useful for letters and other short documents, and as a supplement
|
|
** to a text formatter.
|
|
*/
|
|
|
|
#define ADD_CHAR_MACRO 0
|
|
#define NEW_FILE_MACRO 1
|
|
#define DEFAULT_MARGIN 70
|
|
|
|
/*
|
|
** _init:
|
|
**
|
|
** This macro starts the package by setting up word_wrap and initializing
|
|
** the margin.
|
|
*/
|
|
|
|
void _init ()
|
|
{
|
|
global int margin_val,
|
|
default_margin;
|
|
|
|
margin_val = default_margin = DEFAULT_MARGIN;
|
|
}
|
|
|
|
void wp ()
|
|
{
|
|
error ("You must set BPACKAGES to turn on WP.");
|
|
}
|
|
|
|
/*
|
|
** _wp_on, _wp_off:
|
|
**
|
|
** These macros are called to turn word processing on and off for specific
|
|
** files. Note that an optional margin can be specified in the BPACKAGES
|
|
** line; the previous margin is restored when the current file is changed.
|
|
*/
|
|
|
|
string _wp_on (~int)
|
|
{
|
|
if (!get_parm (0, margin_val))
|
|
margin_val = default_margin;
|
|
|
|
register_macro (ADD_CHAR_MACRO, "_word_wrap");
|
|
returns ("_wp_off");
|
|
}
|
|
|
|
void _wp_off ()
|
|
{
|
|
unregister_macro (ADD_CHAR_MACRO, "_word_wrap");
|
|
}
|
|
|
|
/*
|
|
** center:
|
|
**
|
|
** Centers the current line in the work area (the area between column 1
|
|
** and the current margin).
|
|
*/
|
|
|
|
void center ()
|
|
{
|
|
string text;
|
|
|
|
search_back ("<[ \\t]@\\c[~ \\t]");
|
|
text = read ();
|
|
text = substr (text, 1, strlen (text) - 1);
|
|
beginning_of_line ();
|
|
delete_to_eol ();
|
|
move_rel (0, (margin_val - strlen (text)) / 2);
|
|
insert (text);
|
|
}
|
|
|
|
/*
|
|
** word_wrap:
|
|
**
|
|
** This macro is automatically invoked after each time that a character
|
|
** is typed. It moves the cursor to the next line when it is past the
|
|
** margin, taking the current word with it if necessary.
|
|
**
|
|
** Automatic invocation is done via the standard BPACKAGES interface.
|
|
*/
|
|
|
|
void _word_wrap ()
|
|
{
|
|
int col;
|
|
|
|
inq_position (NULL, col);
|
|
|
|
if (col > margin_val)
|
|
{
|
|
prev_char ();
|
|
|
|
if (!index (" \t", read (1)))
|
|
{
|
|
int new_col,
|
|
space_between_words = 1;
|
|
|
|
search_back ("<|[ \\t][~ \\t]");
|
|
inq_position (NULL, new_col);
|
|
|
|
if (read (1) == "\t")
|
|
space_between_words = distance_to_tab ();
|
|
|
|
if (new_col == 1)
|
|
end_of_line ();
|
|
|
|
insert ("\n");
|
|
|
|
if (new_col != 1)
|
|
{
|
|
delete_char ();
|
|
move_rel (0, (col - new_col) - space_between_words);
|
|
}
|
|
}
|
|
else
|
|
next_char ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
** margin:
|
|
**
|
|
** Resets the current margin, prompting the user if necessary.
|
|
*/
|
|
|
|
void margin (int)
|
|
{
|
|
get_parm (0, default_margin, "Enter margin: ");
|
|
margin_val = default_margin;
|
|
}
|
|
|
|
/*
|
|
** reform:
|
|
**
|
|
** Reformats the currently marked area a line at a time. The main
|
|
** loop goes through each line, adjusting it to the margin as necessary.
|
|
** If the line is too long, it splits it at the last space before the
|
|
** margin; it it's too short, it keeps joining the following lines to it,
|
|
** or parts of them if they are too long, until the line fits the margin.
|
|
*/
|
|
|
|
void reform ()
|
|
{
|
|
string last_char,
|
|
tab_reply;
|
|
|
|
int old_buffer,
|
|
temp_buffer,
|
|
start_line,
|
|
start_col,
|
|
end_line,
|
|
end_col,
|
|
curr_line,
|
|
curr_col,
|
|
prev_line,
|
|
prev_col,
|
|
not_done,
|
|
tab_stop;
|
|
|
|
tab_reply = use_tab_char ("n");
|
|
|
|
message ("Reformatting paragraph...");
|
|
|
|
/*
|
|
** If no paragraph marked, find ends of it at blank or indented lines.
|
|
*/
|
|
|
|
if (!inq_marked ())
|
|
{
|
|
end_of_line ();
|
|
move_rel (0, -1);
|
|
|
|
if (!search_back ("{<[ \t]+[~ \t\n]}|{\n @\n\\c}"))
|
|
top_of_buffer ();
|
|
|
|
drop_anchor ();
|
|
next_char ();
|
|
|
|
if (!search_fwd ("{\\c\n[ \t]+[~ \t]}|{\\c\n[ \t]@\n}"))
|
|
end_of_buffer ();
|
|
}
|
|
/*
|
|
** Transfer marked area into a fresh buffer, then delete it.
|
|
*/
|
|
|
|
inq_marked (start_line, start_col, end_line, end_col);
|
|
|
|
save_position ();
|
|
beginning_of_line ();
|
|
tab_stop = distance_to_tab ();
|
|
restore_position ();
|
|
|
|
old_buffer = inq_buffer ();
|
|
set_buffer (temp_buffer = create_buffer ("Word Process", NULL, 1));
|
|
tabs (tab_stop + 1);
|
|
transfer (old_buffer, start_line, start_col, end_line, end_col);
|
|
set_buffer (old_buffer);
|
|
delete_block ();
|
|
move_abs (start_line, start_col);
|
|
set_buffer (temp_buffer);
|
|
top_of_buffer ();
|
|
|
|
/*
|
|
** Loop through buffer a line at a time, shrinking or expanding
|
|
** each line as necessary.
|
|
*/
|
|
|
|
while (!inq_position ())
|
|
{
|
|
end_of_line ();
|
|
inq_position (NULL, curr_col);
|
|
|
|
/*
|
|
** If line is too long, split it.
|
|
*/
|
|
|
|
if (curr_col > margin_val)
|
|
{
|
|
move_abs (0, margin_val + 1);
|
|
search_back ("[ \t]");
|
|
insert ("\n");
|
|
|
|
while (" " == read (1))
|
|
delete_char ();
|
|
|
|
up ();
|
|
}
|
|
else
|
|
{
|
|
not_done = 1;
|
|
|
|
while (not_done)
|
|
{
|
|
left ();
|
|
last_char = read (1);
|
|
|
|
/*
|
|
** Skip current character and leave two spaces after
|
|
** .:!?
|
|
*/
|
|
|
|
curr_col += last_char != " ";
|
|
curr_col += index (".:!?", last_char) > 0;
|
|
|
|
/*
|
|
** Stop if we don't need any more after punc.
|
|
*/
|
|
|
|
if (curr_col >= margin_val)
|
|
not_done = 0;
|
|
else
|
|
{
|
|
down ();
|
|
end_of_line ();
|
|
inq_position (prev_line, prev_col);
|
|
|
|
/*
|
|
** If we need the entire next line, prepare for join.
|
|
*/
|
|
|
|
if (--prev_col <= margin_val - curr_col)
|
|
{
|
|
beginning_of_line ();
|
|
|
|
if (read () == "\n")
|
|
not_done = 0;
|
|
|
|
up ();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
** Find the maximum amt. we can take.
|
|
*/
|
|
|
|
move_abs (0, 1 + (margin_val - curr_col));
|
|
search_back ("[ \t][~ \t]");
|
|
inq_position (curr_line);
|
|
|
|
/*
|
|
** If the first word on the next line is
|
|
** too long, we're done with the line.
|
|
*/
|
|
|
|
if (curr_line != prev_line)
|
|
not_done = 0;
|
|
else
|
|
{
|
|
/*
|
|
** Split off line and clean up start of next.
|
|
*/
|
|
|
|
insert ("\n");
|
|
delete_char ();
|
|
|
|
/*
|
|
** Go back up and prepare to join.
|
|
*/
|
|
|
|
move_rel (-2, 0);
|
|
}
|
|
}
|
|
/*
|
|
** Now join the lines together if needed.
|
|
*/
|
|
|
|
if (not_done)
|
|
{
|
|
move_abs (0, curr_col);
|
|
delete_char ();
|
|
}
|
|
/*
|
|
** Prepare to loop again.
|
|
*/
|
|
|
|
end_of_line ();
|
|
inq_position (NULL, curr_col);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
** Read line into string and insert in other buffer.
|
|
*/
|
|
|
|
beginning_of_line ();
|
|
last_char = read ();
|
|
set_buffer (old_buffer);
|
|
|
|
if (last_char != "\n")
|
|
insert (last_char);
|
|
|
|
refresh ();
|
|
set_buffer (temp_buffer);
|
|
delete_line ();
|
|
|
|
if (read () == "\n")
|
|
delete_line ();
|
|
}
|
|
/*
|
|
** Get rid of the temporary buffer and insert the remaining text.
|
|
*/
|
|
|
|
set_buffer (old_buffer);
|
|
delete_buffer (temp_buffer);
|
|
message ("Reformatting complete.");
|
|
use_tab_char (tab_reply);
|
|
}
|