[BACK]Return to line.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Diff for /src/usr.bin/less/line.c between version 1.4 and 1.5

version 1.4, 2003/04/06 23:38:07 version 1.5, 2003/04/13 18:26:26
Line 1 
Line 1 
 /*      $OpenBSD$       */  
   
 /*  /*
  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman   * Copyright (C) 1984-2002  Mark Nudelman
  * All rights reserved.  
  *   *
  * Redistribution and use in source and binary forms, with or without   * You may distribute under the terms of either the GNU General Public
  * modification, are permitted provided that the following conditions   * License or the Less License, as specified in the README file.
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice in the documentation and/or other materials provided with  
  *    the distribution.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY   * For more information about less, or for information on how to
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   * contact the author, see the README file.
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE  
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */   */
   
   
Line 35 
Line 17 
   
 #include "less.h"  #include "less.h"
   
 public char linebuf[1024];      /* Buffer which holds the current output line */  #define IS_CONT(c)  (((c) & 0xC0) == 0x80)
 public int size_linebuf = sizeof(linebuf);  
   
 static char attr[1024];         /* Extension of linebuf to hold attributes */  public char *linebuf = NULL;    /* Buffer which holds the current output line */
   static char *attr = NULL;       /* Extension of linebuf to hold attributes */
   public int size_linebuf = 0;    /* Size of line buffer (and attr buffer) */
   
   public int cshift;              /* Current left-shift of output line buffer */
   public int hshift;              /* Desired left-shift of output line buffer */
   public int tabstops[TABSTOP_MAX] = { 0 }; /* Custom tabstops */
   public int ntabstops = 1;       /* Number of tabstops */
   public int tabdefault = 8;      /* Default repeated tabstops */
   
 static int curr;                /* Index into linebuf */  static int curr;                /* Index into linebuf */
 static int column;              /* Printable length, accounting for  static int column;              /* Printable length, accounting for
                                    backspaces, etc. */                                     backspaces, etc. */
 static int lno_indent;          /* Number of chars used for line number */  
 static int overstrike;          /* Next char should overstrike previous char */  static int overstrike;          /* Next char should overstrike previous char */
   static int last_overstrike = AT_NORMAL;
 static int is_null_line;        /* There is no current line */  static int is_null_line;        /* There is no current line */
   static int lmargin;             /* Left margin */
   static int hilites;             /* Number of hilites in this line */
 static char pendc;  static char pendc;
 static POSITION pendpos;  static POSITION pendpos;
   static char *end_ansi_chars;
   
 static int do_append();  static int do_append();
   
 extern int bs_mode;  extern int bs_mode;
 extern int tabstop;  
 extern int linenums;  extern int linenums;
 extern int ctldisp;  extern int ctldisp;
 extern int twiddle;  extern int twiddle;
 extern int binattr;  extern int binattr;
   extern int status_col;
 extern int auto_wrap, ignaw;  extern int auto_wrap, ignaw;
 extern int bo_s_width, bo_e_width;  extern int bo_s_width, bo_e_width;
 extern int ul_s_width, ul_e_width;  extern int ul_s_width, ul_e_width;
 extern int bl_s_width, bl_e_width;  extern int bl_s_width, bl_e_width;
 extern int so_s_width, so_e_width;  extern int so_s_width, so_e_width;
 extern int sc_width, sc_height;  extern int sc_width, sc_height;
   extern int utf_mode;
   extern POSITION start_attnpos;
   extern POSITION end_attnpos;
   
 /*  /*
    * Initialize from environment variables.
    */
           public void
   init_line()
   {
           end_ansi_chars = lgetenv("LESSANSIENDCHARS");
           if (end_ansi_chars == NULL || *end_ansi_chars == '\0')
                   end_ansi_chars = "m";
           linebuf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
           attr = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
           size_linebuf = LINEBUF_SIZE;
   }
   
   /*
    * Expand the line buffer.
    */
           static int
   expand_linebuf()
   {
           int new_size = size_linebuf + LINEBUF_SIZE;
           char *new_buf = (char *) calloc(new_size, sizeof(char));
           char *new_attr = (char *) calloc(new_size, sizeof(char));
           if (new_buf == NULL || new_attr == NULL)
           {
                   if (new_attr != NULL)
                           free(new_attr);
                   if (new_buf != NULL)
                           free(new_buf);
                   return 1;
           }
           memcpy(new_buf, linebuf, size_linebuf * sizeof(char));
           memcpy(new_attr, attr, size_linebuf * sizeof(char));
           free(attr);
           free(linebuf);
           linebuf = new_buf;
           attr = new_attr;
           size_linebuf = new_size;
           return 0;
   }
   
   /*
  * Rewind the line buffer.   * Rewind the line buffer.
  */   */
         public void          public void
