=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/less/line.c,v retrieving revision 1.12 retrieving revision 1.13 diff -c -r1.12 -r1.13 *** src/usr.bin/less/line.c 2014/04/25 13:38:21 1.12 --- src/usr.bin/less/line.c 2015/11/05 22:08:44 1.13 *************** *** 6,13 **** * * For more information, see the README file. */ - /* * Routines to manipulate the "line buffer". * The line buffer holds a line of output as it is being built --- 6,16 ---- * * For more information, see the README file. */ + /* + * Modified for use with illumos. + * Copyright 2014 Garrett D'Amore + */ /* * Routines to manipulate the "line buffer". * The line buffer holds a line of output as it is being built *************** *** 17,50 **** #include "less.h" #include "charset.h" - #include - static 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) */ static 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 */ ! public POSITION highest_hilite; /* Pos of last hilite in file found so far */ static int curr; /* Index into linebuf */ ! static int column; /* Printable length, accounting for ! backspaces, etc. */ 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 lmargin; /* Left margin */ static char pendc; ! static POSITION pendpos; static char *end_ansi_chars; static char *mid_ansi_chars; ! static int attr_swidth(); ! static int attr_ewidth(); ! static int do_append(); extern volatile sig_atomic_t sigs; extern int bs_mode; --- 20,50 ---- #include "less.h" #include "charset.h" static char *linebuf = NULL; /* Buffer which holds the current output line */ static char *attr = NULL; /* Extension of linebuf to hold attributes */ ! int size_linebuf = 0; /* Size of line buffer (and attr buffer) */ static int cshift; /* Current left-shift of output line buffer */ ! int hshift; /* Desired left-shift of output line buffer */ ! int tabstops[TABSTOP_MAX] = { 0 }; /* Custom tabstops */ ! int ntabstops = 1; /* Number of tabstops */ ! int tabdefault = 8; /* Default repeated tabstops */ ! off_t highest_hilite; /* Pos of last hilite in file found so far */ static int curr; /* Index into linebuf */ ! static int column; /* Printable length, accounting for backspaces, etc. */ 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 lmargin; /* Left margin */ static char pendc; ! static off_t pendpos; static char *end_ansi_chars; static char *mid_ansi_chars; ! static int attr_swidth(int); ! static int attr_ewidth(int); ! static int do_append(LWCHAR, char *, off_t); extern volatile sig_atomic_t sigs; extern int bs_mode; *************** *** 60,78 **** extern int so_s_width, so_e_width; extern int sc_width, sc_height; extern int utf_mode; ! extern POSITION start_attnpos; ! extern POSITION end_attnpos; static char mbc_buf[MAX_UTF_CHAR_LEN]; static int mbc_buf_len = 0; static int mbc_buf_index = 0; ! static POSITION mbc_pos; /* * Initialize from environment variables. */ ! public void ! init_line() { end_ansi_chars = lgetenv("LESSANSIENDCHARS"); if (end_ansi_chars == NULL || *end_ansi_chars == '\0') --- 60,78 ---- extern int so_s_width, so_e_width; extern int sc_width, sc_height; extern int utf_mode; ! extern off_t start_attnpos; ! extern off_t end_attnpos; static char mbc_buf[MAX_UTF_CHAR_LEN]; static int mbc_buf_len = 0; static int mbc_buf_index = 0; ! static off_t mbc_pos; /* * Initialize from environment variables. */ ! void ! init_line(void) { end_ansi_chars = lgetenv("LESSANSIENDCHARS"); if (end_ansi_chars == NULL || *end_ansi_chars == '\0') *************** *** 82,133 **** if (mid_ansi_chars == NULL || *mid_ansi_chars == '\0') mid_ansi_chars = "0123456789;[?!\"'#%()*+ "; ! 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() { /* Double the size of the line buffer. */ int new_size = size_linebuf * 2; /* Just realloc to expand the buffer, if we can. */ ! char *new_buf; ! char *new_attr; ! ! new_buf = realloc(linebuf, new_size); ! if (new_buf == NULL) ! return 1; ! new_attr = realloc(attr, new_size); ! if (new_attr == NULL) { ! /* realloc linebuf back to original size */ ! linebuf = realloc(new_buf, size_linebuf); ! if (linebuf == NULL) ! err(1, NULL); ! return 1; } - /* - * We realloc'd the buffers; they already have the old contents. - */ - memset(new_buf + size_linebuf, 0, new_size - size_linebuf); - memset(new_attr + size_linebuf, 0, new_size - size_linebuf); linebuf = new_buf; attr = new_attr; size_linebuf = new_size; ! return 0; } /* * Is a character ASCII? */ ! public int ! is_ascii_char(ch) ! LWCHAR ch; { return (ch <= 0x7F); } --- 82,122 ---- if (mid_ansi_chars == NULL || *mid_ansi_chars == '\0') mid_ansi_chars = "0123456789;[?!\"'#%()*+ "; ! linebuf = ecalloc(LINEBUF_SIZE, sizeof (char)); ! attr = ecalloc(LINEBUF_SIZE, sizeof (char)); size_linebuf = LINEBUF_SIZE; } /* * Expand the line buffer. */ ! static int ! expand_linebuf(void) { /* Double the size of the line buffer. */ int new_size = size_linebuf * 2; /* Just realloc to expand the buffer, if we can. */ ! char *new_buf = realloc(linebuf, new_size); ! char *new_attr = realloc(attr, new_size); ! if (new_buf == NULL || new_attr == NULL) { ! if (new_attr != NULL) ! free(new_attr); ! if (new_buf != NULL) ! free(new_buf); ! return (1); } linebuf = new_buf; attr = new_attr; size_linebuf = new_size; ! return (0); } /* * Is a character ASCII? */ ! int ! is_ascii_char(LWCHAR ch) { return (ch <= 0x7F); } *************** *** 135,142 **** /* * Rewind the line buffer. */ ! public void ! prewind() { curr = 0; column = 0; --- 124,131 ---- /* * Rewind the line buffer. */ ! void ! prewind(void) { curr = 0; column = 0; *************** *** 154,172 **** /* * Insert the line number (of the given position) into the line buffer. */ ! public void ! plinenum(pos) ! POSITION pos; { ! register LINENUM linenum = 0; ! register int i; ! 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. }} --- 143,159 ---- /* * Insert the line number (of the given position) into the line buffer. */ ! void ! plinenum(off_t pos) { ! LINENUM linenum = 0; ! int i; ! 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. }} *************** *** 177,186 **** /* * Display a status column if the -J option is set. */ ! if (status_col) ! { linebuf[curr] = ' '; ! if (start_attnpos != NULL_POSITION && pos >= start_attnpos && pos < end_attnpos) attr[curr] = AT_NORMAL|AT_HILITE; else --- 164,172 ---- /* * Display a status column if the -J option is set. */ ! if (status_col) { linebuf[curr] = ' '; ! if (start_attnpos != -1 && pos >= start_attnpos && pos < end_attnpos) attr[curr] = AT_NORMAL|AT_HILITE; else *************** *** 192,203 **** * Display the line number at the start of each line * if the -N option is set. */ ! if (linenums == OPT_ONPLUS) ! { char buf[INT_STRLEN_BOUND(pos) + 2]; int n; ! linenumtoa(linenum, buf, sizeof(buf)); n = strlen(buf); if (n < MIN_LINENUM_WIDTH) n = MIN_LINENUM_WIDTH; --- 178,188 ---- * Display the line number at the start of each line * if the -N option is set. */ ! if (linenums == OPT_ONPLUS) { char buf[INT_STRLEN_BOUND(pos) + 2]; int n; ! linenumtoa(linenum, buf, sizeof (buf)); n = strlen(buf); if (n < MIN_LINENUM_WIDTH) n = MIN_LINENUM_WIDTH; *************** *** 213,220 **** /* * Append enough spaces to bring us to the lmargin. */ ! while (column < lmargin) ! { linebuf[curr] = ' '; attr[curr++] = AT_NORMAL; column++; --- 198,204 ---- /* * Append enough spaces to bring us to the lmargin. */ ! while (column < lmargin) { linebuf[curr] = ' '; attr[curr++] = AT_NORMAL; column++; *************** *** 225,233 **** * Shift the input line left. * This means discarding N printable chars at the start of the buffer. */ ! static void ! pshift(shift) ! int shift; { LWCHAR prev_ch = 0; unsigned char c; --- 209,216 ---- * Shift the input line left. * This means discarding N printable chars at the start of the buffer. */ ! static void ! pshift(int shift) { LWCHAR prev_ch = 0; unsigned char c; *************** *** 249,277 **** * We keep on going when shifted == shift * to get all combining chars. */ ! while (shifted <= shift && from < curr) ! { c = linebuf[from]; ! if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) ! { /* Keep cumulative effect. */ linebuf[to] = c; attr[to++] = attr[from++]; ! while (from < curr && linebuf[from]) ! { linebuf[to] = linebuf[from]; attr[to++] = attr[from]; if (!is_ansi_middle(linebuf[from++])) break; ! } continue; } width = 0; ! #if !SMALL ! if (!IS_ASCII_OCTET(c) && utf_mode) ! { /* Assumes well-formedness validation already done. */ LWCHAR ch; --- 232,255 ---- * We keep on going when shifted == shift * to get all combining chars. */ ! while (shifted <= shift && from < curr) { c = linebuf[from]; ! if (ctldisp == OPT_ONPLUS && IS_CSI_START(c)) { /* Keep cumulative effect. */ linebuf[to] = c; attr[to++] = attr[from++]; ! while (from < curr && linebuf[from]) { linebuf[to] = linebuf[from]; attr[to++] = attr[from]; if (!is_ansi_middle(linebuf[from++])) break; ! } continue; } width = 0; ! if (!IS_ASCII_OCTET(c) && utf_mode) { /* Assumes well-formedness validation already done. */ LWCHAR ch; *************** *** 279,298 **** if (from + len > curr) break; ch = get_wchar(linebuf + from); ! if (!is_composing_char(ch) && !is_combining_char(prev_ch, ch)) width = is_wide_char(ch) ? 2 : 1; prev_ch = ch; ! } else ! #endif /* !SMALL */ ! { len = 1; if (c == '\b') /* XXX - Incorrect if several '\b' in a row. */ ! #if !SMALL ! width = (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; ! #else ! width = -1; ! #endif /* !SMALL */ else if (!control_char(c)) width = 1; prev_ch = 0; --- 257,272 ---- if (from + len > curr) break; ch = get_wchar(linebuf + from); ! if (!is_composing_char(ch) && ! !is_combining_char(prev_ch, ch)) width = is_wide_char(ch) ? 2 : 1; prev_ch = ch; ! } else { len = 1; if (c == '\b') /* XXX - Incorrect if several '\b' in a row. */ ! width = (utf_mode && is_wide_char(prev_ch)) ? ! -2 : -1; else if (!control_char(c)) width = 1; prev_ch = 0; *************** *** 315,328 **** /* Adjust width for magic cookies. */ prev_attr = (to > 0) ? attr[to-1] : AT_NORMAL; next_attr = (from + len < curr) ? attr[from + len] : prev_attr; ! if (!is_at_equiv(attr[from], prev_attr) && ! !is_at_equiv(attr[from], next_attr)) ! { width += attr_swidth(attr[from]); if (from + len < curr) width += attr_ewidth(attr[from]); ! if (is_at_equiv(prev_attr, next_attr)) ! { width += attr_ewidth(prev_attr); if (from + len < curr) width += attr_swidth(next_attr); --- 289,300 ---- /* Adjust width for magic cookies. */ prev_attr = (to > 0) ? attr[to-1] : AT_NORMAL; next_attr = (from + len < curr) ? attr[from + len] : prev_attr; ! if (!is_at_equiv(attr[from], prev_attr) && ! !is_at_equiv(attr[from], next_attr)) { width += attr_swidth(attr[from]); if (from + len < curr) width += attr_ewidth(attr[from]); ! if (is_at_equiv(prev_attr, next_attr)) { width += attr_ewidth(prev_attr); if (from + len < curr) width += attr_swidth(next_attr); *************** *** 336,343 **** if (shifted < 0) shifted = 0; } ! while (from < curr) ! { linebuf[to] = linebuf[from]; attr[to++] = attr[from++]; } --- 308,314 ---- if (shifted < 0) shifted = 0; } ! while (from < curr) { linebuf[to] = linebuf[from]; attr[to++] = attr[from++]; } *************** *** 349,356 **** /* * */ ! public void ! pshift_all() { pshift(column); } --- 320,327 ---- /* * */ ! void ! pshift_all(void) { pshift(column); } *************** *** 359,367 **** * Return the printing width of the start (enter) sequence * for a given character attribute. */ ! static int ! attr_swidth(a) ! int a; { int w = 0; --- 330,337 ---- * Return the printing width of the start (enter) sequence * for a given character attribute. */ ! static int ! attr_swidth(int a) { int w = 0; *************** *** 376,391 **** if (a & AT_STANDOUT) w += so_s_width; ! return w; } /* * Return the printing width of the end (exit) sequence * for a given character attribute. */ ! static int ! attr_ewidth(a) ! int a; { int w = 0; --- 346,360 ---- if (a & AT_STANDOUT) w += so_s_width; ! return (w); } /* * Return the printing width of the end (exit) sequence * for a given character attribute. */ ! static int ! attr_ewidth(int a) { int w = 0; *************** *** 400,406 **** if (a & AT_STANDOUT) w += so_e_width; ! return w; } /* --- 369,375 ---- if (a & AT_STANDOUT) w += so_e_width; ! return (w); } /* *************** *** 409,419 **** * Adding a character with a given attribute may cause an enter or exit * attribute sequence to be inserted, so this must be taken into account. */ ! static int ! pwidth(ch, a, prev_ch) ! LWCHAR ch; ! int a; ! LWCHAR prev_ch; { int w; --- 378,385 ---- * Adding a character with a given attribute may cause an enter or exit * attribute sequence to be inserted, so this must be taken into account. */ ! static int ! pwidth(LWCHAR ch, int a, LWCHAR prev_ch) { int w; *************** *** 422,437 **** * Backspace moves backwards one or two positions. * XXX - Incorrect if several '\b' in a row. */ ! #if !SMALL ! return (utf_mode && is_wide_char(prev_ch)) ? -2 : -1; ! #else ! return -1; ! #endif /* !SMALL */ ! if (!utf_mode || is_ascii_char(ch)) ! { ! if (control_char((char)ch)) ! { /* * Control characters do unpredictable things, * so we don't even try to guess; say it doesn't move. --- 388,397 ---- * Backspace moves backwards one or two positions. * XXX - Incorrect if several '\b' in a row. */ ! return ((utf_mode && is_wide_char(prev_ch)) ? -2 : -1); ! if (!utf_mode || is_ascii_char(ch)) { ! if (control_char((char)ch)) { /* * Control characters do unpredictable things, * so we don't even try to guess; say it doesn't move. *************** *** 439,450 **** */ return (0); } ! } ! #if !SMALL ! else ! { ! if (is_composing_char(ch) || is_combining_char(prev_ch, ch)) ! { /* * Composing and combining chars take up no space. * --- 399,406 ---- */ return (0); } ! } else { ! if (is_composing_char(ch) || is_combining_char(prev_ch, ch)) { /* * Composing and combining chars take up no space. * *************** *** 459,475 **** return (0); } } - #endif /* !SMALL */ /* * Other characters take one or two columns, * plus the width of any attribute enter/exit sequence. */ w = 1; - #if !SMALL if (is_wide_char(ch)) w++; - #endif /* !SMALL */ if (curr > 0 && !is_at_equiv(attr[curr-1], a)) w += attr_ewidth(attr[curr-1]); if ((apply_at_specials(a) != AT_NORMAL) && --- 415,428 ---- *************** *** 482,489 **** * Delete to the previous base character in the line buffer. * Return 1 if one is found. */ ! static int ! backc() { LWCHAR prev_ch; char *p = linebuf + curr; --- 435,442 ---- * Delete to the previous base character in the line buffer. * Return 1 if one is found. */ ! static int ! backc(void) { LWCHAR prev_ch; char *p = linebuf + curr; *************** *** 491,517 **** int width; /* This assumes that there is no '\b' in linebuf. */ ! while ( curr > lmargin ! && column > lmargin ! && (!(attr[curr - 1] & (AT_ANSI|AT_BINARY)))) ! { curr = p - linebuf; prev_ch = step_char(&p, -1, linebuf + lmargin); width = pwidth(ch, attr[curr], prev_ch); column -= width; if (width > 0) ! return 1; ch = prev_ch; } ! return 0; } /* * Are we currently within a recognized ANSI escape sequence? */ ! static int ! in_ansi_esc_seq() { char *p; --- 444,468 ---- int width; /* This assumes that there is no '\b' in linebuf. */ ! while (curr > lmargin && column > lmargin && ! (!(attr[curr - 1] & (AT_ANSI|AT_BINARY)))) { curr = p - linebuf; prev_ch = step_char(&p, -1, linebuf + lmargin); width = pwidth(ch, attr[curr], prev_ch); column -= width; if (width > 0) ! return (1); ch = prev_ch; } ! return (0); } /* * Are we currently within a recognized ANSI escape sequence? */ ! static int ! in_ansi_esc_seq(void) { char *p; *************** *** 519,526 **** * 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 (p = &linebuf[curr]; p > linebuf; ) ! { LWCHAR ch = step_char(&p, -1, linebuf); if (IS_CSI_START(ch)) return (1); --- 470,476 ---- * 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 (p = &linebuf[curr]; p > linebuf; ) { LWCHAR ch = step_char(&p, -1, linebuf); if (IS_CSI_START(ch)) return (1); *************** *** 533,606 **** /* * Is a character the end of an ANSI escape sequence? */ ! public int ! is_ansi_end(ch) ! LWCHAR ch; { if (!is_ascii_char(ch)) return (0); ! return (strchr(end_ansi_chars, (char) ch) != NULL); } /* * */ ! public int ! is_ansi_middle(ch) ! LWCHAR ch; { if (!is_ascii_char(ch)) return (0); if (is_ansi_end(ch)) return (0); ! return (strchr(mid_ansi_chars, (char) ch) != NULL); } /* * Append a character and attribute to the line buffer. */ ! #define STORE_CHAR(ch,a,rep,pos) \ ! do { \ ! if (store_char((ch),(a),(rep),(pos))) return (1); \ ! } while (0) ! static int ! store_char(ch, a, rep, pos) ! LWCHAR ch; ! int a; ! char *rep; ! POSITION pos; { int w; int replen; char cs; w = (a & (AT_UNDERLINE|AT_BOLD)); /* Pre-use w. */ if (w != AT_NORMAL) last_overstrike = w; ! #if HILITE_SEARCH ! { ! int matches; ! if (is_hilited(pos, pos+1, 0, &matches)) ! { ! /* ! * This character should be highlighted. ! * Override the attribute passed in. ! */ ! if (a != AT_ANSI) ! { ! if (highest_hilite != NULL_POSITION && ! pos > highest_hilite) ! highest_hilite = pos; ! a |= AT_HILITE; ! } } } - #endif ! if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq()) ! { if (!is_ansi_end(ch) && !is_ansi_middle(ch)) { /* Remove whole unrecognized sequence. */ char *p = &linebuf[curr]; --- 483,541 ---- /* * Is a character the end of an ANSI escape sequence? */ ! int ! is_ansi_end(LWCHAR ch) { if (!is_ascii_char(ch)) return (0); ! return (strchr(end_ansi_chars, (char)ch) != NULL); } /* * */ ! int ! is_ansi_middle(LWCHAR ch) { if (!is_ascii_char(ch)) return (0); if (is_ansi_end(ch)) return (0); ! return (strchr(mid_ansi_chars, (char)ch) != NULL); } /* * Append a character and attribute to the line buffer. */ ! #define STORE_CHAR(ch, a, rep, pos) \ ! if (store_char((ch), (a), (rep), (pos))) \ ! return (1) ! static int ! store_char(LWCHAR ch, char a, char *rep, off_t pos) { int w; int replen; char cs; + int matches; w = (a & (AT_UNDERLINE|AT_BOLD)); /* Pre-use w. */ if (w != AT_NORMAL) last_overstrike = w; ! if (is_hilited(pos, pos+1, 0, &matches)) { ! /* ! * This character should be highlighted. ! * Override the attribute passed in. ! */ ! if (a != AT_ANSI) { ! if (highest_hilite != -1 && pos > highest_hilite) ! highest_hilite = pos; ! a |= AT_HILITE; } } ! if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq()) { if (!is_ansi_end(ch) && !is_ansi_middle(ch)) { /* Remove whole unrecognized sequence. */ char *p = &linebuf[curr]; *************** *** 609,626 **** bch = step_char(&p, -1, linebuf); } while (p > linebuf && !IS_CSI_START(bch)); curr = p - linebuf; ! return 0; } a = AT_ANSI; /* Will force re-AT_'ing around it. */ w = 0; ! } ! else if (ctldisp == OPT_ONPLUS && IS_CSI_START(ch)) ! { a = AT_ANSI; /* Will force re-AT_'ing around it. */ w = 0; ! } ! else ! { char *p = &linebuf[curr]; LWCHAR prev_ch = step_char(&p, -1, linebuf); w = pwidth(ch, a, prev_ch); --- 544,557 ---- bch = step_char(&p, -1, linebuf); } while (p > linebuf && !IS_CSI_START(bch)); curr = p - linebuf; ! return (0); } a = AT_ANSI; /* Will force re-AT_'ing around it. */ w = 0; ! } else if (ctldisp == OPT_ONPLUS && IS_CSI_START(ch)) { a = AT_ANSI; /* Will force re-AT_'ing around it. */ w = 0; ! } else { char *p = &linebuf[curr]; LWCHAR prev_ch = step_char(&p, -1, linebuf); w = pwidth(ch, a, prev_ch); *************** *** 632,652 **** */ return (1); ! if (rep == NULL) ! { ! cs = (char) ch; rep = &cs; replen = 1; ! } else ! { ! #if !SMALL replen = utf_len(rep[0]); - #else - replen = 1; - #endif /* !SMALL */ } ! if (curr + replen >= size_linebuf-6) ! { /* * Won't fit in line buffer. * Try to expand it. --- 563,576 ---- */ return (1); ! if (rep == NULL) { ! cs = (char)ch; rep = &cs; replen = 1; ! } else { replen = utf_len(rep[0]); } ! if (curr + replen >= size_linebuf-6) { /* * Won't fit in line buffer. * Try to expand it. *************** *** 655,662 **** return (1); } ! while (replen-- > 0) ! { linebuf[curr] = *rep++; attr[curr] = a; curr++; --- 579,585 ---- return (1); } ! while (replen-- > 0) { linebuf[curr] = *rep++; attr[curr] = a; curr++; *************** *** 669,712 **** * 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; } ! if (column + to_tab - 1 + pwidth(' ', attr, 0) + attr_ewidth(attr) > sc_width) ! return 1; do { STORE_CHAR(' ', attr, " ", pos); } while (--to_tab > 0); ! return 0; } ! #define STORE_PRCHAR(c, pos) \ ! do { if (store_prchar((c), (pos))) return 1; } while (0) ! static int ! store_prchar(c, pos) ! char c; ! POSITION pos; { char *s; --- 592,633 ---- * Append a tab to the line buffer. * Store spaces to represent the tab. */ ! #define STORE_TAB(a, pos) \ ! if (store_tab((a), (pos))) \ ! return (1) ! static int ! store_tab(int attr, off_t 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; } ! if (column + to_tab - 1 + pwidth(' ', attr, 0) + ! attr_ewidth(attr) > sc_width) ! return (1); do { STORE_CHAR(' ', attr, " ", pos); } while (--to_tab > 0); ! return (0); } ! #define STORE_PRCHAR(c, pos) \ ! if (store_prchar((c), (pos))) \ ! return (1) ! static int ! store_prchar(char c, off_t pos) { char *s; *************** *** 719,763 **** * Make sure we can get the entire representation * of the character on this line. */ ! if (column + (int) strlen(s) - 1 + ! pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) ! return 1; ! for ( ; *s != 0; s++) STORE_CHAR(*s, AT_BINARY, NULL, pos); ! ! return 0; } ! #if !SMALL ! static int ! flush_mbc_buf(pos) ! POSITION pos; { int i; for (i = 0; i < mbc_buf_index; i++) if (store_prchar(mbc_buf[i], pos)) ! return mbc_buf_index - i; ! return 0; } - #endif /* !SMALL */ /* * Append a character to the line buffer. * Expand tabs into spaces, handle underlining, boldfacing, etc. * Returns 0 if ok, 1 if couldn't fit in buffer. */ ! public int ! pappend(c, pos) ! char c; ! POSITION pos; { int r; ! if (pendc) ! { if (do_append(pendc, NULL, pendpos)) /* * Oops. We've probably lost the char which --- 640,678 ---- * Make sure we can get the entire representation * of the character on this line. */ ! if (column + (int)strlen(s) - 1 + ! pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) ! return (1); ! for (; *s != 0; s++) { STORE_CHAR(*s, AT_BINARY, NULL, pos); ! } ! return (0); } ! static int ! flush_mbc_buf(off_t pos) { int i; for (i = 0; i < mbc_buf_index; i++) if (store_prchar(mbc_buf[i], pos)) ! return (mbc_buf_index - i); ! return (0); } /* * Append a character to the line buffer. * Expand tabs into spaces, handle underlining, boldfacing, etc. * Returns 0 if ok, 1 if couldn't fit in buffer. */ ! int ! pappend(char c, off_t pos) { int r; ! if (pendc) { if (do_append(pendc, NULL, pendpos)) /* * Oops. We've probably lost the char which *************** *** 767,777 **** pendc = '\0'; } ! if (c == '\r' && bs_mode == BS_SPECIAL) ! { ! #if !SMALL ! if (mbc_buf_len > 0) /* utf_mode must be on. */ ! { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_index = r + 1; --- 682,689 ---- pendc = '\0'; } ! if (c == '\r' && bs_mode == BS_SPECIAL) { ! if (mbc_buf_len > 0) /* utf_mode must be on. */ { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_index = r + 1; *************** *** 779,788 **** if (r) return (mbc_buf_index); } - #endif /* !SMALL */ /* ! * Don't put the CR into the buffer until we see * the next char. If the next char is a newline, * discard the CR. */ --- 691,699 ---- if (r) return (mbc_buf_index); } /* ! * Don't put the CR into the buffer until we see * the next char. If the next char is a newline, * discard the CR. */ *************** *** 791,832 **** return (0); } ! if (!utf_mode) ! { r = do_append((LWCHAR) c, NULL, pos); ! } ! #if !SMALL ! else ! { /* Perform strict validation in all possible cases. */ ! if (mbc_buf_len == 0) ! { ! retry: mbc_buf_index = 1; *mbc_buf = c; ! if (IS_ASCII_OCTET(c)) r = do_append((LWCHAR) c, NULL, pos); ! else if (IS_UTF8_LEAD(c)) ! { mbc_buf_len = utf_len(c); mbc_pos = pos; return (0); ! } else /* UTF8_INVALID or stray UTF8_TRAIL */ r = flush_mbc_buf(pos); ! } else if (IS_UTF8_TRAIL(c)) ! { mbc_buf[mbc_buf_index++] = c; if (mbc_buf_index < mbc_buf_len) return (0); if (is_utf8_well_formed(mbc_buf)) ! r = do_append(get_wchar(mbc_buf), mbc_buf, mbc_pos); else /* Complete, but not shortest form, sequence. */ mbc_buf_index = r = flush_mbc_buf(mbc_pos); mbc_buf_len = 0; ! } else ! { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_index = r + 1; --- 702,737 ---- return (0); } ! if (!utf_mode) { r = do_append((LWCHAR) c, NULL, pos); ! } else { /* Perform strict validation in all possible cases. */ ! if (mbc_buf_len == 0) { ! retry: mbc_buf_index = 1; *mbc_buf = c; ! if (IS_ASCII_OCTET(c)) { r = do_append((LWCHAR) c, NULL, pos); ! } else if (IS_UTF8_LEAD(c)) { mbc_buf_len = utf_len(c); mbc_pos = pos; return (0); ! } else { /* UTF8_INVALID or stray UTF8_TRAIL */ r = flush_mbc_buf(pos); ! } ! } else if (IS_UTF8_TRAIL(c)) { mbc_buf[mbc_buf_index++] = c; if (mbc_buf_index < mbc_buf_len) return (0); if (is_utf8_well_formed(mbc_buf)) ! r = do_append(get_wchar(mbc_buf), mbc_buf, ! mbc_pos); else /* Complete, but not shortest form, sequence. */ mbc_buf_index = r = flush_mbc_buf(mbc_pos); mbc_buf_len = 0; ! } else { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_index = r + 1; *************** *** 834,842 **** /* Handle new char. */ if (!r) goto retry; ! } } - #endif /* !SMALL */ /* * If we need to shift the line, do it. --- 739,746 ---- /* Handle new char. */ if (!r) goto retry; ! } } /* * If we need to shift the line, do it. *************** *** 844,875 **** * 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); } ! if (r) ! { /* How many chars should caller back up? */ r = (!utf_mode) ? 1 : mbc_buf_index; } return (r); } ! static int ! do_append(ch, rep, pos) ! LWCHAR ch; ! char *rep; ! POSITION pos; { ! register int a; LWCHAR prev_ch; a = AT_NORMAL; ! if (ch == '\b') ! { if (bs_mode == BS_CONTROL) goto do_control_char; --- 748,773 ---- * 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); } ! if (r) { /* How many chars should caller back up? */ r = (!utf_mode) ? 1 : mbc_buf_index; } return (r); } ! static int ! do_append(LWCHAR ch, char *rep, off_t pos) { ! int a; LWCHAR prev_ch; a = AT_NORMAL; ! if (ch == '\b') { if (bs_mode == BS_CONTROL) goto do_control_char; *************** *** 878,914 **** * backspace over part of the printed * representation of a binary character. */ ! if ( curr <= lmargin ! || column <= lmargin ! || (attr[curr - 1] & (AT_ANSI|AT_BINARY))) STORE_PRCHAR('\b', pos); ! else if (bs_mode == BS_NORMAL) STORE_CHAR(ch, AT_NORMAL, NULL, pos); ! else if (bs_mode == BS_SPECIAL) overstrike = backc(); ! return 0; } ! if (overstrike > 0) ! { /* * Overstrike the character at the current position ! * in the line buffer. This will cause either ! * underline (if a "_" is overstruck), * bold (if an identical character is overstruck), * or just deletion of the character in the buffer. */ overstrike = utf_mode ? -1 : 0; /* To be correct, this must be a base character. */ - #if !SMALL prev_ch = get_wchar(linebuf + curr); - #else - prev_ch = (LWCHAR)((char)(linebuf + curr)[0] & 0xFF); - #endif /* !SMALL */ a = attr[curr]; ! if (ch == prev_ch) ! { /* * Overstriking a char with itself means make it bold. * But overstriking an underscore with itself is --- 776,807 ---- * backspace over part of the printed * representation of a binary character. */ ! if (curr <= lmargin || ! column <= lmargin || ! (attr[curr - 1] & (AT_ANSI|AT_BINARY))) { STORE_PRCHAR('\b', pos); ! } else if (bs_mode == BS_NORMAL) { STORE_CHAR(ch, AT_NORMAL, NULL, pos); ! } else if (bs_mode == BS_SPECIAL) { overstrike = backc(); + } ! return (0); } ! if (overstrike > 0) { /* * Overstrike the character at the current position ! * in the line buffer. This will cause either ! * underline (if a "_" is overstruck), * bold (if an identical character is overstruck), * or just deletion of the character in the buffer. */ overstrike = utf_mode ? -1 : 0; /* To be correct, this must be a base character. */ prev_ch = get_wchar(linebuf + curr); a = attr[curr]; ! if (ch == prev_ch) { /* * Overstriking a char with itself means make it bold. * But overstriking an underscore with itself is *************** *** 916,960 **** * it could mean make it underlined. * Use the previous overstrike to resolve it. */ ! if (ch == '_') ! { if ((a & (AT_BOLD|AT_UNDERLINE)) != AT_NORMAL) a |= (AT_BOLD|AT_UNDERLINE); else if (last_overstrike != AT_NORMAL) a |= last_overstrike; else a |= AT_BOLD; ! } else a |= AT_BOLD; ! } else if (ch == '_') ! { a |= AT_UNDERLINE; ch = prev_ch; rep = linebuf + curr; ! } else if (prev_ch == '_') ! { a |= AT_UNDERLINE; } /* Else we replace prev_ch, but we keep its attributes. */ ! } else if (overstrike < 0) ! { ! #if !SMALL ! if ( is_composing_char(ch) ! || is_combining_char(get_wchar(linebuf + curr), ch)) /* Continuation of the same overstrike. */ a = last_overstrike; else - #endif /* !SMALL */ overstrike = 0; } ! if (ch == '\t') ! { /* * Expand a tab into spaces. */ ! switch (bs_mode) ! { case BS_CONTROL: goto do_control_char; case BS_NORMAL: --- 809,846 ---- * it could mean make it underlined. * Use the previous overstrike to resolve it. */ ! if (ch == '_') { if ((a & (AT_BOLD|AT_UNDERLINE)) != AT_NORMAL) a |= (AT_BOLD|AT_UNDERLINE); else if (last_overstrike != AT_NORMAL) a |= last_overstrike; else a |= AT_BOLD; ! } else { a |= AT_BOLD; ! } ! } else if (ch == '_') { a |= AT_UNDERLINE; ch = prev_ch; rep = linebuf + curr; ! } else if (prev_ch == '_') { a |= AT_UNDERLINE; } /* Else we replace prev_ch, but we keep its attributes. */ ! } else if (overstrike < 0) { ! if (is_composing_char(ch) || ! is_combining_char(get_wchar(linebuf + curr), ch)) /* Continuation of the same overstrike. */ a = last_overstrike; else overstrike = 0; } ! if (ch == '\t') { /* * Expand a tab into spaces. */ ! switch (bs_mode) { case BS_CONTROL: goto do_control_char; case BS_NORMAL: *************** *** 962,1029 **** STORE_TAB(a, pos); break; } ! } else if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) ! { ! do_control_char: ! if (ctldisp == OPT_ON || (ctldisp == OPT_ONPLUS && IS_CSI_START(ch))) ! { /* * Output as a normal character. */ STORE_CHAR(ch, AT_NORMAL, rep, pos); ! } else ! { ! STORE_PRCHAR((char) ch, pos); } ! } ! #if !SMALL ! else if (utf_mode && ctldisp != OPT_ON && is_ubin_char(ch)) ! { char *s; s = prutfchar(ch); ! if (column + (int) strlen(s) - 1 + pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) return (1); ! for ( ; *s != 0; s++) STORE_CHAR(*s, AT_BINARY, NULL, pos); ! } ! #endif /* !SMALL */ ! else ! { STORE_CHAR(ch, a, rep, pos); } ! return (0); } /* * */ ! public int ! pflushmbc() { int r = 0; ! #if !SMALL ! if (mbc_buf_len > 0) ! { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_len = 0; } ! #endif /* !SMALL */ ! return r; } /* * Terminate the line in the line buffer. */ ! public void ! pdone(endline, forw) ! int endline; ! int forw; { (void) pflushmbc(); --- 848,902 ---- STORE_TAB(a, pos); break; } ! } else if ((!utf_mode || is_ascii_char(ch)) && control_char((char)ch)) { ! do_control_char: ! if (ctldisp == OPT_ON || ! (ctldisp == OPT_ONPLUS && IS_CSI_START(ch))) { /* * Output as a normal character. */ STORE_CHAR(ch, AT_NORMAL, rep, pos); ! } else { ! STORE_PRCHAR((char)ch, pos); } ! } else if (utf_mode && ctldisp != OPT_ON && is_ubin_char(ch)) { char *s; s = prutfchar(ch); ! if (column + (int)strlen(s) - 1 + pwidth(' ', binattr, 0) + attr_ewidth(binattr) > sc_width) return (1); ! for (; *s != 0; s++) STORE_CHAR(*s, AT_BINARY, NULL, pos); ! } else { STORE_CHAR(ch, a, rep, pos); } ! return (0); } /* * */ ! int ! pflushmbc(void) { int r = 0; ! if (mbc_buf_len > 0) { /* Flush incomplete (truncated) sequence. */ r = flush_mbc_buf(mbc_pos); mbc_buf_len = 0; } ! return (r); } /* * Terminate the line in the line buffer. */ ! void ! pdone(int endline, int forw) { (void) pflushmbc(); *************** *** 1041,1052 **** if (cshift < hshift) pshift(hshift - cshift); ! if (ctldisp == OPT_ONPLUS && is_ansi_end('m')) ! { /* Switch to normal attribute at end of line. */ char *p = "\033[m"; ! for ( ; *p != '\0'; p++) ! { linebuf[curr] = *p; attr[curr++] = AT_ANSI; } --- 914,923 ---- if (cshift < hshift) pshift(hshift - cshift); ! if (ctldisp == OPT_ONPLUS && is_ansi_end('m')) { /* Switch to normal attribute at end of line. */ char *p = "\033[m"; ! for (; *p != '\0'; p++) { linebuf[curr] = *p; attr[curr++] = AT_ANSI; } *************** *** 1059,1078 **** * or if the terminal doesn't auto wrap, * or if this is really the end of the line AND the terminal ignores * a newline at the right edge. ! * (In the last case we don't want to output a newline if the terminal * doesn't ignore it since that would produce an extra blank line. * But we do want to output a newline if the terminal ignores it in case * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ ! if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) ! { linebuf[curr] = '\n'; attr[curr] = AT_NORMAL; curr++; ! } ! else if (ignaw && column >= sc_width && forw) ! { /* * Terminals with "ignaw" don't wrap until they *really* need * to, i.e. when the character *after* the last one to fit on a --- 930,947 ---- * or if the terminal doesn't auto wrap, * or if this is really the end of the line AND the terminal ignores * a newline at the right edge. ! * (In the last case we don't want to output a newline if the terminal * doesn't ignore it since that would produce an extra blank line. * But we do want to output a newline if the terminal ignores it in case * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ ! if (column < sc_width || !auto_wrap || (endline && ignaw) || ! ctldisp == OPT_ON) { linebuf[curr] = '\n'; attr[curr] = AT_NORMAL; curr++; ! } else if (ignaw && column >= sc_width && forw) { /* * Terminals with "ignaw" don't wrap until they *really* need * to, i.e. when the character *after* the last one to fit on a *************** *** 1080,1095 **** * get in the state where a full screen width of characters * have been output but the cursor is sitting on the right edge * instead of at the start of the next line. ! * So we nudge them into wrapping by outputting a space ! * character plus a backspace. But do this only if moving * forward; if we're moving backward and drawing this line at * the top of the screen, the space would overwrite the first ! * char on the next line. We don't need to do this "nudge" * at the top of the screen anyway. */ linebuf[curr] = ' '; attr[curr++] = AT_NORMAL; ! linebuf[curr] = '\b'; attr[curr++] = AT_NORMAL; } linebuf[curr] = '\0'; --- 949,964 ---- * get in the state where a full screen width of characters * have been output but the cursor is sitting on the right edge * instead of at the start of the next line. ! * So we nudge them into wrapping by outputting a space ! * character plus a backspace. But do this only if moving * forward; if we're moving backward and drawing this line at * the top of the screen, the space would overwrite the first ! * char on the next line. We don't need to do this "nudge" * at the top of the screen anyway. */ linebuf[curr] = ' '; attr[curr++] = AT_NORMAL; ! linebuf[curr] = '\b'; attr[curr++] = AT_NORMAL; } linebuf[curr] = '\0'; *************** *** 1099,1107 **** /* * */ ! public void ! set_status_col(c) ! char c; { linebuf[0] = c; attr[0] = AT_NORMAL|AT_HILITE; --- 968,975 ---- /* * */ ! void ! set_status_col(char c) { linebuf[0] = c; attr[0] = AT_NORMAL|AT_HILITE; *************** *** 1112,1140 **** * Return the character as the function return value, * and the character attribute in *ap. */ ! public int ! gline(i, ap) ! register int i; ! register int *ap; { ! if (is_null_line) ! { /* * If there is no current line, we pretend the line is * either "~" or "", depending on the "twiddle" flag. */ ! if (twiddle) ! { ! if (i == 0) ! { *ap = AT_BOLD; ! return '~'; } --i; } /* Make sure we're back to AT_NORMAL before the '\n'. */ *ap = AT_NORMAL; ! return i ? '\0' : '\n'; } *ap = attr[i]; --- 980,1003 ---- * Return the character as the function return value, * and the character attribute in *ap. */ ! int ! gline(int i, int *ap) { ! if (is_null_line) { /* * If there is no current line, we pretend the line is * either "~" or "", depending on the "twiddle" flag. */ ! if (twiddle) { ! if (i == 0) { *ap = AT_BOLD; ! return ('~'); } --i; } /* Make sure we're back to AT_NORMAL before the '\n'. */ *ap = AT_NORMAL; ! return (i ? '\0' : '\n'); } *ap = attr[i]; *************** *** 1144,1151 **** /* * Indicate that there is no current line. */ ! public void ! null_line() { is_null_line = 1; cshift = 0; --- 1007,1014 ---- /* * Indicate that there is no current line. */ ! void ! null_line(void) { is_null_line = 1; cshift = 0; *************** *** 1156,1187 **** * lines which are not split for screen width. * {{ This is supposed to be more efficient than forw_line(). }} */ ! public POSITION ! forw_raw_line(curr_pos, linep, line_lenp) ! POSITION curr_pos; ! char **linep; ! int *line_lenp; { ! register int n; ! register int c; ! POSITION new_pos; ! if (curr_pos == NULL_POSITION || ch_seek(curr_pos) || ! (c = ch_forw_get()) == EOI) ! return (NULL_POSITION); n = 0; ! for (;;) ! { ! if (c == '\n' || c == EOI || ABORT_SIGS()) ! { new_pos = ch_tell(); break; } ! if (n >= size_linebuf-1) ! { ! if (expand_linebuf()) ! { /* * Overflowed the input buffer. * Pretend the line ended here. --- 1019,1043 ---- * lines which are not split for screen width. * {{ This is supposed to be more efficient than forw_line(). }} */ ! off_t ! forw_raw_line(off_t curr_pos, char **linep, int *line_lenp) { ! int n; ! int c; ! off_t new_pos; ! if (curr_pos == -1 || ch_seek(curr_pos) || ! (c = ch_forw_get()) == EOI) ! return (-1); n = 0; ! for (;;) { ! if (c == '\n' || c == EOI || ABORT_SIGS()) { new_pos = ch_tell(); break; } ! if (n >= size_linebuf-1) { ! if (expand_linebuf()) { /* * Overflowed the input buffer. * Pretend the line ended here. *************** *** 1190,1196 **** break; } } ! linebuf[n++] = c; c = ch_forw_get(); } linebuf[n] = '\0'; --- 1046,1052 ---- break; } } ! linebuf[n++] = (char)c; c = ch_forw_get(); } linebuf[n] = '\0'; *************** *** 1205,1231 **** * Analogous to back_line(), but deals with "raw lines". * {{ This is supposed to be more efficient than back_line(). }} */ ! public POSITION ! back_raw_line(curr_pos, linep, line_lenp) ! POSITION curr_pos; ! char **linep; ! int *line_lenp; { ! register int n; ! register int c; ! POSITION new_pos; ! if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() || ! ch_seek(curr_pos-1)) ! return (NULL_POSITION); n = size_linebuf; linebuf[--n] = '\0'; ! for (;;) ! { c = ch_back_get(); ! if (c == '\n' || ABORT_SIGS()) ! { /* * This is the newline ending the previous line. * We have hit the beginning of the line. --- 1061,1081 ---- * Analogous to back_line(), but deals with "raw lines". * {{ This is supposed to be more efficient than back_line(). }} */ ! off_t ! back_raw_line(off_t curr_pos, char **linep, int *line_lenp) { ! int n; ! int c; ! off_t new_pos; ! if (curr_pos == -1 || curr_pos <= ch_zero() || ch_seek(curr_pos - 1)) ! return (-1); n = size_linebuf; linebuf[--n] = '\0'; ! for (;;) { c = ch_back_get(); ! if (c == '\n' || ABORT_SIGS()) { /* * This is the newline ending the previous line. * We have hit the beginning of the line. *************** *** 1233,1240 **** new_pos = ch_tell() + 1; break; } ! if (c == EOI) ! { /* * We have hit the beginning of the file. * This must be the first line in the file. --- 1083,1089 ---- new_pos = ch_tell() + 1; break; } ! if (c == EOI) { /* * We have hit the beginning of the file. * This must be the first line in the file. *************** *** 1243,1253 **** new_pos = ch_zero(); break; } ! if (n <= 0) ! { int old_size_linebuf = size_linebuf; ! if (expand_linebuf()) ! { /* * Overflowed the input buffer. * Pretend the line ended here. --- 1092,1100 ---- new_pos = ch_zero(); break; } ! if (n <= 0) { int old_size_linebuf = size_linebuf; ! if (expand_linebuf()) { /* * Overflowed the input buffer. * Pretend the line ended here.