Files
TeslaRel410/sda4/BRIEF/MACROS/WP.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

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);
}