Line 73 
Line 110 
         column = 0;          column = 0;
         overstrike = 0;          overstrike = 0;
         is_null_line = 0;          is_null_line = 0;
         lno_indent = 0;  
         pendc = '\0';          pendc = '\0';
           lmargin = 0;
           if (status_col)
                   lmargin += 1;
   #if HILITE_SEARCH
           hilites = 0;
   #endif
 }  }
   
 /*  /*
Line 84 
Line 126 
 plinenum(pos)  plinenum(pos)
         POSITION pos;          POSITION pos;
 {  {
         int lno;          register LINENUM linenum = 0;
         int i;          register int i;
         int n;  
   
           if (linenums == OPT_ONPLUS)
           {
                   /*
                    * Get the line number and put it in the current line.
                    * {{ Note: since find_linenum calls forw_raw_line,
                    *    it may seek in the input file, requiring the caller
                    *    of plinenum to re-seek if necessary. }}
                    * {{ Since forw_raw_line modifies linebuf, we must
                    *    do this first, before storing anything in linebuf. }}
                    */
                   linenum = find_linenum(pos);
           }
   
         /*          /*
          * We display the line number at the start of each line           * Display a status column if the -J option is set.
          * only if the -N option is set.  
          */           */
         if (linenums != OPT_ONPLUS)          if (status_col)
                 return;          {
                   linebuf[curr] = ' ';
                   if (start_attnpos != NULL_POSITION &&
                       pos >= start_attnpos && pos < end_attnpos)
                           attr[curr] = AT_STANDOUT;
                   else
                           attr[curr] = 0;
                   curr++;
                   column++;
           }
         /*          /*
          * Get the line number and put it in the current line.           * Display the line number at the start of each line
          * {{ Note: since find_linenum calls forw_raw_line,           * if the -N option is set.
          *    it may seek in the input file, requiring the caller  
          *    of plinenum to re-seek if necessary. }}  
          */           */
         lno = find_linenum(pos);          if (linenums == OPT_ONPLUS)
           {
                   char buf[INT_STRLEN_BOUND(pos) + 2];
                   int n;
   
         snprintf(&linebuf[curr], sizeof linebuf - curr, "%6d", lno);                  linenumtoa(linenum, buf, sizeof(buf));
         n = strlen(&linebuf[curr]);                  n = strlen(buf);
         column += n;                  if (n < MIN_LINENUM_WIDTH)
         for (i = 0;  i < n;  i++)                          n = MIN_LINENUM_WIDTH;
                 attr[curr++] = 0;                  snprintf(linebuf+curr, sizeof(linebuf)-curr, "%*s ", n, buf);
                   n++;  /* One space after the line number. */
                   for (i = 0; i < n; i++)
                           attr[curr+i] = AT_NORMAL;
                   curr += n;
                   column += n;
                   lmargin += n;
           }
   
         /*          /*
          * Append enough spaces to bring us to the next tab stop.           * Append enough spaces to bring us to the lmargin.
          * {{ We could avoid this at the cost of adding some  
          *    complication to the tab stop logic in pappend(). }}  
          */           */
         if (tabstop == 0)          while (column < lmargin)
                 tabstop = 1;  
         do  
         {          {
                 linebuf[curr] = ' ';                  linebuf[curr] = ' ';
                 attr[curr++] = AT_NORMAL;                  attr[curr++] = AT_NORMAL;
                 column++;                  column++;
         } while ((column % tabstop) != 0);          }
         lno_indent = column;  
 }  }
   
 /*  /*
    * Determine how many characters are required to shift N columns.
    */
           static int
   shift_chars(s, len)
           char *s;
           int len;
   {
           char *p = s;
   
           /*
            * Each char counts for one column, except ANSI color escape
            * sequences use no columns since they don't move the cursor.
            */
           while (*p != '\0' && len > 0)
           {
                   if (*p++ != ESC)
                   {
                           len--;
                   } else
                   {
                           while (*p != '\0')
                           {
                                   if (is_ansi_end(*p++))
                                           break;
                           }
                   }
           }
           return (p - s);
   }
   
   /*
    * Determine how many characters are required to shift N columns (UTF version).
    * {{ FIXME: what about color escape sequences in UTF mode? }}
    */
           static int
   utf_shift_chars(s, len)
           char *s;
           int len;
   {
           int ulen = 0;
   
           while (*s != '\0' && len > 0)
           {
                   if (!IS_CONT(*s))
                           len--;
                   s++;
                   ulen++;
           }
           while (IS_CONT(*s))
           {
                   s++;
                   ulen++;
           }
           return (ulen);
   }
   
   /*
    * Shift the input line left.
    * This means discarding N printable chars at the start of the buffer.
    */
           static void
   pshift(shift)
           int shift;
   {
           int i;
           int nchars;
   
           if (shift > column - lmargin)
                   shift = column - lmargin;
           if (shift > curr - lmargin)
                   shift = curr - lmargin;
   
           if (utf_mode)
                   nchars = utf_shift_chars(linebuf + lmargin, shift);
           else
                   nchars = shift_chars(linebuf + lmargin, shift);
           if (nchars > curr)
                   nchars = curr;
           for (i = 0;  i < curr - nchars;  i++)
           {
                   linebuf[lmargin + i] = linebuf[lmargin + i + nchars];
                   attr[lmargin + i] = attr[lmargin + i + nchars];
           }
           curr -= nchars;
           column -= shift;
           cshift += shift;
   }
   
   /*
  * Return the printing width of the start (enter) sequence   * Return the printing width of the start (enter) sequence
  * for a given character attribute.   * for a given character attribute.
  */   */
         int          static int
 attr_swidth(a)  attr_swidth(a)
         int a;          int a;
 {  {
Line 147 
Line 300 
  * Return the printing width of the end (exit) sequence   * Return the printing width of the end (exit) sequence
  * for a given character attribute.   * for a given character attribute.
  */   */
         int          static int
 attr_ewidth(a)  attr_ewidth(a)
         int a;          int a;
 {  {
Line 172 
Line 325 
         int c;          int c;
         int a;          int a;
 {  {
         int w;          register int w;
   
           if (utf_mode && IS_CONT(c))
                   return (0);
   
         if (c == '\b')          if (c == '\b')
                 /*                  /*
                  * Backspace moves backwards one position.                   * Backspace moves backwards one position.
Line 211 
Line 367 
 }  }
   
 /*  /*
    * Are we currently within a recognized ANSI escape sequence?
    */
           static int
   in_ansi_esc_seq()
   {
           int i;
   
           /*
            * Search backwards for either an ESC (which means we ARE in a seq);
            * or an end char (which means we're NOT in a seq).
            */
           for (i = curr-1;  i >= 0;  i--)
           {
                   if (linebuf[i] == ESC)
                           return (1);
                   if (is_ansi_end(linebuf[i]))
                           return (0);
           }
           return (0);
   }
   
   /*
    * Is a character the end of an ANSI escape sequence?
    */
           public int
   is_ansi_end(c)
           char c;
   {
           return (strchr(end_ansi_chars, c) != NULL);
   }
   
   /*
  * Append a character and attribute to the line buffer.   * Append a character and attribute to the line buffer.
  */   */
   #define STORE_CHAR(c,a,pos) \
           do { if (store_char((c),(a),(pos))) return (1); else curr++; } while (0)
   
         static int          static int
 storec(c, a, pos)  store_char(c, a, pos)
         int c;          int c;
         int a;          int a;
         POSITION pos;          POSITION pos;
 {  {
         int w;          register int w;
   
           if (a != AT_NORMAL)
                   last_overstrike = a;
 #if HILITE_SEARCH  #if HILITE_SEARCH
         if (is_hilited(pos, pos+1, 0))          if (is_hilited(pos, pos+1, 0))
           {
                 /*                  /*
                  * This character should be highlighted.                   * This character should be highlighted.
                  * Override the attribute passed in.                   * Override the attribute passed in.
                  */                   */
                 a = AT_STANDOUT;                  a = AT_STANDOUT;
                   hilites++;
           }
 #endif  #endif
         w = pwidth(c, a);          if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq())
         if (ctldisp > 0 && column + w + attr_ewidth(a) > sc_width)                  w = 0;
           else
                   w = pwidth(c, a);
           if (ctldisp != OPT_ON && column + w + attr_ewidth(a) > sc_width)
                 /*                  /*
                  * Won't fit on screen.                   * Won't fit on screen.
                  */                   */
                 return (1);                  return (1);
   
         if (curr >= sizeof(linebuf)-2)          if (curr >= size_linebuf-2)
           {
                 /*                  /*
                  * Won't fit in line buffer.                   * Won't fit in line buffer.
                    * Try to expand it.
                  */                   */
                 return (1);                  if (expand_linebuf())
                           return (1);
           }
   
         /*          /*
          * Special handling for "magic cookie" terminals.           * Special handling for "magic cookie" terminals.
Line 282 
Line 485 
 }  }
   
 /*  /*
    * Append a tab to the line buffer.
    * Store spaces to represent the tab.
    */
   #define STORE_TAB(a,pos) \
           do { if (store_tab((a),(pos))) return (1); } while (0)
   
           static int
   store_tab(attr, pos)
           int attr;
           POSITION pos;
   {
           int to_tab = column + cshift - lmargin;
           int i;
   
           if (ntabstops < 2 || to_tab >= tabstops[ntabstops-1])
                   to_tab = tabdefault -
                        ((to_tab - tabstops[ntabstops-1]) % tabdefault);
           else
           {
                   for (i = ntabstops - 2;  i >= 0;  i--)
                           if (to_tab >= tabstops[i])
                                   break;
                   to_tab = tabstops[i+1] - to_tab;
           }
   
           do {
                   STORE_CHAR(' ', attr, pos);
           } while (--to_tab > 0);
           return 0;
   }
   
   /*
  * Append a character to the line buffer.   * Append a character to the line buffer.
  * Expand tabs into spaces, handle underlining, boldfacing, etc.   * Expand tabs into spaces, handle underlining, boldfacing, etc.
  * Returns 0 if ok, 1 if couldn't fit in buffer.   * Returns 0 if ok, 1 if couldn't fit in buffer.
  */   */
         public int          public int
 pappend(c, pos)  pappend(c, pos)
         int c;          register int c;
         POSITION pos;          POSITION pos;
 {  {
           int r;
   
         if (pendc)          if (pendc)
         {          {
                 if (do_append(pendc, pendpos))                  if (do_append(pendc, pendpos))
Line 314 
Line 551 
                 return (0);                  return (0);
         }          }
   
         return (do_append(c, pos));          r = do_append(c, pos);
           /*
            * If we need to shift the line, do it.
            * But wait until we get to at least the middle of the screen,
            * so shifting it doesn't affect the chars we're currently
            * pappending.  (Bold & underline can get messed up otherwise.)
            */
           if (cshift < hshift && column > sc_width / 2)
           {
                   linebuf[curr] = '\0';
                   pshift(hshift - cshift);
           }
           return (r);
 }  }
   
   #define IS_UTF8_4BYTE(c) ( ((c) & 0xf8) == 0xf0 )
   #define IS_UTF8_3BYTE(c) ( ((c) & 0xf0) == 0xe0 )
   #define IS_UTF8_2BYTE(c) ( ((c) & 0xe0) == 0xc0 )
   #define IS_UTF8_TRAIL(c) ( ((c) & 0xc0) == 0x80 )
   
         static int          static int
 do_append(c, pos)  do_append(c, pos)
         int c;          int c;
         POSITION pos;          POSITION pos;
 {  {
         char *s;          register char *s;
         int a;          register int a;
   
 #define STOREC(c,a) \  #define STOREC(c,a) \
         if (storec((c),(a),pos)) return (1); else curr++          if ((c) == '\t') STORE_TAB((a),pos); else STORE_CHAR((c),(a),pos)
   
         if (overstrike)          if (c == '\b')
         {          {
                   switch (bs_mode)
                   {
                   case BS_NORMAL:
                           STORE_CHAR(c, AT_NORMAL, pos);
                           break;
                   case BS_CONTROL:
                           goto do_control_char;
                   case BS_SPECIAL:
                           if (curr == 0)
                                   break;
                           backc();
                           overstrike = 1;
                           break;
                   }
           } else if (overstrike)
           {
                 /*                  /*
                  * Overstrike the character at the current position                   * Overstrike the character at the current position
                  * in the line buffer.  This will cause either                   * in the line buffer.  This will cause either
Line 337 
Line 607 
                  * bold (if an identical character is overstruck),                   * bold (if an identical character is overstruck),
                  * or just deletion of the character in the buffer.                   * or just deletion of the character in the buffer.
                  */                   */
                 overstrike = 0;                  overstrike--;
                 if ((char)c == linebuf[curr])                  if (utf_mode && IS_UTF8_4BYTE(c) && curr > 2 && (char)c == linebuf[curr-3])
                         STOREC(linebuf[curr], AT_BOLD);                  {
                 else if (c == '_')                          backc();
                           backc();
                           backc();
                           STORE_CHAR(linebuf[curr], AT_BOLD, pos);
                           overstrike = 3;
                   } else if (utf_mode && (IS_UTF8_3BYTE(c) || (overstrike==2 && IS_UTF8_TRAIL(c))) && curr > 1 && (char)c == linebuf[curr-2])
                   {
                           backc();
                           backc();
                           STORE_CHAR(linebuf[curr], AT_BOLD, pos);
                           overstrike = 2;
                   } else if (utf_mode && curr > 0 && (IS_UTF8_2BYTE(c) || (overstrike==1 && IS_UTF8_TRAIL(c))) && (char)c == linebuf[curr-1])
                   {
                           backc();
                           STORE_CHAR(linebuf[curr], AT_BOLD, pos);
                           overstrike = 1;
                   } else if (utf_mode && curr > 0 && IS_UTF8_TRAIL(c) && attr[curr-1] == AT_UNDERLINE)
                   {
                           STOREC(c, AT_UNDERLINE);
                   } else if ((char)c == linebuf[curr])
                   {
                           /*
                            * Overstriking a char with itself means make it bold.
                            * But overstriking an underscore with itself is
                            * ambiguous.  It could mean make it bold, or
                            * it could mean make it underlined.
                            * Use the previous overstrike to resolve it.
                            */
                           if (c == '_' && last_overstrike != AT_NORMAL)
                                   STOREC(c, last_overstrike);
                           else
                                   STOREC(c, AT_BOLD);
                   } else if (c == '_')
                   {
                           if (utf_mode)
                           {
                                   int i;
                                   for (i = 0;  i < 5;  i++)
                                   {
                                           if (curr <= i || !IS_CONT(linebuf[curr-i]))
                                                   break;
                                           attr[curr-i-1] = AT_UNDERLINE;
                                   }
                           }
                         STOREC(linebuf[curr], AT_UNDERLINE);                          STOREC(linebuf[curr], AT_UNDERLINE);
                 else if (linebuf[curr] == '_')                  } else if (linebuf[curr] == '_')
                   {
                           if (utf_mode)
                           {
                                   if (IS_UTF8_2BYTE(c))
                                           overstrike = 1;
                                   else if (IS_UTF8_3BYTE(c))
                                           overstrike = 2;
                                   else if (IS_UTF8_4BYTE(c))
                                           overstrike = 3;
                           }
                         STOREC(c, AT_UNDERLINE);                          STOREC(c, AT_UNDERLINE);
                 else if (control_char(c))                  } else if (control_char(c))
                         goto do_control_char;                          goto do_control_char;
                 else                  else
                         STOREC(c, AT_NORMAL);                          STOREC(c, AT_NORMAL);
         } else if (c == '\b')          } else if (c == '\t')
         {          {
                   /*
                    * Expand a tab into spaces.
                    */
                 switch (bs_mode)                  switch (bs_mode)
                 {                  {
                 case BS_NORMAL:  
                         STOREC(c, AT_NORMAL);  
                         break;  
                 case BS_CONTROL:                  case BS_CONTROL:
                         goto do_control_char;                          goto do_control_char;
                   case BS_NORMAL:
                 case BS_SPECIAL:                  case BS_SPECIAL:
                         if (curr == 0)                          STORE_TAB(AT_NORMAL, pos);
                                 break;  
                         backc();  
                         overstrike = 1;  
                         break;                          break;
                 }                  }
         } else if (c == '\t')  
         {  
                 /*  
                  * Expand a tab into spaces.  
                  */  
                 if (tabstop == 0)  
                         tabstop = 1;  
                 do  
                 {  
                         STOREC(' ', AT_NORMAL);  
                 } while ((column % tabstop) != 0);  
         } else if (control_char(c))          } else if (control_char(c))
         {          {
         do_control_char:          do_control_char:
                 if (ctldisp == 0)                  if (ctldisp == OPT_ON || (ctldisp == OPT_ONPLUS && c == ESC))
                 {                  {
                         /*                          /*
                          * Output as a normal character.                           * Output as a normal character.
                          */                           */
                         STOREC(c, AT_NORMAL);                          STORE_CHAR(c, AT_NORMAL, pos);
                 } else                  } else
                 {                  {
                         /*                          /*
Line 401 
Line 711 
                                 return (1);                                  return (1);
   
                         for ( ;  *s != 0;  s++)                          for ( ;  *s != 0;  s++)
                                 STOREC(*s, a);                                  STORE_CHAR(*s, a, pos);
                 }                  }
         } else          } else
         {          {
Line 427 
Line 737 
                 (void) do_append(pendc, pendpos);                  (void) do_append(pendc, pendpos);
   
         /*          /*
            * Make sure we've shifted the line, if we need to.
            */
           if (cshift < hshift)
                   pshift(hshift - cshift);
   
           /*
          * Add a newline if necessary,           * Add a newline if necessary,
          * and append a '\0' to the end of the line.           * and append a '\0' to the end of the line.
          */           */
         if (column < sc_width || !auto_wrap || ignaw || ctldisp == 0)          if (column < sc_width || !auto_wrap || ignaw || ctldisp == OPT_ON)
         {          {
                 linebuf[curr] = '\n';                  linebuf[curr] = '\n';
                 attr[curr] = AT_NORMAL;                  attr[curr] = AT_NORMAL;
Line 438 
Line 754 
         }          }
         linebuf[curr] = '\0';          linebuf[curr] = '\0';
         attr[curr] = AT_NORMAL;          attr[curr] = AT_NORMAL;
   
   #if HILITE_SEARCH
           if (status_col && hilites > 0)
           {
                   linebuf[0] = '*';
                   attr[0] = AT_STANDOUT;
           }
   #endif
           /*
            * If we are done with this line, reset the current shift.
            */
           if (endline)
                   cshift = 0;
 }  }
   
 /*  /*
Line 447 
Line 776 
  */   */
         public int          public int
 gline(i, ap)  gline(i, ap)
         int i;          register int i;
         int *ap;          register int *ap;
 {  {
         char *s;          char *s;
   
Line 458 
Line 787 
                  * If there is no current line, we pretend the line is                   * If there is no current line, we pretend the line is
                  * either "~" or "", depending on the "twiddle" flag.                   * either "~" or "", depending on the "twiddle" flag.
                  */                   */
                 *ap = AT_NORMAL;                  *ap = AT_BOLD;
                 s = (twiddle) ? "~\n" : "\n";                  s = (twiddle) ? "~\n" : "\n";
                 return (s[i]);                  return (s[i]);
         }          }
Line 474 
Line 803 
 null_line()  null_line()
 {  {
         is_null_line = 1;          is_null_line = 1;
           cshift = 0;
 }  }
   
 #if 1  
 /*  /*
  * Analogous to forw_line(), but deals with "raw lines":   * Analogous to forw_line(), but deals with "raw lines":
  * lines which are not split for screen width.   * lines which are not split for screen width.
Line 487 
Line 816 
         POSITION curr_pos;          POSITION curr_pos;
         char **linep;          char **linep;
 {  {
         char *p;          register int n;
         int c;          register int c;
         POSITION new_pos;          POSITION new_pos;
   
         if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||          if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||
                 (c = ch_forw_get()) == EOI)                  (c = ch_forw_get()) == EOI)
                 return (NULL_POSITION);                  return (NULL_POSITION);
   
         p = linebuf;          n = 0;
   
         for (;;)          for (;;)
         {          {
                 if (c == '\n' || c == EOI)                  if (c == '\n' || c == EOI)
Line 504 
Line 832 
                         new_pos = ch_tell();                          new_pos = ch_tell();
                         break;                          break;
                 }                  }
                 if (p >= &linebuf[sizeof(linebuf)-1])                  if (n >= size_linebuf-1)
                 {                  {
                         /*                          if (expand_linebuf())
                          * Overflowed the input buffer.                          {
                          * Pretend the line ended here.                                  /*
                          * {{ The line buffer is supposed to be big                                   * Overflowed the input buffer.
                          *    enough that this never happens. }}                                   * Pretend the line ended here.
                          */                                   */
                         new_pos = ch_tell() - 1;                                  new_pos = ch_tell() - 1;
                         break;                                  break;
                           }
                 }                  }
                 *p++ = c;                  linebuf[n++] = c;
                 c = ch_forw_get();                  c = ch_forw_get();
         }          }
         *p = '\0';          linebuf[n] = '\0';
         if (linep != NULL)          if (linep != NULL)
                 *linep = linebuf;                  *linep = linebuf;
         return (new_pos);          return (new_pos);
Line 533 
Line 862 
         POSITION curr_pos;          POSITION curr_pos;
         char **linep;          char **linep;
 {  {
         char *p;          register int n;
         int c;          register int c;
         POSITION new_pos;          POSITION new_pos;
   
         if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||          if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||
                 ch_seek(curr_pos-1))                  ch_seek(curr_pos-1))
                 return (NULL_POSITION);                  return (NULL_POSITION);
   
         p = &linebuf[sizeof(linebuf)];          n = size_linebuf;
         *--p = '\0';          linebuf[--n] = '\0';
   
         for (;;)          for (;;)
         {          {
                 c = ch_back_get();                  c = ch_back_get();
Line 566 
Line 894 
                         new_pos = ch_zero();                          new_pos = ch_zero();
                         break;                          break;
                 }                  }
                 if (p <= linebuf)                  if (n <= 0)
                 {                  {
                           int old_size_linebuf = size_linebuf;
                           char *fm;
                           char *to;
                           if (expand_linebuf())
                           {
                                   /*
                                    * Overflowed the input buffer.
                                    * Pretend the line ended here.
                                    */
                                   new_pos = ch_tell() + 1;
                                   break;
                           }
                         /*                          /*
                          * Overflowed the input buffer.                           * Shift the data to the end of the new linebuf.
                          * Pretend the line ended here.  
                          */                           */
                         new_pos = ch_tell() + 1;                          for (fm = linebuf + old_size_linebuf,
                         break;                                to = linebuf + size_linebuf;
                                fm >= linebuf;  fm--, to--)
                                   *to = *fm;
                           n = size_linebuf - old_size_linebuf;
                 }                  }
                 *--p = c;                  linebuf[--n] = c;
         }          }
         if (linep != NULL)          if (linep != NULL)
                 *linep = p;                  *linep = &linebuf[n];
         return (new_pos);          return (new_pos);
 }  }
 #endif  

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5