home *** CD-ROM | disk | FTP | other *** search
- /******************* 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 ********************/
-
- /*
- * 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. One disadvantage of not using buffers is that block
- * operations can be slow. The most complicated routine in this editor is by
- * far "move_copy_delete_overlay_block( window )". I put some comments in,
- * but it is still a bitch. Come to think of it, most of these block functions
- * are a bitch.
- *
- * Maybe in the next version I'll use buffers to speed up block operations.
- *
- * In tde, version 1.1, I separated the BOX and LINE actions. LINE actions
- * are a LOT faster, now. Still need to speed up BOX 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.
- *
- * 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
- *
- * This modification of Douglas Thomson's code is released into the
- * public domain, Frank Davis. You may distribute it freely.
- */
-
- #include <bios.h>
- #include "tdestr.h"
- #include "common.h"
- #include "tdefunc.h"
- #include "define.h"
-
-
- /*
- * Name: mark_block
- * Purpose: To record the position of the start of the block in the file.
- * Date: June 5, 1991
- * Passed: window: information required to access 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.
- */
- void 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 */
-
- win = window;
- file = win->file_info;
- if (win->rline > file->length)
- return;
- 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;
-
- /*
- * 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;
- }
- }
- }
- file->block_type = type;
- file->dirty = GLOBAL;
- } else
- error( WARNING, win->bottom_line,
- "a block is already defined in another file" );
- }
-
-
- /*
- * Name: unmark_block
- * 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 block is unmarked then redraw the screen(s).
- */
- void 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;
- }
- }
-
-
- /*
- * Name: restore_marked_block
- * Purpose: To restore block beginning and ending row after an editing function
- * Date: June 5, 1991
- * Passed: window: information required to access 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
- * Purpose: To prepare a window/file for a block read, move or copy.
- * Date: June 5, 1991
- * Passed: window: 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.
- */
- int prepare_block( WINDOW *window, text_ptr text_line, int lend, int bc )
- {
- register int pad; /* amount of padding to be added */
- register char *source; /* source for block moves */
-
- copy_line( text_line, window->bottom_line );
-
- /*
- * work out how much padding is required to extend the current
- * line to the cursor position
- */
-
- pad = bc - lend;
-
- /*
- * make room for the padding spaces
- */
- source = g_status.line_buff + lend;
- memmove( source+pad, source, pad+2 );
-
- /*
- * insert the padding spaces
- */
- memset( source, ' ', pad );
- un_copy_line( text_line, window, FALSE );
- return( pad );
- }
-
-
- /*
- * Name: pad_dest_line
- * Purpose: To prepare a window/file for a block move or copy.
- * Date: June 5, 1991
- * Passed: window: current window
- * dest_file: pointer to file information.
- * dest_line: pointer to line in file to prepare.
- * 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.
- */
- void pad_dest_line( WINDOW *window, file_infos *dest_file, text_ptr dest_line)
- {
- /*
- * put linefeed in line_buff. dest_line should be pointing to
- * file->end_text - 1. since we inserted line feed, increment file length.
- */
- g_status.line_buff[0] = '\n';
- g_status.line_buff[1] = CONTROL_Z;
- g_status.copied = TRUE;
- un_copy_line( dest_line, window, FALSE );
- ++dest_file->length;
- }
-
-
- /*
- * Name: move_copy_delete_overlay_block
- * Purpose: Master BOX, STREAM, or LINE routine.
- * Date: June 5, 1991
- * Passed: window: information required to access current window
- * Notes: Operations on BOXs, STREAMs, or LINEs require several common
- * operations. All require finding the beginning and ending marks.
- * The big differences are whether to delete the source block, copy
- * the source block, or leave the source block marked.
- * This routine will handle block operations across files. Since one
- * must determine the relationship of source and destination blocks
- * within a file, it is relatively easy to expand this relationship
- * across files. There are several caveats. Most deal with the
- * difference between LINE and BOX operations others deal with
- * differences between operations within a file and operations
- * across files.
- * This is probably the most complicated routine in the editor. It
- * is not easy to understand.
- */
- void move_copy_delete_overlay_block( WINDOW *window )
- {
- int action;
- WINDOW *source_window; /* source window for block moves */
- text_ptr source; /* source for block moves */
- text_ptr dest; /* destination for block moves */
- text_ptr p; /* temporary text pointer */
- long number; /* number of characters for block moves */
- int lens; /* length of source line */
- int lend; /* length of destination line */
- int add; /* characters being added from another line */
- int block_len; /* length of the block */
- text_ptr block_start; /* start of block in file */
- text_ptr block_end; /* end of block in file - not same for LINE or BOX */
- char block_buff[BUFF_SIZE+2];
- int prompt_line;
- int same; /* are these files the same */
- int source_first; /* is source file lower in memory than dest */
- file_infos *source_file, *dest_file;
- int rcol, bc, ec; /* temporary column variables */
- int xbc, xec; /* temporary column variables */
- long rline; /* temporary real line variable */
- long br, er, li; /* temporary line variables */
- long dest_add; /* number of bytes added to destination file */
- long source_sub; /* number of bytes sub from source file */
- long diff;
- long block_num; /* starting number for block number */
- long block_inc; /* increment to use for block number */
- int block_just; /* left or right justify numbers? */
- unsigned long block_size;
- int block_type;
- int fill_char;
- WINDOW s_w, d_w; /* a couple of temporary WINDOWs for BOX stuff */
- char *ltol = "Error: line would be too long.";
- int padded_file;
- WINDOW *w;
-
- /*
- * initialize block variables
- */
- un_copy_line( window->cursor, window, TRUE );
- if (g_status.marked == FALSE)
- return;
- switch (g_status.command) {
- case MoveBlock :
- action = MOVE;
- break;
- case DeleteBlock :
- action = DELETE;
- break;
- case CopyBlock :
- action = COPY;
- break;
- case KopyBlock :
- action = KOPY;
- break;
- case FillBlock :
- action = FILL;
- break;
- case OverlayBlock :
- action = OVERLAY;
- break;
- case NumberBlock :
- action = NUMBER;
- break;
- }
- source_file = g_status.marked_file;
- 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;
- block_start = source_file->block_start;
- block_end = source_file->block_end;
- block_type = source_file->block_type;
- dest = window->cursor = cpf( window->cursor );
- rline = window->rline;
-
- /*
- * 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;
- dest_add = source_sub = 0;
-
- /*
- * if this is a LINE action, put the text below the current line
- */
- if (block_type == LINE && action != DELETE)
- if ((p = find_next( dest )) != NULL)
- dest = p;
- /*
- * 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.
- */
- same = FALSE;
- if (action == FILL) {
- if (block_type == BOX) {
- if (get_block_fill_char( window, &fill_char ) == ERROR)
- return;
- dest = block_start;
- same = TRUE;
- } else {
- error( WARNING, prompt_line, "can only fill box blocks" );
- return;
- }
- }
- if (action == NUMBER) {
- if (block_type == BOX) {
- if (get_block_numbers( window, &block_num, &block_inc, &block_just )
- == ERROR)
- return;
- dest = block_start;
- same = TRUE;
- } else {
- error( WARNING, prompt_line, "can only number box blocks" );
- return;
- }
- }
- 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;
- } 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 = cpf( block_end );
- /*
- * a block moved to within the block itself has no effect
- */
- else if (action == MOVE)
- return;
- } 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) || (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 = cpf( block_end );
- rcol = ec + 1;
- rline = er;
- } else if (action == MOVE)
- return;
- }
- }
- }
- }
- }
-
- /*
- * must know if source of block is before or after destination
- */
- source_first = FALSE;
- if (ptoul( dest ) > ptoul( source_file->block_start ))
- source_first = TRUE;
- if (same && block_type == BOX) {
- if ( rline >= br)
- source_first = TRUE;
- }
-
- /*
- * work out how much has to be moved
- */
- if (block_type == BOX) {
- block_size = ((ec+1) - bc) * ((er+1) - br);
- if (action != DELETE)
- block_size += ((rcol+1) * ((er+1) - br));
- else
- block_size = 0;
- } else if (block_type == LINE || block_type == STREAM) {
- if (action == COPY || action == KOPY)
- block_size = ptoul( block_end ) - ptoul( block_start );
- else
- block_size = 0;
- } else
- return;
-
- /*
- * check that there is room to add block to file
- */
- if (ptoul( g_status.end_mem ) + block_size >= ptoul( g_status.max_mem )) {
- error( WARNING, prompt_line, "not enough memory for block" );
- return;
- }
-
- /*
- * set the command to word wrap so the un_copy_line function will
- * not display the lines while doing block stuff.
- */
- g_status.command = WordWrap;
-
- /*
- * 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
- */
- if (block_type == BOX) {
- block_len = (ec+1) - bc;
- if (action != DELETE && action != FILL) {
- if (rcol + block_len > MAX_LINE_LENGTH) {
- error( WARNING, prompt_line, ltol );
- return;
- }
- } else if (action == FILL)
- block_fill( block_buff, fill_char, block_len );
- } else if (block_type == LINE) {
- block_len = 0;
- if (action == OVERLAY) {
- error( WARNING, prompt_line, "can only overlay blocks" );
- return;
- }
- } else if (block_type == STREAM) {
- lend = linelen( block_end );
- 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) {
- error( WARNING, prompt_line, ltol );
- return;
- }
- }
-
- 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 = linelen( block_start );
-
- /*
- * if we had to move the destination of the STREAM COPY or KOPY
- * to the end of the STREAM block, then dest and window->cursor
- * 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 (ptoul( dest ) == ptoul( window->cursor ))
- add = linelen( dest );
- 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) {
- error( WARNING, prompt_line, ltol );
- return;
- }
-
- /*
- * 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) {
- error( WARNING, prompt_line, ltol );
- return;
- }
- }
- }
-
- /*
- * all block actions go forward thru file - check those pointers
- */
- source = cpf( block_start );
- dest = cpf( dest );
- if (block_type == LINE || block_type == STREAM) {
- if (block_type == STREAM) {
- dup_window_info( &s_w, source_window );
- dup_window_info( &d_w, window );
- s_w.rline = br;
- d_w.rline = rline;
-
- /*
- * pad the start of the STREAM block if needed.
- */
- lens = linelen( block_start );
- if (lens < bc+1) {
- add = prepare_block( &s_w, block_start, lens, bc );
- if (br != er)
- block_end += add;
- if (source_first)
- dest += add;
- }
- block_start += bc;
- source = cpf( block_start );
-
- /*
- * pad the end of the STREAM block if needed.
- */
- lens = linelen( block_end );
- if (lens < ec+1) {
- add = prepare_block( &s_w, block_end, lens, ec+1 );
- if (source_first)
- dest += add;
- }
- block_end += ec + 1;
-
- /*
- * pad the destination line if necessary
- */
- lend = linelen( dest );
- if (action==MOVE || action==COPY || action==KOPY) {
- if (lend < rcol+1) {
- add = prepare_block( &d_w, dest, lend, rcol );
- if (!source_first) {
- source += add;
- block_start += add;
- block_end += add;
- }
- }
- dest += rcol;
- }
- }
-
- diff = ptoul( block_end ) - ptoul( block_start );
- dest_add = source_sub = diff;
- if (action != DELETE) {
- p = addltop( diff, dest );
- number = ptoul( g_status.end_mem ) - ptoul( dest );
- hw_move( p, dest, number );
- g_status.end_mem = addltop( diff, g_status.end_mem);
- }
- if (action != DELETE && !source_first)
- source = addltop( diff, source );
- if (action == COPY || action == KOPY || action == MOVE)
- hw_move( dest, source, diff );
- if (action == DELETE || action == MOVE) {
- p = addltop( diff, source );
- number = ptoul( g_status.end_mem ) - ptoul( p );
- hw_move( source, p, number );
- g_status.end_mem = addltop( -diff, g_status.end_mem);
- }
- if (action == DELETE)
- dest_add = 0;
- else if (action == COPY || action == KOPY)
- source_sub = 0;
- diff = block_type == LINE ? (er+1l) - br : er - br;
- if (action == COPY || action == KOPY || action == MOVE)
- dest_file->length += diff;
- if (action == DELETE || action == MOVE)
- source_file->length -= diff;
- if (action == DELETE && source_window->rline >= br) {
- source_window->rline -= diff;
- if (source_window->rline < br)
- source_window->rline = br;
- }
- /*
- * the block action is now complete. restore all the start_text and
- * end_text pointers for all open files.
- */
- if (action == MOVE || action == DELETE)
- restore_start_end( dest_file, source_file, dest_add, -source_sub,
- source_first );
- else
- restore_start_end( dest_file, source_file, dest_add, source_sub,
- source_first );
- /*
- * restore all cursors in all windows
- */
- restore_cursors( dest_file, source_file );
- } else {
- padded_file = FALSE;
- dup_window_info( &s_w, source_window );
- dup_window_info( &d_w, window );
- s_w.rline = br;
-
- /*
- * special case for block actions. since block actions always
- * move forward thru the file, overlapping text in an OVERLAY
- * action don't do right. make the operation start at the end
- * of the block and work backwards.
- */
- if (action == OVERLAY && same && rline > br && rline <= er) {
-
- /*
- * see if we need to add padd lines at eof.
- */
- dest_add = rline - br;
- if (dest_add + er > window->file_info->length) {
- dest_add = dest_add - (window->file_info->length - er);
- for (; dest_add > 0; dest_add--) {
- p = addltop( -1, dest_file->end_text );
- pad_dest_line( window, dest_file, p );
- }
- padded_file = TRUE;
- dup_window_info( &s_w, source_window );
- dup_window_info( &d_w, window );
- }
-
- /*
- * move source and dest pointers to the end of the OVERLAY
- */
- for (li=er-br; li > 0; li--) {
- dest = find_next( dest );
- ++d_w.rline;
- source = find_next( source );
- ++s_w.rline;
- }
-
- /*
- * work backwards so the overlapped OVERLAY block don't use
- * overlayed text to fill the block.
- */
- source = cpb( source );
- dest = cpb( dest );
- for (li=er; li>=br; li--, s_w.rline--, d_w.rline--) {
- lens = linelen( source );
- lend = linelen( dest );
- if (lens != 0 || lend != 0) {
- d_w.cursor = dest;
- load_box_buff( block_buff, cpf( source ), bc, ec );
- if (lend < (rcol+1))
- prepare_block( &d_w, cpf( dest ), lend, rcol );
- copy_buff_2file( &d_w, block_buff, cpf( dest ), rcol, block_len,
- OVERLAY );
- }
- source = find_prev( source );
- dest = find_prev( dest );
- }
- } else {
- for (li=br; li<=er; li++, s_w.rline++, d_w.rline++) {
- lens = linelen( source );
- lend = linelen( dest );
-
- if (action == FILL || action == NUMBER) {
- s_w.cursor = source;
- add = 0;
- if (lens < (rcol+1))
- add = prepare_block( &s_w, source, lens, rcol );
- if (action == NUMBER) {
- number_block_buff( block_buff, block_len, block_num, block_just );
- block_num += block_inc;
- }
- add += copy_buff_2file( &s_w, block_buff, source, rcol,
- block_len, action );
-
- /*
- * if we are doing a BOX action and both the source and
- * destination are 0 then we have nothing to do.
- */
- } else if (lens != 0 || lend != 0) {
-
- /*
- * do actions that may require adding to file
- */
- if (action==MOVE || action==COPY || action==KOPY ||
- action == OVERLAY) {
- d_w.cursor = dest;
- xbc = bc;
- xec = ec;
- if (action != OVERLAY && same) {
- if (rcol < bc && rline > br && rline <=er)
- if (li >= rline) {
- xbc = bc + block_len;
- xec = ec + block_len;
- }
- }
- load_box_buff( block_buff, source, xbc, xec );
- add = 0;
- if (lend < (rcol+1))
- add = prepare_block( &d_w, dest, lend, rcol );
- add += copy_buff_2file( &d_w, block_buff, dest, rcol,
- block_len, action );
- if (!source_first)
- source += add;
- }
-
- /*
- * do actions that may require deleting from file
- */
- if (action == MOVE || action == DELETE) {
- s_w.cursor = source;
- if (lens >= (bc + 1)) {
- if (same && action == MOVE)
- lens = linelen( source );
- add = block_len;
- xbc = bc;
- if (lens <= (ec + 1))
- add = lens - bc;
- if (same && action == MOVE) {
- if (rcol < bc && rline >= br && rline <=er)
- if (li >= rline) {
- xbc = bc + block_len;
- if (lens <= (ec + block_len + 1))
- add = lens - xbc;
- }
- }
- delete_box_block( &s_w, source, xbc, add, prompt_line );
- if (action == MOVE && source_first) {
- if (!same || s_w.rline != d_w.rline) {
- dest = addltop( -add, dest );
- dest = cpf( dest );
- }
- }
- }
- }
- }
-
- /*
- * if we are doing any BOX action we need to move the source pointer
- * to the next line.
- */
- source = find_next( source );
-
- /*
- * if we are doing any action other than DELETE, we need to move
- * the destination to the next line in marked block.
- * In BOX mode, we may need to pad the end of the file
- * with a blank line before we process the next line.
- */
- if (action != DELETE && action != FILL && action != NUMBER) {
- p = find_next( dest );
- if (p != NULL && *p != CONTROL_Z)
- dest = p;
- else {
- padded_file = TRUE;
- p = addltop( -1, dest_file->end_text );
- pad_dest_line( window, dest_file, p );
- dest = find_next( dest );
- if (!source_first)
- ++source;
- }
- }
- }
- }
- if (padded_file) {
- w = g_status.window_list;
- while (w != NULL) {
- if (w->file_info == dest_file && w->visible )
- show_size( w );
- w = w->next;
- }
- }
- }
-
- 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) {
- number = (er+1) - br;
- source_file->block_br += number;
- source_file->block_er += number;
- } else if (same && !source_first && window->rline == br &&
- block_type == BOX) {
- add = (ec+1) - bc;
- source_file->block_bc += add;
- source_file->block_ec += add;
- }
- } else if (action != FILL && action != OVERLAY && action != NUMBER)
- unmark_block( window );
- show_avail_mem( );
- g_status.copied = FALSE;
- }
-
-
- /*
- * Name: load_box_buff
- * Purpose: copy the contents of a BOX to a block buffer.
- * Date: June 5, 1991
- * Passed: block_buff: local buffer for block moves
- * source: source line in file
- * bc: beginning column of BOX. used only in BOX operations.
- * ec: ending column of BOX. used only in BOX operations.
- * Notes: For BOX blocks, there are several things to take care of:
- * 1) The BOX begins and ends within a line - just copy the blocked
- * characters to the block buff. 2) the BOX begins within a line but
- * ends past the eol - copy all the characters within the line to
- * the block buff then fill with padding. 3) the BOX begins and
- * ends past eol - fill entire block buff with padding.
- */
- void load_box_buff( char *block_buff, text_ptr source, int bc, int ec )
- {
- int len, pad, avlen;
- register int i;
- register char *bb;
-
- bb = block_buff;
- len = linelen( source );
- /*
- * block start may be past eol
- */
- if (len < ec + 1) {
- /*
- * does block start past eol? - fill with pad
- */
- if (len < bc) {
- pad = (ec + 1) - bc;
- for (i=pad; i>0; i--)
- *bb++ = ' ';
- } else {
- /*
- * block ends past eol - fill with pad
- */
- pad = (ec + 1) - len;
- avlen = len - bc;
- source = source + bc;
- for (i=avlen; i>0; i--)
- *bb++ = *source++;
- for (i=pad; i>0; i--)
- *bb++ = ' ';
- }
- } else {
- /*
- * block is within line - copy block to buffer
- */
- avlen = (ec + 1) - bc;
- source = source + bc;
- for (i=avlen; i>0; i--)
- *bb++ = *source++;
- }
- *bb++ = CONTROL_Z;
- *bb = '\0';
- }
-
-
- /*
- * Name: copy_buff_2file
- * Purpose: copy the contents of block buffer to destination file
- * Date: June 5, 1991
- * Passed: window: current window
- * block_buff: local buffer for moves
- * dest: pointer to destination line in destination file
- * rcol: if in BOX mode, destination column in destination file
- * block_len: if in BOX mode, width of block to copy
- * action: type of block action
- * Notes: In BOX mode, the destination line has already been prepared.
- * Just copy the BOX buffer to the destination line.
- */
- int copy_buff_2file( WINDOW *window, char *block_buff, text_ptr dest,
- int rcol, int block_len, int action )
- {
- register char *s;
- char *d;
- int i;
- int rc;
-
- rc = 0;
- copy_line( dest, window->bottom_line );
- s = g_status.line_buff + rcol;
-
- /*
- * s is pointing to location to perform BOX operation. If we do a
- * FILL or OVERLAY, we do not necessarily add any extra space. If the
- * line does not extend all the thru the BOX then we add.
- * we always add space when we COPY, KOPY, or MOVE
- */
- if (action == FILL || action == OVERLAY || action == NUMBER) {
- i = linelen( s );
- if (i < block_len) {
- rc = block_len - i;
- d = s + rc;
- i = block_len + 1 + linelen( g_status.line_buff ) - rcol;
- memmove( d, s, i );
- }
- } else {
- rc = block_len;
- d = s + block_len;
- i = block_len + 1 + linelen( g_status.line_buff ) - rcol;
- memmove( d, s, i );
- }
- memmove( s, block_buff, block_len );
- un_copy_line( dest, window, FALSE );
- return( rc );
- }
-
-
- /*
- * Name: block_fill
- * Purpose: fill the block buffer with character
- * Date: June 5, 1991
- * Passed: block_buff: local buffer for moves
- * fill_char: fill character
- * block_len: number of columns in block
- * Notes: Fill block_buffer for block_len characters using fill_char. This
- * function is used only for BOX blocks.
- */
- void block_fill( char *block_buff, int fill_char, int block_len )
- {
- memset( block_buff, fill_char, block_len );
- *(block_buff+block_len) = CONTROL_Z;
- }
-
-
- /*
- * Name: number_block_buff
- * Purpose: put a number into the block buffer
- * Date: June 5, 1991
- * Passed: block_buff: local buffer for moves
- * block_len: number of columns in block
- * block_num: long number to fill block
- * just: LEFT or RIGHT justified?
- * Notes: Fill block_buffer for block_len characters with number.
- * This function is used only for BOX blocks.
- */
- void number_block_buff( char *block_buff, int block_len, long block_num,
- int just )
- {
- int len; /* length of number buffer */
- int i;
- char temp[MAX_COLS]; /* buffer for long number to ascii conversion */
-
- block_fill( block_buff, ' ', block_len );
- len = strlen( ltoa( block_num, temp, 10 ) );
- if (just == RIGHT) {
- block_len--;
- len--;
- for (;block_len >= 0 && len >= 0; block_len--, len--)
- block_buff[block_len] = temp[len];
- } else {
- for (i=0; block_len > 0 && i < len; block_len--, i++)
- block_buff[i] = temp[i];
- }
- }
-
-
- /*
- * Name: restore_start_end
- * Purpose: a file has been modified - must restore all start and end pointers
- * Date: June 5, 1991
- * Passed: dest_file: pointer to destination file structure
- * source_file: pointer to source file structure
- * dest_mod: net modifications in the destination file
- * source_mod: net modifications in the source file
- * source_first: we must know which file is stored first in memory
- * Notes: Go through the file list and adjust the start_text and end_text
- * file pointers as needed. There are several cases that must be
- * be considered. 1) destination file and source file could be the
- * same. 2) if the file pointer we're looking at is below both
- * the source and destination, no action is needed. 3) the file
- * we're looking at could be between the source and destination.
- * 4) the file we're looking at could be either source or destination.
- * 5) the file we're looking at could be past both source and dest.
- * Use unsigned longs to compare pointers.
- */
- void restore_start_end( file_infos *df, file_infos *source_file,
- long dest_mod, long source_mod, int source_first )
- {
- int same;
- long net_mod;
- unsigned long sst; /* source start_text - keep these around for if's */
- unsigned long dst; /* destination start_text */
- unsigned long ost; /* open_file start_text */
- register file_infos *open_file;
- register file_infos *dest_file;
-
- dest_file = df;
- net_mod = dest_mod + source_mod;
- sst = ptoul( source_file->start_text );
- dst = ptoul( dest_file->start_text );
- same = sst == dst ? TRUE : FALSE;
- for (open_file=g_status.file_list; open_file != NULL;
- open_file=open_file->next) {
- sst = ptoul( source_file->start_text );
- dst = ptoul( dest_file->start_text );
- ost = ptoul( open_file->start_text );
- if (ost == sst) {
- if (same)
- source_file->end_text = addltop( net_mod, source_file->end_text);
- else if (source_first)
- source_file->end_text = addltop( source_mod,
- source_file->end_text);
- else {
- source_file->start_text = addltop( dest_mod,
- source_file->start_text);
- source_file->end_text = addltop( net_mod, source_file->end_text);
- }
- } else if (ost == dst) {
- if (source_first) {
- dest_file->start_text = addltop( source_mod,
- dest_file->start_text);
- dest_file->end_text = addltop( net_mod, dest_file->end_text);
- } else
- dest_file->end_text = addltop( dest_mod, dest_file->end_text);
- } else if (ost > sst) {
- if (ost < dst) {
- open_file->start_text = addltop( source_mod,
- open_file->start_text);
- open_file->end_text = addltop( source_mod, open_file->end_text);
- } else {
- open_file->start_text = addltop( net_mod, open_file->start_text);
- open_file->end_text = addltop( net_mod, open_file->end_text);
- }
- } else if (ost > dst) {
- if (ost < sst) {
- open_file->start_text = addltop( dest_mod, open_file->start_text);
- open_file->end_text = addltop( dest_mod, open_file->end_text);
- } else {
- open_file->start_text = addltop( net_mod, open_file->start_text);
- open_file->end_text = addltop( net_mod, open_file->end_text);
- }
- }
- }
- }
-
-
- /*
- * Name: restore_cursors
- * Purpose: a file has been modified - must restore all cursor pointers
- * Date: June 5, 1991
- * Passed: dest_file: target file for block actions
- * source_file: source file for block actions
- * Notes: Go through the window list and adjust the cursor pointers
- * as needed. This could be done by using the changes made by
- * the block actions, but it would be a real pain in the neck.
- * I chose to use the brute force approach.
- */
- void restore_cursors( file_infos *dest_file, file_infos *source_file )
- {
- register WINDOW *window;
- register file_infos *file;
- text_ptr p;
- long beg_line, cur_line, test_line;
- unsigned long df, sf, f;
-
- df = ptoul( (text_ptr)dest_file );
- sf = ptoul( (text_ptr)source_file );
- window = g_status.window_list;
- while (window != NULL) {
- file = window->file_info;
- f = ptoul( (text_ptr)file );
- beg_line = 1;
- cur_line = window->rline;
- if (cur_line > file->length) {
- file->end_text = cpb( file->end_text );
- p = find_prev( file->end_text-1 );
- window->cursor = p != NULL ? p : file->start_text;
- window->rline = file->length;
- test_line = cur_line - file->length;
- if (test_line<(long)(window->cline-(window->top_line+window->ruler-1)))
- window->cline -= test_line;
- } else {
- file->start_text = cpf( file->start_text );
- for (p=file->start_text; p!=NULL && beg_line<cur_line; beg_line++)
- p = find_next( p );
- if (p != NULL )
- window->cursor = p;
- else {
- window->cursor = file->start_text;
- cur_line = file->length;
- }
- window->rline = cur_line;
- }
- if (window->rline <= 0l)
- window->rline = 1l;
- if (window->rline < (window->cline - (window->top_line+window->ruler-1)))
- window->cline = (int)window->rline + window->top_line+window->ruler-1;
- if (window->cline < window->top_line + window->ruler)
- window->cline = window->top_line + window->ruler;
- if ((f == df || f == sf) && window->visible )
- show_size( window );
- window = window->next;
- }
- }
-
-
- /*
- * Name: delete_box_block
- * Purpose: delete the marked text
- * Date: June 5, 1991
- * Passed: s_w: source window
- * source: pointer to line with block to delete
- * bc: beginning column of block - BOX mode only
- * add: number of characters in block to delete
- * prompt_line: line to display error message if needed
- * Notes: Used only for BOX blocks. Delete the block.
- */
- void delete_box_block( WINDOW *s_w, text_ptr source, int bc, int add,
- int prompt_line )
- {
- char *s;
- int number;
-
- number = linelen( source ) - bc + 2;
- copy_line( source, prompt_line );
- s = g_status.line_buff + bc + add;
- memmove( s - add, s, number );
- un_copy_line( source, s_w, FALSE );
- }
-
-
- /*
- * Name: check_block
- * Purpose: To check that the block is still valid.
- * Date: June 5, 1991
- * Notes: After some editing, the marked block may not be valid. For example,
- * deleting all the lines in a block in another window. We don't
- * need to keep up with the block text pointers while doing normal
- * editing; however, we need to refresh them before doing block stuff.
- */
- void check_block( void )
- {
- register file_infos *file;
- WINDOW filler;
-
- file = g_status.marked_file;
- if (file == NULL || file->block_br > file->length)
- unmark_block( &filler );
- else {
- if (file->length < file->block_er)
- file->block_er = file->length;
- find_begblock( file );
- find_endblock( file );
- }
- }
-
-
- /*
- * Name: find_begblock
- * Purpose: find the beginning line in file with marked block
- * Date: June 5, 1991
- * Passed: file: file containing marked block
- * Notes: file->block_start contains starting line of marked block.
- */
- void find_begblock( file_infos *file )
- {
- text_ptr next; /* start from beginning of file and go to end */
- long i; /* line counter */
-
- next = cpf( file->start_text );
- for (i=1; i<file->block_br && next != NULL; i++)
- next = find_next( next );
- if (next != NULL)
- file->block_start = next;
- }
-
-
- /*
- * Name: find_endblock
- * Purpose: find the ending line in file with marked block
- * Date: June 5, 1991
- * Passed: file: file containing marked block
- * Notes: If in LINE mode, file->block_end is set to end of line of last
- * line in block. If in BOX mode, file->block_end is set to
- * beginning of last line in marked block. If the search for the
- * ending line of the marked block goes past the eof, set the
- * ending line of the block to the last line in the file.
- */
- void find_endblock( file_infos *file )
- {
- text_ptr next; /* start from beginning of file and go to end */
- long i; /* line counter */
- int end_column;
- register file_infos *fp;
-
- fp = file;
- next = cpf( fp->start_text );
- for (i=1; i<fp->block_er && next != NULL; i++)
- next = find_next( next );
- if (next != NULL) {
- end_column = linelen( next );
- if (next[end_column] == '\n')
- ++end_column;
-
- /*
- * if LINE block somewhere in the file, set block_end to first
- * line past end of marked block.
- */
- fp->block_end = fp->block_type == LINE ? next + end_column : next;
- } else {
-
- /*
- * last line in marked block is NULL. if LINE block, set end to
- * last character in the file. if STREAM or BOX block, set end to
- * start of last line in file. ending row, or er, is then set to
- * file length.
- */
- fp->end_text = cpb( fp->end_text );
- if (fp->block_type == LINE)
- fp->block_end = fp->end_text - 1;
- else {
- next = find_prev( fp->end_text - 1 );
- fp->block_end = next != NULL ? next : fp->end_text - 1;
- }
- fp->block_er = fp->length;
- }
- }
-
-
- /*
- * Name: block_write
- * Purpose: To write the currently marked block to a disk file.
- * Date: June 5, 1991
- * Passed: window: information required to access current window
- * Notes: If the file already exists, the user gets to choose whether
- * to overwrite or append.
- */
- void block_write( WINDOW *window )
- {
- int prompt_line;
- int rc;
- char buff[MAX_COLS+2]; /* buffer for char and attribute */
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- text_ptr block_start; /* start of block in file */
- text_ptr block_end; /* end of block in file */
- file_infos *file;
- int block_type;
-
- /*
- * make sure block is marked OK
- */
- un_copy_line( window->cursor, window, TRUE );
- check_block( );
- if (g_status.marked == TRUE) {
- prompt_line = window->bottom_line;
- file = g_status.marked_file;
- block_start = file->block_start;
- block_end = file->block_end;
- block_type = file->block_type;
-
- /*
- * find out which file to write to
- */
- save_screen_line( 0, prompt_line, line_buff );
- if (get_name( "Filename: ", prompt_line, g_status.rw_name,
- g_display.message_color ) == OK) {
- /*
- * if the file exists, find out whether to overwrite or append
- */
- rc = hw_fattrib( g_status.rw_name );
- if (rc == OK) {
- set_prompt( "File exists. Overwrite or Append? (o/a): ",
- prompt_line );
- switch (get_oa( )) {
- case A_OVERWRITE :
- change_mode( g_status.rw_name, prompt_line );
- combine_strings( buff, "writing block to '",
- g_status.rw_name, "'" );
- s_output( buff, prompt_line, 0, g_display.message_color );
- rc = hw_save( g_status.rw_name, block_start, block_end,
- block_type );
- if (rc == ERROR)
- error( WARNING, prompt_line, "could not write block" );
- break;
- case A_APPEND :
- combine_strings( buff, "appending block to '",
- g_status.rw_name, "'" );
- s_output( buff, prompt_line, 0, g_display.message_color );
- rc = hw_append( g_status.rw_name, block_start, block_end,
- block_type );
- if (rc == ERROR)
- error( WARNING, prompt_line, "could not append block" );
- break;
- }
- } else if (rc != ERROR) {
- combine_strings( buff, "writing block to '", g_status.rw_name,
- "'" );
- s_output( buff, prompt_line, 0, g_display.message_color );
- if (hw_save( g_status.rw_name, block_start, block_end,
- block_type ) == ERROR)
- error( WARNING, prompt_line, "could not write block" );
- }
- }
- restore_screen_line( 0, prompt_line, line_buff );
- }
- }
-
-
- /*
- * Name: block_print
- * Purpose: Print an entire file or the currently marked block.
- * Date: June 5, 1991
- * Passed: window: information required to access current window
- * Notes: With the added Critical Error Handler routine, let's fflush
- * the print buffer first.
- */
- void block_print( WINDOW *window )
- {
- char answer[MAX_COLS]; /* entire file or just marked block? */
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- int col, func;
- int prompt_line;
- text_ptr block_start; /* start of block in file */
- text_ptr block_end; /* end of block in file */
- file_infos *file;
- int block_type;
- char *p;
- int len;
- int bc, ec, last_c;
- unsigned long lbegin, lend;
- long l;
- int color;
-
- color = g_display.message_color;
- un_copy_line( window->cursor, window, TRUE );
- prompt_line = window->bottom_line;
- save_screen_line( 0, prompt_line, line_buff );
- /*
- * print entire file or just marked block?
- */
- strcpy( answer, "Print file or block? (f/b): " );
- col = strlen( answer );
- s_output( answer, prompt_line, 0, color );
- eol_clear( col, prompt_line, g_display.text_color );
- xygoto( col, prompt_line );
- func = col = 0;
- while (col != 'f' && col != 'F' && col != 'b' && col != 'B' &&
- func != AbortCommand) {
- col = getkey( );
- func = getfunc( col );
- if (col == ESC)
- func = AbortCommand;
- }
- fflush( stdprn );
- if (ceh.flag == ERROR)
- func = AbortCommand;
- if (func != AbortCommand) {
- file = window->file_info;
- if (col == 'f' || col == 'F') {
- block_start = file->start_text;
- block_end = cpb( file->end_text ) - 1;
- block_type = NOTMARKED;
- l = file->length;
- } else if (col == 'b' || col == 'B') {
- check_block( );
- if (g_status.marked == TRUE) {
- file = g_status.marked_file;
- block_start = file->block_start;
- block_end = file->block_end;
- block_type = file->block_type;
- l = file->block_er + 1l - file->block_br;
- } else
- col = AbortCommand;
- }
- if (block_type == LINE) {
- block_end = cpb( block_end );
- block_end = find_prev( block_end );
- }
-
- if (col != AbortCommand) {
- eol_clear( 0, prompt_line, color );
- s_output( "Printing line of Press ESC to cancel.",
- prompt_line, 0, color );
- ltoa( l, answer, 10 );
- s_output( answer, prompt_line, 25, color );
- xygoto( 14, prompt_line );
- block_start = cpf( block_start );
- if (block_type == BOX || block_type == STREAM) {
- bc = file->block_bc;
- ec = file->block_ec;
- last_c = ec + 1 - bc;
- }
- p = g_status.line_buff;
- lend = ptoul( block_end );
- for (l=1,col=OK; ptoul( block_start ) <= lend && col == OK; l++) {
- ltoa( l, answer, 10 );
- s_output( answer, prompt_line, 14, color );
- g_status.copied = FALSE;
- if (block_type == BOX) {
- load_box_buff( p, block_start, bc, ec );
- *(p+last_c) = '\n';
- *(p+last_c+1) = CONTROL_Z;
- } else if (block_type == STREAM && l == 1) {
- len = linelen( block_start );
- lbegin = ptoul( block_start );
- block_start += bc < len ? bc : len;
- copy_line( block_start, prompt_line );
- if (lbegin == lend) {
- if (len > ec) {
- *(p+last_c) = '\n';
- *(p+last_c+1) = CONTROL_Z;
- }
- }
- } else if (block_type == STREAM && ptoul( block_start )==lend) {
- copy_line( block_start, prompt_line );
- if (linelen( block_start ) > ec) {
- *(p+ec+1) = '\n';
- *(p+ec+2) = CONTROL_Z;
- }
- } else
- copy_line( block_start, prompt_line );
- len = find_CONTROL_Z( p );
- if (fwrite( p, sizeof( char ), len, stdprn ) < (unsigned)len ||
- ceh.flag == ERROR)
- col = ERROR;
- if (col != ERROR) {
- fputc( '\r', stdprn );
- if (ceh.flag == ERROR)
- col = ERROR;
- }
- block_start = find_next( block_start );
- if (block_start == NULL)
- block_start = block_end + 1;
- if (col == OK && _bios_keybrd( mode.enh_kbd ? 0x11 : 0x01 )) {
- col = getkey( );
- col = col == ESC ? AbortCommand : getfunc( col );
- if (col != AbortCommand)
- col = OK;
- }
- }
- g_status.copied = FALSE;
- if (ceh.flag != ERROR)
- fflush( stdprn );
- }
- }
- g_status.copied = FALSE;
- restore_screen_line( 0, prompt_line, line_buff );
- }
-
-
- /*
- * Name: get_block_fill_char
- * Purpose: get the character to fill marked block.
- * Date: June 5, 1991
- * Passed: window: information required to access current window
- * c: address of character to fill block
- */
- int get_block_fill_char( WINDOW *window, int *c )
- {
- char answer[MAX_COLS];
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- register int col;
- int prompt_line;
- int rc;
-
- rc = OK;
- prompt_line = window->bottom_line;
- save_screen_line( 0, prompt_line, line_buff );
- strcpy( answer, "Enter character to fill block (ESC to exit): " );
- s_output( answer, prompt_line, 0, g_display.message_color );
- col = strlen( answer );
- eol_clear( col, prompt_line, g_display.text_color );
- xygoto( col, prompt_line );
- col = getkey( );
- if (col >= 256)
- rc = ERROR;
- else
- *c = col;
- restore_screen_line( 0, prompt_line, line_buff );
- return( rc );
- }
-
-
- /*
- * Name: get_block_numbers
- * Purpose: get the starting number and increment
- * Date: June 5, 1991
- * Passed: window: information required to access current window
- * block_num: address of number to start numbering
- * block_inc: address of number to add to block_num
- * just: left or right justify numbers in block?
- */
- int get_block_numbers( WINDOW *window, long *block_num, long *block_inc,
- int *just )
- {
- char answer[MAX_COLS];
- int prompt_line;
- register int rc;
- char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
- register int col;
-
- prompt_line = window->bottom_line;
-
- /*
- * don't assume anything on starting number - start w/ null string.
- */
- answer[0] = '\0';
- rc = get_name( "Enter starting number: ", prompt_line, answer,
- g_display.message_color );
- if (answer[0] == '\0')
- rc = ERROR;
- if (rc != ERROR) {
- *block_num = atol( answer );
-
- /*
- * assume increment is 1
- */
- answer[0] = '1';
- answer[1] = '\0';
- rc = get_name( "Enter increment: ", prompt_line, answer,
- g_display.message_color );
- if (answer[0] == '\0')
- rc = ERROR;
- if (rc != ERROR) {
- *block_inc = atol( answer );
-
- /*
- * now, get left or right justification. save contents of screen
- * in a buffer, then write contents of buffer back to screen when
- * we get through w/ justification.
- */
- save_screen_line( 0, prompt_line, line_buff );
- strcpy( answer, "Left or Right justify numbers in block? (l/r): " );
- s_output( answer, prompt_line, 0, g_display.message_color );
- col = strlen( answer );
- eol_clear( col, prompt_line, g_display.text_color );
- xygoto( col, prompt_line );
- rc = get_lr( );
- if (rc != ERROR) {
- *just = rc;
- rc = OK;
- }
- restore_screen_line( 0, prompt_line, line_buff );
- }
- }
-
- /*
- * if everything is everything then return code = OK.
- */
- return( rc );
- }
-
-
- /*
- * Name: block_expand_tabs
- * Purpose: Expand tabs in a marked block.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: Tabs are expanded using the current tab interval.
- * Lines are checked to make sure they are not too long.
- */
- void block_expand_tabs( WINDOW *window )
- {
- int prompt_line;
- int len;
- int tab;
- int tab_size;
- int dirty;
- int spaces;
- int net_change;
- text_ptr p; /* pointer to block line */
- file_infos *file;
- WINDOW *sw, s_w;
- long er;
- int i;
- char *b, *d, *lb;
-
- /*
- * make sure block is marked OK and that this is a LINE block
- */
- prompt_line = window->bottom_line;
- un_copy_line( window->cursor, window, TRUE );
- check_block( );
- if (g_status.marked == TRUE) {
-
- file = g_status.marked_file;
- if (file->block_type != LINE) {
- error( WARNING, prompt_line,
- "can only expand tabs in line blocks" );
- return;
- }
-
- /*
- * set the command to word wrap so the un_copy_line function will
- * not display the lines while expanding.
- */
- g_status.command = WordWrap;
-
- /*
- * initialize everything
- */
- dirty = FALSE;
- tab_size = mode.tab_size;
- sw = g_status.window_list;
- for (; ptoul( sw->file_info ) != ptoul( file );)
- sw = sw->next;
- dup_window_info( &s_w, sw );
- p = cpf( file->block_start );
- er = file->block_er;
- lb = g_status.line_buff;
- s_w.rline = file->block_br;
- for (; s_w.rline<=er; s_w.rline++) {
-
- /*
- * use the line buffer to expand LINE blocks.
- */
- tab = FALSE;
- len = linelen( p );
- net_change = 0;
- g_status.copied = FALSE;
-
- copy_line( p, prompt_line );
- for (b=lb, i=1; *b != CONTROL_Z; b++) {
-
- /*
- * each line in the LINE block is copied to the g_status.line_buff.
- * look at the text in the buffer and expand tabs.
- */
- if (*b == '\t') {
- tab = TRUE;
- spaces = i % tab_size;
- if (spaces)
- spaces = tab_size - spaces;
- if (spaces) {
- d = b + spaces;
- memmove( d, b, linelen( b )+2 );
- }
- memset( b, ' ', spaces+1 );
- net_change += spaces;
- i += spaces + 1;
- b += spaces;
- } else
- i++;
- }
-
- /*
- * if any tabs were found, write g_status.line_buff to file.
- */
- if (tab) {
- un_copy_line( p, &s_w, TRUE );
- dirty = TRUE;
- }
- p = find_next( p );
- }
-
- /*
- * IMPORTANT: we need to reset the copied flag because the cursor may
- * not necessarily be on the last line of the block.
- */
- g_status.copied = FALSE;
- if (dirty) {
- check_block( );
- file->dirty = GLOBAL;
- }
- }
- }
-
-
- /*
- * Name: block_trim_trailing
- * Purpose: Trim trailing space in a LINE block.
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- * Notes: Use copy_line and un_copy_line to do the work.
- */
- void block_trim_trailing( WINDOW *window )
- {
- int prompt_line;
- text_ptr p; /* pointer to block line */
- file_infos *file;
- WINDOW *sw, s_w;
- long er;
- int trailing; /* save trailing setting */
-
- /*
- * make sure block is marked OK and that this is a LINE block
- */
- prompt_line = window->bottom_line;
- un_copy_line( window->cursor, window, TRUE );
- check_block( );
- if (g_status.marked == TRUE) {
-
- trailing = mode.trailing;
- mode.trailing = TRUE;
- file = g_status.marked_file;
- if (file->block_type != LINE) {
- error( WARNING, prompt_line,
- "can only trim trailing space in line blocks" );
- return;
- }
-
- /*
- * set the command to word wrap so the un_copy_line function will
- * not display the lines while trimming.
- */
- g_status.command = WordWrap;
-
- /*
- * initialize everything
- */
- sw = g_status.window_list;
- for (; ptoul( sw->file_info ) != ptoul( file );)
- sw = sw->next;
- dup_window_info( &s_w, sw );
- p = cpf( file->block_start );
- er = file->block_er;
- s_w.rline = file->block_br;
- for (; s_w.rline<=er; s_w.rline++) {
-
- /*
- * use the line buffer to trim space.
- */
- copy_line( p, prompt_line );
- un_copy_line( p, &s_w, TRUE );
- p = find_next( p );
- }
-
- /*
- * IMPORTANT: we need to reset the copied flag because the cursor may
- * not necessarily be on the last line of the block.
- */
- g_status.copied = FALSE;
- file->dirty = GLOBAL;
- mode.trailing = trailing;
- }
- }
-
-
- /*
- * Name: block_convert_case
- * Purpose: convert characters to lower case, upper case, or strip hi bits
- * Date: June 5, 1991
- * Passed: window: pointer to current window
- */
- void block_convert_case( WINDOW *window )
- {
- int len;
- int block_type;
- text_ptr begin;
- text_ptr end; /* pointer to block line */
- register file_infos *file;
- unsigned long number;
- unsigned long er;
- unsigned int count;
- int bc, ec;
- int block_len;
- void (*char_func)( text_ptr, unsigned int );
-
- /*
- * make sure block is marked OK
- */
- un_copy_line( window->cursor, window, TRUE );
- check_block( );
- if (g_status.marked == TRUE) {
-
- /*
- * set char_func() to the required block function in tdeasm.c
- */
- switch (g_status.command) {
- case BlockUpperCase :
- char_func = upper_asm;
- break;
- case BlockLowerCase :
- char_func = lower_asm;
- break;
- case BlockStripHiBit :
- char_func = strip_asm;
- break;
- }
-
- file = g_status.marked_file;
- block_type = file->block_type;
- bc = file->block_bc;
- ec = file->block_ec;
-
- begin = cpf( file->block_start );
- end = cpf( file->block_end );
-
- /*
- * if this is a LINE or STREAM block, process characters in
- * chunks of 0xf000.
- */
- if (block_type == LINE || block_type == STREAM) {
- if (block_type == STREAM) {
- len = linelen( begin );
- begin += len < bc ? len : bc;
- len = linelen( end );
- end += len < ec ? len : ec + 1;
- }
- number = ptoul( end ) - ptoul( begin );
- count = 0xf000;
- begin = nptos( begin );
- while (number > count) {
- (*char_func)( begin, count );
- number -= count;
- begin = nptos( begin + count );
- }
- /*
- * now less than 0xf000 is left, so finish off the conversion
- */
- (*char_func)( begin, (unsigned)number );
-
- /*
- * For BOX blocks, process characters by lines
- */
- } else {
- begin = cpf( begin );
- er = file->block_er;
- block_len = ec + 1 - bc;
- for (number=file->block_br; number <= er; number++) {
- len = linelen( begin );
- if (len > bc) {
- count = len >= ec ? block_len : len - bc;
- (*char_func)( begin+bc, count );
- }
- begin = find_next( begin );
- }
- }
-
- /*
- * IMPORTANT: we need to reset the copied flag because the cursor may
- * not necessarily be on the last line of the block.
- */
- g_status.copied = FALSE;
- file->dirty = GLOBAL;
- file->modified = TRUE;
- }
- }
-