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>
767 lines
16 KiB
Objective-C
767 lines
16 KiB
Objective-C
;**
|
|
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
|
|
;**
|
|
;** Written by Dave Nanian and Michael Strickman.
|
|
;**
|
|
|
|
#include "dialog.h"
|
|
|
|
;**
|
|
;** buffers.m:
|
|
;**
|
|
;** This file contains all of the standard BRIEF macros for buffer
|
|
;** manipulation.
|
|
;**
|
|
;** Revision history:
|
|
;** -----------------
|
|
|
|
;**
|
|
;** buf_list:
|
|
;**
|
|
;** This macro provides the user with a list of buffers that can be
|
|
;** manipulated and scrolled through. It is of interest because it
|
|
;** simulates an array of buffer ids using a system buffer. Macro
|
|
;** programmers interested in using arrays should examine this code
|
|
;** carefully before implementing an array system of their own.
|
|
;**
|
|
|
|
#define SYSTEM 1 ;** The value to use for system buffers.
|
|
#define NEW_FILE 1 ;** The value to use for new file attachments.
|
|
|
|
(extern display_file_name
|
|
_bad_key
|
|
)
|
|
|
|
(macro buf_list
|
|
(
|
|
(int _buf_list ;** Buffer that contains visible list.
|
|
_buf_array ;** Buffer that simulates an array.
|
|
_end_buf ;** The buffer to be attached on exit.
|
|
num_bufs ;** The number of buffers in the list.
|
|
start_buf ;** The buffer we started on.
|
|
curr_buf ;** The buffer we're on (in the loop).
|
|
modified ;** Is the current buffer modified?
|
|
_expert ;** Are we in expert mode?
|
|
)
|
|
(string file_name ;** The file name of the buffer.
|
|
buffer_name ;** The buffer name.
|
|
file_line ;** Buffer for line to insert.
|
|
)
|
|
(global _buf_list
|
|
_buf_array
|
|
_end_buf
|
|
_expert
|
|
)
|
|
(if (get_parm 0 _expert)
|
|
(= _expert (! (! _expert)))
|
|
;else
|
|
(= _expert 0)
|
|
)
|
|
|
|
;**
|
|
;** First, we create the array and list buffers, making sure that they
|
|
;** have the "system" attributes. We use non-file buffers because this is
|
|
;** temporary information.
|
|
;**
|
|
;** The "_buf_list" buffer contains a textual list of all of the non
|
|
;** system buffers currently in memory. "_buf_array" contains a list of the
|
|
;** corresponding buffer pointers. Note that the buffer pointers are not
|
|
;** inserted into the buffer as is -- they are converted to string integers
|
|
;** first. This prevents inserting bad characters like tab, return and EOF.
|
|
;**
|
|
|
|
(message "Creating buffer list...")
|
|
|
|
;** First, we get the ID of the current buffer -- we have to
|
|
;** restore it at the end of the macro. After that, we create the
|
|
;** array buffer and put it aside for the moment. Note that the
|
|
;** array buffer is a non-file buffer -- this prevents disk accesses
|
|
;** since the file is held completely in memory.
|
|
|
|
(= start_buf (= _end_buf (inq_buffer)))
|
|
(= _buf_array (create_buffer "Buffer Array" NULL SYSTEM))
|
|
|
|
;** Now, we create the buffer that the user will actually see on
|
|
;** the screen, set it to be the current buffer, and set the tabs to
|
|
;** the values we want (tabs default to every column).
|
|
|
|
(= _buf_list (create_buffer "Buffer List" NULL SYSTEM))
|
|
(set_buffer _buf_list)
|
|
(tabs 5)
|
|
|
|
;** This loop creates both buffer lists: the non-system buffers
|
|
;** are looped through and information about them are culled and added
|
|
;** to the list.
|
|
|
|
(while (!= start_buf curr_buf)
|
|
(
|
|
(if (! curr_buf)
|
|
(= curr_buf start_buf)
|
|
;else
|
|
(
|
|
(set_buffer _buf_list)
|
|
(insert "\n")
|
|
(set_buffer _buf_array)
|
|
(insert "\n")
|
|
)
|
|
)
|
|
(++ num_bufs)
|
|
(message "Creating buffer list [#%d]..." num_bufs)
|
|
(set_buffer curr_buf)
|
|
(inq_names file_name NULL buffer_name)
|
|
(= modified (inq_modified))
|
|
(set_buffer _buf_list)
|
|
|
|
(if (! _expert)
|
|
(
|
|
(sprintf file_line "%d)\tBuffer \"%s\" has " num_bufs buffer_name)
|
|
(insert file_line)
|
|
(sprintf file_line "%sbeen modified.\n\tFile: " (if modified "" "not "))
|
|
(insert file_line)
|
|
)
|
|
;else
|
|
(
|
|
(sprintf file_line "%d)\t" num_bufs)
|
|
(insert file_line)
|
|
)
|
|
)
|
|
(insert file_name)
|
|
|
|
(if modified
|
|
(insert "*")
|
|
)
|
|
(set_buffer _buf_array)
|
|
(sprintf file_line "%d" curr_buf)
|
|
(insert file_line)
|
|
(set_buffer curr_buf)
|
|
(= curr_buf (next_buffer))
|
|
)
|
|
)
|
|
(message "List created.")
|
|
|
|
;**
|
|
;** At this point, the array buffer and list buffer have been created
|
|
;** and filled in. We create a window to display the list in, initialize
|
|
;** the marked area, set up a keymap, and call process. Process handles
|
|
;** the mainline loop -- we need only provide action routines.
|
|
;**
|
|
|
|
(create_window 5 17 74 4 " or to select, E to edit, D to delete, W to write, ESC to exit.")
|
|
(attach_buffer _buf_list)
|
|
|
|
(keyboard_push)
|
|
(assign_to_key "<Down-Arrow>" "_buf_down")
|
|
(assign_to_key "<Up-Arrow>" "_buf_up")
|
|
(assign_to_key "<PgUp>" "_buf_pgup")
|
|
(assign_to_key "<PgDn>" "_buf_pgdn")
|
|
(assign_to_key "<Home>" "_buf_home")
|
|
(assign_to_key "<End>" "_buf_end")
|
|
(assign_to_key "<Ctrl-PgUp>" "_buf_home")
|
|
(assign_to_key "<Ctrl-PgDn>" "_buf_end")
|
|
(assign_to_key "d" "_buf_delete")
|
|
(assign_to_key "D" "_buf_delete")
|
|
(assign_to_key "<Ctrl-minus>" "_buf_delete")
|
|
(assign_to_key "e" "_buf_edit")
|
|
(assign_to_key "E" "_buf_edit")
|
|
(assign_to_key "<Alt-e>" "_buf_edit")
|
|
(assign_to_key "W" "_buf_write")
|
|
(assign_to_key "w" "_buf_write")
|
|
(assign_to_key "<Alt-w>" "_buf_write")
|
|
(assign_to_key "<Enter>" "_buf_edit")
|
|
(assign_to_key "<Esc>" "exit")
|
|
|
|
(move_abs (- 2 _expert) 100)
|
|
(drop_anchor)
|
|
(move_abs 1 1)
|
|
(set_buffer _buf_array)
|
|
(move_abs 1 1)
|
|
(set_buffer _buf_list)
|
|
(refresh)
|
|
|
|
(process)
|
|
|
|
;** Now that we're back from the processing, we pop the keymap that
|
|
;** we created, raise the assorted anchors, and delete the temporary
|
|
;** window and the buffers.
|
|
|
|
(keyboard_pop)
|
|
(raise_anchor)
|
|
(delete_window)
|
|
(delete_buffer _buf_list)
|
|
(delete_buffer _buf_array)
|
|
|
|
;** If we end with a different buffer than we started with, we
|
|
;** attach it to the current window and display its file name.
|
|
;** Otherwise, we set the current buffer back, and call NEW_FILE
|
|
;** to make sure its defaults are reset.
|
|
|
|
(set_buffer _end_buf)
|
|
(inq_names file_name)
|
|
(edit_file file_name)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _buf_down:
|
|
;**
|
|
;** This routine is called whenever the user presses a down arrow.
|
|
;** It moves the array buffer and list buffer's current lines, ensuring
|
|
;** the user does not go past the end of the buffer.
|
|
;**
|
|
|
|
(macro _buf_down
|
|
(
|
|
(move_rel (- 3 (* _expert 2)) 0)
|
|
|
|
(if (inq_position)
|
|
(
|
|
(move_rel (+ -3 (* _expert 2)) 0)
|
|
(return 0)
|
|
)
|
|
;else
|
|
(
|
|
(raise_anchor)
|
|
(drop_anchor 3)
|
|
(move_rel (+ -1 _expert) 0)
|
|
(set_buffer _buf_array)
|
|
(down)
|
|
(set_buffer _buf_list)
|
|
(return 1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _buf_up:
|
|
;**
|
|
;** This macro is called whenever the user presses the up arrow. It
|
|
;** moves up in the list and array buffers, not going past the top of the
|
|
;** buffer.
|
|
;**
|
|
|
|
(macro _buf_up
|
|
(
|
|
(int line)
|
|
|
|
(inq_position line)
|
|
|
|
(if (! (up))
|
|
(return 0)
|
|
;else
|
|
(
|
|
(raise_anchor)
|
|
(drop_anchor 3)
|
|
(move_rel (+ -1 _expert) 0)
|
|
(set_buffer _buf_array)
|
|
(move_rel -1 0)
|
|
(set_buffer _buf_list)
|
|
(return 1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _buf_pgup:
|
|
;**
|
|
;** This macro is called whenever the user presses PgUp. It moves up
|
|
;** one screen in the list and array buffers, not going past the top of the
|
|
;** buffer.
|
|
;**
|
|
|
|
(macro _buf_pgup
|
|
(
|
|
(int num_lines)
|
|
|
|
(= num_lines (* 6 (+ _expert 1)))
|
|
|
|
(while num_lines
|
|
(
|
|
(_buf_up)
|
|
(-- num_lines)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
(macro _buf_home
|
|
(while (_buf_up))
|
|
)
|
|
|
|
;**
|
|
;** _buf_pgdn:
|
|
;**
|
|
;** This macro is called whenever the user presses PgDn. It moves
|
|
;** down one page/screen in the buffer list and the array.
|
|
;**
|
|
|
|
(macro _buf_pgdn
|
|
(
|
|
(int num_lines)
|
|
|
|
(= num_lines (* 6 (+ _expert 1)))
|
|
|
|
(while num_lines
|
|
(
|
|
(_buf_down)
|
|
(-- num_lines)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
(macro _buf_end
|
|
(while (_buf_down))
|
|
)
|
|
|
|
;**
|
|
;** _buf_delete:
|
|
;**
|
|
;** This routine is called when the user wants to delete a buffer.
|
|
;** It makes sure the buffer is not in a window, and prompts the user
|
|
;** if the buffer has been modified.
|
|
;**
|
|
|
|
(macro _buf_delete
|
|
(
|
|
(int buf_to_delete
|
|
ret_code
|
|
)
|
|
(string misc_str)
|
|
|
|
(set_buffer _buf_array)
|
|
(= buf_to_delete (atoi (read)))
|
|
(set_buffer buf_to_delete)
|
|
(= misc_str "y")
|
|
|
|
(if (! (inq_views))
|
|
(
|
|
(if (inq_modified)
|
|
(
|
|
(keyboard_flush)
|
|
|
|
(if (! (get_parm NULL misc_str "This buffer has not been saved. Delete [ynw]? " 1))
|
|
(= misc_str "n")
|
|
)
|
|
)
|
|
)
|
|
(if (|| (index "yY" misc_str) (&& (index "wW" misc_str) (> (_buf_write) 0)))
|
|
(
|
|
(set_buffer _buf_list)
|
|
(delete_line)
|
|
|
|
(if (! _expert)
|
|
(delete_line)
|
|
)
|
|
(set_buffer _buf_array)
|
|
(delete_line)
|
|
(delete_buffer buf_to_delete)
|
|
(set_buffer _buf_list)
|
|
|
|
(if (inq_position)
|
|
(_buf_up)
|
|
;else
|
|
(
|
|
(raise_anchor)
|
|
(move_rel (- 1 _expert) 0)
|
|
(drop_anchor 3)
|
|
(move_rel (+ -1 _expert) 0)
|
|
)
|
|
)
|
|
)
|
|
;else
|
|
(if (! (index "wW" misc_str))
|
|
(message "Buffer not deleted.")
|
|
)
|
|
)
|
|
)
|
|
;else
|
|
(error "You can't delete a viewed buffer.")
|
|
)
|
|
(set_buffer _buf_list)
|
|
)
|
|
)
|
|
|
|
;** _buf_edit:
|
|
;**
|
|
;** This routine is called when the user is on a buffer that he wants
|
|
;** to edit. It sets the global "_end_buf" variable to the current
|
|
;** line's buffer, and calls exit so no further processing takes place.
|
|
;**
|
|
|
|
(macro _buf_edit
|
|
(
|
|
(set_buffer _buf_array)
|
|
(= _end_buf (atoi (read)))
|
|
(set_buffer _buf_list)
|
|
(exit)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _buf_write:
|
|
;**
|
|
;** This routine is called when the user wants to write a modified
|
|
;** buffer. It makes sure the buffer is modified -- if so, it's written
|
|
;** and the information in the window is updated.
|
|
;**
|
|
|
|
(macro _buf_write
|
|
(
|
|
(int old_msg_level
|
|
ret_code
|
|
)
|
|
|
|
(set_buffer _buf_array)
|
|
(set_buffer (atoi (read)))
|
|
|
|
(if (inq_modified)
|
|
(
|
|
(= old_msg_level (inq_msg_level))
|
|
(set_msg_level 0)
|
|
|
|
(if (> (= ret_code (write_buffer)) 0)
|
|
(
|
|
(set_msg_level old_msg_level)
|
|
(set_buffer _buf_list)
|
|
|
|
(if (! _expert)
|
|
(
|
|
(search_fwd "has \\c")
|
|
(insert "not ")
|
|
(down)
|
|
)
|
|
)
|
|
(end_of_line)
|
|
(backspace)
|
|
(move_rel (+ -1 _expert) -100)
|
|
)
|
|
;else
|
|
(set_msg_level old_msg_level)
|
|
)
|
|
)
|
|
;else
|
|
(error "Buffer not modified.")
|
|
)
|
|
(set_buffer _buf_list)
|
|
(returns ret_code)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** edit_file:
|
|
;**
|
|
;** This macro replaces the built-in edit_file function: it displays
|
|
;** the file name of the edited file if the edit operation was successful.
|
|
;**
|
|
|
|
(replacement edit_file
|
|
(
|
|
(int ret_code
|
|
old_msg_level
|
|
)
|
|
(= old_msg_level (inq_msg_level))
|
|
|
|
(if (== (inq_called) "")
|
|
(set_msg_level 0)
|
|
)
|
|
(= ret_code (edit_file))
|
|
(set_msg_level old_msg_level)
|
|
|
|
(if (== ret_code 1)
|
|
(display_file_name)
|
|
)
|
|
(return ret_code)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** edit_next_buffer:
|
|
;**
|
|
;** Edits the next buffer in the buffer list in the current window. If
|
|
;** there are no other buffers, an error message is displayed.
|
|
;**
|
|
|
|
(macro edit_next_buffer
|
|
(
|
|
(string file_name)
|
|
|
|
(int new_buffer)
|
|
|
|
(= new_buffer (next_buffer))
|
|
|
|
(if (!= new_buffer (inq_buffer))
|
|
(
|
|
(set_buffer new_buffer)
|
|
(inq_names file_name)
|
|
(edit_file file_name)
|
|
)
|
|
;else
|
|
(error "No other buffers.")
|
|
)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** edit_prev_buffer:
|
|
;**
|
|
;** Edits the previous buffer in the buffer list.
|
|
;**
|
|
|
|
(macro edit_prev_buffer
|
|
(
|
|
(string file_name)
|
|
|
|
(int old_buffer)
|
|
|
|
(= old_buffer (inq_buffer))
|
|
|
|
(while (!= (next_buffer) old_buffer)
|
|
(set_buffer (next_buffer))
|
|
)
|
|
(if (!= (inq_buffer) old_buffer)
|
|
(
|
|
(inq_names file_name)
|
|
(edit_file file_name)
|
|
)
|
|
;else
|
|
(error "No other buffers.")
|
|
)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** delete_curr_buffer:
|
|
;**
|
|
;** This function deletes the current buffer, if it is unmodified,
|
|
;** there is another buffer in the list to replace it, and it is only
|
|
;** visible in one window.
|
|
;**
|
|
;** If the buffer is modified, the user is asked if he really wants to
|
|
;** delete the buffer. If he answers yes, the deletion is performed.
|
|
;**
|
|
;** If there are no other buffers, or the buffer is in more than one
|
|
;** window, the deletion is not performed.
|
|
;**
|
|
|
|
(macro delete_curr_buffer
|
|
(
|
|
(int old_buf_id
|
|
new_buf_id
|
|
)
|
|
(string reply
|
|
file_name
|
|
)
|
|
(= old_buf_id (inq_buffer))
|
|
(= new_buf_id (next_buffer))
|
|
|
|
(if (== old_buf_id new_buf_id)
|
|
(
|
|
(error "Can't delete: no other buffers.")
|
|
(return 0)
|
|
)
|
|
)
|
|
(if (!= (inq_views) 1)
|
|
(
|
|
(message "Can't delete: buffer is in multiple windows.")
|
|
(return 0)
|
|
)
|
|
)
|
|
(if (inq_modified)
|
|
(
|
|
(keyboard_flush)
|
|
|
|
(if (! (get_parm NULL reply "This buffer has not been saved. Delete [ynw]? " 1))
|
|
(return 0)
|
|
;else
|
|
(if (|| (! (strlen reply)) (! (index "yYwW" reply)))
|
|
(
|
|
(message "Buffer not deleted.")
|
|
(return 0)
|
|
)
|
|
)
|
|
)
|
|
(if (index "wW" reply)
|
|
(
|
|
(int old_msg_level
|
|
ret_code
|
|
)
|
|
(= old_msg_level (inq_msg_level))
|
|
(set_msg_level 0)
|
|
(= ret_code (write_buffer))
|
|
(set_msg_level old_msg_level)
|
|
|
|
(if (<= ret_code 0)
|
|
(return 0)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set_buffer new_buf_id)
|
|
(inq_names file_name NULL)
|
|
(set_buffer old_buf_id)
|
|
(edit_file file_name)
|
|
(delete_buffer old_buf_id)
|
|
(return 1)
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _bad_key:
|
|
;**
|
|
;** This routine adds menus to some prompts.
|
|
;**
|
|
|
|
(replacement _bad_key
|
|
(
|
|
(int key_pressed)
|
|
|
|
(= key_pressed (read_char))
|
|
|
|
(if (&& (== (inq_command) "goto_bookmark") (== key_pressed (key_to_int "<Tab>")))
|
|
(return (_bookmark_menu))
|
|
)
|
|
(push_back key_pressed)
|
|
(return (_bad_key))
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _bookmark_menu:
|
|
;**
|
|
;** This routine actually handles the "invalid keystroke" event
|
|
;** when in the bookmark prompt.
|
|
;**
|
|
|
|
(macro _bookmark_menu
|
|
(
|
|
(int menu_buf
|
|
old_buf
|
|
curr_buf
|
|
line
|
|
col
|
|
i
|
|
num_bookmarks
|
|
_bookmark
|
|
)
|
|
(string bookmark
|
|
file_name
|
|
)
|
|
(global _bookmark)
|
|
|
|
(while (< i 10)
|
|
(
|
|
(if (goto_bookmark i curr_buf line col)
|
|
(++ num_bookmarks)
|
|
)
|
|
(++ i)
|
|
)
|
|
)
|
|
(if (== num_bookmarks 0)
|
|
(beep)
|
|
;else
|
|
(
|
|
(int num_lines
|
|
num_cols
|
|
lx
|
|
by
|
|
rx
|
|
ty
|
|
)
|
|
(= old_buf (inq_buffer))
|
|
(sprintf bookmark "%d bookmark%s" num_bookmarks (if (== num_bookmarks 1) "" "s"))
|
|
(set_buffer (= menu_buf (create_buffer bookmark NULL SYSTEM)))
|
|
(= num_bookmarks 0)
|
|
(= i 1)
|
|
(tabs 2 13 19 25 80)
|
|
|
|
(while (<= i 10)
|
|
(
|
|
(if (goto_bookmark i curr_buf line col)
|
|
(
|
|
(if (== (++ num_bookmarks) 1)
|
|
(insert "\n\tBookmark\tLine\tCol\tFile\n\t--------\t----\t---\t----")
|
|
)
|
|
(insert "\n")
|
|
(set_buffer curr_buf)
|
|
(inq_names file_name)
|
|
(sprintf bookmark "\t%d\t%d\t%d\t%s\t;" i line col file_name)
|
|
(sprintf bookmark "%s%d" bookmark i)
|
|
(set_buffer menu_buf)
|
|
(insert bookmark)
|
|
)
|
|
)
|
|
(++ i)
|
|
)
|
|
)
|
|
(set_buffer old_buf)
|
|
|
|
(= _bookmark -1)
|
|
(inq_screen_size num_lines num_cols)
|
|
|
|
(/= num_lines 2)
|
|
(/= num_cols 2)
|
|
|
|
(= lx (- num_cols 36))
|
|
(= rx (+ num_cols 36))
|
|
(= ty (- num_lines (+ 4 (/ (+ num_bookmarks 4) 2))))
|
|
(= by (+ ty (+ num_bookmarks 5)))
|
|
|
|
(_process_menu lx by rx ty NULL
|
|
" or to move, <Enter> to select, <Esc> to exit"
|
|
NULL menu_buf "_bookmark_action" TRUE)
|
|
|
|
(if (>= _bookmark 0)
|
|
(
|
|
(sprintf bookmark "%d" _bookmark)
|
|
(push_back (key_to_int "<Enter>"))
|
|
(return bookmark)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(returns (inq_cmd_line))
|
|
)
|
|
)
|
|
|
|
;**
|
|
;** _bookmark_action:
|
|
;**
|
|
;** This is the action routine for the dialog manager.
|
|
;**
|
|
|
|
(macro _bookmark_action
|
|
(
|
|
(int event_type)
|
|
|
|
(string button_text)
|
|
|
|
(get_parm 0 event_type)
|
|
|
|
(switch event_type
|
|
|
|
DIALOG_MOVE_MENU
|
|
(
|
|
(get_parm 2 button_text)
|
|
|
|
(if (index button_text ";")
|
|
(returns TRUE)
|
|
;else
|
|
(returns FALSE)
|
|
)
|
|
)
|
|
DIALOG_PICK_MENU
|
|
NULL
|
|
DIALOG_F10
|
|
(
|
|
(get_parm 2 button_text)
|
|
(= _bookmark (atoi (substr button_text (+ (rindex button_text ";") 1))))
|
|
(_dialog_esc)
|
|
(returns TRUE)
|
|
)
|
|
)
|
|
)
|
|
)
|