📄 block.c
字号:
/******************* start of original comments ********************/
/*
* Written by Douglas Thomson (1989/1990)
*
* This source code is released into the public domain.
*/
/*
* Name: dte - Doug's Text Editor program - block commands module
* Purpose: This file contains all the commands than manipulate blocks.
* File: block.c
* Author: Douglas Thomson
* System: this file is intended to be system-independent
* Date: October 1, 1989
*/
/********************* end of original comments ********************/
/*
* In the DTE editor, Doug only supported functions for STREAM blocks.
*
* The block routines have been EXTENSIVELY rewritten. This editor uses LINE,
* STREAM, and BOX blocks. That is, one may mark entire lines, streams of
* characters, or column blocks. Block operations are done in place. There
* are no paste and cut buffers. In limited memory situations, larger block
* operations can be carried out. Block operations can be done within or
* across files.
*
* In TDE, version 1.1, I separated the BOX and LINE actions.
*
* In TDE, version 1.3, I put STREAM blocks back in. Added block upper case,
* block lower case, and block strip high bit.
*
* In TDE, version 1.4, I added a block number function. Here at our lab,
* I often need to number samples, lines, etc..., comes in fairly useful.
*
* In TDE, version 2.0, I added a box block sort function.
*
* In TDE, version 2.0e, I added BlockFixUUE, and BlockEmailReply.
*
* In TDE, version 2.2, the big text buffer was changed to a double linked list.
* all characters in the line of each node must be accurately counted.
*
* 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 modification of Douglas Thomson's code 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: mark_block
* Class: primary editor function
* Purpose: To record the position of the start of the block in the file.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: Assume the user will mark begin and end of a block in either
* line, stream, or box mode. If the user mixes types, then block
* type defaults to current block type.
*/
int mark_block( WINDOW *window )
{
int type;
int num;
long lnum;
register file_infos *file; /* temporary file variable */
register WINDOW *win; /* put window pointer in a register */
int rc;
win = window;
file = win->file_info;
if (win->rline > file->length || win->ll->len == EOF)
return( ERROR );
if (g_status.marked == FALSE) {
g_status.marked = TRUE;
g_status.marked_file = file;
}
if (g_status.command == MarkBox)
type = BOX;
else if (g_status.command == MarkLine)
type = LINE;
else if (g_status.command == MarkStream)
type = STREAM;
else
return( ERROR );
rc = OK;
/*
* define blocks for only one file. it is ok to modify blocks in any window
* pointing to original marked file.
*/
if (file == g_status.marked_file) {
/*
* mark beginning and ending column regardless of block mode.
*/
if (file->block_type == NOTMARKED) {
file->block_ec = file->block_bc = win->rcol;
file->block_er = file->block_br = win->rline;
} else {
if (file->block_br > win->rline) {
file->block_br = win->rline;
if (file->block_bc < win->rcol && type != STREAM)
file->block_ec = win->rcol;
else
file->block_bc = win->rcol;
} else {
if (type != STREAM) {
file->block_ec = win->rcol;
file->block_er = win->rline;
} else {
if (win->rline == file->block_br &&
win->rline == file->block_er) {
if (win->rcol < file->block_bc)
file->block_bc = win->rcol;
else
file->block_ec = win->rcol;
} else if (win->rline == file->block_br)
file->block_bc = win->rcol;
else {
file->block_ec = win->rcol;
file->block_er = win->rline;
}
}
}
/*
* if user marks ending line less than beginning line then switch
*/
if (file->block_er < file->block_br) {
lnum = file->block_er;
file->block_er = file->block_br;
file->block_br = lnum;
}
/*
* if user marks ending column less than beginning column then switch
*/
if ((file->block_ec < file->block_bc) && (type != STREAM ||
(type == STREAM && file->block_br == file->block_er))) {
num = file->block_ec;
file->block_ec = file->block_bc;
file->block_bc = num;
}
}
/*
* block type in now defined. if user mixes block types then block
* is defined as current block type.
*/
if (file->block_type != NOTMARKED) {
/*
* if block type goes to BOX, check to make sure ec is greater than
* or equal to bc. ec can be less than bc in STREAM blocks.
*/
if (type == BOX) {
if (file->block_ec < file->block_bc) {
num = file->block_ec;
file->block_ec = file->block_bc;
file->block_bc = num;
}
}
}
assert( file->block_er >= file->block_br );
file->block_type = type;
file->dirty = GLOBAL;
} else {
/*
* block already defined
*/
error( WARNING, win->bottom_line, block1 );
rc = ERROR;
}
return( rc );
}
/*
* Name: unmark_block
* Class: primary editor function
* Purpose: To set all block information to NULL or 0
* Date: June 5, 1991
* Passed: arg_filler: variable to match array of function pointers prototype
* Notes: Reset all block variables if marked, otherwise return.
* If a marked block is unmarked then redraw the screen(s).
*/
int unmark_block( WINDOW *arg_filler )
{
register file_infos *marked_file;
if (g_status.marked == TRUE) {
marked_file = g_status.marked_file;
g_status.marked = FALSE;
g_status.marked_file = NULL;
marked_file->block_start = NULL;
marked_file->block_end = NULL;
marked_file->block_bc = marked_file->block_ec = 0;
marked_file->block_br = marked_file->block_er = 0l;
if (marked_file->block_type)
marked_file->dirty = GLOBAL;
marked_file->block_type = NOTMARKED;
}
return( OK );
}
/*
* Name: restore_marked_block
* Class: helper function
* Purpose: To restore block beginning and ending row after an editing function
* Date: June 5, 1991
* Passed: window: pointer to current window
* net_change: number of bytes added or subtracted
* Notes: If a change has been made before the marked block then the
* beginning and ending row need to be adjusted by the number of
* lines added or subtracted from file.
*/
void restore_marked_block( WINDOW *window, int net_change )
{
long length;
register file_infos *marked_file;
if (g_status.marked == TRUE && net_change != 0) {
marked_file = g_status.marked_file;
length = marked_file->length;
/*
* restore is needed only if a block is defined and window->file_info is
* same as marked file and there was a net change in file length.
*/
if (marked_file == window->file_info) {
/*
* if cursor is before marked block then adjust block by net change.
*/
if (marked_file->block_br > window->rline) {
marked_file->block_br += net_change;
marked_file->block_er += net_change;
marked_file->dirty = GLOBAL;
/*
* if cursor is somewhere in marked block don't restore, do redisplay
*/
} else if (marked_file->block_er >= window->rline)
marked_file->dirty = GLOBAL;
/*
* check for lines of marked block beyond end of file
*/
if (marked_file->block_br > length)
unmark_block( window );
else if (marked_file->block_er > length) {
marked_file->block_er = length;
marked_file->dirty = GLOBAL;
}
}
}
}
/*
* Name: prepare_block
* Class: helper function
* Purpose: To prepare a window/file for a block read, move or copy.
* Date: June 5, 1991
* Passed: window: pointer to current window
* file: pointer to file information.
* text_line: pointer to line in file to prepare.
* lend: line length.
* bc: beginning column of BOX.
* Notes: The main complication is that the cursor may be beyond the end
* of the current line, in which case extra padding spaces have
* to be added before the block operation can take place.
* this only occurs in BOX and STREAM operations.
* since we are padding a line, do not trim trailing space.
*/
int prepare_block( WINDOW *window, line_list_ptr ll, int bc )
{
register int pad = 0; /* amount of padding to be added */
register int len;
assert( bc >= 0 );
assert( bc < MAX_LINE_LENGTH );
assert( ll->len != EOF );
assert( g_status.copied == FALSE );
copy_line( ll );
detab_linebuff( );
len = g_status.line_buff_len;
pad = bc - len;
if (pad > 0) {
/*
* insert the padding spaces
*/
assert( pad >= 0 );
assert( pad < MAX_LINE_LENGTH );
memset( g_status.line_buff+len, ' ', pad );
g_status.line_buff_len += pad;
}
/*
* if mode.inflate_tabs, let's don't entab the line until we get
* thru processing this line, e.g. copying, numbering....
*/
return( un_copy_line( ll, window, FALSE ) );
}
/*
* Name: pad_dest_line
* Class: helper function
* Purpose: To prepare a window/file for a block move or copy.
* Date: June 5, 1991
* Passed: window: pointer to current window
* dest_file: pointer to file information.
* dest_line: pointer to line in file to prepare.
* ll: pointer to linked list node to insert new node
* Notes: We are doing a BOX action (except DELETE). We have come
* to the end of the file and have no more lines. All this
* routine does is add a blank line to file.
*/
int pad_dest_line( WINDOW *window, file_infos *dest_file, line_list_ptr ll )
{
int rc;
text_ptr l;
line_list_ptr new_node;
rc = OK;
l = NULL;
new_node = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
if (rc == OK) {
new_node->len = 0;
new_node->dirty = FALSE;
new_node->line = l;
if (ll->next != NULL) {
ll->next->prev = new_node;
new_node->next = ll->next;
ll->next = new_node;
new_node->prev = ll;
} else {
new_node->next = ll;
if (ll->prev != NULL)
ll->prev->next = new_node;
new_node->prev = ll->prev;
ll->prev = new_node;
if (new_node->prev == NULL)
window->file_info->line_list = new_node;
}
++dest_file->length;
} else {
/*
* file too big
*/
error( WARNING, window->bottom_line, block4 );
if (new_node != NULL)
my_free( new_node );
rc = ERROR;
}
return( rc );
}
/*
* Name: move_copy_delete_overlay_block
* Class: primary editor function
* Purpose: Master BOX, STREAM, or LINE routine.
* Date: June 5, 1991
* Passed: window: pointer to current window
* Notes: Operations on BOXs, STREAMs, or LINEs require several common
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -