Category : Miscellaneous Language Source Code
Archive   : EC304.ZIP
Filename : EC-TOP.ORG

 
Output of file : EC-TOP.ORG contained in archive : EC304.ZIP
/****************************************************************************\
* *
* Template: <^f^> *
* *
* File: ec-top.cb *
* *
* Description: This file contains the top level routines used by the Elec-c *
* package for Brief. *
* *
* Created by: Bruce A. Mallett 18-Sep-1989 *
* *
* Electric C macro package for the Brief(tm) editor. *
* *
* Copyright (C) 1986 - 1989 Bruce A. Mallett *
* *
* US Mail: *
* M-Tek *
* PO Box 855 *
* Derry, N.H. 03038 *
* (603) 434-1625 *
* *
* Electronic: *
* Genie: B.MALLETT *
* *
* *
* ("Brief" is a trademark of UnderWare, Inc). *
* *
* *
* Conditions of use: *
* *
* As the author of the Elec-C package I grant you, the user, the right *
* to use, modify, distribute, and make copies of this package providing *
* that: *
* *
* - you do not sell this package or seek to make a profit *
* by the sale of this package or any modified version of *
* it. *
* - this and the copyright notices are retained. *
* - you communicate to me either by a postcard (to *
* the above address) or by electronic mail (also *
* given above) at least one of the following pieces *
* of information: *
* 1) what you like about Elec-c *
* 2) what you don't like about Elec-c *
* 3) what you would like to see improved *
* in the next release of Elec-c *
* 4) any suggestions you have for the next *
* release of Elec-c (either for the *
* macro package or ancilliary utilities) *
* *
\****************************************************************************/


/*
*
* Revision history:
*
* 7-22-Jul-91 Bruce A. Mallett
* Incorporated John Booth's _RtJustifyComment() and box comment right
* margin changes (thanks John!). His revision history comments follow
* (highlighted with ">" because the chronological ordering can get
* confusing):
*
* > 10-Jul-90 John S. Booth, Jr.
* > When in line comment mode, a beep will be heard with each character
* > entered within the last few columns before line wrap occurs. Shades
* > of the old typewriter days!
*
* > 09-Jul-90 John S. Booth, Jr.
* > Added _RtJustifyComment routine to right justify the closing '*'
* > and '/' of a comment to the global right margin column for comments.
* > This will work only if the comment started at the comment left
* > margin position or greater so as to allow the comment-only lines
* > to be of any length.
*
* 06-Jan-91 Bruce A. Mallett
* Got rid of that pesky _SetTabs() and _GetTabData() stuff. Don't know
* what I was thinking when I put the #$%^@! stuff in here. I now let
* the normal (and perfectly adequate) Brief setup (in initials file)
* code handle it.
*
* Moved the initialization code from _ec_first() to _ec_on(), as this
* allows _EditBoxBuffer() to inherit the correct tab stops.
*
* 23-Oct-90 Bruce A. Mallett
* Changed _InCommentOrString() so that the return value indicates which
* we are in. Rewrote _StartComment() to eliminate _InBox() call and to
* make use of the return value from _InCommentOrString(). This eliminates
* a redundant call to _InCommentOrString(), thus improving performance.
*
* 16-Oct-90 Bruce A. Mallett
* Modified _FindMatch() to return the position at which the match was
* found. Since this changed the number of parameters passed to it I
* had to modify all callers as well.
*
* Removed _InString() mod.s made 15-Jun-90, as these did not work in all
* cases. Kept the deletion of _FirstStmtLine() however.
*
* Modified _CloseBrace() to more accurately find the opening brace keyword.
*
* 15-Jun-90 Bruce A. Mallett
* Modified _InString() to use a regular expression search to find the
* closing quote of a string. This improves the execution speed slightly.
*
* Deleted _FirstStmtLine() and made this in-line to _InString(), which
* was the only one who used it.
*
* 06-Mar-90 Bruce A. Mallett
* Lots of stuff. Made Elec-c compatible with Underware's language.cb
* package. This allows Elec-c and Underware's smart or template C
* editing packages to work together.
*
* Changed _CloseParen() and _CloseBracket() to call _FindMatch() with
* a check level of one (I don't know why I had left it at zero). This
* makes the match checking more extensive thus preventing Elec-c from
* becoming confused by opening parenthasis and brackets within strings
* and comments.
*
* Reformatted a lot of headers and code to use my headers, comment
* style, and formatting.
*
* Changed _CloseBrace() to supply via a comment what is being closed.
* Thus you can now get things like:
* for ()
* {
* } / * for() * /
*
* 02-Dec-89 Bruce A. Mallett
* Improved _InString() routine. It was excessively checking to
* see if the current position is inside a comment or not. It is
* now a bit more efficient in dealing with strings and comments.
*
* Improved _FirstStmtLine(). Regular expression searches just
* would not hack it and I could not get Brief to handle looking
* for the last non-continuation line noway,nohow. Even something
* simple like:
* search_back( "[~\\\\]\n", -2 );
* would not work (even tried -1, -3, 1, 2, and 3!).
*
* 30-Nov-89 Bruce A. Mallett
* Added _GoToInclude() and modified _GoToThisTag() and _GoToTag()
* to support it. The user may now place the cursor on the file
* name of a #include directive and goto that include file. The
* user may also designate an include file by prefixing the tag
* name with a "#". If the tag name is prefixed with "#" and
* bracketed by "<>" (as in "#") then _GoToInclude()
* will search for the include file along the system include file
* paths.
*
* Two new configuration parameters are now required:
* CNF_INCLUDE_SYS designates the *environment* variable name
* from which a search path is obtained by
* Elec-c when searching for a system include
* file.
* CNF_INCLUDE_USR designates the *environment* variable name
* from which to get the search path used to
* locate non-system include files.
*
* Fixed bug in _StartComment that has been driving me NUTS! This
* routine was flushing-left an asterisk placed at a column (i.e.,
* there were no actual characters preceding this column). This
* would occur when, for example, I was typing in the revision history
* like I am now with the asterisk being placed in column 2.
*
* Fixed _ReformBlock() to not use more than one "%s" in the sprintf()
* which forms the dos() command. In fact I eliminated the sprintf()
* altogether!
*
* 12-Nov-89 Bruce A. Mallett
* Fixed bug in _InComment() routine in which it would declare that
* the current position was not inside a comment if a slash were
* found in it.
*
* Fixed bug in _StartComment() in which an extra space was being
* inserted after an asterisk typed in column 1
*
* 18-Sep-89 Bruce A. Mallett
* Created this file by canabalizing other elec-c files.
*
*/
#include "ascfind.h"
#include "config.h"
#include "elec-c.h"
#include "win_ctrl.h"


extern string search_path(string, string);


extern
_EditBoxComment, /* Edit a box comment */
_bbcm, /* What to execute when opening a box comment */
_box_edge_l, /* Characters for left edge of box comment */
_box_edge_le, /* Characters for left edge of box comment - escaped */
_box_edge_r, /* Characters for right edge of box comment */
_box_edge_re, /* Characters for right edge of box comment - escaped */
_box_rmargin, /* Right margin for box comments <- JSB */
_box_width_l, /* Left margin width of box comment */
_box_width_r, /* Right margin width of box comment */
_cbrace_cmnt_col, /* Closing brace comment columun */
_comment_col, /* Column to start comments in */
_comment_rmargin, /* Column to wrap comments at */
_ebcm, /* What to execute when closing a box comment */
_ec_new_flag, /* Non-zero to edit a new file */
_km_cmt, /* Local keymap when inside a comment */
_km_src, /* Local keymap for source files */
_file_drive, /* Drive letter of the file being edited */
_file_ext, /* Extension of the file being edited */
_file_name, /* Name of the file being edited */
_file_path, /* Path of the file being edited */
_m_delay, /* Delay for showing []{} and () matches */
_mac_cbrace, /* Prior Close Brace macro */
_mac_cbracket, /* Prior Close Bracket macro */
_mac_cparen, /* Prior Close paren macro */
_mac_obrace, /* Prior Open Brace macro */
_match_up, /* Determines what matching assistance is given */
_nc_start, /* Start of No Comment area */
_notice_delay, /* Determines how long notice is presented */
_tag_file, /* Names the tag file */
center_line; /* Center current line in window */

