⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block.c

📁 编辑器Tdedit3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************  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 + -