Category : Miscellaneous Language Source Code
Archive   : NEWBUFFS.ZIP
Filename : BUFFERS.CB

 
Output of file : BUFFERS.CB contained in archive : NEWBUFFS.ZIP
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/

#include "dialog.h"

/*
** buffers.cb:
**
** This file contains all of the standard BRIEF macros for buffer
** manipulation.
*/

/*
** 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.
*/

/* Change history:
**
** Added wrap around to menu light bar.
** Only the file path and name now appear in the list, with an asterisk
** appended to changed file names.
** The window now occupies up to the full screen length if enough
** buffers are open but only enough lines for all buffers if less
** than screen length. It also auto sizes to the width of the longest
** file name + 1 (To allow for the asterisk against changed files).
** Since this could make for very narrow windows, the message at the
** bottom of the window has been cut to a list of active keys.
** The buffer list no longer contains the buffer number. This is now
** displayed on the command line as you move the highlight.
** Oh, by the way, the window is now autocentering, so if you are
** working in VGA 132 column mode you will still have a centered
** window.
**
** Jon O'Brien (cody@cix) 4/10/89
*/

#define SYSTEM 1 // The value to use for system buffers.
#define NEW_FILE 1 // The value to use for new file attachments.

void display_file_name ();
int _buf_write ();
string _bookmark_menu ();

void buf_list (~int)
{
global 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.
_currbuf, // Current buffer No.
_scrlines, // No of lines on screen
_scrcols, // No of columns on screen
_bottom, // Last row for window
_max_len, // Length of longest buffer name
_leftc, // Left window column
_rightc; // Right window column

int start_buf, // The buffer we started on.
curr_buf, // The buffer we're on (in the loop).
modified; // Is the current buffer modified?

string file_name, // The file name of the buffer.
buffer_name; // The buffer name.

_num_bufs = 0;
_max_len = 13;
_leftc = 0;
_rightc = 0;
_currbuf = 0;
inq_screen_size(_scrlines, _scrcols);

/*
** 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).
*/

set_buffer (_buf_list = create_buffer ("Buffers", NULL, SYSTEM));
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 (strlen(file_name) > _max_len)
_max_len = strlen(file_name);

insert (file_name + (modified ? "*" : ""));

set_buffer (_buf_array);
insert ("%d", curr_buf);
set_buffer (curr_buf);
curr_buf = next_buffer ();
}

if (_num_bufs > _scrlines - 3)
_bottom = _scrlines - 3
;else
_bottom = _num_bufs + 1;

message ("%d buffers in use", _num_bufs);

/*
** 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.
*/

_leftc = (_scrcols - _max_len - 4)/2;
_rightc = _leftc + _max_len + 2;

create_window (_leftc, _bottom, _rightc, 0, ",E,D,W,ESC");
attach_buffer (_buf_list);

keyboard_push ();
assign_to_key ("", "_buf_down");
assign_to_key ("", "_buf_up");
assign_to_key ("", "_buf_pgup");
assign_to_key ("", "_buf_pgdn");
assign_to_key ("", "_buf_home");
assign_to_key ("", "_buf_end");
assign_to_key ("", "_buf_home");
assign_to_key ("", "_buf_end");
assign_to_key ("d", "_buf_delete");
assign_to_key ("D", "_buf_delete");
assign_to_key ("", "_buf_delete");
assign_to_key ("e", "_buf_edit");
assign_to_key ("E", "_buf_edit");
assign_to_key ("", "_buf_edit");
assign_to_key ("W", "_buf_write");
assign_to_key ("w", "_buf_write");
assign_to_key ("", "_buf_write");
assign_to_key ("", "_buf_edit");
assign_to_key ("", "exit");

move_abs (1, 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);
}


void _buf_home ()
{
raise_anchor ();
top_of_buffer ();
drop_anchor (3);
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
set_buffer (_buf_array);
top_of_buffer ();
set_buffer (_buf_list);
}

/*
** _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.
**
** Now wraps around. Jon O'Brien.
**
*/
int _buf_down ()
{

int line;

inq_position (line);

if (line == _num_bufs)
{
_buf_home ();
return (1);
}
else
{
raise_anchor ();
move_abs (line + 1, 0);
drop_anchor (3);
set_buffer (_buf_array);
move_abs (line + 1, 0);
set_buffer (_buf_list);
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
returns (1);
}
}

void _buf_end ()
{
int num_lines = _bottom - 1;


raise_anchor ();
end_of_buffer ();
beginning_of_line ();
to_bottom ();
drop_anchor (3);
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
set_buffer (_buf_array);
end_of_buffer ();
beginning_of_line ();
set_buffer (_buf_list);
}

/*
** _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.
**
** Now wraps around. Jon O'Brien.
**
*/

int _buf_up ()
{
int line;

inq_position (line);

if (line == 1)
{
_buf_end ();
return (1);
}
else
{
raise_anchor ();
move_abs (line-1, 0);
drop_anchor (3);
set_buffer (_buf_array);
move_abs (line-1, 0);
set_buffer (_buf_list);
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
returns (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.
*/

void _buf_pgup ()
{
int num_lines = _bottom - 1;

inq_position (_currbuf);
if (num_lines >= _currbuf)
_buf_home ();
else
while (num_lines--)
_buf_up ();
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
}

/*
** _buf_pgdn:
**
** This macro is called whenever the user presses PgDn. It moves
** down one page/screen in the buffer list and the array.
*/

void _buf_pgdn ()
{
int num_lines = _bottom - 1;

if (num_lines + _currbuf >= _num_bufs)
_buf_end ();
else
while (num_lines--)
_buf_down ();
inq_position (_currbuf);
message ("Buffer #%d", _currbuf);
}



/*
** _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.
*/

void _buf_delete ()
{
int buf_to_delete;

string misc_str = "y";

set_buffer (_buf_array);
buf_to_delete = atoi (read ());
set_buffer (buf_to_delete);

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

set_buffer (_buf_array);
delete_line ();
delete_buffer (buf_to_delete);
--_num_bufs;
set_buffer (_buf_list);

if (inq_position ())
_buf_up ();
else
{
raise_anchor ();
move_rel (0, 0);
drop_anchor (3);
move_rel (0, 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.
*/

void _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.
*/

int _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);

end_of_line ();
backspace ();
move_rel (0, -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 int edit_file (~string)
{
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 ();

returns (ret_code);
}

/*
** _multifile_edit_file:
**
** This macro is called by the file completion functions when more then
** one file is selected from the completion menu.
*/

void _multifile_edit_file (int completion_buf_id, string path)
{
int old_buf_id = set_buffer (completion_buf_id);

string file_name;

top_of_buffer ();

while (!inq_position () && (file_name = trim (ltrim (read ()))) != "")
{
edit_file (path + file_name);
set_buffer (completion_buf_id);
down ();
}
set_buffer (old_buf_id);
}

/*
** 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.
*/

void edit_next_buffer ()
{
string file_name;

int 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.
*/

void edit_prev_buffer ()
{
string file_name;

int 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 an overlapping
** window and any other window, the deletion is not performed.
*/

int delete_curr_buffer ()
{
int old_buf_id = inq_buffer (),
new_buf_id = next_buffer (),
window_buf_id,
orig_window_id,
curr_window_id;

string reply,
file_name;

if (old_buf_id == new_buf_id)
{
error ("Can't delete: no other buffers.");
return (0);
}
orig_window_id = inq_window ();

if (inq_window_info () == 1)
{
curr_window_id = next_window ();

while (orig_window_id != curr_window_id)
{
inq_window_info (curr_window_id, window_buf_id);

if (window_buf_id == old_buf_id)
{
error ("Can't delete: buffer's windows overlap.");
return (0);
}
curr_window_id = next_window (curr_window_id);
}
}
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 = inq_msg_level (),
ret_code;

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

if (inq_views (old_buf_id) != 0)
{
curr_window_id = next_window ();

while (orig_window_id != curr_window_id)
{
inq_window_info (curr_window_id, window_buf_id);

if (old_buf_id == window_buf_id)
{
set_window (curr_window_id);
edit_file (file_name);
}
curr_window_id = next_window (curr_window_id);
}
if (inq_window () != orig_window_id)
set_window (orig_window_id);
}
delete_buffer (old_buf_id);
returns (1);
}

/*
** _bad_key:
**
** This routine adds menus to some prompts.
*/

replacement _bad_key ()
{
int key_pressed = read_char ();

if (inq_command () == "goto_bookmark" && key_pressed == key_to_int (""))
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.
*/

string _bookmark_menu ()
{
global int _bookmark;

int menu_buf,
old_buf,
curr_buf,
line,
col,
i,
num_bookmarks;

string bookmark,
file_name;

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, 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);
set_buffer (menu_buf);
insert ("\t%d\t%d\t%d\t%s\t;%d", i, line, col, file_name, i);
}
++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, to select, to exit", NULL, menu_buf, "_bookmark_action", TRUE);

if (_bookmark >= 0)
{
sprintf (bookmark, "%d", _bookmark);
push_back (key_to_int (""));
return (bookmark);
}
}
returns (inq_cmd_line ());
}

/*
** _bookmark_action:
**
** This is the action routine for the dialog manager.
*/

int _bookmark_action (int event_type, ~string)
{
string button_text;

switch (event_type)
{
case DIALOG_MOVE_MENU:
{
get_parm (2, button_text);

if (index (button_text, ";"))
returns (TRUE);
else
returns (FALSE);
}
case DIALOG_PICK_MENU:
case DIALOG_F10:
{
get_parm (2, button_text);
_bookmark = atoi (substr (button_text, rindex (button_text, ";") + 1));
_dialog_esc ();
returns (TRUE);
}
}
}


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : NEWBUFFS.ZIP
Filename : BUFFERS.CB

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/