_init()
{
int
_appended_comment, /* Nz if comment appends something on a line */
_mktmpbuf_cnt, /* Counts # temp. buffers for _MkTmpBuf */
_rjustify_comments, /* Nz if comments are to be "right justified" */
_rmargin_bell, /* Distance to right margin before bell is gonged */
_wwleft, /* Left column wrap point */
_wwright; /* Right columb wrap point */


string
_ec_def_mouse, /* Default Mouse Handler */
_include_sys, /* For system include files */
_include_usr, /* For user include files */
_wwbreak; /* Holds name of the break macro */

global
_appended_comment, /* Nz if comment appends something on a line */
_ec_def_mouse, /* Default Mouse Handler */
_include_sys, /* For system include files */
_include_usr, /* For user include files */
_mktmpbuf_cnt, /* Counts # temp. buffers for _MkTmpBuf */
_rjustify_comments, /* Nz if comments are to be "right justified" */
_rmargin_bell, /* Distance to right margin before bell is gonged */
_wwleft, /* Left column wrap point */
_wwright, /* Right columb wrap point */
_wwbreak; /* Holds name of the break macro */


_mktmpbuf_cnt = 0; /* Req'd by _MkTmpBuf early on! */
_wwbreak = "nothing"; /* Assign to do-nothing macro */

autoload( "ascfind", "_AscendFind" );
autoload( "config", "config_end", "inq_config", "inq_config_int" );
autoload( "ec-tags", "_FindTag", "_NextField" );
autoload( "ec-tplat", "_FixupTemplate", "_GetTemplate", "_OpenTemplate" );

/************************************************************************\
* *
* Find out the names of the environment variables which contain the *
* search paths for system and user include files: *
* *
\************************************************************************/

_include_sys = inq_config( CNF_PACKAGE, CNF_INCLUDE_SYS );
_include_usr = inq_config( CNF_PACKAGE, CNF_INCLUDE_USR );

/************************************************************************\
* *
* Load up information from configuration file: *
* *
\************************************************************************/

_LoadConfigData();

/************************************************************************\
* *
* Make a local key map to be used whenever a comment has been *
* opened. This is just like the source local map except the *
* asterisk is assigned to self_insert and the division sign *
* is assigned to _EndComment. *
* *
\************************************************************************/

_km_cmt = _CreateLocalMap();

keyboard_push( _km_cmt ); /* Set this keyboard */
assign_to_key ("*", "self_insert"); /* Doctor it a bit */
assign_to_key ("/", "_EndComment"); /* Assigned to "/" */
keyboard_pop( 1 );

/************************************************************************\
* *
* Make a local key map to be used whenever a source file is *
* being edited: *
* *
\************************************************************************/

_ec_def_mouse = inq_mouse_action(); /* Save current mouse handler */
_km_src = _CreateLocalMap();
set_mouse_action( "_EcMouseHandler" );

config_end(); /* Done with configuration data */

} /* _init() */

/*******************************************************************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _EcMouseHandler( event, modifier, parm2, parm3 ) *
* *
* Description: This is the mouse handler for Elec-c. What is not processed *
* here gets passed off to the default mouse handler named by *
* "_ec_def_mouse". *
* *
* Parameters: event - The mouse event *
* modifier - Modifier keys *
* parm2 - Line or scroll bar code *
* parm3 - Column or thumb position *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 23-Jul-1991 Bruce A. Mallett *
* Created Module. *
* *
\*******************************************************************************************************************************/

void _EcMouseHandler( int event, int modifier, int parm2, int parm3 )

{
switch ( event )
{

case BTN1_DBLCLK:
_GoToThisTag();

default:
execute_macro( _ec_def_mouse, event, modifier, parm2, parm3 );

} /* switch() */

} /* _EcMouseHandler() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _EcNotice() *
* *
* Description: This routine presents the copyright and startup notice. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 28-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _EcNotice()

{
int
c_bid,
n_bid;
string
lbuf;

n_bid = create_buffer( "Notice", NULL, 1 );
c_bid = inq_buffer();
set_buffer( n_bid );

create_window( 17, 17, 61, 9, "Elec-c" );
attach_buffer( n_bid );

move_abs( 1, 1 );

sprintf(lbuf, "Elec-c %s", ELEC_C_VERSION);
insert( "\n" );
_InsertCentered( lbuf );

insert( "\n\n" );
_InsertCentered( "Copyright (C) 1987-1990 Bruce A. Mallett" );

insert( "\n\n" );
_InsertCentered( "All rights reserved" );

refresh();

set_buffer(c_bid);

c_bid = _notice_delay; /* Reuse this variable for a delay loop */

while (c_bid)
{
_MatchDelay();
--c_bid;
}

delete_window();
delete_buffer(n_bid);

} /* _EcNotice() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _InsertCentered( line ) *
* *
* Description: This routine will insert the passed string (no imbedded *
* newlines please) into the current buffer centered in the *
* attached window. A newline is appended to the string. *
* *
* Parameters: line - String (sans newline characters) to be inserted *
* and centered *
* *
* Returns: Nothing *
* *
* Notes: No attention is paid to whether or not the window is *
* horizontally scrolled. *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 14-Apr-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _InsertCentered( string line )

{
int cols; /* Number of columns in window */
int lno; /* Where we are now */

inq_position( lno ); /* Save line we are on */
inq_window_size( NULL, cols ); /* Get # columns in window */

if ( (cols-=strlen(line)) < 1 )
cols = 1; /* Force to move to column 1 */

insert( "\n" ); /* Open up a new line */
move_abs( lno, (cols+1)/2 ); /* Where to insert */
insert( line ); /* Insert the line! */

} /* _InsertCentered() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _ec_first() *
* *
* Description: This macro is called by the languages package the first time *
* a file is edited. *
* *
* Parameters: None *
* *
* Returns: (string) "" - Must be a place-holder for *
* something better! *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 27-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

string _ec_first()
{
/************************************************************************\
* *
* Assign a key map to use with this buffer: *
* *
\************************************************************************/

use_local_keyboard(_km_src);

return ( "" );

} /* _ec_first() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _ec_off() *
* *
* Description: This macro is called by the languages package to turn off *
* elec-c mode. It is called whenever we are leaving a buffer *
* controlled by elec-c. *
* *
* Parameters: None *
* *
* Returns: (string) "" - Must be a place-holder for *
* something better! *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 27-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

string _ec_off()
{
return ( "" );

} /* _ec_off() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _ec_on() *
* *
* Description: This routine is called by the languages package whenever the *
* user switches to a buffer containing a file to be processed *
* by elec-c. It will setup relevent data including internal *
* switches and the like. *
* *
* Parameters: None *
* *
* Returns: (string) The name of the macro to be called when the *
* user switches out of this file extention *
* type. *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.1 15-Jun-1990 Bruce A. Mallett *
* In response to a bug reported by Charles Fleisher I added a check *
* with _ec_new_flag to see if the buffer is empty or not. See the *
* new documentation which heads this section for further explaination. *
* *
* 0.0 27-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

string _ec_on()

{
int
c_bid; /* Current buffer Id. */

string
ifile, /* Name of initial file */
ipath, /* Path to initial file */
path; /* Of where we are now */

_SetupFileData(); /* Initialize file data */

/************************************************************************\
* *
* Test to see if Brief is in a stable state or not. If not then we *
* cannot display the startup banner. *
* *
\************************************************************************/

if ( first_time() )
{
if ( inq_window() & 0xffff )
_EcNotice(); /* Display elec-c banner */
}

/************************************************************************\
* *
* Set the No Comment Start line number. This value is set when *
* it is known that the text from _nc_start to the current position *
* is not in a comment. Only the line number is saved in _nc_start *
* (not the column) so as to avoid having to do double compares. *
* *
\************************************************************************/

_nc_start = -1; /* Set to max. unsigned integer */

/************************************************************************\
* *
* Initially there are not beginning or ending box comment macros: *
* *
\************************************************************************/

_bbcm = "";
_ebcm = "";

/************************************************************************\
* *
* See if this is a new file being edited or not. If so then setup *
* the file (after asking for permission). Note that this action was *
* deferred to this routine (rather than being done in "_ec_new") *
* because it is necessary to ensure that all other "*_first" routines *
* were executed first. This is required because we build upon the *
* keyboard template established by these other routines. *
* *
* Note: *
* Just because _ec_new_flag is set does not mean that we are about *
* to edit a new file. One of the other *_first routines (such as *
* _pvcs_first) may have created the file on-the-sly. So another *
* check is made to see if there is anything in the buffer (we get *
* positioned to the top of the buffer for the new file). *
* *
\************************************************************************/

if ( _ec_new_flag && next_char() )
{
prev_char(); /* Restore position */

/********************************************************************\
* *
* Now for the new file specific stuff. *
* *
\********************************************************************/

ifile = "." + _file_ext + " " + CNF_INITIAL_FILE;

ifile = inq_config( CNF_PACKAGE, ifile ); /* Get initial file name */

if (ifile != "")
{
while (path != "y" && path != "n")
{
beep();
get_parm(0, path, "Initialize file (y,n) ?");
path = lower(path);
}

if (path == "y")
{
getwd(NULL, path); /* Get where we are now */
ipath = _AscendFind(path, ifile, inq_environment(ELEC_C_DIR));

if (ipath != "")
{
if (read_file(ipath) > 0)
{
/****************************************************\
* *
* Somewhere in this process (specifically in the *
* routine "_EditBoxComment()" called from *
* "_FixupTemplate()") we can end up unattached to *
* our buffer. *
* *
* So ... *
* we must save the current buffer Id. and reattach *
* it when done. *
* *
\****************************************************/

c_bid = inq_buffer();

_FixupTemplate(); /* If found then fix it up */
move_abs(1, 1); /* Reset position */
_NextField(); /* Position to first template field. */

_SwitchToBuffer(c_bid); /* Attach back to our buffer */
}
}
}
}

} /* if() */

