home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best Objectech Shareware Selections
/
UNTITLED.iso
/
boss
/
word
/
text
/
024
/
tab.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-04
|
27KB
|
953 lines
/*
* Most of the tab routines were gathered into one file. There is an
* assembly routine tdeasm.c that expands tabs. That routine is in
* assembly to keep screen updates fairly fast.
*
* The basic detab and entab algorithms were supplied by Dave Regan,
* regan@jacobs.cs.orst.edu
*
* For more info on tabs see:
*
* Brian W. Kernighan and P. J. Plauger, _Software Tools_, Addison-
* Wesley Publishing Company, Reading, Mass, 1976, pp 18-27 and 35-39,
* ISBN 0-20103669-X.
*
* The above reference gives info on fixed and variable tabs. But when
* it comes to non-fixed tabs, I prefer "smart" tabs. Being lazy, I find
* it more convenient to let the editor figure variable tabs for me.
*
*
* New editor name: TDE, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, version 1.0
* Date: July 29, 1991, version 1.1
* Date: October 5, 1991, version 1.2
* Date: January 20, 1992, version 1.3
* Date: February 17, 1992, version 1.4
* Date: April 1, 1992, version 1.5
* Date: June 5, 1992, version 2.0
* Date: October 31, 1992, version 2.1
* Date: April 1, 1993, version 2.2
* Date: June 5, 1993, version 3.0
*
* This program is released into the public domain, Frank Davis.
* You may distribute it freely.
*/
#include "tdestr.h"
#include "common.h"
#include "tdefunc.h"
#include "define.h"
/*
* Name: tab_key
* Purpose: To make the necessary changes after the user types the tab key.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: If in insert mode, then this function adds the required
* number of spaces in the file.
* If not in insert mode, then tab simply moves the cursor right
* the required distance.
*/
int tab_key( WINDOW *window )
{
int spaces; /* the spaces to move to the next tab stop */
char *source; /* source for block move to make room for c */
char *dest; /* destination for block move */
int pad;
int len;
register int rcol;
int old_bcol;
register WINDOW *win; /* put window pointer in a register */
int rc;
win = window;
if (win->ll->len == EOF)
return( OK );
rcol = win->rcol;
old_bcol = win->bcol;
show_ruler_char( win );
/*
* work out the number of spaces to the next tab stop
*/
if (mode.smart_tab)
spaces = next_smart_tab( win );
else
spaces = mode.ltab_size - (rcol % mode.ltab_size);
assert( spaces >= 0 );
assert( spaces < MAX_LINE_LENGTH );
rc = OK;
if (mode.insert && rcol + spaces < g_display.line_length) {
copy_line( win->ll );
detab_linebuff( );
/*
* work out how many characters need to be inserted
*/
len = g_status.line_buff_len;
pad = rcol > len ? rcol - len : 0;
if (len + pad + spaces >= g_display.line_length) {
/*
* line too long to add
*/
error( WARNING, win->bottom_line, ed1 );
rc = ERROR;
g_status.copied = FALSE;
} else {
if (pad > 0 || spaces > 0) {
source = g_status.line_buff + rcol - pad;
dest = source + pad + spaces;
assert( len + pad - rcol >= 0 );
assert( len + pad - rcol < MAX_LINE_LENGTH );
memmove( dest, source, len + pad - rcol );
/*
* if padding was required, then put in the required spaces
*/
assert( pad + spaces >= 0 );
assert( pad + spaces < MAX_LINE_LENGTH );
memset( source, ' ', pad + spaces );
g_status.line_buff_len += pad + spaces;
entab_linebuff( );
}
win->ll->dirty = TRUE;
win->file_info->dirty = GLOBAL;
show_changed_line( win );
rcol += spaces;
win->ccol += spaces;
}
} else if (rcol + spaces <= g_display.line_length) {
/*
* advance the cursor without changing the text underneath
*/
rcol += spaces;
win->ccol += spaces;
}
check_virtual_col( win, rcol, win->ccol );
if (old_bcol != win->bcol) {
make_ruler( win );
show_ruler( win );
}
return( rc );
}
/*
* Name: backtab
* Purpose: To make the necessary changes after the user presses the backtab.
* Date: November 1, 1991
* Passed: window: pointer to current window
* Notes: If in insert mode, then this function subs the required
* number of spaces in the file.
* If not in insert mode, then tab simply moves the cursor left
* the required distance.
*/
int backtab( WINDOW *window )
{
int spaces; /* the spaces to move to the next tab stop */
char *source; /* source for block move to make room for c */
char *dest; /* destination for block move */
int pad;
int len;
register int rcol;
int old_bcol;
register WINDOW *win; /* put window pointer in a register */
win = window;
rcol = win->rcol;
if (win->ll->len == EOF || win->rcol == 0)
return( OK );
old_bcol = win->bcol;
show_ruler_char( win );
/*
* work out the number of spaces to the previous tab stop
*/
if (mode.smart_tab)
spaces = prev_smart_tab( win );
else
spaces = win->rcol % mode.ltab_size;
if (spaces == 0)
spaces = mode.ltab_size;
copy_line( win->ll );
detab_linebuff( );
len = g_status.line_buff_len;
if (mode.insert && rcol - spaces < len) {
pad = rcol > len ? rcol - len : 0;
if (pad > 0 || spaces > 0) {
/*
* if padding was required, then put in the required spaces
*/
if (pad > 0) {
assert( rcol - pad >= 0 );
assert( pad < MAX_LINE_LENGTH );
source = g_status.line_buff + rcol - pad;
dest = source + pad;
assert( pad >= 0 );
assert( pad < MAX_LINE_LENGTH );
memmove( dest, source, pad );
memset( source, ' ', pad );
g_status.line_buff_len += pad;
}
source = g_status.line_buff + rcol;
dest = source - spaces;
assert( len + pad - rcol >= 0 );
assert( len + pad - rcol < MAX_LINE_LENGTH );
memmove( dest, source, len + pad - rcol );
g_status.line_buff_len -= spaces;
entab_linebuff( );
}
win->ll->dirty = TRUE;
win->file_info->dirty = GLOBAL;
show_changed_line( win );
rcol -= spaces;
win->ccol -= spaces;
} else {
/*
* move the cursor without changing the text underneath
*/
rcol -= spaces;
if (rcol < 0)
rcol = 0;
win->ccol -= spaces;
}
check_virtual_col( win, rcol, win->ccol );
if (old_bcol != win->bcol) {
make_ruler( win );
show_ruler( win );
}
return( OK );
}
/*
* Name: next_smart_tab
* Purpose: To find next smart tab
* Date: June 5, 1992
* Passed: window: pointer to the current window
* Notes: To find a smart tab 1) find the first non-blank line above the
* current line, 2) find the first non-blank character after
* column of the cursor.
*/
int next_smart_tab( WINDOW *window )
{
register int spaces; /* the spaces to move to the next tab stop */
text_ptr s; /* pointer to text */
line_list_ptr ll;
register WINDOW *win; /* put window pointer in a register */
int len;
/*
* find first previous non-blank line above the cursor.
*/
win = window;
ll = win->ll->prev;
while (ll != NULL && is_line_blank( ll->line, ll->len ))
ll = ll->prev;
if (ll != NULL) {
s = ll->line;
/*
* if cursor is past the eol of the smart line, lets find the
* next fixed tab.
*/
if (window->rcol >= find_end( s, ll->len ))
spaces =