diff options
Diffstat (limited to 'line.c')
-rw-r--r-- | line.c | 182 |
1 files changed, 135 insertions, 47 deletions
@@ -7,7 +7,6 @@ * 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 @@ -18,6 +17,11 @@ #include "charset.h" #include "position.h" +#if MSDOS_COMPILER==WIN32C +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + 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) */ @@ -32,6 +36,8 @@ 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 right_curr; +static int right_column; 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 */ @@ -41,9 +47,9 @@ 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(); +static int attr_swidth LESSPARAMS ((int a)); +static int attr_ewidth LESSPARAMS ((int a)); +static int do_append LESSPARAMS ((LWCHAR ch, char *rep, POSITION pos)); extern int sigs; extern int bs_mode; @@ -61,6 +67,8 @@ extern int sc_width, sc_height; extern int utf_mode; extern POSITION start_attnpos; extern POSITION end_attnpos; +extern LWCHAR rscroll_char; +extern int rscroll_attr; static char mbc_buf[MAX_UTF_CHAR_LEN]; static int mbc_buf_len = 0; @@ -152,6 +160,8 @@ prewind() { curr = 0; column = 0; + right_curr = 0; + right_column = 0; cshift = 0; overstrike = 0; last_overstrike = AT_NORMAL; @@ -160,7 +170,33 @@ prewind() pendc = '\0'; lmargin = 0; if (status_col) - lmargin += 1; + lmargin += 2; +} + +/* + * Set a character in the line buffer. + */ + static void +set_linebuf(n, ch, a) + int n; + LWCHAR ch; + char a; +{ + linebuf[n] = ch; + attr[n] = a; +} + +/* + * Append a character to the line buffer. + */ + static void +add_linebuf(ch, a, w) + LWCHAR ch; + char a; + int w; +{ + set_linebuf(curr++, ch, a); + column += w; } /* @@ -191,45 +227,48 @@ plinenum(pos) */ if (status_col) { - linebuf[curr] = ' '; - if (start_attnpos != NULL_POSITION && - pos >= start_attnpos && pos < end_attnpos) - attr[curr] = AT_NORMAL|AT_HILITE; - else - attr[curr] = AT_NORMAL; - curr++; - column++; + int a = AT_NORMAL; + char c = posmark(pos); + if (c != 0) + a |= AT_HILITE; + else + { + c = ' '; + if (start_attnpos != NULL_POSITION && + pos >= start_attnpos && pos <= end_attnpos) + a |= AT_HILITE; + } + add_linebuf(c, a, 1); /* column 0: status */ + add_linebuf(' ', AT_NORMAL, 1); /* column 1: empty */ } + /* * 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]; + char buf[INT_STRLEN_BOUND(linenum) + 2]; + int pad = 0; int n; linenumtoa(linenum, buf); n = (int) strlen(buf); if (n < MIN_LINENUM_WIDTH) - n = MIN_LINENUM_WIDTH; - sprintf(linebuf+curr, "%*s ", n, buf); - n++; /* One space after the line number. */ + pad = MIN_LINENUM_WIDTH - n; + for (i = 0; i < pad; i++) + add_linebuf(' ', AT_NORMAL, 1); for (i = 0; i < n; i++) - attr[curr+i] = AT_BOLD; - curr += n; - column += n; - lmargin += n; + add_linebuf(buf[i], AT_BOLD, 1); + add_linebuf(' ', AT_NORMAL, 1); + lmargin += n + pad + 1; } - /* * Append enough spaces to bring us to the lmargin. */ while (column < lmargin) { - linebuf[curr] = ' '; - attr[curr++] = AT_NORMAL; - column++; + add_linebuf(' ', AT_NORMAL, 1); } } @@ -540,7 +579,7 @@ is_ansi_end(ch) } /* - * + * Can a char appear in an ANSI escape sequence, before the end char? */ public int is_ansi_middle(ch) @@ -554,6 +593,23 @@ is_ansi_middle(ch) } /* + * Skip past an ANSI escape sequence. + * pp is initially positioned just after the CSI_START char. + */ + public void +skip_ansi(pp, limit) + char **pp; + constant char *limit; +{ + LWCHAR c; + do { + c = step_char(pp, +1, limit); + } while (*pp < limit && is_ansi_middle(c)); + /* Note that we discard final char, for which is_ansi_middle is false. */ +} + + +/* * Append a character and attribute to the line buffer. */ #define STORE_CHAR(ch,a,rep,pos) \ @@ -648,11 +704,15 @@ store_char(ch, a, rep, pos) return (1); } + if (column > right_column && w > 0) + { + right_column = column; + right_curr = curr; + } + while (replen-- > 0) { - linebuf[curr] = *rep++; - attr[curr] = a; - curr++; + add_linebuf(*rep++, a, 0); } column += w; return (0); @@ -1000,11 +1060,26 @@ pflushmbc() } /* + * Switch to normal attribute at end of line. + */ + static void +add_attr_normal() +{ + char *p = "\033[m"; + + if (ctldisp != OPT_ONPLUS || !is_ansi_end('m')) + return; + for ( ; *p != '\0'; p++) + add_linebuf(*p, AT_ANSI, 0); +} + +/* * Terminate the line in the line buffer. */ public void -pdone(endline, forw) +pdone(endline, chopped, forw) int endline; + int chopped; int forw; { (void) pflushmbc(); @@ -1023,15 +1098,34 @@ pdone(endline, forw) if (cshift < hshift) pshift(hshift - cshift); - if (ctldisp == OPT_ONPLUS && is_ansi_end('m')) + if (chopped && rscroll_char) { - /* Switch to normal attribute at end of line. */ - char *p = "\033[m"; - for ( ; *p != '\0'; p++) + /* + * Display the right scrolling char. + * If we've already filled the rightmost screen char + * (in the buffer), overwrite it. + */ + if (column >= sc_width) { - linebuf[curr] = *p; - attr[curr++] = AT_ANSI; + /* We've already written in the rightmost char. */ + column = right_column; + curr = right_curr; } + add_attr_normal(); + while (column < sc_width-1) + { + /* + * Space to last (rightmost) char on screen. + * This may be necessary if the char we overwrote + * was double-width. + */ + add_linebuf(' ', AT_NORMAL, 1); + } + /* Print rscroll char. It must be single-width. */ + add_linebuf(rscroll_char, rscroll_attr, 1); + } else + { + add_attr_normal(); } /* @@ -1049,9 +1143,7 @@ pdone(endline, forw) */ if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) { - linebuf[curr] = '\n'; - attr[curr] = AT_NORMAL; - curr++; + add_linebuf('\n', AT_NORMAL, 0); } else if (ignaw && column >= sc_width && forw) { @@ -1069,13 +1161,10 @@ pdone(endline, forw) * 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; + add_linebuf(' ', AT_NORMAL, 1); + add_linebuf('\b', AT_NORMAL, -1); } - linebuf[curr] = '\0'; - attr[curr] = AT_NORMAL; + set_linebuf(curr, '\0', AT_NORMAL); } /* @@ -1085,8 +1174,7 @@ pdone(endline, forw) set_status_col(c) char c; { - linebuf[0] = c; - attr[0] = AT_NORMAL|AT_HILITE; + set_linebuf(0, c, AT_NORMAL|AT_HILITE); } /* |