_ec_new_flag = 0; /* Ensure that this is off! */

return ( "_ec_off" ); /* Specify macro to turn off elec-c */

} /* _ec_on() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _CreateLocalMap() *
* *
* Description: This routine will create a local keyboard map and set it up *
* with the defaults required by the elec-c package. The new *
* keyboard map identifier is returned. *
* *
* Parameters: None *
* *
* Returns: (int) Key map identifier of the new keyboard map *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 28-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _CreateLocalMap()

{
int kmap_new; /* Id of the new keyboard */
int kmap_old; /* Id of the old keyboard */

/************************************************************************\
* *
* Setup key assignments. To do this we will first create a local key *
* map: *
* *
\************************************************************************/

kmap_old = inq_local_keyboard(); /* Get original keyboard identifier */
kmap_new = copy_keyboard(kmap_old); /* Create a new keyboard */

/************************************************************************\
* *
* Before making our own key assignments save some of the crucial ones in *
* global string variables. This will allow the individual key handlers *
* to call these if they so desire. *
* *
\************************************************************************/

if ( first_time() )
{
_mac_cbrace = inq_assignment( "<}>" );
_mac_cbracket = inq_assignment( "<}>" );
_mac_cparen = inq_assignment( "<}>" );
_mac_obrace = inq_assignment( "<{>" );
}

assign_to_key("<*>", "_StartComment");
assign_to_key("", "_GoToThisTag");
assign_to_key("", ".c_next_word");
assign_to_key("", ".c_previous_word");
assign_to_key("", "EcSet");

/************************************************************************\
* *
* Assignments to the closing characters of matched sets are only done if *
* they are specified in the _match_up global (read from the config file):*
* *
\************************************************************************/

if ( index(_match_up, "()") )
assign_to_key( "<)>", "_CloseParen" );

if ( index(_match_up, "[]") )
assign_to_key( "<]>", "_CloseBracket" );

if ( index(_match_up, "{}") )
assign_to_key( "<}>", "_CloseBrace" );

keyboard_pop( 1 ); /* Save the new keyboard */

return ( kmap_new );

} /* _CreateLocalMap() */

/* */
/* Call */
/* (_EscStr str) */
/* */
/* Parameters */
/* */
/* str - String to be escaped. This routine will escape all of */
/* the special Brief regular expression characters and */
/* return the result. */
/* */
/* Returns */
/* Escaped version of str */
/* */
/* Description */
/* This routine will prepend a "\" to any occurance of a Brief regular */
/* expression character found in the passed string and return the string */
/* result. */
/* */
/* */
_EscStr (...)
{
int
i, /* HDV */
j, /* Another */
len; /* Length of str */

string
ch, /* Holds a single character from str */
result, /* The result (how 'bout that!). */
str; /* String to be escaped */

get_parm (0, str); /* Get string to escape */
len = strlen (str); /* Capture its length */

i = 0; /* Start here */

while (i < len)
{
++i; /* Bump to next character slot */
ch = substr (str, i, 1); /* Get the next character */

if (search_string (ch, "?*\\<>%$@+|{}[]", j, NOT_RE))
result += "\\";

result += ch; /* Add the character */
}

return result;
}

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _LoadConfigData() *
* *
* Description: This macro centralizes the loading/inquirying of *
* configuration data. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 02-Mar-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _LoadConfigData()

{
_cbrace_cmnt_col = inq_config_int( CNF_PACKAGE, CNF_CBRACE_CMNT_COL, 0 );
_comment_col = inq_config_int(CNF_PACKAGE, CNF_COMMENT_COL, COMMENT_COL);
_comment_rmargin = inq_config_int(CNF_PACKAGE, CNF_COMMENT_RMARGIN, COMMENT_RMARGIN);
_m_delay = inq_config_int(CNF_PACKAGE, CNF_MATCH_DELAY, M_DELAY);

_box_edge_l = inq_config(CNF_PACKAGE, CNF_BOX_EDGE_LEFT, BOX_EDGE_LEFT);
_box_edge_r = inq_config(CNF_PACKAGE, CNF_BOX_EDGE_RIGHT, BOX_EDGE_RIGHT);

_box_edge_le = _EscStr(_box_edge_l);
_box_edge_re = _EscStr(_box_edge_r);

_box_width_l = strlen(_box_edge_l) + 1;
_box_width_r = strlen(_box_edge_r) + 1;

_notice_delay = inq_config_int(CNF_PACKAGE, CNF_NOTICE_DELAY, NOTICE_DELAY);

_tag_file = inq_config(CNF_PACKAGE, CNF_TAG_FILE, TAG_FILE);

_match_up = inq_config(CNF_PACKAGE, CNF_MATCH_UP, MATCH_UP);

/* Added by John Booth to load the box comment right margin value. JSB */

_box_rmargin = inq_config_int( CNF_PACKAGE, CNF_BOX_RMARGIN, BOX_RMARGIN );

_rmargin_bell = inq_config_int( CNF_PACKAGE, CNF_RMARGIN_BELL, RMARGIN_BELL );

_rjustify_comments = lower( substr(inq_config(CNF_PACKAGE, CNF_RJUSTIFY_COMMENTS, "no" ), 1, 1) ) == "y";

config_end();

} /* _LoadConfigData() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _MatchDelay() *
* *
* Description: This routine is called to pause long enough to show a match *
* to the user. It aborts as soon as a keystrike has occured. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 28-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _MatchDelay()
{
int
i; /* A delay counter */

refresh(); /* Refresh the display */
i = _m_delay; /* Delay counter */

while ( !inq_kbd_char() && --i ); /* Delay a mite */

} /* _MatchDelay() */

/* */
/* */
/* Call */
/* (_MkTmpBuf bname sys) */
/* */
/* Parameters */
/* */
/* bname - Buffer name. Three digits will be appended to ensure */
/* that the name is unique */
/* sys - Nonzero for system buffer, zero for non-system buffer. */
/* */
/* Returns */
/* Buffer identifier of the new buffer */
/* */
/* This macro centralizes the creation of temporary buffers and ensures */
/* that they are assigned names which do not conflict. Note that it is */
/* possible to have a buffer-rollover situation, but this would require */
/* 1000 calls to this routine without intervening delete buffer calls! */
/* */
/* */

int _MkTmpBuf(...)
{
int
sys; /* System or non-system buffer */

string
bname, /* Holds passed buffer name */
fname; /* Holds generated file name */

if (get_parm (0, bname) <= 0) /* If no name passed */
bname = "_elec-c_"; /* Make one up */

if (get_parm (1, sys) <= 0) /* If system designator not passed */
sys = SYSTEM; /* Assume system buffer */

sprintf (fname, "%s.%03d", bname, _mktmpbuf_cnt);
++_mktmpbuf_cnt; /* Bump for next time! */

return create_buffer (bname, fname, sys); /* Thats all folks! */
}

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _comment() *
* *
* Description: This macro is invoked when a standard comment is being *
* entered. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.1 22-Jul-1991 Bruce A. Mallett *
* Reformatted module (and header) *
* *
* 0.0 ??-???-???? Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _comment()
{
int cur_col, /* Current column number. */
end_col; /* End of line column number. */

message("Comment open");

use_local_keyboard(_km_cmt); /* Use comment keymap. */
inq_position(NULL, cur_col); /* Get where we are at now. */

end_of_line(); /* Go to the end of the line. */
search_back("[~ \n\t]\\c"); /* Eliminate trailing blanks and
* tabs. */
delete_to_eol();

inq_position(NULL, end_col); /* Get end column number. */
move_abs(0, cur_col); /* Restore our position. */

if (cur_col >= end_col) /* If at end of the line */
{
move_rel(0, -3); /* Backup a bit */
delete_to_eol(); /* Kill start of comment. */
inq_position(NULL, cur_col); /* Update current column number. */

/********************************************************************\
* *
* Now see if there are any characters preceding the cursor on the *
* line. If there are then the comment is moved over to the comment *
* column. If there are not then the comment will begin at the *
* cursor location. *
* *
\********************************************************************/

beginning_of_line(); /* Go to start of the line. */

/********************************************************************\
* *
* Note that the following search will find the new line at the *
* end of the string if there were nothing but tabs and/or spaces *
* preceding the cursor: *
* *
\********************************************************************/

search_fwd("[~ \t]"); /* Search for something. */
inq_position(NULL, end_col); /* Find out where we ended up. */
end_of_line();
_appended_comment = (end_col != cur_col);

if ( _appended_comment ) /* If other than just blanks and tabs on line */
{
search_back("[~ \n\t]\\c");
delete_to_eol(); /* Eliminate trailing blanks and tabs */
inq_position(NULL, cur_col);

if (cur_col < _comment_col)
move_abs(0, _comment_col); /* Get to the comment column. */
}

inq_position(NULL, cur_col); /* Update cur_col, again. */
insert("/* "); /* Start her up there! */

_StartWordWrap(cur_col, _comment_rmargin, "_CommentBreak");
}

} /* _comment() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: StartComment() *
* *
* Description: This routine is invoked when the user has typed the "*" key. *
* It will test to see if the preceding character is a slash *
* ("/"), in which case it will open a new comment or a box *
* comment. If the current position is in a box comment then *
* it is opened to allow editing, otherwise a new comment is *
* opened. *
* *
* If the next character is another asterisk then a new box *
* comment is created. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.1 23-Oct-1990 Bruce A. Mallett *
* Rewrote to eliminate _InBox() call and thereby eliminate a redundant *
* call to _InCommentOrString(). *
* *
* 0.0 ??-???-19?? Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _StartComment()
{
int bcol; /* Beginning column of comment */
int bline; /* Beginning line of comment */
int chr; /* Scratch character */
int ecol; /* Ending column of comment */
int eline; /* Ending line of comment */
int inflag; /* Non-zero if in string or comment */

