mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-01-19 04:18:12 +01:00
First successful box with unicode and ansi sequences #1
Existing test cases all green
This commit is contained in:
parent
865432a2da
commit
eeeacf2949
155
src/generate.c
155
src/generate.c
@ -27,6 +27,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <uniconv.h>
|
||||
#include <unistr.h>
|
||||
|
||||
#include "shape.h"
|
||||
#include "boxes.h"
|
||||
#include "tools.h"
|
||||
@ -706,48 +710,50 @@ static int justify_line(line_t *line, int skew)
|
||||
*
|
||||
* line is assumed to be already free of trailing whitespace.
|
||||
*
|
||||
* RETURNS: == 0 success, input array was modified
|
||||
* != 0 error
|
||||
* RETURNS: number of space characters which must be added to (> 0)
|
||||
* or removed from (< 0) the beginning of the line
|
||||
* A return value of 0 means "nothing to do".
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
{
|
||||
char *p; /* pointer to first non-whitespace char */
|
||||
char *newtext;
|
||||
size_t newlen;
|
||||
char *spaces;
|
||||
size_t shift;
|
||||
size_t oldlen = line->len;
|
||||
|
||||
if (empty_line(line)) {
|
||||
line->num_leading_blanks = SIZE_MAX;
|
||||
return 0;
|
||||
}
|
||||
if (opt.justify == '\0') {
|
||||
line->num_leading_blanks = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (p = line->text; *p == ' ' || *p == '\t'; ++p) {
|
||||
}
|
||||
newlen = line->len - (p - line->text);
|
||||
#if defined(DEBUG) || 0
|
||||
fprintf (stderr, "justify_line(%c): Input: real: (%02d) \"%s\", text: (%02d) \"%s\", invisible=%d, skew=%d",
|
||||
opt.justify ? opt.justify : '0', (int) line->num_chars, u32_strconv_to_locale(line->mbtext),
|
||||
(int) line->len, line->text, (int) line->invis, skew);
|
||||
#endif
|
||||
|
||||
int result = 0;
|
||||
size_t initial_space_size = strspn(line->text, " \t");
|
||||
size_t newlen = line->len - initial_space_size;
|
||||
size_t shift;
|
||||
|
||||
switch (opt.justify) {
|
||||
|
||||
case 'l':
|
||||
if (opt.design->indentmode == 't') {
|
||||
memmove(line->text + input.indent, p, newlen + 1);
|
||||
line->len = newlen + input.indent;
|
||||
/* text indented inside of box */
|
||||
line->num_leading_blanks = input.indent;
|
||||
result = (int) input.indent - (int) initial_space_size;
|
||||
}
|
||||
else {
|
||||
memmove(line->text, p, newlen + 1);
|
||||
line->len = newlen;
|
||||
line->num_leading_blanks = 0;
|
||||
result = -1 * (int) initial_space_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (opt.design->indentmode == 't') {
|
||||
/* text indented inside of box */
|
||||
shift = (input.maxline - input.indent - newlen) / 2 + input.indent;
|
||||
skew -= input.indent;
|
||||
if ((input.maxline - input.indent - newlen) % 2 && skew == 1) {
|
||||
@ -760,78 +766,26 @@ static int justify_line(line_t *line, int skew)
|
||||
++shift;
|
||||
}
|
||||
}
|
||||
|
||||
newtext = (char *) calloc(shift + newlen + 1, sizeof(char));
|
||||
if (newtext == NULL) {
|
||||
perror(PROJECT);
|
||||
return 2;
|
||||
}
|
||||
spaces = (char *) malloc(shift + 1);
|
||||
if (spaces == NULL) {
|
||||
perror(PROJECT);
|
||||
BFREE (newtext);
|
||||
return 3;
|
||||
}
|
||||
memset(spaces, ' ', shift);
|
||||
spaces[shift] = '\0';
|
||||
#if defined(DEBUG) && 0
|
||||
fprintf (stderr, "j(c): newlen=%d, shift=%d, spaces=\"%s\"\n",
|
||||
newlen, shift, spaces);
|
||||
#endif
|
||||
strncpy(newtext, spaces, shift);
|
||||
strncat(newtext, p, newlen);
|
||||
newtext[shift + newlen] = '\0';
|
||||
BFREE (spaces);
|
||||
BFREE (line->text);
|
||||
line->text = newtext;
|
||||
line->len = shift + newlen;
|
||||
line->num_leading_blanks = shift;
|
||||
result = (int) shift - (int) initial_space_size;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
shift = input.maxline - newlen;
|
||||
newtext = (char *) calloc (input.maxline+1, sizeof(char));
|
||||
if (newtext == NULL) {
|
||||
perror(PROJECT);
|
||||
return 2;
|
||||
}
|
||||
spaces = (char *) malloc(shift + 1);
|
||||
if (spaces == NULL) {
|
||||
perror(PROJECT);
|
||||
BFREE (newtext);
|
||||
return 3;
|
||||
}
|
||||
memset(spaces, ' ', shift);
|
||||
spaces[shift] = '\0';
|
||||
strncpy(newtext, spaces, shift);
|
||||
strncat(newtext, p, newlen);
|
||||
newtext[input.maxline] = '\0';
|
||||
BFREE (spaces);
|
||||
BFREE (line->text);
|
||||
line->text = newtext;
|
||||
line->len = input.maxline;
|
||||
line->num_leading_blanks = shift;
|
||||
result = (int) shift - (int) initial_space_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: internal error\n", PROJECT);
|
||||
return 1;
|
||||
fprintf(stderr, "%s: internal error (unknown justify option: %c)\n", PROJECT, opt.justify);
|
||||
line->num_leading_blanks = 0;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we might have broken the maxline value, recalculate it.
|
||||
*/
|
||||
if (opt.justify != 'r' && oldlen == input.maxline) {
|
||||
size_t k;
|
||||
input.maxline = 0;
|
||||
for (k = 0; k < input.anz_lines; ++k) {
|
||||
if (input.lines[k].len > input.maxline) {
|
||||
input.maxline = input.lines[k].len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#if defined(DEBUG) || 0
|
||||
fprintf (stderr, " -> %d (%d leading spaces)\n", result, (int) line->num_leading_blanks);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -851,15 +805,12 @@ int output_box(const sentry_t *thebox)
|
||||
{
|
||||
size_t j;
|
||||
size_t nol = thebox[BRIG].height; /* number of output lines */
|
||||
char trailspc[LINE_MAX_BYTES + 1];
|
||||
char *indentspc;
|
||||
int indentspclen;
|
||||
size_t vfill, vfill1, vfill1_save, vfill2; /* empty lines/columns in box */
|
||||
size_t hfill;
|
||||
char *hfill1, *hfill2; /* space before/after text */
|
||||
size_t hpl, hpr;
|
||||
size_t r;
|
||||
int rc;
|
||||
char obuf[LINE_MAX_BYTES + 1]; /* final output buffer */
|
||||
size_t obuf_len; /* length of content of obuf */
|
||||
size_t skip_start; /* lines to skip for box top */
|
||||
@ -912,13 +863,6 @@ int output_box(const sentry_t *thebox)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide string of spaces for filling of space between text and
|
||||
* right side of box
|
||||
*/
|
||||
memset(trailspc, (int) ' ', LINE_MAX_BYTES);
|
||||
trailspc[LINE_MAX_BYTES] = '\0';
|
||||
|
||||
/*
|
||||
* Compute number of empty lines in box (vfill).
|
||||
*/
|
||||
@ -1029,29 +973,17 @@ int output_box(const sentry_t *thebox)
|
||||
}
|
||||
|
||||
else if (vfill1) { /* top vfill */
|
||||
r = thebox[BTOP].width;
|
||||
trailspc[r] = '\0';
|
||||
restored_indent = tabbify_indent(0, indentspc, indentspclen);
|
||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
||||
skip_left ? "" : thebox[BLEF].chars[j], trailspc,
|
||||
skip_left ? "" : thebox[BLEF].chars[j], nspaces(thebox[BTOP].width),
|
||||
thebox[BRIG].chars[j]);
|
||||
trailspc[r] = ' ';
|
||||
--vfill1;
|
||||
}
|
||||
|
||||
else if (j < nol - thebox[BBOT].height) {
|
||||
long ti = j - thebox[BTOP].height - (vfill - vfill2);
|
||||
if (ti < (long) input.anz_lines) { /* box content (lines) */
|
||||
#if defined(DEBUG) && 0
|
||||
fprintf (stderr, "justify_line ({\"%s\",%d}, %d);\n",
|
||||
input.lines[ti].text, input.lines[ti].len, hpr-hpl);
|
||||
#endif
|
||||
rc = justify_line(input.lines + ti, hpr - hpl);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
r = input.maxline - input.lines[ti].len;
|
||||
trailspc[r] = '\0';
|
||||
int shift = justify_line(input.lines + ti, hpr - hpl);
|
||||
restored_indent = tabbify_indent(ti, indentspc, indentspclen);
|
||||
if (input.lines[ti].num_leading_blanks == SIZE_MAX) {
|
||||
contentPos[ti] = SIZE_MAX;
|
||||
@ -1061,20 +993,19 @@ int output_box(const sentry_t *thebox)
|
||||
+ strlen(hfill1)
|
||||
+ input.lines[ti].num_leading_blanks;
|
||||
}
|
||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 7, restored_indent,
|
||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 8, restored_indent,
|
||||
skip_left ? "" : thebox[BLEF].chars[j], hfill1,
|
||||
ti >= 0 ? input.lines[ti].text : "", hfill2,
|
||||
trailspc, thebox[BRIG].chars[j]);
|
||||
}
|
||||
else { /* bottom vfill */
|
||||
r = thebox[BTOP].width;
|
||||
trailspc[r] = '\0';
|
||||
restored_indent = tabbify_indent(input.anz_lines - 1, indentspc, indentspclen);
|
||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
||||
skip_left ? "" : thebox[BLEF].chars[j], trailspc,
|
||||
ti >= 0 && shift > 0 ? nspaces(shift) : "",
|
||||
ti >= 0 ? u32_strconv_to_locale(input.lines[ti].mbtext - (shift < 0 ? shift : 0)) : "",
|
||||
hfill2, nspaces(input.maxline - input.lines[ti].len - shift),
|
||||
thebox[BRIG].chars[j]);
|
||||
}
|
||||
else { /* bottom vfill */
|
||||
restored_indent = tabbify_indent(input.anz_lines - 1, indentspc, indentspclen);
|
||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
||||
skip_left ? "" : thebox[BLEF].chars[j], nspaces(thebox[BTOP].width),
|
||||
thebox[BRIG].chars[j]);
|
||||
}
|
||||
trailspc[r] = ' ';
|
||||
}
|
||||
|
||||
else { /* box bottom */
|
||||
|
21
src/tools.c
21
src/tools.c
@ -196,7 +196,7 @@ void concat_strings(char *dst, int max_len, int count, ...)
|
||||
/*
|
||||
* Concatenate 'src' onto 'dst', as long as we have room.
|
||||
*/
|
||||
while (*src && max_len > 1) {
|
||||
while (*src && max_len > 1) { // TODO Can this be improved via strcpy
|
||||
*dst++ = *src++;
|
||||
max_len--;
|
||||
}
|
||||
@ -478,4 +478,23 @@ char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentsp
|
||||
|
||||
|
||||
|
||||
char *nspaces(const size_t n)
|
||||
{
|
||||
char *spaces = (char *) memset(malloc(n + 1), (int) ' ', n);
|
||||
spaces[n] = '\0';
|
||||
return spaces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t *nspaces32(const size_t n)
|
||||
{
|
||||
uint32_t *spaces = (uint32_t *) malloc((n + 1) * sizeof(uint32_t));
|
||||
u32_set(spaces, char_space, n);
|
||||
u32_set(spaces + n, char_nul, 1);
|
||||
return spaces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*EOF*/ /* vim: set sw=4: */
|
||||
|
@ -19,13 +19,14 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tool functions for error reporting and some string handling and other
|
||||
* needful things
|
||||
* Tool functions for error reporting and some string handling and other needful things
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_H
|
||||
#define TOOLS_H
|
||||
|
||||
#include <unitypes.h>
|
||||
|
||||
|
||||
#define BMAX(a, b) ((a)>(b)? (a):(b)) /* return the larger value */
|
||||
|
||||
@ -61,6 +62,9 @@ void concat_strings(char *dst, int max_len, int count, ...);
|
||||
|
||||
char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentspc_len);
|
||||
|
||||
char *nspaces(const size_t n);
|
||||
|
||||
uint32_t *nspaces32(const size_t n);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user