From 056a497cc8e028a9df9116d71918f5a643ed76d4 Mon Sep 17 00:00:00 2001 From: Thomas Jensen Date: Sun, 17 Feb 2019 14:28:20 +0100 Subject: [PATCH] Improve handling of partial lines When boxes is fed text selected in a visual editor, this often means that the final line of input text has no terminating newline (it's a "partial line"). This caused an extra blank line to appear in the editor after running boxes. #57 This commit changes the behavior of boxes so that a newline is only added at the very end of the output, if there also was one at the very end of the input. --- src/boxes.c | 32 ++++++++++++++++++++++++++++++-- src/boxes.h.in | 3 ++- src/generate.c | 2 +- src/remove.c | 3 ++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/boxes.c b/src/boxes.c index 3fdb32a..d28902c 100644 --- a/src/boxes.c +++ b/src/boxes.c @@ -1328,6 +1328,32 @@ static int apply_substitutions (const int mode) +static int has_linebreak (const char *s, const int len) +/* + * Determine if the given line of raw text is ended by a line break. + * + * s: the string to check + * len: length of s + * + * RETURNS: != 0 line break found + * == 0 line break not found + * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ +{ + int result = 0; + if (s != NULL && len > 0) { + char the_last = s[len - 1]; + result = the_last == '\r' || the_last == '\n'; + #if defined(DEBUG) + fprintf(stderr, "has_linebreak: (%d) %d\n", the_last, result); + #endif + } + return result; +} + + + static int read_all_input (const int use_stdin) /* * Read entire input (possibly from stdin) and store it in 'input' array. @@ -1375,6 +1401,7 @@ static int read_all_input (const int use_stdin) } input.lines[input.anz_lines].len = strlen (buf); + input.final_newline = has_linebreak(buf, input.lines[input.anz_lines].len); if (opt.r) { input.lines[input.anz_lines].len -= 1; @@ -1488,8 +1515,9 @@ static int read_all_input (const int use_stdin) } fprintf (stderr, "] (%d)\n", input.lines[i].tabpos_len); } - fprintf (stderr, "\nLongest line: %d characters.\n", input.maxline); - fprintf (stderr, " Indentation: %2d spaces.\n", input.indent); + fprintf (stderr, "\n Longest line: %d characters.\n", input.maxline); + fprintf (stderr, " Indentation: %2d spaces.\n", input.indent); + fprintf (stderr, "Final newline: %d.\n", input.final_newline); #endif return 0; diff --git a/src/boxes.h.in b/src/boxes.h.in index b35fd96..235961e 100644 --- a/src/boxes.h.in +++ b/src/boxes.h.in @@ -154,9 +154,10 @@ typedef struct { size_t anz_lines; /* number of entries in input */ size_t maxline; /* length of longest input line */ size_t indent; /* number of leading spaces found */ + int final_newline; /* true if the last line of input ends with newline */ } input_t; -#define INPUT_INITIALIZER {NULL, 0, 0, LINE_MAX} +#define INPUT_INITIALIZER {NULL, 0, 0, LINE_MAX, 0} extern input_t input; #endif /*!FILE_LEXER_L*/ diff --git a/src/generate.c b/src/generate.c index 7f8d390..1a1a5c3 100644 --- a/src/generate.c +++ b/src/generate.c @@ -1043,7 +1043,7 @@ int output_box (const sentry_t *thebox) BFREE (restored_indent); } - fprintf (opt.outfile, "%s\n", obuf); + fprintf (opt.outfile, "%s%s", obuf, (input.final_newline || j < nol-skip_end-1 ? "\n" : "")); } BFREE (indentspc); diff --git a/src/remove.c b/src/remove.c index c45c3ce..eca1977 100644 --- a/src/remove.c +++ b/src/remove.c @@ -1051,7 +1051,8 @@ void output_input (const int trim_only) indent = 0; } - fprintf (opt.outfile, "%s%s\n", indentspc, input.lines[j].text + indent); + fprintf (opt.outfile, "%s%s%s", indentspc, input.lines[j].text + indent, + (input.final_newline || j < input.anz_lines-1 ? "\n" : "")); BFREE (indentspc); } }