/************************************************************************\
* *
* First check to see if we are in a comment or a string. If we are in a *
* string then there is nothing special to do: insert the asterisk and *
* exit! If we are in a comment then the position is saved so that we *
* can see if we are in a box comment or not (later). *
* *
\************************************************************************/

_nc_start = -1; /* Invalidate this */

if ( ((inflag=_InCommentOrString(bline, bcol)) == 2) || !left() )
{
self_insert(); /* Insert the "*" */
return;
}

/************************************************************************\
* *
* Here having moved to the left one character. Get that character and *
* check if it is a slash or not. If not then we are not opening a *
* comment and so the asterisk must be inserted. *
* *
\************************************************************************/

if ( read(1) != "/" )
{
right(); /* Undo the left() */
self_insert(); /* Insert the "*" */
return;
}

/************************************************************************\
* *
* Here if an opening comment pair is present. Now to see if we are in *
* a box comment or not, if we are then open the thing up, otherwise *

* prepare to insert a comment. *
* *
\************************************************************************/

if ( inflag ) /* If in a comment */
{
save_position(); /* Prepare to go to start of comment */
move_abs( bline, bcol ); /* Go there */

if ( read(3) == "/**" ) /* Open box comment? */
{
/****************************************************************\
* *
* It is beginning to look like we are in a box comment. If we *
* can find the end of it then that will cinch it. If not then *
* just assume that we are in a standard comment. *
* *
\****************************************************************/

if ( search_fwd("**/",NOT_RE) )
{
move_rel( 0, 3 );
inq_position( eline, ecol );
restore_position();
delete_char(); /* Delete the slash */
_EditBoxComment( bline, bcol, eline, ecol );

return;
}
}

/********************************************************************\
* *
* Here if we are not in a box comment, so we must be in a normal *
* comment. In this case just insert the asterisk: *
* *
\********************************************************************/

restore_position(); /* Restore where we were */
right(); /* Undo the left() done earlier */
self_insert(); /* Insert the asterisk */

return;
}

/************************************************************************\
* *
* Ok! Here we know that a comment is being opened. So lets insert the *
* asterisk followed by a space and then wait to see what the next thing *
* that the user types is. If it is another asterisk then a box comment *
* is to be created. *
* *
\************************************************************************/

inq_position( NULL, bcol ); /* In case we open a box comment */

right(); /* Undo the left() done earlier */
self_insert(); /* Insert the asterisk */
insert(" "); /* Supply the space after comment. */
refresh(); /* Show it. */

chr = _getchar(); /* Get next char. from keyboard */

if ( (chr & 0xff) == ASTERISK ) /* Do block comment? */
{
/********************************************************************\
* *
* Message added to help for borders 0 option -CHF *
* *
\********************************************************************/

message("Block comment opened: use */ to terminate");

drop_anchor(); /* Delete to beginning of line */
beginning_of_line();
delete_block();
_EditBoxComment( bcol ); /* Get the thing */
}

else
{
/********************************************************************\
* *
* Not a block comment, so the character fetched is valuable and must *
* be shoved back into the input stream and then a comment started: *
* *
\********************************************************************/

push_back( chr ); /* Nope, put the character back! */
_comment(); /* Do the comment thing. */
}

} /* _StartComment() */

/****************************************************************************\
* *
* <^r^>*
* Name: RtJustifyComment() *
* *
* Description: Right justify the closing of a comment to align columns *
* *
* Input: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* *
* Vers Date Author Changes *
* ---- ---- ------ ------- *
* 0.0 09-Jul-1990 John Booth Created Module. *
* *
\****************************************************************************/

_RtJustifyComment(...)
{
int cur_col; /* Current column # */

inq_position (NULL, cur_col); /* Get where we are at now. */
if (cur_col > _comment_col) /* If we set the left margin automatically.. */
{
if (cur_col < _comment_rmargin) /* If we are short of the right margin, move there */
move_abs(0,_comment_rmargin);
} /* if() */

} /* _RtJustifyComment() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _EndComment() *
* *
* Description: This macro is called when the user types a '/' key when a *
* standard comment is being entered. It will determine *
* whether or not the comment is being closed by checking if *
* the previous character is an asterisk ("*"). If so then *
* the closing "*" & "/" is moved down to the next line and *
* aligned with the preceding line's asterisk, which is *
* assumed to be at _wwleft + 1. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 1.0 09-Jul-1990 John S. Booth, Jr. *
* Added right justification of single line comment close *
* *
* 0.0 09-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

_EndComment(...)
{
int c_line, /* Line # comment starts on. */
c_col, /* Column # comment starts in. */
cur_line; /* Current line cursor is on. */

string ch; /* A character */

_nc_start = -1; /* Set to max. unsigned integer */

save_position(); /* ch = the previous character */
prev_char();
ch = read(1);
restore_position(1);

if ("*" == ch) /* Ending the comment? */
{
_EndWordWrap(); /* Turn of word wrapping. */

use_local_keyboard(_km_src); /* Change back to source keymap */

if (_InComment(c_line, c_col)) /* If we are in a comment ... */
{
prev_char(); /* Delete previous asterisk. */
delete_char();

inq_position(cur_line); /* Find out what line we are on. */

if (c_line == cur_line) /* If closing on same line ... */
{
if ( _appended_comment && _rjustify_comments )
_RtJustifyComment();/* Right justify the comment border to make it purty! - JSB */

insert(" */"); /* Then close it here! */
}

else
{
insert("\n"); /* Stick in a new line. */
move_abs(0, _wwleft + 1); /* Go to where the "*" & "/" should be put. */
insert("*/\n"); /* Close the comment. */
}

message("Comment closed");
}

else /* If we are not in a comment */
{
self_insert();
beep(); /* Warn the user! */
message("Comment cancelled!");
}
}

else /* We are not ending the comment */
self_insert();

} /* _EndComment() */

/* */
/* Call */
/* (_SlideLineIn col) */
/* */
/* Parameters */
/* col - Column to slide to. */
/* */
/* Returns */
/* Nothing */
/* */
/* If the current position upon entry is less than or equal to */
/* the passed column number then upon exit it is set to the */
/* passed column number, otherwise it is unchanged. */
/* */
/* Description */
/* This macro will insert sufficient tabs and spaces to slide */
/* the current position out to the passed column. If the current */
/* position is already at or beyond the passed column then no action */
/* is taken. */
/* */
/* */
_SlideLineIn (...)
{
int col, /* Column to slide out to. */
cur_col, /* Where we are now. */
cur_lin; /* */

get_parm (0, col, "slide to?"); /* Get column to go to. */
inq_position (cur_lin, cur_col); /* Where are we now? */

if (cur_col < col) /* Off to it! */
{
insert ("\n");
move_abs (cur_lin, col); /* Get to where we want to be. */
delete_char (); /* Delete the new line character. */
}
}

/* */
/* Call */
/* (_SlideBlockIn bline eline col leader) */
/* */
/* Parameters */
/* bline - Beginning line number */
/* eline - Ending line number */
/* col - Column to slide out to. */
/* leader - Leader string (optional) */
/* */
/* Returns */
/* Nothing */
/* */
/* Description */
/* This is a specialized macro which will optionally insert a */
/* leader string in front of each line and then slide each over to */
/* begin at a specified column. Used primarily by the _boxit macro. */
/* */
/* */
_SlideBlockIn (...)
{
int
bline, /* Beginning line number */
col, /* Column to slide out to */
eline; /* Ending line number */

string
leader; /* Stuff which slided blocks are made of */

get_parm (0, bline); /* Get passed values */
get_parm (1, eline); /* */
get_parm (2, col); /* */
if (!get_parm (3, leader))
leader = "";

move_abs (bline, 1); /* Go to first line in the block */
insert ("\n"); /* Open up a line */
move_abs (bline, col); /* Go to where we want to be. */
insert (leader + "x"); /* Force insert of spaces &| tabs */
beginning_of_line (); /* Go to start of the line */

leader = read (); /* Read & strip trailing new-line */
leader = substr (leader, 1, strlen (leader) - 2);
delete_line (); /* Delete the extra line */

while (bline <= eline)
{
move_abs (bline, 1); /* Go to first column of desired line */
insert (leader); /* Slide the line over */
++bline; /* Advance to next line */
}
}

