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

📄 ed.c

📁 一个开源著名的TDE编辑器源代码
💻 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 - main editor module * Purpose: This file contains the main editor module, and a number of the *           smaller miscellaneous editing commands. *          It also contains the code for dispatching commands. * File:    ed.c * Author:  Douglas Thomson * System:  this file is intended to be system-independent * Date:    October 1, 1989 * I/O:     file being edited *          files read or written *          user commands and prompts * Notes:   see the file "dte.doc" for general program documentation *//*********************  end of original comments   ********************//* * The basic editor routines have been EXTENSIVELY rewritten.  I have added * support for lines longer than 80 columns and I have added line number * support.  I like to know the real line number that editor functions are * working on and I like to know the total number of lines in a file. * * I rewrote the big series of ifs in the dispatch subroutine.  It is now * an array of pointers to functions.  We know what function to call as soon * as a key is pressed.  It is also makes it easier to implement a configuration * utility and macros. * * I added a few functions that I use quite often and I deleted a few that I * rarely use.  Added are Split Line, Join Line, and Duplicate Line.  Deleted * are Goto Marker 0-9 (others?). * * ************ In TDE 1.3, I put Goto Marker 0-9 back in.  *************** * * I felt that the insert routine should be separated into two routines.  One * for inserting the various combinations of newlines and one for inserting * ASCII and extended ASCII characters. * * One of Doug's design considerations was keeping screen updates to a minimum. * I have expanded upon that idea and added support for updating windows * LOCALly, GLOBALly, or NOT_LOCALly.  For example, scrolling in one window * does not affect the text in another window - LOCAL update.  Adding, deleting, * or modifying text in one window may affect text in other windows - GLOBAL * update.  Sometimes, updates to the current window are handled in the task * routines so updates to other windows are done NOT_LOCALly. * * In version 2.2, the big text buffer scheme was replaced by a double *  linked list. * * 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 * Date:             August 29, 1993, version 3.1 * Date:             November 13, 1993, version 3.2 * Date:             June 5, 1994, version 4.0 * Date:             December 5, 1998, version 5.0 (jmh) * * This modification of Douglas Thomson's code is released into the * public domain, Frank Davis.   You may distribute it freely. */#include "tdestr.h"     /* typedefs for global variables */#include "define.h"     /* editor function defs */#include "tdefunc.h"    /* prototypes for all functions in tde */#include "common.h"#if !defined( __DOS16__ )#include <setjmp.h>jmp_buf editor_jmp;#endif#if defined( __WIN32__ )extern int    handle_mouse;     /* defined in win32/console.c */extern HANDLE conin;#endifextern long found_rline;        /* defined in findrep.c *//* * Name:    insert_newline * Purpose: insert a newline * Date:    June 5, 1991 * Passed:  window:  pointer to current window * Notes:   There a several ways to insert a line into a file:  1) pressing *          a key, 2) word wrap, 3) any others? *          When doing word wrap or format paragraph, don't show any changes. *            Wait until the function finishes then show all changes at once. */int  insert_newline( TDE_WIN *window ){text_ptr source;        /* source for block move to make room for c */text_ptr dest;          /* destination for block move */int  len;               /* length of current line */int  split_len;int  add;               /* characters to be added (usually 1 in insert mode) */int  rcol;int  rc;long length;int  carriage_return;int  split_line;int  wordwrap;int  dirty;int  old_bcol;register TDE_WIN *win;  /* put window pointer in a register */file_infos *file;       /* pointer to file structure in current window */line_list_ptr new_node;   rc = OK;   win = window;   file = win->file_info;   length = file->length;   wordwrap = mode.word_wrap;   switch (g_status.command) {      case WordWrap :         carriage_return = TRUE;         split_line = FALSE;         break;      case AddLine  :         split_line = carriage_return = FALSE;         break;      case SplitLine :         split_line = carriage_return = TRUE;         break;      case Rturn :      default    :         /*          * if file is opened in BINARY mode, lets keep the user from          *   unintentially inserting a line feed into the text.          */         if (file->crlf == BINARY)            return( next_line( win ) );         show_ruler_char( win );         carriage_return = TRUE;         split_line = FALSE;         break;   }   /*    * make window temporarily invisible to the un_copy_line function    */   win->visible = FALSE;   old_bcol = win->bcol;   new_node = new_line( DIRTY, &rc );   if (rc == OK) {      if (win->ll->len != EOF) {         file->modified = TRUE;         if (mode.do_backups == TRUE)            rc = backup_file( win );         copy_line( win->ll, win, TRUE );         len = g_status.line_buff_len;         split_len = 0;         /* jmh - added the AddLine test, since the current line is unchanged */         if (win->rcol < len  &&  g_status.command != AddLine)            win->ll->type |= DIRTY;         if (carriage_return || split_line) {            if (win->rcol < len) {               split_len = len - win->rcol;               len = win->rcol;            }         }         source = g_status.line_buff + len;         g_status.line_buff_len = len;         if (un_copy_line( win->ll, win, TRUE, TRUE ) == OK) {            assert( split_len >= 0 );            assert( split_len < MAX_LINE_LENGTH );            memmove( g_status.line_buff, source, split_len );            g_status.line_buff_len = len = split_len;            g_status.copied = TRUE;         } else            rc = ERROR;      } else {         g_status.line_buff_len = len = 0;         g_status.copied = TRUE;      }      if (rc == OK) {         /*          * we are somewhere in the list and we need to insert the new node.          *  if we are anywhere except the EOF node, insert the new node          *  after the current node.  if the current node is the EOF node,          *  insert the new node before the EOF node.  this keeps the          *  EOF node at the end of the list.          */         if (win->ll->next == NULL) {            insert_node( file, win->ll, new_node );            win->ll = new_node;         } else            insert_node( file, win->ll, new_node );         rc = un_copy_line( new_node, win, FALSE, TRUE );         adjust_windows_cursor( win, 1 );         restore_marked_block( win, 1 );         if (win->ll->len != EOF && file->syntax != NULL)            syntax_check( win->ll, file->syntax->info );         syntax_check_lines( new_node, file->syntax );         if (file->dirty != GLOBAL)            file->dirty = NOT_LOCAL;         if (length == 0l || wordwrap || win->cline == win->bottom_line)            file->dirty = GLOBAL;         else if (!split_line)            update_line( win );         /*          * If the cursor is to move down to the next line, then update          *  the line and column appropriately.          */         if (rc == OK  &&  (carriage_return || split_line)) {            dirty = file->dirty;            if (win->cline < win->bottom_line)               win->cline++;            inc_line( win, TRUE );            rcol = win->rcol;            old_bcol = win->bcol;            if (win->ll->next != NULL) {               if (mode.indent || wordwrap) {                  /*                   * autoindentation is required. Match the indentation of                   *  the first line above that is not blank.                   */                  add = find_left_margin( wordwrap == FIXED_WRAP ?                                            win->ll : win->ll->prev, wordwrap,                                          file->inflate_tabs, file->ptab_size );                  assert( add >= 0 );                  assert( add < MAX_LINE_LENGTH );                  copy_line( win->ll, win, TRUE );                  len = g_status.line_buff_len;                  source = g_status.line_buff;                  if (len + add > MAX_LINE_LENGTH)                     add = MAX_LINE_LENGTH - len;                  dest = source + add;                  assert( len >= 0);                  assert( len < MAX_LINE_LENGTH );                  memmove( dest, source, len );                  /*                   * now put in the autoindent characters                   */                  assert( add >= 0 );                  assert( add < MAX_LINE_LENGTH );                  memset( source, ' ', add );                  win->rcol = add;                  g_status.line_buff_len += add;                  shift_block( file, win->rline, 0, add );                  rc = un_copy_line( win->ll, win, TRUE, TRUE );               } else                  win->rcol = 0;            }            if (rc == OK  &&  split_line) {               win->rline--;               win->ll = win->ll->prev;               if (win->cline > win->top_line)                  win->cline--;               win->rcol = rcol;            }            check_virtual_col( win, win->rcol, win->ccol );            if (dirty == GLOBAL || file->dirty == LOCAL || wordwrap)               file->dirty = GLOBAL;            else               file->dirty = dirty;         }      } else         my_free( new_node );   } else      error( WARNING, window->bottom_line, main4 );   /*    * record that file has been modified    */   win->visible = TRUE;   if (rc == OK) {      if (file->dirty != GLOBAL)         my_scroll_down( win );      show_size( win );      show_avail_mem( );      if (old_bcol != win->bcol)         show_ruler( win );   }   return( rc );}/* * Name:    adjust_for_tabs * Purpose: handle tabs in the line buffer in an appropriate manner * Date:    May 24, 1998 (jmh) * Passed:  rcol:  pointer to current (real) column *          inflate_tabs: are tabs being expanded? *          tab_size: size of tab expansion * Returns: rcol adjusted if needed * Notes:   If tabs are deflated or inflated, call detab_linebuff(), but if *          real tabs are in use and it's insert mode, then leave the tabs *          alone and adjust rcol.  However, if we're in a tab, insert spaces *          before it. * jmh 981129: must be updating the cursor in the normal direction. * jmh 991010: if it's not normal direction, it's overwrite mode. */static void adjust_for_tabs( int *rcol, int inflate_tabs, int tab_size ){int   col;int   len;int   pad;text_ptr source;text_ptr dest;   if (inflate_tabs == 2 && mode.insert) {      len   = g_status.line_buff_len;      col   = *rcol;      *rcol = entab_adjust_rcol( g_status.line_buff, len, col, tab_size );      pad   = col - detab_adjust_rcol( g_status.line_buff, *rcol, tab_size );      if (*rcol < len && g_status.line_buff[*rcol] == '\t') {         if (pad > 0 && len + pad < MAX_LINE_LENGTH) {            source = g_status.line_buff + *rcol;            dest   = source + pad;            memmove( dest, source, len - *rcol );            memset( source, ' ', pad );            g_status.line_buff_len += pad;            *rcol += pad;         }      } else if (*rcol == len)         *rcol += pad;   } else      detab_linebuff( inflate_tabs, tab_size );}/* * Name:    insert_overwrite * Purpose: To make the necessary changes after the user has typed a normal *           printable character * Date:    June 5, 1991 * Passed:  window:  pointer to current window * * jmh 980524: use a "real tabs" mode. If insert is on, don't detab the line. * jmh 981129: added the ability to update the cursor in different directions, *              however, it always functions in overwrite mode (which is *              assumed to be on). * jmh 020913: tab character in tab mode will use tab_key() with fixed tabs; *              will probably cause problems in overwrite mode, but overwriting *              tab characters should be done in deflate mode, anyway. */int  insert_overwrite( TDE_WIN *window ){text_ptr source;        /* source for block move to make room for c */text_ptr dest;          /* destination for block move */int  len;               /* length of current line */int  pad;               /* padding to add if cursor beyond end of line */int  add;               /* characters to be added (usually 1 in insert mode) */int  rcol;register TDE_WIN *win;  /* put window pointer in a register */int  rc = OK;int  dir = mode.cur_dir; /* direction to update cursor */   win = window;   if (win->ll->len != EOF && g_status.key_pressed < 256) {      rcol = win->rcol;      /*       * first check we have room - the editor can not       *  cope with lines wider than MAX_LINE_LENGTH       */      if (rcol >= MAX_LINE_LENGTH) {         /*          * cannot insert more characters          */         error( WARNING, win->bottom_line, ed2 );         rc = ERROR;      } else if (g_status.key_pressed == '\t' && win->file_info->inflate_tabs) {         add = mode.smart_tab;         mode.smart_tab = FALSE;         rc = tab_key( win );         mode.smart_tab = add;      } else {         copy_line( win->ll, window, FALSE );         adjust_for_tabs( &rcol, win->file_info->inflate_tabs,                                 win->file_info->ptab_size );         /*          * work out how many characters need to be inserted          */         len = g_status.line_buff_len;         pad = rcol > len ? rcol - len : 0;         if (mode.insert || rcol >= len || (dir == CUR_LEFT && rcol == 0)) {            /*             * inserted characters, or overwritten characters at the end of             *  the line, are inserted.             */            add = 1;            if (dir == CUR_LEFT && len == 0)               ++add;         } else            /*             *  and no extra space is required to overwrite existing characters             */            add = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -