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

📄 tab.c

📁 一个开源著名的TDE编辑器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Most of the tab routines were gathered into one file.  There is an * assembly routine tdeasm.c that expands tabs.  That routine is in * assembly to keep screen updates fairly fast. (jmh 991202: moved it here.) * * The basic detab and entab algorithms were supplied by Dave Regan, *   regan@jacobs.cs.orst.edu * * For more info on tabs see: * *     Brian W. Kernighan and P. J. Plauger, _Software Tools_, Addison- *     Wesley Publishing Company, Reading, Mass, 1976, pp 18-27 and 35-39, *     ISBN 0-20103669-X. * * The above reference gives info on fixed and variable tabs.  But when *  it comes to non-fixed tabs, I prefer "smart" tabs.  Being lazy, I find *  it more convenient to let the editor figure variable tabs for me. * * jmh 990501: lots of changes due to tabs becoming file dependent. This also *             causes lots of changes in other files that are not documented. * * 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 program 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:    detab_to_col * Purpose: copy the line to the line buffer, detabbing up to rcol * Author:  Jason Hood * Date:    October 4, 1999 * Passed:  rcol: column to stop detabbing *          tabs: tab mode *          size: size of tabs * Notes:   helper function for tab_key() and backtab() using real tabs. * * jmh 030305: due to the extra restoring functionality of copy_line(), made *              this routine more similar to adjust_for_tabs(). */static void detab_to_col( int rcol, int tabs, int size ){text_ptr p;int  len;   if (tabs == 2) {      len = g_status.line_buff_len;      if (len > 0) {         rcol = entab_adjust_rcol( g_status.line_buff, len, rcol, size );         if (rcol < len)            len = ++rcol;         else            rcol = len;         p = tabout( g_status.line_buff, &len, size, 0 );         memmove( g_status.line_buff + len, g_status.line_buff + rcol,                  g_status.line_buff_len - rcol );         memcpy( g_status.line_buff, p, len );         g_status.line_buff_len += len - rcol;      }   } else      detab_linebuff( tabs, size );}/* * Name:    tab_key * Purpose: To make the necessary changes after the user types the tab key. * Date:    June 5, 1991 * Passed:  window:  pointer to current window * Notes:   If in insert mode, then this function adds the required *           number of spaces in the file. *          If not in insert mode, then tab simply moves the cursor right *           the required distance. */int  tab_key( TDE_WIN *window ){int  spaces;            /* the spaces to move to the next tab stop */text_ptr source;        /* source for block move to make room for c */text_ptr dest;          /* destination for block move */int  pad;int  len;register int rcol;register TDE_WIN *win;   /* put window pointer in a register */file_infos *file;int  rc;   win = window;   if (win->ll->len == EOF)      return( OK );   show_ruler_char( win );   rcol = win->rcol;   file = win->file_info;   /*    * work out the number of spaces to the next tab stop    */   if (mode.smart_tab)      spaces = next_smart_tab( win );   else      spaces = file->ltab_size - (rcol % file->ltab_size);   assert( spaces >= 0 );   assert( spaces < MAX_LINE_LENGTH );   rc = OK;   if (rcol + spaces < MAX_LINE_LENGTH) {      if (mode.insert && !file->read_only) {         copy_line( win->ll, win, FALSE );         detab_to_col( rcol, file->inflate_tabs, file->ptab_size );         /*          * work out how many characters need to be inserted          */         len = g_status.line_buff_len;         pad = rcol > len ? rcol - len : 0;         if (len + pad + spaces >= MAX_LINE_LENGTH) {            /*             *  line too long to add             */            error( WARNING, win->bottom_line, ed1 );            rc = ERROR;            g_status.copied = FALSE;         } else {            if (pad > 0  || spaces > 0) {               source = g_status.line_buff + rcol - pad;               dest = source + pad + spaces;               shift_tabbed_block( file );               assert( len + pad - rcol >= 0 );               assert( len + pad - rcol < MAX_LINE_LENGTH );               memmove( dest, source, len + pad - rcol );               /*                * if padding was required, then put in the required spaces                */               assert( pad + spaces >= 0 );               assert( pad + spaces < MAX_LINE_LENGTH );               memset( source, ' ', pad + spaces );               g_status.line_buff_len += pad + spaces;               shift_block( file, win->rline, rcol, spaces );               entab_linebuff( file->inflate_tabs, file->ptab_size );            }            win->ll->type |= DIRTY;            file->modified = TRUE;            file->dirty = GLOBAL;            show_changed_line( win );         }      }      if (rc == OK) {         rcol += spaces;         win->ccol += spaces;         check_virtual_col( win, rcol, win->ccol );      }   }   return( rc );}/* * Name:    backtab * Purpose: To make the necessary changes after the user presses the backtab. * Date:    November 1, 1991 * Passed:  window:  pointer to current window * Notes:   If in insert mode, then this function subs the required *           number of spaces in the file. *          If not in insert mode, then tab simply moves the cursor left *           the required distance. */int  backtab( TDE_WIN *window ){int  spaces;            /* the spaces to move to the next tab stop */text_ptr source;        /* source for block move to make room for c */text_ptr dest;          /* destination for block move */int  pad;int  len;register int rcol;register TDE_WIN *win;   /* put window pointer in a register */file_infos *file;   win  = window;   rcol = win->rcol;   if (win->ll->len == EOF || rcol == 0)      return( OK );   show_ruler_char( win );   file = win->file_info;   /*    * work out the number of spaces to the previous tab stop    */   if (mode.smart_tab)      spaces = prev_smart_tab( win );   else      spaces = rcol % file->ltab_size;   if (spaces == 0)      spaces = file->ltab_size;   copy_line( win->ll, win, FALSE );   detab_to_col( rcol, file->inflate_tabs, file->ptab_size );   len = g_status.line_buff_len;   if (mode.insert && rcol - spaces < len && !file->read_only) {      pad = rcol > len ? rcol - len : 0;      if (pad > 0  || spaces > 0) {         /*          * if padding was required, then put in the required spaces          */         if (pad > 0) {            assert( rcol - pad >= 0 );            assert( pad < MAX_LINE_LENGTH );            source = g_status.line_buff + rcol - pad;            dest = source + pad;            assert( pad >= 0 );            assert( pad < MAX_LINE_LENGTH );            memmove( dest, source, pad );            memset( source, ' ', pad );            g_status.line_buff_len += pad;         }         source = g_status.line_buff + rcol;         dest = source - spaces;         shift_tabbed_block( file );         assert( len + pad - rcol >= 0 );         assert( len + pad - rcol < MAX_LINE_LENGTH );         memmove( dest, source, len + pad - rcol );         g_status.line_buff_len -= spaces;         shift_block( file, win->rline, rcol, -spaces );         entab_linebuff( file->inflate_tabs, file->ptab_size);      }      win->ll->type |= DIRTY;      file->modified = TRUE;      file->dirty = GLOBAL;      show_changed_line( win );      rcol -= spaces;      win->ccol -= spaces;   } else {      /*       * move the cursor without changing the text underneath       */      rcol -= spaces;      if (rcol < 0)         rcol = 0;      win->ccol -= spaces;   }   check_virtual_col( win, rcol, win->ccol );   return( OK );}/* * Name:    next_smart_tab * Purpose: To find next smart tab * Date:    June 5, 1992 * Passed:  window: pointer to the current window * Notes:   To find a smart tab 1) find the first non-blank line above the *            current line, 2) find the first non-blank character after *            column of the cursor. */int  next_smart_tab( TDE_WIN *window ){register int spaces;    /* the spaces to move to the next tab stop */text_ptr s;             /* pointer to text */line_list_ptr ll;register TDE_WIN *win;   /* put window pointer in a register */int  rcol;int  len;int  tabs;int  ltab_size;int  ptab_size;   win = window;   tabs = win->file_info->inflate_tabs;   ltab_size = win->file_info->ltab_size;   ptab_size = win->file_info->ptab_size;   rcol = win->rcol;   /*    * find first previous non-blank line above the cursor.    */   ll = win->ll->prev;   while (ll->prev != NULL  &&  is_line_blank( ll->line, ll->len, tabs ))      ll = ll->prev;   if (ll->prev != NULL) {      s = ll->line;      /*       * if cursor is past the eol of the smart line, lets find the       *   next fixed tab.       * jmh 991004: find next fixed tab if on the last character, as well.       */      if (rcol >= find_end( s, ll->len, tabs, ptab_size ) - 1)         spaces = ltab_size - (rcol % ltab_size);      else {         len = ll->len;         s = detab_a_line( s, &len, tabs, ptab_size );         spaces = 0;         s   += rcol;         len -= rcol;         /*          * if we are on a word, find the end of it.          */         while (len > 0  &&  *s != ' ') {            ++s;            ++spaces;            --len;         }         /*          * jmh 991004: if we found eol, move to the next fixed tab.          */         if (len == 0)            spaces += ltab_size - ((rcol + spaces) % ltab_size);         /*          * now find the start of the next word.          */         else while (len > 0  &&  *s == ' ') {            ++s;            ++spaces;            --len;         }      }   } else      spaces = ltab_size - (rcol % ltab_size);   return( spaces );}/* * Name:    prev_smart_tab * Purpose: To find previous smart tab * Date:    June 5, 1992 * Passed:  window: pointer to the current window * Notes:   To find a smart tab 1) find the first non-blank line above the *            current line, 2) find the first non-blank character before *            column of the cursor. *          there are several cases to consider:  1) the cursor is past the *            the end of the smart line, 2) the smart pointer is in the *            middle of a word, 3) there are no more words between the *            smart pointer and the beginning of the line. */int  prev_smart_tab( TDE_WIN *window ){register int spaces;    /* the spaces to move to the next tab stop */text_ptr s;             /* pointer to text */int  len;line_list_ptr ll;register TDE_WIN *win;  /* put window pointer in a register */int  rcol;int  tabs;int  tab_size;int  ptab_size;   win = window;   tabs = win->file_info->inflate_tabs;   tab_size = win->file_info->ltab_size;   ptab_size = win->file_info->ptab_size;   rcol = win->rcol;   /*    * find first previous non-blank line above the cursor, if it exists.    */   ll = win->ll->prev;   while (ll->prev != NULL  && is_line_blank( ll->line, ll->len, tabs ))      ll = ll->prev;   if (ll->prev != NULL) {      s = ll->line;      /*       * if there are no words between the cursor and column 1 of the       *   smart tab line, find previous fixed tab.       */      if (rcol <= first_non_blank( s, ll->len, tabs, ptab_size ))         spaces = rcol % tab_size;      else {         len = ll->len;         s = detab_a_line( s, &len, tabs, ptab_size );         /*          * now, we need to figure the initial pointer and space.          *   if the cursor is past the eol of the smart line, then          *   set the smart pointer "s" to the end of line and "spaces" to          *   the number of characters between the cursor and the eol          *   of the smart line.  otherwise, set the smart pointer "s" to          *   the column of the cursor and "spaces" to 0.          */         if (len < rcol) {            spaces = rcol - len;         } else {            len = rcol;            spaces = 0;         }         s += len;         while (len > 0  &&  *(s-1) == ' ' ) {            --s;            ++spaces;            --len;         }         /*          * now find the beginning of the previous word.          */         while (len > 0  &&  *(s-1) != ' ') {            --s;            ++spaces;            --len;         }      }   } else      spaces = rcol % tab_size;   return( spaces );}/* * Name:    entab * Purpose: To compress spaces to tabs * Date:    October 31, 1992 * Passed:  s:   pointer to line *          len: length of line *          tab_size: size of tabs *          ind: TRUE to indent only (stop at first non-blank) * Returns: TRUE if the line changed, FALSE otherwise * Notes:   the text_ptr can point to either the g_status.line_buff or *            a line in the main text buffer. * * jmh 991202: modified to work with the block compress. *             Don't bother using the tab buffer, since the only times it is *              called the line buffer is wanted. *             Treat tabs as spaces (since " \t" can usually just become "\t"). */int  entab( text_ptr s, int len, int tab_size, int ind ){int  last_col;int  space;register int col;text_ptr to;int  rc;   assert( s != NULL );   assert( len >= 0 );   assert( len < MAX_LINE_LENGTH );   rc = FALSE;   to = g_status.line_buff;   if (len > 0) {      last_col = col = 0;      do {         if (*s == ' ')            col++;         else if (*s == '\t')            col += tab_size - (col % tab_size);         else {            if (col != last_col) {               do {                  space = tab_size - (last_col % tab_size);                  /*                   * when space == 1, forget about emmitting a tab                   *   for 1 space.                   * jmh 991202: in real tabs, let's keep the tab.                   * jmh 010630: perhaps not.                   */                  if (last_col + space <= col) {                     if (space == 1) {

⌨️ 快捷键说明

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