/* */
/* Call */
/* (_InComment LINE, COLUMN) */
/* */
/* Parameters */
/* LINE Returned with the line number where the current */
/* comment begins. Returned with the current position */
/* if it is not within a comment. */
/* COLUMN Returned with the column number where the current */
/* comment begins. Returned with the current position */
/* if it is not within a comment. */
/* */
/* Returns */
/* 0 - If the current position is not within comment. */
/* 1 - If the current position is within a comment. */
/* */
/* Description */
/* This macro will examine the text which precedes the current */
/* position to determine if it lies within what the C language regards */
/* as a comment. If so then this macro returns a value of 1 and */
/* the passed parameters are updated to show the position at which the */
/* comment begins (the position is that of the opening slash). */
/* If not then the passed parameters are set to the current position */
/* and this macro returns a value of zero. */
/* */
/* The current position is maintained across the call. */
/* */
/* */
int _InComment(...)
{
int line, /* Saves line number */
col, /* Saves column number */

retval; /* Return value */

inq_position(line, col); /* Save where we are at */
retval = 0; /* Default to not in a comment */

/************************************************************************\
* *
* Figure out if we already know that we are not in a comment. *
* If so then don't waste time checking it again! *
* *
\************************************************************************/

if (below_eq(line, _nc_start))
{
save_position();

while (prev_char()) /* prev_char to make search right */
{
if ( search_back("\\c{/\\*}|{\\*/}", RE_SD_MIN) > 0 )
{
if ("/" == read(1)) /* In a comment! */
{
if ( ! _InString(line, col) )
{
retval = 1; /* Show that we are in a comment */
_nc_start = -1; /* Set to max. unsigned integer */
inq_position(line, col); /* Set for beg. of comment */
break;
}

move_abs( line, col );/* Move to start of string */
continue;
}

/************************************************************\
* *
* Here for end of comment: *
* *
\************************************************************/

inq_position( _nc_start );
break;
}

/****************************************************************\
* *
* No comment back to beg. of buffer, so set _nc_start to zero *
* and exit: *
* *
\****************************************************************/

_nc_start = 0;
break;
}

restore_position(); /* Restore entry position */
}

/************************************************************************\
* *
* Here when done. Set the returned values and restore the entry *
* position: *
* *
\************************************************************************/

put_parm(0, line); /* Set the returned position */
put_parm(1, col);

return retval;

} /* _InComment() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _InCommentOrString( ... ) *
* *
* Description: This routine determines if the current position is inside a *
* comment or a string. The returned value indicates which, if *
* any we are in. The optional parameters are set to the line *
* and column number of where the culprit starts (the opening *
* character of the comment or string that is). *
* *
* Parameters: line - Returned with starting line number *
* col - Returned with starting column number *
* *
* Returns: (int) 0 If the current position is neither in a *
* comment or a string *
* *
* 1 If the current position is in a comment *
* *
* 2 If the current position is in a string *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.1 23-Oct-1990 Bruce A. Mallett *
* Revised module header & cleaned up the appearance of the source *
* code. *
* *
* 0.0 ??-???-19?? Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _InCommentOrString(...)
{
int col; /* Beginning column number */
int line; /* Beginning line number */

if ( _InComment(line,col) ) /* If in a comment */
{
put_parm( 0, line ); /* Return starting position */
put_parm( 1, col );
return ( 1 ); /* Show in a comment */
}

if ( _InString(line,col) ) /* If in a string */
{
put_parm( 0, line ); /* Return starting position */
put_parm( 1, col );
return ( 2 ); /* Show in a string */
}

} /* _InCommentOrString() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _InString( line, column ) *
* *
* Description: This macro will examine the text which precedes the current *
* position to determine if it lies within what the C language *
* regards as a quoted string. If so then this macro returns *
* a value of 1 and the passed parameters are updated to show *
* the position at which the string begins (the position is *
* that of the single or double quote). If not then the passed *
* parameters are set to the current position and this macro *
* returns a value of zero. *
* *
* Parameters: line - Returned with the line number where the *
* current quote begins. Returned with the *
* current position if it is not within a quote. *
* column - Returned with the column number where the *
* current quote begins. Returned with the *
* current position if it is not within a quote. *
* *
* *
* Returns: (int) 0 If the current position is not within a *
* string literal. *
* 1 If the current position is within a *
* string literal. *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 05-Dec-1989 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _InString(...)
{
int
l, /* Scratch line # */
c, /* Scratch column # */
lin, /* Holds beginning line # of range. */
col, /* beginning column # of range. */
inside; /* Inside a string flag. */


inq_position(lin, col); /* Default these values. */
put_parm(0, lin);
put_parm(1, col);

save_position(); /* Save the entry position. */
inside = 0; /* Assume not inside a string. */

/************************************************************************\
* *
* A bug in Brief's bounded search exists in which the marked area must *
* be at least one character beyond the last occurance of what we are *
* looking for. The only way that this can be guaranteed is to insert *
* something other than what is desired. So here goes (it gets deleted *
* later)! *
* *
\************************************************************************/

insert( " " );
drop_anchor(4); /* For bounded searching. */
left(); /* Skip back over insertion */

/************************************************************************\
* *
* Scan backward through the current buffer and find the first *
* line which is not a continuation line. *
* *
* Note: *
* You might think that this could be done using a regular *
* expression search. I tried. And tried. And TRIED! However *
* there are some strange boundary conditions in Brief that make *
* this absolutely unreliable! *
* *
\************************************************************************/

for ( ;; )
{
beginning_of_line(); /* Ready to move to last char. */

if ( !prev_char(2) ) /* If cannot then we are done */
break;

if ( read(1) != "\\" ) /* Continuation line? */
{
next_char(2); /* Nope, we are done */
break;
}

} /* for() */

/************************************************************************\
* *
* The following loop will search for all occurances of the string *
* delimiter character between the opening of the string and the *
* position of the cursor saved at entry to this macro. *
* *
\************************************************************************/

while ( search_fwd("\"", NOT_RE, CASE_SENSITIVE, SEARCH_BLOCK) > 0 )
{
if ( !inside && _InComment(l,c) ) /* Find end of comment */
{
if ( search_fwd("*/\\c", NOT_RE, CASE_SENSITIVE, SEARCH_BLOCK) <= 0 )
break;
}

else
{
if ( left() )
{
if ( read(1) == "\\" ) /* Not start or end of a string */
{
right(); /* Restore position */
right(); /* Skip past double quote */
continue;
}

right(); /* Restore position */
}

inside = !inside; /* Toggle inside string flag */

if ( inside ) /* If inside a string */
{
inq_position(lin, col); /* Get our position in the buffer. */
_nc_start = -1; /* Invalidate this for next time */
}

right(); /* Skip past double quote */
}
}

raise_anchor(); /* Unmark the search area. */
restore_position(1); /* Go back to where we were. */
delete_char(); /* Delete the inserted space */

if ( inside ) /* Show where string starts (if in one) */
{
put_parm(0, lin);
put_parm(1, col);
}

return ( inside ); /* Return the inside/outside flag. */

} /* _InString() */

/* */
/* */
/* Call */
/* (_getchar) */
/* */
/* Parameters */
/* None */
/* */
/* Returns */
/* int as returned from "read_char" macro. */
/* */
/* Description */
/* This routine will wait for the user to type a character on */
/* the keyboard and will return that character to the caller. */
/* */
/* */
_getchar (...)
{
int kbd_chr; /* Keyboard character typed. */

while (-1 == (kbd_chr = read_char ()))
;
returns kbd_chr;
}

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _SwitchToBuffer( new_bid ) *
* *
* Description: This routine will set the current buffer to the buffer Id. *
* passed and attach it to the current window. The Id. of the *
* buffer which was switched from is returned. *
* *
* Parameters: new_bid - New buffer Id. to switch to *
* *
* Returns: (int) Old buffer Id. (switched from) *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 28-Feb-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _SwitchToBuffer( int new_bid )

{
int cur_bid; /* Current buffer id */

cur_bid = set_buffer( new_bid ); /* Setup for the new buffer. */
attach_buffer( new_bid ); /* All set! */

return ( cur_bid ); /* Return old buffer Id. */

} /* _SwitchToBuffer() */

/* */
/* */
/* Call */
/* (_CommentBreak) */
/* */
/* Parameters */
/* None */
/* */
/* Returns */
/* Nothing */
/* */
/* Description */
/* This macro is called by the word wrap package during the */
/* insertion of a comment whenever it has done a line break inorder */
/* to wrap a word to the next line. This macro will insert a space */
/* followed by an asterisk followed by a space. */
/* */
/* */
_CommentBreak (...)
{
move_abs (0, _wwleft); /* Go to proper column. */
insert (" * "); /* Do our deed. */
end_of_line (); /* Position for more input. */
}

/* */
/* */
/* WordWrap: */
/* */
/* 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. Note that the */
/* macro named by "_wwbreak" is called AFTER the break processing has */
/* been performed. This means that the work will have been wrapped to */
/* the next line when the macro is called. */
/* */
/* Automatic invocation is specified in the "_StartWordWrap" */
/* macro below, by calling the "register_macro" function. */
/* */
/* 10-Jul-1990 John S. Booth, Jr. */
/* Added "typewriter bell" function when the wordwrap point is near */
/* */

_WordWrap (...)
{
int col;

inq_position (NULL, col);

if ( col > _wwright-_rmargin_bell ) /* Warn user we are nearing wrap - JSB */
beep();

if (col > _wwright)
{
prev_char ();

if (!index (" \t", read (1)))
{
int new_col;

search_back ("<|[ \\t][~ \\t]");
inq_position (NULL, new_col);

if (new_col == 1)
end_of_line ();
insert ("\n");

if (new_col != 1)
{
delete_char ();
_SlideLineIn (_wwleft);
move_rel (0, (col - new_col) - 1);
}
else
_SlideLineIn (_wwleft);

execute_macro (_wwbreak); /* Do the line break macro now. */
}
else
next_char ();
}
}

/* */
/* Call */
/* (_StartWordWrap _wwleft _wwright _wwbreak) */
/* */
/* Parameters */
/* _wwleft Left column limit to which words are to be */
/* wrapped. */
/* _wwright Right column limit which if exceeded by a */
/* word then that word gets wrapped to left_col. */
/* _wwbreak The name of a macro to call whenever the word */
/* wrap system performs a line break. */
/* */
/* Returns */
/* Nothing */
/* */
/* Description */
/* This macro will start a word wrap sequence. Any word which goes */
/* beyond the right column limit will be wrapped such that it begins */
/* at the indicated left column. */
/* */
/* */
_StartWordWrap (...)
{
get_parm (0, _wwleft);
get_parm (1, _wwright);

if (get_parm (2, _wwbreak) == 0) /* If parameter not supplied. */
_wwbreak = "nothing";

register_macro (ADD_CHAR_MACRO, "_WordWrap");
}

/* */
/* _EndWordWrap: */
/* */
/* This macro will terminate the word wrap function. */
/* */

_EndWordWrap (...)
{
unregister_macro (ADD_CHAR_MACRO, "_WordWrap");
}

/* */
/* Call */
/* (_ClearBuffer) */
/* */
/* Parameters */
/* -None- */
/* */
/* Returns */
/* -Nothing- */
/* */
/* Description */
/* This macro clears the current buffer. */
/* */
/* */
_ClearBuffer (...)
{
move_abs (1, 1); /* Clear the thing. */
drop_anchor (); /* */
end_of_buffer (); /* */
delete_block (); /* */
}

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _FindMatch( l_open, c_open, opn, chk ) *
* *
* Description: This routine centralizes the function of searching for a *
* matching opening parenthasis, square bracket, or brace. The *
* opening character sought is passed. If found then the *
* cursor is left on the matching character and a value of zero *
* is returned. *
* *
* Parameters: opn - Opening character to look for (passed as an *
* integer). *
* chk - Level of checking to be done while looking for *
* the opening character. If zero then no string *
* or comment checking is done (hence the search *
* is faster). If non-zero then full string and *
* comment checking are performed. *
* *
* Returns: (int) 0 If a proper match for open was found. *
* nz If a match could not be found. The return *
* value is the character code which is *
* missing. *
* *
* Notes: The cursor is left before the matching character if found or *
* before the last matching character (in a search nest) if the *
* match was not found. *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 <> Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _FindMatch( int opn, int chk )
{
string ch; /* Holds a character. */
int col; /* Holds a column number */
int line; /* Holds a line number */
int missing; /* Result from recursive call */
string opn_str; /* Holds opening character desired. */

sprintf(opn_str, "%c", opn); /* Make it into a string */

for ( ;; ) /* Loop looking for opening whatever */
{
if (prev_char() && search_back("[()\\[\\]{}]") > 0) /* If found */
{
/****************************************************************\
* *
* If we stopped inside a comment or a string then skip out of *
* it: *
* *
\****************************************************************/

if ( chk ) /* If doing string & comment checking */
{
if ( _InCommentOrString(line, col) )
{
move_abs( line, col );
continue;
}
}

ch = read( 1 ); /* Get what we found. */

switch ( ch )
{

case opn_str:
return 0; /* We are done! */

case "[":
return ']'; /* Missing closing bracket! */

case "]":
if ( missing = _FindMatch('[', chk) )
return '['; /* If no match. */

case "(":
return ')'; /* Missing closing parenthasis! */

case ")":
if ( missing = _FindMatch('(', chk) )
return '('; /* If no match. */

case "{":
return opn; /* Missing whatever we are looking
* for! */

case "}":
if (opn != '{') /* "}" not allowed in "[]" or "()" */
return opn;
else
if ( missing = _FindMatch('{', chk) )
return missing;

default:
return opn; /* Problem! */

}
}

else
return opn;
}

return opn;

} /* _FindMatch() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _CloseParen() *
* *
* Description: This macro is bound to the closing parenthasis key. It will *
* insert the closing parenthasis and call _FindMatch "(" to *
* check the nesting. The opening parenthasis will be shown to *
* the user. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 06-Mar-1990 Bruce A. Mallett *
* Changed module header. I do not know when this routine was *
* originally created. *
* *
\****************************************************************************/

void _CloseParen()

{
self_insert(); /* Insert the closing parenthasis. */
save_position(); /* Save where we are. */
prev_char(); /* Backup one. */
_nc_start = -1; /* Set to max. unsigned integer */

if ( !_InCommentOrString() )
_ShowMissing( _FindMatch('(', 1) );

restore_position(1); /* Restore our position. */

} /* _CloseParen() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _CloseBracket() *
* *
* Description: This macro is bound to the closing bracket key. It will *
* insert the closing bracket and call _FindMatch "[" to check *
* the nesting. The opening bracket will be shown to the user. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 06-Mar-1990 Bruce A. Mallett *
* Changed module header. I do not know when this routine was *
* originally created. *
* *
\****************************************************************************/

void _CloseBracket()
{
self_insert(); /* Insert the closing bracket. */
save_position(); /* Save where we are. */
prev_char(); /* Backup one. */
_nc_start = -1; /* Set to max. unsigned integer */

if ( !_InCommentOrString() )
_ShowMissing( _FindMatch('[', 1) );

restore_position(1); /* Restore our position. */

} /* _CloseBracket() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _CloseBrace() *
* *
* Description: This macro is bound to the closing brace key. It will *
* insert the closing brace and call _FindMatch "{" to check *
* the nesting. The opening brace will be shown to the user. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 02-Mar-1990 Bruce A. Mallett *
* Reformatted module header. I don't know when this routine was *
* originally created. *
* *
\****************************************************************************/

void _CloseBrace()

