📄 block.c
字号:
source_window = g_status.window_list;
for (; ptoul( source_window->file_info ) != ptoul( source_file );)
source_window = source_window->next;
prompt_line = window->bottom_line;
dest_file = window->file_info;
check_block( );
if (g_status.marked == FALSE)
return( ERROR );
block_start = source_file->block_start;
block_end = source_file->block_end;
if (block_start == NULL || block_end == NULL)
return( ERROR );
block_type = source_file->block_type;
if (block_type != LINE && block_type != STREAM && block_type != BOX)
return( ERROR );
dest = window->ll;
rline = window->rline;
if (dest->len == EOF)
return( ERROR );
rc = OK;
/*
* set up Beginning Column, Ending Column, Beginning Row, Ending Row
*/
bc = source_file->block_bc;
ec = source_file->block_ec;
br = source_file->block_br;
er = source_file->block_er;
/*
* if we are BOX FILLing or BOX NUMBERing, beginning column is bc,
* not the column of cursor
*/
rcol = (action == FILL || action == NUMBER) ? bc : window->rcol;
/*
* must find out if source and destination file are the same.
* it don't matter with FILL and DELETE - those actions only modify the
* source file.
*/
source_first = same = FALSE;
if (action == FILL) {
if (block_type == BOX) {
if (get_block_fill_char( window, &fill_char ) == ERROR)
return( ERROR );
dest = block_start;
same = TRUE;
} else {
/*
* can only fill box blocks.
*/
error( WARNING, prompt_line, block2 );
return( ERROR );
}
}
block_inc = 1;
if (action == NUMBER) {
if (block_type == BOX) {
if (get_block_numbers( window, &block_num, &block_inc, &block_just )
== ERROR)
return( ERROR );
dest = block_start;
same = TRUE;
} else {
/*
* can only number box blocks.
*/
error( WARNING, prompt_line, block3a );
return( ERROR );
}
}
if (action == SWAP) {
if (block_type != BOX) {
/*
* can only swap box blocks.
*/
error( WARNING, prompt_line, block3b );
return( ERROR );
}
}
if (source_file == dest_file && action != DELETE && action != FILL) {
same = TRUE;
if (block_type == BOX && action == MOVE) {
if (rline == br && (rcol >= bc && rcol <= ec))
/*
* a block moved to within the block itself has no effect
*/
return( ERROR );
} else if (block_type == LINE || block_type == STREAM) {
if (rline >= br && rline <= er) {
if (block_type == LINE) {
/*
* if COPYing or KOPYing within the block itself, reposition the
* destination to the next line after the block (if it exists)
*/
if (action == COPY || action == KOPY)
dest = block_end;
/*
* a block moved to within the block itself has no effect
*/
else if (action == MOVE)
return( ERROR );
} else {
/*
* to find out if cursor is in a STREAM block we have to do
* a few more tests. if cursor is on the beginning row or
* ending row, then check the beginning and ending column.
*/
if ((rline > br && rline < er) ||
(br == er && rcol >= bc && rcol <= ec) ||
(br != er && ((rline == br && rcol >= bc) ||
(rline == er && rcol <= ec)))) {
/*
* if the cursor is in middle of STREAM, make destination
* the last character following the STREAM block.
*/
if (action == COPY || action == KOPY) {
dest = block_end;
rcol = ec + 1;
rline = er;
} else if (action == MOVE)
return( ERROR );
}
}
}
}
}
if (br < rline)
source_first = TRUE;
/*
* 1. can't create lines greater than g_display.line_length
* 2. if we are FILLing a BOX - fill block buff once right here
* 3. only allow overlaying BOXs
*/
block_len = (ec+1) - bc;
if (block_type == BOX) {
if (action != DELETE && action != FILL) {
if (rcol + block_len > MAX_LINE_LENGTH) {
/*
* line too long
*/
error( WARNING, prompt_line, ltol );
return( ERROR );
}
}
} else if (block_type == LINE) {
block_len = 0;
if (action == OVERLAY) {
/*
* can only overlay box blocks
*/
error( WARNING, prompt_line, block5 );
return( ERROR );
}
} else if (block_type == STREAM) {
if (action == OVERLAY) {
/*
* can only overlay box blocks
*/
error( WARNING, prompt_line, block5 );
return( ERROR );
}
lend = block_end->len;
if (action == DELETE || action == MOVE) {
/*
* Is what's left on start of STREAM block line plus what's left at
* end of STREAM block line too long?
*/
if (lend > ec)
lend -= ec;
else
lend = 0;
if (bc + lend > MAX_LINE_LENGTH) {
/*
* line too long
*/
error( WARNING, prompt_line, ltol );
return( ERROR );
}
}
if (action != DELETE) {
/*
* We are doing a MOVE, COPY, or KOPY. Find out if what's on the
* current line plus the start of the STREAM line are too long.
* Then find out if end of the STREAM line plus what's left of
* the current line are too long.
*/
lens = block_start->len;
/*
* if we had to move the destination of the STREAM COPY or KOPY
* to the end of the STREAM block, then dest and window->ll->line
* will not be the same. In this case, set length to length of
* first line in STREAM block. Then we can add the residue of
* the first line in block plus residue of the last line of block.
*/
if (dest->line == window->ll->line)
add = dest->len;
else
add = lens;
/*
* Is current line plus start of STREAM block line too long?
*/
if (lens > bc)
lens -= bc;
else
lens = 0;
if (rcol + lens > MAX_LINE_LENGTH) {
/*
* line too long
*/
error( WARNING, prompt_line, ltol );
return( ERROR );
}
/*
* Is residue of current line plus residue of STREAM block line
* too long?
*/
if (add > bc)
add -= bc;
else
add = 0;
if (lend > ec)
lend -= ec;
else
lend = 0;
if (add + lend > MAX_LINE_LENGTH) {
/*
* line too long
*/
error( WARNING, prompt_line, ltol );
return( ERROR );
}
}
if (ptoul( block_start ) == ptoul( block_end )) {
block_type = BOX;
block_len = (ec+1) - bc;
}
}
if (mode.do_backups == TRUE) {
switch (action) {
case MOVE :
case DELETE :
case COPY :
case KOPY :
case SWAP :
window->file_info->modified = TRUE;
rc = backup_file( window );
break;
}
switch (action) {
case MOVE :
case DELETE :
case FILL :
case NUMBER :
case SWAP :
source_window->file_info->modified = TRUE;
if (rc != ERROR)
rc = backup_file( source_window );
break;
}
}
source = block_start;
assert( block_start != NULL );
assert( block_start->len != EOF );
assert( block_end != NULL );
assert( block_end->len != EOF );
if (block_type == LINE)
do_line_block( window, source_window, action,
source_file, dest_file, block_start, block_end,
source, dest, br, er, &rc );
else if (block_type == STREAM)
do_stream_block( window, source_window, action,
source_file, dest_file, block_start, block_end,
source, dest, rline, br, er, bc, ec, rcol, &rc );
else
do_box_block( window, source_window, action,
source_file, dest_file, source, dest, br, er,
block_inc, rline, block_num, block_just, fill_char,
same, block_len, bc, ec, rcol, &rc );
dest_file->modified = TRUE;
dest_file->dirty = GLOBAL;
if (action == MOVE || action == DELETE || action == FILL || action==NUMBER) {
source_file->modified = TRUE;
source_file->dirty = GLOBAL;
}
/*
* unless we are doing a KOPY, FILL, NUMBER, or OVERLAY we need to unmark
* the block. if we just did a KOPY, the beginning and ending may have
* changed. so, we must readjust beginning and ending rows.
*/
if (action == KOPY) {
if (same && !source_first && block_type == LINE && rc != ERROR) {
number = (er+1) - br;
source_file->block_br += number;
source_file->block_er += number;
}
} else if (action != FILL && action != OVERLAY && action != NUMBER)
unmark_block( window );
show_avail_mem( );
g_status.copied = FALSE;
return( rc );
}
/*
* Name: do_line_block
* Purpose: delete, move, copy, or kopy a LINE block
* Date: April 1, 1993
* Passed: window: pointer to current window
* Passed: window: pointer to destination window (current window)
* source_window: pointer to source window
* action: block action -- KOPY, MOVE, etc...
* source_file: pointer to source file structure
* dest_file: pointer to destination file
* block_start: pointer to first node in block
* block_end: pointer to last node in block
* source: pointer to source node
* dest: pointer to destination node
* br: beginning line number in marked block
* er: ending line number in marked block
* rc: return code
*/
void do_line_block( WINDOW *window, WINDOW *source_window, int action,
file_infos *source_file, file_infos *dest_file,
line_list_ptr block_start, line_list_ptr block_end,
line_list_ptr source, line_list_ptr dest,
long br, long er, int *rc )
{
line_list_ptr temp_ll; /* temporary list pointer */
text_ptr l;
int lens; /* length of source line */
long li; /* temporary line variables */
long diff;
if (action == COPY || action == KOPY) {
assert( br >= 1 );
assert( br <= source_file->length );
assert( er >= br );
assert( er <= source_file->length );
for (li=br; li <= er && *rc == OK; li++) {
lens = source->len;
assert( lens * sizeof(char) < MAX_LINE_LENGTH );
l = (text_ptr)my_malloc( lens * sizeof(char), rc );
temp_ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), rc );
if (*rc == OK) {
if (lens > 0)
_fmemcpy( l, source->line, lens );
temp_ll->line = l;
temp_ll->len = lens;
temp_ll->dirty = TRUE;
if (dest->next != NULL) {
dest->next->prev = temp_ll;
temp_ll->next = dest->next;
dest->next = temp_ll;
temp_ll->prev = dest;
} else {
temp_ll->next = dest;
if (dest->prev != NULL)
dest->prev->next = temp_ll;
temp_ll->prev = dest->prev;
dest->prev = temp_ll;
if (temp_ll->prev == NULL)
window->file_info->line_list = temp_ll;
}
dest = temp_ll;
source = source->next;
} else {
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -