Category : Files from Magazines
Archive   : PJ96.ZIP
Filename : EDITOR.C

 
Output of file : EDITOR.C contained in archive : PJ96.ZIP
/* edit.c-- Low-Level Workhorse Functions */

#include
#include
#include
#include
#include
#include
#include
#include
#include

#include

/* Interface functions to test the edit engine. They are described
* in engine.h
*
* These functions are used internally, they do not interface
* with the edit engine:
*/

static int draw (win *const p, int ask_top, int ask_left );
static int hscroll (win *const p, int left);
static int bottom (win *const p, int offset);
static int del_line(win *const p, textbuf *const b,int which_line);
static int export (win *const p, textbuf *const b,int which_line);
static void status (win *const p, char *fmt, ... );

/*------------------------------------------------------------*/
int e_open( win *const this )
{
/* Called when engine for a specific window is opened.
* Try to initialize buffer by importing the top few lines.
* On the first call, the import function should take care
* of both opening the file and adjusting this->bottom to hold
* the line number of the bottom line in the file. It should
* set up the line-number table at this time, as well.
*/

textbuf *b = &this->b;
int nrows = b_nrows(b);
int row, i;
char *new_line;

if( this->import )
{
for( row = 0; row < nrows; ++row )
{
if( !(new_line = (*this->import)(this,row)) )
break;

bottom( this, +1 );
b_gotorc(b, row, 0);
for( i = b_ncols(b); --i >= 0 && *new_line ๐Ÿ˜‰
*b_advance(b) = *new_line++;
}
e_gotorc(this,0,0);
draw (this,0,0);
}
return 1;
}
/*------------------------------------------------------------*/
int e_close( win *const this )
{
/* Prepare for closing the window. Save the window state by
* exporting the current buffer and various important offsets.
* This function may be called several times.
*/

textbuf *b = &this->b;
viewport *v = &this->v;
int nrows = b_nrows(b);
int row;

if( this->export )
{
for( row = 0; row < nrows && row <= this->bottom; ++row )
{
b_gotorc(b, row, 0);
if( !export( this, b, this->file_off + row ) )
break;
}
status( this, "%%%% row, viewport = %d %%%%",v_row(v) );
status( this, "%%%% col, viewport = %d %%%%",v_col(v) );
status( this, "%%%% row, offset = %d %%%%",this->row_off );
status( this, "%%%% col, offset = %d %%%%",this->col_off );
status( this, "%%%% file offset = %d %%%%",this->file_off);
}
return 1;
}
/*------------------------------------------------------------
* Little stuff:
* e_vrow Current viewport row (top == 0).
* e_vcol Current viewport column (left == 0).
* e_vnrows Number of rows in viewport.
* e_vncols Number of columns in viewport.
* e_isword True if c argument is a "word".
* e_maxrow Largest virtual (file) row index
* e_maxcol Largest virtual (file and buffer) column index
* e_col Current virtual (file and buffer) cursor column
* e_row Current virtual (file) cursor row
* e_cur Character at current cursor position.
* e_last Index of rightmost nonwhite character on line,
* zero if the line is blank.
*/

#pragma warn -par /* turn off warnings about arguments not used */

int e_vrow (win *const w) { return v_row (&w->v); }
int e_vcol (win *const w) { return v_col (&w->v); }
int e_vnrows (win *const w) { return v_nrows (&w->v); }
int e_vncols (win *const w) { return v_ncols (&w->v); }
int e_isword (win *const w,
int c) { return( isalnum(c) || c=='_' );}
int e_maxrow (win *const w) { return w->bottom; }
int e_maxcol (win *const w) { return b_ncols(&w->b) -1; }
int e_col (win *const w) { return b_col(&w->b); }
int e_row (win *const w) { return b_row(&w->b)
+ w->file_off;}
int e_cur (win *const w) { return *b_current(&w->b); }
int e_last (win *const w) { return b_last(&w->b); }

#pragma warn +par
/*------------------------------------------------------------
* e_attention() and e_error();
*
* e_attention() rings the bell if not a horizontal motion. In
* any event it sets the window's error flag.
* e_error() returns the value of the flag and resets the
* flag to zero.
*/

void e_attention(win *const this, int h)
{
if(!h)
putchar('\a');
this->error = 1;
}

int e_error( win *const this )
{
int rv = this->error;
this->error = 0;
return rv;
}
/*------------------------------------------------------------*/
int e_first (win *const this)
{
// Return the column index of the first nonwhite character
// on the current line or 0 if the line is blank

textbuf *const b = &this->b;
int start_col = b_col(b);
int start_row = b_row(b);
int last_col = b_ncols(b) - 1;
int col;

b_gotorc(b, start_row, 0);
for( col = 0; (col {
++col;
b_advance(b);
}
if( isspace(*b_current(b)) ) /* line was entirely blank */
col = 0;
b_gotorc( b, start_row, start_col );
return col;
}
/*------------------------------------------------------------*/
int e_find_c(win *const this, int c, int forward, int incl)
{
/* If the character is found on the current line (to the
* right of the current cursor position if "forward" is true,
* to the left otherwise) return the column index of c.
* Otherwise return -1. If "incl" is false, return the index
* of the character next to the c rather than the index of
* c itself.
*/

textbuf *b = &this->b;
int row = b_row(b);
int col = b_col(b);
int last = b_last(b);
int start_col = col;
int rv = -1;

if( forward ) forward = 1;
else forward = -1;

col += forward; /* start search at least one column */
if( !incl ) /* away if not inclusive, add one more */
col += forward;

if( !(0 <= col && col <= last) ) /* col isn't on the line */
rv = -1;
else
{
b_gotorc(b, row, col);
while( *b_current(b) != c && !b_ateol(b) )
{
col += forward;
b_gotorc(b, row, col);
}
rv = (*b_current(b) == c) ? col : -1 ;

if(rv != -1 && !incl) /* if not including, */
if( (rv -= forward) < 0 ) /* back up a notch */
rv = -1;

b_gotorc(b, row, start_col);
}
return rv;
}
/*------------------------------------------------------------*/
static void status( win *const this, char *fmt, ... )
{
/* works like fprintf, but outputs string using the
* current window's export function. String is exported as
* line -1.
*/

char scratch[W_LINEMAX];
va_list args;
int len;
if( this->export )
{
va_start(args, fmt);
len = vsprintf(scratch, fmt, args);
va_end(args);
(*this->export)( this, -1, scratch, len+1, len );
}
}
/*---------------------------------------------------------------*/
static int export( win *const this,textbuf *const b,int which_line)
{
/* Export current buffer-cursor line as line which_line,
* cursor does not move.
*/

int row = b_row(b);
int col = b_col(b);

char scratch[W_LINEMAX];
char *p;
int i;

if( this->export )
{
b_gotorc(b,row,0);
for(p=scratch, i=b_ncols(b); --i >= 0; )
*p++ = *b_advance(b);

b_gotorc(b,row,col);
(*this->export)( this, which_line, scratch, b_ncols(b),
b_last (b)+1);
return 1;
}
return 0;
}
/*------------------------------------------------------------*/
static int del_line( win *const this, textbuf *const b,
int which_line )
{
/* export current buffer-cursor line for delete, cursor */
/* does not move. */

int row = b_row(b);
int col = b_col(b);

char scratch[W_LINEMAX];
char *p;
int i;

if( this->remove )
{
b_gotorc(b,row,0);
for(p=scratch, i=b_ncols(b); --i >= 0; )
*p++ = *b_advance(b);

b_gotorc(b,row,col);
(*this->remove)( this, which_line, scratch,
b_ncols(b), b_last(b)+1);
return 1;
}
return 0;
}
/*------------------------------------------------------------*/
int e_vscroll( win *const this, int up, int import )
{
/* Scroll text up one line if if up > 0, down otherwise. If
* import is true, the scroll won't happen unless a new top
* or bottom line can be imported from the overflow file. If
* it's false, the scroll always happens, no attempt is made
* to do an import, and the bottom (or top) line will be
* filled with blanks. Return true on success, false
* otherwise.
*/

viewport *const v = &this->v ;
textbuf *const b = &this->b ;
int rv = 1; /* return value */
int brow = b_row(b); /* buffer row/column */
int bcol = b_col(b);
int vrow = v_row(v); /* viewport row/column */
int vcol = v_col(v);
int i;
char *new_line;

if( up > 0 ) /* Move text up, viewport moves down */
{ /* relative to buffer */

if( (this->row_off + v_nrows(v)) < b_nrows(b) )
{
/* Viewport isn't banged up against bottom of
* buffer. Slide viewport over text, but don't have
* to modify buffer. Position buffer cursor at left
* edge of line with which to fill the viewport's
* opened up bottom line: the buffer line corres-
* ponding to the one just below the viewport.
* Slide the viewport by incrementing row_off.
*/
b_gotorc(b, this->row_off+v_nrows(v), this->col_off);
++this->row_off;
}
else if( !import ) /* import is suppressed */
{
new_line = ""; /* pretend we got an empty line */
goto got_bot;
}
else if( !this->import ) /* try to import bottom line */
{
rv = 0; /* no import function */
goto exit;
}
else if( (i = this->file_off + b_nrows(b)) > this->bottom )
{
rv = 0; /* line doesn't exist */
goto exit;
}
else if( !(new_line = (*this->import)(this,i)) )
{
rv = 0; /* couldn't import it */
goto exit;
}
else /* got the line, add it to the buffer & viewport */
{
got_bot:
b_gotorc(b, 0, 0); /* export the top line */
export (this, b, this->file_off );

++this->file_off ;
b_closedown (b, ' '); /* delete top line and move */
/* following text up. */

b_gotorc(b, b_nrows(b)-1, 0); /* buffer=new last line */
for( i = b_ncols(b); --i >= 0 && *new_line ๐Ÿ˜‰
*b_advance(b) = *new_line++;
b_gotorc(b, b_nrows(b)-1, 0); /* Cursor to line start */
--brow; /* make cursor track previous position */
}

/* Scroll the viewport text up one line, then copy the
* associated text for the bottom line from the buffer
* to the viewport.
*/

if( !this->update )
{
if( vrow == 0 ) /* Old line is gone */
{
/* col of new top line */
b_gotorc(b, this->row_off, bcol);
}
else
b_gotorc(b, brow, bcol );
}
else
{
v_scroll(v, 1, 0); /* scroll up one line */
v_gotorc(v, v_nrows(v)-1, 0); /* last line, column 0 */

/* copy buffer to screen */
for(i = v_ncols(v); --i >= 0 ๐Ÿ˜‰
v_putc(v, *b_advance(b), 1 );

if( vrow == 0 ) /* Old line is gone */
{ /* can't restore cursor */
b_gotorc(b, this->row_off, bcol);
v_gotorc(v, 0, vcol);
}
else /* restore original cursor position */
{
b_gotorc(b, brow, bcol );
v_gotorc(v, vrow-1, vcol );
}
}
}
else /* Move text down, viewport moves up */
{ /* relative to buffer */
if( this->row_off > 0 )
{
/* Viewport isn't banged up against top of buffer.
* Slide viewport over text. Position buffer cursor
* at left edge of line with which to fill the
* viewport's opened-up top line. Note that b_gotorc()
* has side effects so the -- must be done separately.
*/
--this->row_off;
b_gotorc(b, this->row_off, this->col_off );
}
else if( this->file_off <= 0 )
{
rv = 0; /* may not scroll past initial top line */
goto exit;
}
else if( !import ) /* import is suppressed */
{
new_line = ""; /* pretend we got an empty line */
goto got_top;
}
else if(!this->import ) /* try to import new top line */
{
rv = 0; /* No import function */
goto exit;
}
else if( this->file_off <= 0 )
{
rv = 0; /* Line doesn't exist */
goto exit;
}
else if(!(new_line=(*this->import)(this,this->file_off-1)))
{
rv = 0; /* Couldn't import new line */
goto exit;
}
else /* got the line, add it to the buffer & viewport */
{
got_top:
--this->file_off;
b_gotorc (b, b_nrows(b)-1, 0); /* export bottom line */
export (this, b, this->file_off + b_nrows(b) );
b_closeup (b, ' ' ); /* delete bottom line */

b_gotorc(b, 0, 0); /* buffer = new top line */
for( i = b_ncols(b); --i >= 0 && *new_line ๐Ÿ˜‰
*b_advance(b) = *new_line++;
b_gotorc(b, 0, 0); /* Cursor to start of new line */
++brow; /* cursor tracks previous position */
}

/* Scroll the viewport text down one line, then copy the
* associated text for the top line from the buffer to the
* viewport.
*/

if( !this->update )
{
if(vrow >= v_nrows(v)-1) /* Old line is gone */
b_gotorc(b, this->row_off + v_nrows(v)-1, bcol);
else
b_gotorc(b, brow, bcol );
}
else
{
v_scroll(v, -1, 0); /* scroll down 1 line */
v_gotorc(v, 0, 0); /* first line, col. 0 */
for(i = v_ncols(v); --i >= 0 ๐Ÿ˜‰ /* screen = buffer */
v_putc(v, *b_advance(b), 1 );

if(vrow >= v_nrows(v)-1) /* Old line is gone */
{
/* Can't restore old cursor position because the */
/* line's not there anymore. go to the original */
/* column, but of the new bottom line */

b_gotorc(b, this->row_off + v_nrows(v)-1, bcol);
v_gotorc(v, v_nrows(v)-1, vcol);
}
else /* Otherwise restore original cursor to be */
{ /* under original character */
b_gotorc(b, brow, bcol );
v_gotorc(v, vrow+1, vcol );
}
}
}
exit:
monitor(this, UPDATE);
return rv;
}
/*------------------------------------------------------------*/
int draw( win *const this, int ask_top, int ask_left )
{
/* Fill the viewport with text from the buffer, the viewport
* is at offset "top" from the top line of the buffer and
* "left" from the left edge of the buffer. Cursor doesn't
* move with respect to the viewport. Top and left are
* truncated if necessary to prevent the viewport from
* moving off the edge of the buffer. Return false if the
* coordinates were modified to draw things, true otherwise.
*/

viewport *const v = &this->v;
textbuf *const b = &this->b;
int col = 0;
int row = 0;
int nrows = v_nrows( v );
int ncols = v_ncols( v );
const int left = max(0, min(ask_left, b_ncols(b)-v_ncols(v)));
const int top = max(0, min(ask_top, b_nrows(b)-v_nrows(v)));
int cur_top = top;
int start_row = v_row(v);
int start_col = v_col(v);

if( !this->update ) /* no updating, pretend we succeeded */
return 1;

while( --nrows >= 0 )
{
/* both b_gotorc and v_gotorc have side effects */

b_gotorc( b, cur_top, left ); ++cur_top;
v_gotorc( v, row, 0 ); ++row;

for( col = ncols; --col> 0 ๐Ÿ˜‰ /* all but last char. */
v_putc(v, *b_advance(b), 1 );
v_putc(v, *b_current(b), 0 ); /* last character. */
}

this->row_off = top;
this->col_off = left;
v_gotorc(v, start_row, start_col );
b_gotorc(b, start_row + top, start_col + left );

monitor(this, UPDATE);
return( top == ask_top && left == ask_left );
}
/*------------------------------------------------------------*/
static int hscroll( win *const this, int left )
{
/* Scroll horizontally, "left" columns to the left (right if
* negative). There's no import/export feature here, so a
* scroll past the edge of the buffer is illegal. Return true
* if you moved the required number of columns, false if not.
* Note that there still might have been motion in the earlier
* case, just not enough of it. A request of zero columns
* to the left just does a redraw.
*/

return draw( this, this->row_off, this->col_off + left);
}
/*------------------------------------------------------------*/
int e_update( win *const this, int enable )
{
/* If "enable" is false, store a snapshot of the current
* viewport and file states. If it's true, attempt to restore
* previous state (cursor position and relative positions
* of the file, buffer, and viewport).
*
* This routine is meant primarily to disable screen updating
* while the file is being examined. Return 1 if you change
* state 1 if the current state is requested.
*/

if( this->update == enable ) /* nothing to do */
return 0;

if( !enable ) /* disabling */
{
this->update = 0;
this->update_row_off = this->row_off;
this->update_col_off = this->col_off;
this->update_file_off = this->file_off;
this->update_row = e_row(this);
this->update_col = e_col(this);
this->dirty = 0;
}
else /* enabling */
{
/* Get the cursor back to the original place with
* an e_gotorc(), then scroll the screen as necessary
* to get the cursor positioned correctly relative to
* the viewport.
*/

e_gotorc( this, this->update_row, this->update_col );

while( this->file_off < this->update_file_off )
if( !e_vscroll(this, 1, 1) )
break;
while( this->file_off > this->update_file_off )
if( !e_vscroll(this, 0, 1) )
break;

while( this->row_off < this->update_row_off )
if( !e_vscroll(this, 1, 1) )
break;
while( this->row_off > this->update_row_off )
if( !e_vscroll(this, 0, 1) )
break;

this->update = 1;
if( this->col_off != this->update_col_off )
fprintf(stderr,"INTERNAL WINDOW ERROR: "
"unexpected horiz motion\n");

if( this->dirty )
draw( this, this->row_off, this->col_off );
}
monitor(this, UPDATE);
return 1;
}
/*------------------------------------------------------------*/
int e_gotorc( win *const this, int dst_r, int dst_c )
{
/* Go to the indicated virtual row and column. If r and c
* are inside the viewport, just go there. If not, scroll
* the viewport as appropriate. New lines are imported if
* you request a row address that is not in the buffer.
* Note that this subroutine might be used to add lines to
* the end of the file (by going down from the last line).
*/

viewport *const v = &this->v;
textbuf *const b = &this->b;
int rv = 1; /* return value */
int r, c;
int nrows = v_nrows( v );
int ncols = v_ncols( v );

switch( dst_r )
{
case E_HOME: dst_r = this->row_off; break;
case E_MID: dst_r = this->row_off + nrows/2; break;
case E_LAST: dst_r = this->row_off + nrows-1; break;
}
r = dst_r;

if( !(0 <= dst_c && dst_c < b_ncols(b)) || r < 0 )
{
rv = 0; // Illegal address
goto exit;
}
c = dst_c;

/* Get the desired column into the viewport, starting with
* column index:
* Modify c to hold the distance that c is from the right
* of the viewport. For example, c will be 0 if it's
* the first column past the one in the right edge of the
* viewport. If c is -1, it's at the right edge of the
* viewport. If it's -ncols then it's at the left edge of
* the viewport. Then, scroll as necessary to get c into
* the viewport.
*/

c -= this->col_off + ncols;
if( c >= 0 )
{
while( c-- >= 0 )
if( !hscroll(this, 1) ) /* scroll left */
{
rv = 0;
goto exit;
}
}
else if( c < -ncols )
{
c += ncols; /* c = -1 ==> 1 col to left of viewport. */
while( ++c <= 0 )
if( !hscroll(this, -1) ) /* scroll right */
{
rv = 0;
goto exit;
}
}

/* Do the same thing with the vertical coordinate. The
* situation is more complicated here, though, because the row
* coordinate is file relative. In other words:
*
* r == file_off + row_off + v_row(v)
*
* After the subtract, below, r will hold the distance between
* the top of the viewport and the desired row, negative if
* the desired row is above the viewport.
*/

r -= this->row_off + this->file_off;
if( r < 0 ) /* desired row is above viewport */
{
while( ++r <= 0 )
if( !e_vscroll(this, -1, 1) ) /* scroll text down */
{
rv = 0;
goto exit;
}
}
else if( r >= nrows )
for( r -= (nrows-1); --r >= 0 ๐Ÿ˜‰
if( !e_vscroll(this, 1,1) ) /* scroll text up */
{
rv = 0;
goto exit;
}

/* the desired cursor is now in the viewport. Go there. */

b_gotorc(b, dst_r - this->file_off, dst_c);
if( this->update )
v_gotorc(v, dst_r - this->row_off - this->file_off,
dst_c - this->col_off );
exit:
monitor(this, UPDATE);
return rv;
}
/*------------------------------------------------------------*/
static int bottom(win *const this, int offset )
{
/* if offset isn't zero, set bottom to it's current
* value + offset, otherwise set it to the current line.
*/

if( !offset )
{
int lineno = b_row(&this->b) + this->file_off;
if( lineno > this->bottom )
this->bottom = lineno;
}
else if( (this->bottom += offset) < -1 )
this->bottom = -1;

return this->bottom;
}
/*------------------------------------------------------------*/
void e_replace (win *const this,int c)
{
bottom(this,0);
if( c )
{
this->dirty = 1;
if( this->update )
v_putc( &this->v, c, 0 );
*b_current(&this->b) = c;
}
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
void e_ins(win *const this, int c )
{
viewport *const v = &this->v;

bottom(this,0);
b_insert_c( &this->b, 1, c ? c : ' ');
this->dirty = 1;
if( this->update )
{
v_scroll_region( v, 0, -1, v_col(v), v_row(v),
v_ncols(v)-1, v_row(v) );
v_putc( v, c ? c : ' ', 0 );
}
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
void e_del(win *const this)
{
viewport *const v = &this->v;
textbuf *const b = &this->b;
int vrow = v_row(v);
int vcol = v_col(v);
int brow = b_row(b);
int bcol = b_col(b);

b_delete_c( &this->b, 1, ' ' );
this->dirty = 1;

if( this->update )
{
v_scroll_region( v, 0, 1, v_col(v), v_row(v),
v_ncols(v)-1, v_row(v) );

v_gotorc (v, vrow, v_ncols(v)-1);
}
b_gotorc (b, brow, (v_ncols(v)-1) + this->col_off);

if( this->update )
{
v_putc (v, *b_current(b), 0);
v_gotorc (v, vrow, vcol);
}
b_gotorc(b, brow, bcol);
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
int e_closeline(win *const this)
{
viewport *const v = &this->v;
textbuf *const b = &this->b;
int ecol = e_col(this); /* absolute row and column */
int erow = e_row(this);
char *new;
int i, bottom_line_of_buffer;

if( this->bottom < 0 )
return 0;

b_gotorc ( b, b_row(b), 0 );
del_line ( this, b, this->file_off + b_row(b) );
this->dirty = 1;

b_closedown( b, ' ');
if( this->update )
v_scroll_region( v, 1, 0, 0, v_row(v), v_ncols(v)-1,
v_nrows(v)-1 );

bottom(this, -1); /* Bottom line moves up one notch
* because of the delete.
*/
/* Import a new bottom line into the buffer if there's an
* import function and there is text in the file below the
* bottom line of the buffer.
*
* Note that since we just deleted a buffer line, all of the
* file-relative line numbers have changed, so the line being
* imported is actually the last line in the buffer, not the
* line below the last line as was the case in the vertical-
* scroll function.
*/

bottom_line_of_buffer = this->file_off + b_nrows(b) - 1;

if( this->import && this->bottom > bottom_line_of_buffer )
{
if(new = (*this->import)(this, bottom_line_of_buffer) )
{
/* Move the imported line into the buffer */

b_gotorc(b, b_nrows(b)-1, 0 );
for( i = b_ncols(b); --i >= 0 && *new ๐Ÿ˜‰
*b_advance(b) = *new++;
}
}

/* If original row is now off the bottom of the file,
* adjust it down to compensate.
*/

if( erow > this->bottom )
erow = this->bottom < 0 ? 0 : this->bottom ;

/* Update the viewport to display the imported line
*/

if( this->update )
{
b_gotorc(b, v_nrows(v)-1 + this->row_off, this->col_off );
v_gotorc(v, v_nrows(v)-1, 0 );
for( i = v_ncols(v); --i >= 0; v_putc(v,*b_advance(b),1) )
;
}

e_gotorc(this, erow, ecol );
e_gotorc(this, e_row(this), e_first(this) );
monitor(this, UPDATE);
return 1;
}
/*------------------------------------------------------------*/
int e_openline(win *const this, int below)
{
/* open the line on which the cursor is resting by moving all
* following lines down a notch and importing a blank line.
* If below is true, open the line beneath the current one.
* Cursor ends up at far left of new line.
*/

textbuf *b = &this->b;
viewport *v = &this->v;
int line = e_row(this);
int scrolled = 0;
int row;

this->dirty = 1;
if( below )
{
/* If we're inserting below the last line of the file, and
* the cursor's resting on the bottom line of both the
* viewport and the buffer, force a scroll up without
* importing. In any event, adjust the target line to be
* the one beneath the current on.
*/

if( (line == this->bottom) && v_ateob(v) && b_ateob(b) )
scrolled = e_vscroll( this, 1, 0 );
++line;
}
e_gotorc(this, line, 0); /* go to line that will be replaced */

/* export the bottom line of the buffer if it has something
* in it
*/

if( this->bottom >= b_nrows(b)-1 && !scrolled )
{
row = b_row(b);
b_gotorc (b, b_nrows(b)-1, 0);
export (this, b, this->file_off + b_row(b) );
b_gotorc (b, row, 0);
}

/* Scroll everything below current line down a notch and
* put cursor at start of new line.
*/

b_opendown(b,' ');
if( this->update )
v_scroll_region(v, -1, 0, 0, v_row(v), v_ncols(v)-1,
v_nrows(v)-1 );
e_gotorc(this, line, 0);

/* Update file size and tell file-manager to insert line at
* current position
*/

bottom(this, +1); /* update the file size */
return (this->insert) ? (*this->insert)( this, line ) : 1 ;
}
/*------------------------------------------------------------*/
void e_cleartoeol( win *const this )
{
this->dirty = 1;
b_cleartoeol( &this->b,' ');
if( this->update )
v_cleartoeol( &this->v );
monitor(this, UPDATE);
}


  3 Responses to “Category : Files from Magazines
Archive   : PJ96.ZIP
Filename : EDITOR.C

  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/