{
int brace_col; /* Where to put the brace. */
int brace_line; /* Line it is in. */
string buf; /* Holds the line & start-of-brace word */
int cbrace_cmnt; /* Flag: comment "}" or not */
int col1; /* Used to collect start-of-brace ... */
int col2; /* ... word */
int missing; /* Missing match character */
int top_line; /* Top line number in window. */


if ( _InCommentOrString() )
{
self_insert(); /* Ignore if in a comment or string */
return;
}

brace_line = 0; /* We have not yet found opening
* brace. */
save_position(); /* Save where we are. */
_nc_start = -1; /* Set to max. unsigned integer */

/************************************************************************\
* *
* Two attempts will be made to find a valid match for this closing *
* brace. The first does a fast try by calling _FindMatch with the *
* comment/string checking disabled. If this fails then _FindMatch *
* is called with checking enabled. *
* *
\************************************************************************/

message("Quick check for \"{\" ...");

if ( missing=_FindMatch('{', 0) ) /* If no match */
{
/********************************************************************\
* *
* If the _FindMatch failed and we are in a comment or *
* a string then just insert the typed character. *
* *
\********************************************************************/

restore_position(1);

if (_InCommentOrString())
{
self_insert();
return;
}

save_position();

/********************************************************************\
* *
* Not in a comment, so make another stab at it, this time *
* with full checking enabled. If this one fails then we *
* had better believe that something is wrong! *
* *
\********************************************************************/

message( "Long check for \"{\" ..." );

if (missing = _FindMatch('{', 1))
{
restore_position(1);
self_insert();
_ShowMissing(missing);
return;
}
}

/************************************************************************\
* *
* Here if everything matched/nested up properly. Now to figure *
* out where to insert the closing brace. *
* *
\************************************************************************/

message("Found \"{\"");

beginning_of_line(); /* Match w/ first char. on line. */
search_fwd("[~ \t]");
inq_position(brace_line, brace_col);/* Get column number it is in. */

restore_position(1); /* Get back to where we came from. */
save_position(); /* Save it again. */

beginning_of_line(); /* Move it! */
buf = read(); /* Read the line into a buffer. */

/************************************************************************\
* *
* Now see if anything other than blanks and tabs precedes where we *
* want to be on the line. If not then we can position the brace as *
* appropriate! *
* *
\************************************************************************/

if (!search_string("[~ \t\n]", buf))
{
move_abs(0, brace_col); /* Go where we want brace to be. */
delete_to_eol();
restore_position(0); /* Flush saved position. */
}

else
{
/********************************************************************\
* *
* We have something already on this line. So insert the closing *
* brace where the user has us positioned. *
* *
\********************************************************************/

restore_position(1); /* Get to entry position */
}

self_insert(); /* Insert the closing brace. */

/************************************************************************\
* *
* Now check to see if closing brace commenting is enabled. If so then *
* search back for whatever began this brace and show it in a comment: *
* *
\************************************************************************/

if ( _cbrace_cmnt_col ) /* If enabled */
{
/********************************************************************\
* *
* In general when searching back for the keyword that this block *
* defines we can look for something of the form: *
* *
* ( *
* *
* where *
* "" is a sequence of characters constituting a valid *
* C, C++, or C-Brief symbol (for simplicity I just allow the *
* whole set, hence the period is allowed for "C" & "C++" as well *
* as for C-Brief). *
* *
* But, there are a number of things which muck-up this assumption: *
* *
* 1) Opening a block just for the heck of it, as in: *
* *
* o *
* *
* o *
* *
* { *
* *
* } *
* *
* 2) "do" blocks, as in: *
* *
* do *
* { *
* } while (); *
* *
* 3) structure definitions, like: *
* *
* struct Abc *
* { *
* int ...; *
* }; *
* *
* 4) enum definitions, like: *
* *
* enum Abc *
* { *
* int ...; *
* }; *
* *
* 5) Probably other things that I am not thinking about *
* right at the moment. *
* *
* *
* So, to deal with these: *
* *
* 1) This one is too hard to test for (actually it would be *
* too CPU-intensive) since it would require checking the *
* brace nesting level. So I don't bother with it. *
* *
* 2) Fairly easy, just look for "do". *
* *
* 3) Also straight-forward, just look for "struct". *
* *
* 4) Also straight-forward, just look for "enum". *
* *
* 5) You really expect something to be said here? *
* *
\********************************************************************/

save_position(); /* Must return to here */
move_abs(brace_line, brace_col);/* Search back from here */

/********************************************************************\
* *
* Now try to determine what the keyword is that opens this block. A *
* simplified method is chosen which is as follows: *
* *
* 1) Search back for something that might be a symbol. Also *
* keep an eye out for a semicolon, a closing bracket, a *
* closing brace, or a closing parenthasis. *
* *
* 2) If a semicolon is found then we have a routine name with *
* old style parameter declarations. These statements are *
* skipped using the assumption that there is one per line. *
* Step 1 is executed again. *
* *
* 3) If a closing brace ("}") is found then we're confused ... *
* assume there is no keyword. *
* *
* 4) If a closing bracket ("]") or parenthasis (")") is found *
* then its match is located and we continue at step 1. *
* *
* 5) If a symbol is found then this is what is used as the *
* closing brace keyword. *
* *
* Note: In all cases the code checks to see if what was found in *
* step 1 was within a comment or a string. If so then it *
* skips to before the comment or string and repeats the *
* step. *
* *
\********************************************************************/


for ( ;; )
{
if ( !search_back("\\c[A-Za-z0-9._;})\\]]") )
break; /* No keyword present */

if ( _InCommentOrString(col1,col2) )
{
move_abs( col1, col2 ); /* Skip to start of comment/string */
continue;
}

buf = read(1); /* Read the character */

if ( buf == ";" ) /* If a statement */
{
beginning_of_line(); /* Skip this line */
continue;
}

if ( buf == "}" ) /* What's this? */
break; /* I give up ... no keyword */

if ( buf == ")" ) /* If closing parenthasis */
{
if ( _FindMatch('(',1) )
break; /* No match, no keyword! */

continue; /* If match found */
}

if ( buf == "]" ) /* If closing bracket */
{
if ( _FindMatch(']',1) )
break; /* No match, no keyword! */

continue; /* Match found! */
}

/****************************************************************\
* *
* Here with our thumb on the end of a symbol. Lets gather the *
* thing! *
* *
\****************************************************************/

inq_position( NULL, col2 ); /* Get end column number */
++col2; /* 'Cause we are on top of the last char. */

if ( !search_back("\\c[A-Za-z0-9._]+", RE_SD_MAX) )
beginning_of_line();

inq_position( NULL, col1 ); /* Get beg. column number */

buf = read( col2-col1 ); /* Read the keyword */

/****************************************************************\
* *
* Certain keywords are excluded ... lets check for these: *
* *
\****************************************************************/

if ( (buf=="do") || (buf=="enum") || (buf=="struct") || (buf=="typedef") )
break;

/****************************************************************\
* *
* Here with "buf" containing the keyword to be inserted. Now *
* all that is left is to do so! *
* *
\****************************************************************/

restore_position(); /* Go back to where we left off */
save_position(); /* Re-save it */

/****************************************************************\
* *
* Check to see if we can move to the column designated by *
* _cbrace_cmnt_col or not. Of not then just insert the comment *
* right where we are. *
* *
\****************************************************************/

inq_position( NULL, col1 );
end_of_line();
inq_position( NULL, col2 );

if ( (col2 > col1) || (col1 > _cbrace_cmnt_col) )
insert( "\t" );
else
move_abs( 0, _cbrace_cmnt_col );

insert(("/* " + buf) + "() */");

break; /* We are done! */

} /* for() */
}

restore_position(); /* Restore where we were */

/************************************************************************\
* *
* Show where the matching open brace is: *
* *
\************************************************************************/

save_position(); /* Save where we are. */
top_of_window(); /* Find window top. */
inq_position(top_line); /* Top_line = top line # of window. */

if (brace_line >= top_line) /* If opener within window */
{
move_abs(brace_line, brace_col);/* Go to opener. */
_MatchDelay(); /* Show where it is. */
}

restore_position(); /* Restore our position in the scheme
* of things.
*/
} /* _CloseBrace() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _ShowMissing( m_ch ) *
* *
* Description: This macro will display a message which indicates what *
* nesting character is missing when doing a _FindMatch. *
* More than that however, this routine takes care of the *
* general processing desired when _FindMatch has been called. *
* *
* Parameters: m_ch - The character which is missing. Note that it is *
* passed in as an integer and may be zero. If it *
* is zero then there is nothing missing. *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 02-Mar-1990 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

void _ShowMissing( int m_ch )

{
if ( m_ch ) /* If something is indeed missing */
{
beep();
message("Missing \"%c\"", m_ch);
}
else
_MatchDelay(); /* Nothing missing, delay for a bit. */

} /* _ShowMissing() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _GoToInclude( fname ) *
* *
* Description: This routine will search for the include file named by *
* "fname" as follows: *
* - if fname is bracketed by "<" and ">" then these *
* characters are removed and the path specified by *
* the _include_sys environment variable is searched. *
* - if fname is not bracked as above then the current *
* directory followed by that given by the _INCLUDE_USR *
* environment variable. Note that the names of the *
* INCLUDE and USER_INCLUDE environment variables are *
* obtained from the configuration file. *
* *
* If the include file is found then it is read into a separate *
* buffer and a switch is made to it. If it is not found an *
* error message is displayed. *
* *
* Parameters: fname - Name of the include file to search for. This *
* name may be enclosed in "<" and ">" to designate *
* a system include file. *
* *
* Returns: (int) -1 if the search for the include file failed *
* 1 if the search was successful. *
* *
* Notes: The passed file name may optionally be preceeded by "#". If *
* it is then it is removed. *
* *
* The terminating ">" for a system include file is also *
* optional (the leading "<" is mandatory to designate a system *
* include file). *
* *
* Side effects: The include file is read in via edit_file() and the current *
* buffer is switched to the include file if it was found. *
* *
* Revision History: *
* Vers Date Author *
* 0.0 30-Nov-1989 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

int _GoToInclude( string fname )

{
string ipath; /* Path of include file (and to search for it) */

/************************************************************************\
* *
* Determine if we are looking for a system file or a user file. This *
* will determine what paths we look among. *
* *
\************************************************************************/

if ( substr(fname,1,1) == "<" ) /* If system file */
{
fname = substr( fname, 2 ); /* Remove "<" */

if ( substr(fname, strlen(fname)) == ">" )/* Remove ">" (optional) */
fname = substr( fname, 1, strlen(fname)-1 );

ipath = inq_environment( _include_sys );
}
else
{
if ( substr(fname,1,1) == "#" ) /* If system file */
fname = substr( fname, 2 ); /* Remove "#" */

ipath = ".;" + inq_environment( _include_usr );
}

ipath = search_path( ipath, fname );

if ( ipath == "" ) /* Not found! */
{
error( "Include file \"%s\" not found!", fname );
return ( -1 ); /* Show nothing found */
}

edit_file( ipath ); /* Edit the thing */

