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

362 lines
8.1 KiB
Objective-C

;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;** Revision history:
;** -----------------
;**
;**
;** wp.m:
;**
;** 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.
;**
(macro _init
(
(int margin_val
default_margin
)
(global margin_val
default_margin
)
(= margin_val (= default_margin DEFAULT_MARGIN))
)
)
(macro 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.
;**
(macro _wp_on
(
(if (! (get_parm 0 margin_val))
(= margin_val default_margin)
)
(register_macro ADD_CHAR_MACRO "_word_wrap")
(return "_wp_off")
)
)
(macro _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).
;**
(macro 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.
;**
(macro _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
)
(= 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.
;**
(macro margin
(
(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.
;**
(macro 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)
(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 line might need to be merged with following lines.
(
(= 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 try to fill more of line
(
(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 if we need just a chunk of it
(
;** 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)
)
) ;Endif first word is too long
)
) ;Endif (now have old line + chunk)
;** 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)
)
) ;Endif line needs to be extended
)
) ;Endwhile line isn't full
)
) ;Endif (Line is now ready to insert)
;** 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)
)
)
) ;Endwhile there are lines to insert.
;** Get rid of the scrap buffer and insert the remaining text.
(set_buffer old_buffer)
(delete_buffer temp_buffer)
(message "Reformatting complete.")
(use_tab_char tab_reply)
)
)