return ( 1 ); /* Show success! */

} /* _GoToInclude() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _GoToThisTag() *
* *
* Description: This macro will get the tag which the cursor is on and pass *
* it to _GoToTag() thereby positioning to it. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: This routine logically belongs in ec-tags.m however putting *
* it there would cause ec-tags to be loaded whenever the user *
* struck wanted to invoke goto_line. Since the tags support *
* for elec-c should not be loaded when merely trying to go to *
* a line this routine should be kept in the main elec-c file. *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 05-Mar-1990 Bruce A. Mallett *
* Changed to this module header format. I do not know when the *
* original module was created. *
* *
\****************************************************************************/

void _GoToThisTag()
{
int
ask, /* Nz to force _GoToTag() to ask for permission */
bcol, /* Beginning column */
ecol, /* Ending column */
len; /* Length of tag_name */

string delimiter; /* For include file searches */
string tag_name; /* The tag to go to */

bcol = 1; /* Assume no tag found */
ecol = 1;

delimiter = ""; /* No delimiter yet */

save_position(); /* Just in case */

/************************************************************************\
* *
* Setup a variable indicating whether or not _GoToTag() should ask for *
* permission to proceed. If we were called from the keyboard or by a *
* Brief primitive then permission must be obtained. *
* *
\************************************************************************/

tag_name = inq_called(); /* Use tag_name as a scratch string */
ask = (tag_name == "") || (tag_name == "Primitive");

/************************************************************************\
* *
* Check to see if the user is on a #include line, in which case s/he *
* desires to goto the include file designated. *
* *
\************************************************************************/

end_of_line();
drop_anchor( 4 ); /* Prepare for bounded search */
beginning_of_line();

if ( search_fwd( "[ \t]@#include[ \t]", RE_LR_MIN, CASE_SENSITIVE, SEARCH_BLOCK ) > 0 )
{
/********************************************************************\
* *
* Here if we are on an "#include" line. In this case we want to *
* pickup the name of the include file and "goto" it: *
* *
\********************************************************************/

if ( search_fwd( "\\c[<\"]", RE_LR_MIN, CASE_SENSITIVE, SEARCH_BLOCK ) > 0 )
{
if ( read(1) == "<" ) /* Determine matching end delimiter */
delimiter = ">"; /* System include */
else
delimiter = "\""; /* Normal include */

move_rel( 0, 1 ); /* Skip over leading delimiter */
inq_position( NULL, bcol );

/****************************************************************\
* *
* Locate the end of the include file name: *
* *
\****************************************************************/

if ( search_fwd( delimiter, NOT_RE, CASE_SENSITIVE, SEARCH_BLOCK ) > 0 )
inq_position( NULL, ecol );/* Get ending position */
}
}

else
{
/********************************************************************\
* *
* Here if we are not on an "#include" line. *
* *
\********************************************************************/

restore_position(); /* Get back to where we started */
save_position(); /* Make it right for later on */

if ( search_back( "[~A-Za-z0-9_]\\c" ) <= 0 )
bcol = 1; /* Fails only at beginning of buffer */
else
inq_position(NULL, bcol); /* Get beginning column */

search_fwd( "[~A-Za-z0-9_]", RE_LR_MIN, CASE_SENSITIVE, SEARCH_BLOCK ); /* Find end of string */
inq_position(NULL, ecol); /* Get end column */
}

raise_anchor(); /* Remove bounded search anchor */

len = ecol - bcol; /* Compute length to read */

if (len > 0) /* If we have a default */
{
move_abs(0, bcol); /* Go back to start */
tag_name = read(len); /* Read in the tag */
}
else
tag_name = ""; /* We have no default */

restore_position(); /* Restore entry position */

if ( delimiter != "" ) /* If some delimiter */
{
if ( delimiter == ">" ) /* If doing a system include file */
tag_name = "<" + tag_name + ">"; /* Surround with system include designator */

else
tag_name = "#" + tag_name; /* Prefix with normal include designator */
}

_GoToTag(tag_name, ask); /* Go find the tag */

} /* _GoToThisTag() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _GoToTag( tag_name, ask ) *
* *
* Description: This routine will open a buffer and position the cursor on *
* the tag whose name is passed. If successful a value of 1 is *
* returned. If unsuccessful a value of 0 is returned. This *
* routine will BEEP if the tag was not found. *
* *
* Parameters: tag_name - Name of the tag to go to. *
* ask - Flag which, if non-zero, indicates that *
* this routine should ask for permission *
* before proceeding. *
* *
* Returns: (int) -1 if the tag was not found *
* 0 if the tag search aborted *
* +1 if the tag was found *
* *
* Notes: This routine logically belongs in ec-tags.m however putting *
* it there would cause ec-tags to be loaded whenever the user *
* struck wanted to invoke goto_line. Since the tags support *
* for elec-c should not be loaded when merely trying to go to *
* a line this routine should be kept in the main elec-c file. *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 05-Mar-1990 Bruce A. Mallett *
* Created this module header. The module was created much earlier, *
* but I do not know when. *
* *
\****************************************************************************/

_GoToTag( string tag_name, int ask )

{
string fname; /* Name of file containing the tag */
int line_no; /* Line number of tag */
string srch; /* Search string for the tag */

/************************************************************************\
* *
* The passed tag name (if any) is displayed in the "Goto" prompt as the *
* default selection. Inorder to make this work note that the get_parm *
* asks for a parameter which is NOT passed. *
* *
\************************************************************************/

if ( ask && (!get_parm(2, tag_name, "Goto?", NULL, tag_name)) )
return 0; /* If aborted */

if (index("0123456789", substr(tag_name, 1, 1)))
{
line_no = goto_line(atoi(tag_name));
if (line_no <= 0)
return 0;
else
return 1;
}

/************************************************************************\
* *
* See if the tag designates an include file (first character is "#" or *
* "<"). If so then let GoToInclude() handle it: *
* *
\************************************************************************/

if ( index("#<", substr(tag_name, 1, 1)) )
return ( _GoToInclude(tag_name) );

/************************************************************************\
* *
* Here if the tag_name is a bona-fida tag! *
* *
\************************************************************************/

if ((line_no = _FindTag(tag_name, fname, srch)) > 0)
{
edit_file(fname);
move_abs(line_no, 1);

/********************************************************************\
* *
* We have now positioned to the line where the tag should be. If *
* the file has been expanded or contracted then the tag has probably *
* moved. So search forward and backward for it! *
* *
\********************************************************************/

if (search_fwd(srch, NOT_RE) > 0)
{
center_line();
return 1; /* Found! */
}

if (search_back(srch, NOT_RE) > 0)
{
center_line();
return 1; /* Found! */
}
}

/************************************************************************\
* *
* Here if the tag was not found: *
* *
\************************************************************************/

if (line_no < 0)
{
beep(); /* Signal tag not found. */
error("Tag \"%s\" not found!", tag_name);
}

return 0;

} /* _GoToTag() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: ReformBlock() *
* *
* Description: This macro will reformat the currently marked block. This *
* is done by writing it to a temporary file and invoking *
* "indent" to reform it and put its output in another *
* temporary file. The marked block is deleted and replaced by *
* the output of indent. The two temporary files are then *
* deleted. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 30-Nov-1989 Bruce A. Mallett *
* Created Module. *
* *
\****************************************************************************/

ReformBlock()
{
string cmd; /* Dos command string */

save_position(); /* We need to save the boundaries */
swap_anchor(); /* of the marked block */

if (write_block(REFORM_FILE_OUT) > 0)
{
drop_anchor(4);
restore_position();
cmd = "indent " + REFORM_FILE_OUT + " " + REFORM_FILE_IN + ">& NUL";
message(cmd);
dos(cmd, 0);

delete_block(); /* Delete old code and ... */
read_file(REFORM_FILE_IN); /* bring in the new! */

del( REFORM_FILE_IN ); /* Clean up */
del( REFORM_FILE_OUT );
}

/* Else (error writing out the block) */

else
{
restore_position();
error("Cannot write block!");
}

} /* ReformBlock() */

/****************************************************************************\
* *
* Template: <^r^> *
* *
* Name: _SetupFileData() *
* *
* Description: This macro setups the _file globals which are used to keep *
* track of the names of what we are editing. *
* *
* Parameters: None *
* *
* Returns: Nothing *
* *
* Notes: *
* *
* Side effects: *
* *
* Revision History: *
* Vers Date Author *
* 0.0 05-Mar-1990 Bruce A. Mallett *
* Created this new header. I do not know when the module was *
* originally created. *
* *
\****************************************************************************/

void _SetupFileData()

{
int
i; /* HDV */

string
str; /* String form of HDV */

inq_names(_file_path, _file_ext); /* Get full file name and extension */
_file_drive = substr(_file_path, 1, 1);

str = substr(_file_path, 3, 1); /* Use str to hold separator */
i = rindex(_file_path, str); /* Use i to hold last separator position */

_file_name = substr(_file_path, i + 1);
_file_path = substr(_file_path, 3, i - 3);

if (i = rindex(_file_name, "."))
_file_name = substr(_file_name, 1, --i);

} /* _SetupFileData() */



  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : EC304.ZIP
Filename : EC-TOP.ORG

  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/