mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-06-19 17:28:26 +02:00
Add bxstring support to 'generate' module
This commit is contained in:
parent
232be1cdc4
commit
6cea61c327
@ -19,8 +19,10 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unictype.h>
|
#include <unictype.h>
|
||||||
|
#include <unistdio.h>
|
||||||
#include <unistr.h>
|
#include <unistr.h>
|
||||||
#include <uniwidth.h>
|
#include <uniwidth.h>
|
||||||
|
|
||||||
@ -271,6 +273,42 @@ bxstr_t *bxs_strcat(bxstr_t *pString, uint32_t *pToAppend)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bxstr_t *bxs_concat(size_t count, ...)
|
||||||
|
{
|
||||||
|
if (count < 1) {
|
||||||
|
return bxs_from_ascii("");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t total_len = 0;
|
||||||
|
uint32_t *src;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, count);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
src = va_arg(va, uint32_t *);
|
||||||
|
if (src != NULL) {
|
||||||
|
total_len += u32_strlen(src);
|
||||||
|
} else {
|
||||||
|
total_len += 6; /* strlen("(NULL)") == 6 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
uint32_t *utf32 = (uint32_t *) malloc((total_len + 1) * sizeof(uint32_t));
|
||||||
|
char *format = repeat("%llU", count); /* "%llU" stands for a UTF-32 string */
|
||||||
|
|
||||||
|
va_start(va, count);
|
||||||
|
u32_vsnprintf(utf32, total_len + 1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
bxstr_t *result = bxs_from_unicode(utf32);
|
||||||
|
BFREE(format);
|
||||||
|
BFREE(utf32);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t *bxs_strchr(bxstr_t *pString, ucs4_t c, int *cursor)
|
uint32_t *bxs_strchr(bxstr_t *pString, ucs4_t c, int *cursor)
|
||||||
{
|
{
|
||||||
uint32_t *result = NULL;
|
uint32_t *result = NULL;
|
||||||
|
@ -111,6 +111,16 @@ bxstr_t *bxs_trimdup(bxstr_t *pString, size_t start_idx, size_t end_idx);
|
|||||||
bxstr_t *bxs_strcat(bxstr_t *pString, uint32_t *pToAppend);
|
bxstr_t *bxs_strcat(bxstr_t *pString, uint32_t *pToAppend);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate all given strings into a new string.
|
||||||
|
* @param count number of strings given in the following
|
||||||
|
* @param <...> the strings, all of them `uint32_t *`. NULL is discouraged as an argument, but will probably be
|
||||||
|
* printed as "(NULL)". (That's what libunistring did in our tests, but they promise nothing in their docs.)
|
||||||
|
* @return a new string, for which new memory was allocated, might be empty, but never NULL
|
||||||
|
*/
|
||||||
|
bxstr_t *bxs_concat(size_t count, ...);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a pointer to the first visible occurrence of the character `c` in the string `pString`.
|
* Return a pointer to the first visible occurrence of the character `c` in the string `pString`.
|
||||||
* Invisible characters are ignored.
|
* Invisible characters are ignored.
|
||||||
|
317
src/generate.c
317
src/generate.c
@ -408,10 +408,55 @@ static int vert_precalc(const sentry_t *sarr,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the maximum number of characters in a line of a horizontal side (top or bottom). This excludes corners,
|
||||||
|
* which always belong to the vertical sides. This is needed for allocating space for the assembled sides, which will
|
||||||
|
* include shapes multiple times, and also include invisible characters.
|
||||||
|
* @param sarr all shapes of the current design
|
||||||
|
* @param side the side to calculate (`north_side` or `south_side`)
|
||||||
|
* @param iltf the numbers of times that a shape shall appear (array of *three* values)
|
||||||
|
* @param target_width the number of columns we must reach
|
||||||
|
* @param target_height the number of lines of the side
|
||||||
|
* @return the number of characters(!), visible plus invisible, that suffice to store every line of that side
|
||||||
|
*/
|
||||||
|
static size_t horiz_chars_required(const sentry_t *sarr, const shape_t *side, size_t *iltf, size_t target_width,
|
||||||
|
size_t target_height)
|
||||||
|
{
|
||||||
|
size_t *lens = (size_t *) calloc(target_height, sizeof(size_t));
|
||||||
|
size_t *iltf_copy = (size_t *) malloc(3 * sizeof(size_t));
|
||||||
|
memcpy(iltf_copy, iltf, 3 * sizeof(size_t));
|
||||||
|
|
||||||
|
int cshape = (side == north_side) ? 0 : 2;
|
||||||
|
for (size_t j = 0; j < target_width; j += sarr[side[cshape + 1]].width) {
|
||||||
|
while (iltf_copy[cshape] == 0) {
|
||||||
|
cshape += (side == north_side) ? 1 : -1;
|
||||||
|
}
|
||||||
|
for (size_t line = 0; line < target_height; ++line) {
|
||||||
|
lens[line] += sarr[side[cshape + 1]].mbcs[line]->num_chars;
|
||||||
|
}
|
||||||
|
iltf_copy[cshape] -= sarr[side[cshape + 1]].width;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t result = 0;
|
||||||
|
for (size_t i = 0; i < target_height; i++) {
|
||||||
|
if (lens[i] > result) {
|
||||||
|
result = lens[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BFREE(lens);
|
||||||
|
BFREE(iltf_copy);
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "%s side required characters: %d\n", (side == north_side) ? "Top": "Bottom", (int) result);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int vert_assemble(const sentry_t *sarr, const shape_t *seite,
|
static int vert_assemble(const sentry_t *sarr, const shape_t *seite,
|
||||||
size_t *iltf, sentry_t *result)
|
size_t *iltf, sentry_t *result)
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* RETURNS: == 0 on success (result values are set)
|
* RETURNS: == 0 on success (result values are set)
|
||||||
* != 0 on error
|
* != 0 on error
|
||||||
*
|
*
|
||||||
@ -422,17 +467,23 @@ static int vert_assemble(const sentry_t *sarr, const shape_t *seite,
|
|||||||
size_t line;
|
size_t line;
|
||||||
int cshape; /* current shape (idx to iltf) */
|
int cshape; /* current shape (idx to iltf) */
|
||||||
|
|
||||||
|
size_t max_chars = horiz_chars_required(sarr, seite, iltf, result->width, result->height);
|
||||||
|
uint32_t **mbcs_tmp = (uint32_t **) calloc(result->height, sizeof(uint32_t *));
|
||||||
|
|
||||||
for (line = 0; line < result->height; ++line) {
|
for (line = 0; line < result->height; ++line) {
|
||||||
result->chars[line] = (char *) calloc(1, result->width + 1);
|
result->chars[line] = (char *) calloc(1, result->width + 1);
|
||||||
if (result->chars[line] == NULL) {
|
if (result->chars[line] == NULL) {
|
||||||
perror(PROJECT);
|
perror(PROJECT);
|
||||||
if ((long) --line >= 0) {
|
if ((long) --line >= 0) {
|
||||||
do {
|
do {
|
||||||
|
BFREE (mbcs_tmp[line]);
|
||||||
BFREE (result->chars[line--]);
|
BFREE (result->chars[line--]);
|
||||||
} while ((long) line >= 0);
|
} while ((long) line >= 0);
|
||||||
}
|
}
|
||||||
|
BFREE(mbcs_tmp);
|
||||||
return 1; /* out of memory */
|
return 1; /* out of memory */
|
||||||
}
|
}
|
||||||
|
mbcs_tmp[line] = (uint32_t *) calloc(max_chars + 1, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
cshape = (seite == north_side) ? 0 : 2;
|
cshape = (seite == north_side) ? 0 : 2;
|
||||||
@ -443,10 +494,16 @@ static int vert_assemble(const sentry_t *sarr, const shape_t *seite,
|
|||||||
}
|
}
|
||||||
for (line = 0; line < result->height; ++line) {
|
for (line = 0; line < result->height; ++line) {
|
||||||
strcat(result->chars[line], sarr[seite[cshape + 1]].chars[line]);
|
strcat(result->chars[line], sarr[seite[cshape + 1]].chars[line]);
|
||||||
|
u32_strcat(mbcs_tmp[line], sarr[seite[cshape + 1]].mbcs[line]->memory);
|
||||||
}
|
}
|
||||||
iltf[cshape] -= sarr[seite[cshape + 1]].width;
|
iltf[cshape] -= sarr[seite[cshape + 1]].width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (line = 0; line < result->height; ++line) {
|
||||||
|
result->mbcs[line] = bxs_from_unicode(mbcs_tmp[line]);
|
||||||
|
}
|
||||||
|
|
||||||
|
BFREE(mbcs_tmp);
|
||||||
return 0; /* all clear */
|
return 0; /* all clear */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,10 +530,11 @@ static void horiz_assemble(const sentry_t *sarr, const shape_t *seite,
|
|||||||
|
|
||||||
for (j = 0; j < sarr[ctop].height; ++j) {
|
for (j = 0; j < sarr[ctop].height; ++j) {
|
||||||
result->chars[j] = sarr[ctop].chars[j];
|
result->chars[j] = sarr[ctop].chars[j];
|
||||||
|
result->mbcs[j] = sarr[ctop].mbcs[j];
|
||||||
}
|
}
|
||||||
for (j = 0; j < sarr[cbottom].height; ++j) {
|
for (j = 0; j < sarr[cbottom].height; ++j) {
|
||||||
result->chars[result->height - sarr[cbottom].height + j] =
|
result->chars[result->height - sarr[cbottom].height + j] = sarr[cbottom].chars[j];
|
||||||
sarr[cbottom].chars[j];
|
result->mbcs[result->height - sarr[cbottom].height + j] = sarr[cbottom].mbcs[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = 0;
|
sc = 0;
|
||||||
@ -493,6 +551,7 @@ static void horiz_assemble(const sentry_t *sarr, const shape_t *seite,
|
|||||||
sc = 0;
|
sc = 0;
|
||||||
}
|
}
|
||||||
result->chars[j] = sarr[seite[cshape + 1]].chars[sc];
|
result->chars[j] = sarr[seite[cshape + 1]].chars[sc];
|
||||||
|
result->mbcs[j] = sarr[seite[cshape + 1]].mbcs[sc];
|
||||||
++sc;
|
++sc;
|
||||||
iltf[cshape] -= 1;
|
iltf[cshape] -= 1;
|
||||||
}
|
}
|
||||||
@ -525,23 +584,25 @@ static int horiz_generate(sentry_t *tresult, sentry_t *bresult)
|
|||||||
}
|
}
|
||||||
bresult->width = tresult->width;
|
bresult->width = tresult->width;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "Top side box rect width %d, height %d.\n",
|
fprintf (stderr, "Top side box rect width %d, height %d.\n",
|
||||||
(int) tresult->width, (int) tresult->height);
|
(int) tresult->width, (int) tresult->height);
|
||||||
fprintf (stderr, "Top columns to fill: %s %d, %s %d, %s %d.\n",
|
fprintf (stderr, "Top columns to fill: %s %d, %s %d, %s %d.\n",
|
||||||
shape_name[north_side[1]], (int) tiltf[0],
|
shape_name[north_side[1]], (int) tiltf[0],
|
||||||
shape_name[north_side[2]], (int) tiltf[1],
|
shape_name[north_side[2]], (int) tiltf[1],
|
||||||
shape_name[north_side[3]], (int) tiltf[2]);
|
shape_name[north_side[3]], (int) tiltf[2]);
|
||||||
fprintf (stderr, "Bottom side box rect width %d, height %d.\n",
|
fprintf (stderr, "Bottom side box rect width %d, height %d.\n",
|
||||||
(int) bresult->width, (int) bresult->height);
|
(int) bresult->width, (int) bresult->height);
|
||||||
fprintf (stderr, "Bottom columns to fill: %s %d, %s %d, %s %d.\n",
|
fprintf (stderr, "Bottom columns to fill: %s %d, %s %d, %s %d.\n",
|
||||||
shape_name[south_side[1]], (int) biltf[0],
|
shape_name[south_side[1]], (int) biltf[0],
|
||||||
shape_name[south_side[2]], (int) biltf[1],
|
shape_name[south_side[2]], (int) biltf[1],
|
||||||
shape_name[south_side[3]], (int) biltf[2]);
|
shape_name[south_side[3]], (int) biltf[2]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tresult->chars = (char **) calloc(tresult->height, sizeof(char *));
|
tresult->chars = (char **) calloc(tresult->height, sizeof(char *));
|
||||||
|
tresult->mbcs = (bxstr_t **) calloc(tresult->height, sizeof(bxstr_t *));
|
||||||
bresult->chars = (char **) calloc(bresult->height, sizeof(char *));
|
bresult->chars = (char **) calloc(bresult->height, sizeof(char *));
|
||||||
|
bresult->mbcs = (bxstr_t **) calloc(bresult->height, sizeof(bxstr_t *));
|
||||||
if (tresult->chars == NULL || bresult->chars == NULL) {
|
if (tresult->chars == NULL || bresult->chars == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -555,7 +616,7 @@ static int horiz_generate(sentry_t *tresult, sentry_t *bresult)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Debugging code - Output horizontal sides of box
|
* Debugging code - Output horizontal sides of box
|
||||||
@ -563,16 +624,16 @@ static int horiz_generate(sentry_t *tresult, sentry_t *bresult)
|
|||||||
size_t j;
|
size_t j;
|
||||||
fprintf(stderr, "TOP SIDE:\n");
|
fprintf(stderr, "TOP SIDE:\n");
|
||||||
for (j = 0; j < tresult->height; ++j) {
|
for (j = 0; j < tresult->height; ++j) {
|
||||||
fprintf(stderr, " %2d: \'%s\'\n", (int) j,
|
fprintf(stderr, " %2d: \'%s\' - \'%s\'\n", (int) j,
|
||||||
tresult->chars[j] ? tresult->chars[j] : "(null)");
|
bxs_to_output(tresult->mbcs[j]), tresult->chars[j]);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "BOTTOM SIDE:\n");
|
fprintf(stderr, "BOTTOM SIDE:\n");
|
||||||
for (j = 0; j < bresult->height; ++j) {
|
for (j = 0; j < bresult->height; ++j) {
|
||||||
fprintf(stderr, " %2d: \'%s\'\n", (int) j,
|
fprintf(stderr, " %2d: \'%s\' - '%s'\n", (int) j,
|
||||||
bresult->chars[j] ? bresult->chars[j] : "(null)");
|
bxs_to_output(bresult->mbcs[j]), bresult->chars[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0; /* all clear */
|
return 0; /* all clear */
|
||||||
}
|
}
|
||||||
@ -609,51 +670,59 @@ static int vert_generate(sentry_t *lresult, sentry_t *rresult)
|
|||||||
rresult->height = vspace +
|
rresult->height = vspace +
|
||||||
opt.design->shape[NE].height + opt.design->shape[SE].height;
|
opt.design->shape[NE].height + opt.design->shape[SE].height;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "Left side box rect width %d, height %d, vspace %d.\n",
|
fprintf(stderr, "Left side box rect width %d, height %d, vspace %d.\n",
|
||||||
(int) lresult->width, (int) lresult->height, (int) vspace);
|
(int) lresult->width, (int) lresult->height, (int) vspace);
|
||||||
fprintf(stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n",
|
fprintf(stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n",
|
||||||
shape_name[west_side[1]], (int) leftiltf[0],
|
shape_name[west_side[1]], (int) leftiltf[0],
|
||||||
shape_name[west_side[2]], (int) leftiltf[1],
|
shape_name[west_side[2]], (int) leftiltf[1],
|
||||||
shape_name[west_side[3]], (int) leftiltf[2]);
|
shape_name[west_side[3]], (int) leftiltf[2]);
|
||||||
fprintf(stderr, "Right side box rect width %d, height %d, vspace %d.\n",
|
fprintf(stderr, "Right side box rect width %d, height %d, vspace %d.\n",
|
||||||
(int) rresult->width, (int) rresult->height, (int) vspace);
|
(int) rresult->width, (int) rresult->height, (int) vspace);
|
||||||
fprintf(stderr, "Right lines to fill: %s %d, %s %d, %s %d.\n",
|
fprintf(stderr, "Right lines to fill: %s %d, %s %d, %s %d.\n",
|
||||||
shape_name[east_side[1]], (int) rightiltf[0],
|
shape_name[east_side[1]], (int) rightiltf[0],
|
||||||
shape_name[east_side[2]], (int) rightiltf[1],
|
shape_name[east_side[2]], (int) rightiltf[1],
|
||||||
shape_name[east_side[3]], (int) rightiltf[2]);
|
shape_name[east_side[3]], (int) rightiltf[2]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lresult->chars = (char **) calloc(lresult->height, sizeof(char *));
|
lresult->chars = (char **) calloc(lresult->height, sizeof(char *));
|
||||||
if (lresult->chars == NULL) {
|
if (lresult->chars == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
lresult->mbcs = (bxstr_t **) calloc(lresult->height, sizeof(bxstr_t *));
|
||||||
|
if (lresult->mbcs == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
rresult->chars = (char **) calloc(rresult->height, sizeof(char *));
|
rresult->chars = (char **) calloc(rresult->height, sizeof(char *));
|
||||||
if (rresult->chars == NULL) {
|
if (rresult->chars == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
rresult->mbcs = (bxstr_t **) calloc(rresult->height, sizeof(bxstr_t *));
|
||||||
|
if (rresult->mbcs == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
horiz_assemble(opt.design->shape, west_side, leftiltf, lresult);
|
horiz_assemble(opt.design->shape, west_side, leftiltf, lresult);
|
||||||
horiz_assemble(opt.design->shape, east_side, rightiltf, rresult);
|
horiz_assemble(opt.design->shape, east_side, rightiltf, rresult);
|
||||||
|
|
||||||
#if defined(DEBUG) && 1
|
#if defined(DEBUG) && 1
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Debugging code - Output left and right side of box
|
* Debugging code - Output left and right side of box
|
||||||
*/
|
*/
|
||||||
size_t j;
|
size_t j;
|
||||||
fprintf(stderr, "LEFT SIDE:\n");
|
fprintf(stderr, "LEFT SIDE:\n");
|
||||||
for (j = 0; j < lresult->height; ++j) {
|
for (j = 0; j < lresult->height; ++j) {
|
||||||
fprintf(stderr, " %2d: \'%s\'\n", (int) j,
|
fprintf(stderr, " %2d: \'%s\' - \'%s\'\n", (int) j,
|
||||||
lresult->chars[j] ? lresult->chars[j] : "(null)");
|
bxs_to_output(lresult->mbcs[j]), lresult->chars[j]);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "RIGHT SIDE:\n");
|
||||||
|
for (j = 0; j < rresult->height; ++j) {
|
||||||
|
fprintf(stderr, " %2d: \'%s\' - \'%s\'\n", (int) j,
|
||||||
|
bxs_to_output(rresult->mbcs[j]), rresult->chars[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "RIGHT SIDE:\n");
|
#endif
|
||||||
for (j = 0; j < rresult->height; ++j) {
|
|
||||||
fprintf(stderr, " %2d: \'%s\'\n", (int) j,
|
|
||||||
rresult->chars[j] ? rresult->chars[j] : "(null)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0; /* all clear */
|
return 0; /* all clear */
|
||||||
}
|
}
|
||||||
@ -793,31 +862,27 @@ int output_box(const sentry_t *thebox)
|
|||||||
{
|
{
|
||||||
size_t j;
|
size_t j;
|
||||||
size_t nol = thebox[BRIG].height; /* number of output lines */
|
size_t nol = thebox[BRIG].height; /* number of output lines */
|
||||||
char *indentspc;
|
|
||||||
int indentspclen;
|
|
||||||
size_t vfill, vfill1, vfill2; /* empty lines/columns in box */
|
size_t vfill, vfill1, vfill2; /* empty lines/columns in box */
|
||||||
size_t hfill;
|
size_t hfill;
|
||||||
char *hfill1, *hfill2; /* space before/after text */
|
uint32_t *hfill1, *hfill2; /* space before/after text */
|
||||||
size_t hpl, hpr;
|
size_t hpl, hpr;
|
||||||
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 */
|
size_t skip_start; /* lines to skip for box top */
|
||||||
size_t skip_end; /* lines to skip for box bottom */
|
size_t skip_end; /* lines to skip for box bottom */
|
||||||
size_t skip_left; /* true if left box part is to be skipped */
|
size_t skip_left; /* true if left box part is to be skipped */
|
||||||
int ntabs, nspcs; /* needed for unexpand of tabs */
|
size_t ntabs, nspcs; /* needed for unexpand of tabs */
|
||||||
char *restored_indent;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "Padding used: left %d, top %d, right %d, bottom %d\n",
|
fprintf (stderr, "Padding used: left %d, top %d, right %d, bottom %d\n",
|
||||||
opt.design->padding[BLEF], opt.design->padding[BTOP],
|
opt.design->padding[BLEF], opt.design->padding[BTOP],
|
||||||
opt.design->padding[BRIG], opt.design->padding[BBOT]);
|
opt.design->padding[BRIG], opt.design->padding[BBOT]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create string of spaces for indentation
|
* Create string of spaces for indentation
|
||||||
*/
|
*/
|
||||||
indentspc = NULL;
|
uint32_t *indentspc = NULL;
|
||||||
ntabs = nspcs = indentspclen = 0;
|
size_t indentspclen = 0;
|
||||||
|
ntabs = nspcs = 0;
|
||||||
if (opt.design->indentmode == 'b') {
|
if (opt.design->indentmode == 'b') {
|
||||||
if (opt.tabexp == 'u') {
|
if (opt.tabexp == 'u') {
|
||||||
ntabs = input.indent / opt.tabstop;
|
ntabs = input.indent / opt.tabstop;
|
||||||
@ -827,23 +892,24 @@ int output_box(const sentry_t *thebox)
|
|||||||
else {
|
else {
|
||||||
indentspclen = input.indent;
|
indentspclen = input.indent;
|
||||||
}
|
}
|
||||||
indentspc = (char *) malloc(indentspclen + 1);
|
|
||||||
|
indentspc = (uint32_t *) malloc((indentspclen + 1) * sizeof(uint32_t));
|
||||||
if (indentspc == NULL) {
|
if (indentspc == NULL) {
|
||||||
perror(PROJECT);
|
perror(PROJECT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.tabexp == 'u') {
|
if (opt.tabexp == 'u') {
|
||||||
memset(indentspc, (int) '\t', ntabs);
|
u32_set(indentspc, char_tab, ntabs);
|
||||||
memset(indentspc + ntabs, (int) ' ', nspcs);
|
u32_set(indentspc + ntabs, char_space, nspcs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memset(indentspc, (int) ' ', indentspclen);
|
u32_set(indentspc, char_space, indentspclen);
|
||||||
}
|
}
|
||||||
indentspc[indentspclen] = '\0';
|
set_char_at(indentspc, indentspclen, char_nul);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
indentspc = (char *) strdup("");
|
indentspc = new_empty_string32();
|
||||||
if (indentspc == NULL) {
|
if (indentspc == NULL) {
|
||||||
perror(PROJECT);
|
perror(PROJECT);
|
||||||
return 1;
|
return 1;
|
||||||
@ -875,16 +941,16 @@ int output_box(const sentry_t *thebox)
|
|||||||
* Provide strings for horizontal text alignment.
|
* Provide strings for horizontal text alignment.
|
||||||
*/
|
*/
|
||||||
hfill = thebox[BTOP].width - input.maxline;
|
hfill = thebox[BTOP].width - input.maxline;
|
||||||
hfill1 = (char *) malloc(hfill + 1);
|
hfill1 = (uint32_t *) malloc((hfill + 1) * sizeof(uint32_t));
|
||||||
hfill2 = (char *) malloc(hfill + 1);
|
hfill2 = (uint32_t *) malloc((hfill + 1) * sizeof(uint32_t));
|
||||||
if (!hfill1 || !hfill2) {
|
if (!hfill1 || !hfill2) {
|
||||||
perror(PROJECT);
|
perror(PROJECT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(hfill1, (int) ' ', hfill + 1);
|
u32_set(hfill1, char_space, hfill);
|
||||||
memset(hfill2, (int) ' ', hfill + 1);
|
u32_set(hfill2, char_space, hfill);
|
||||||
hfill1[hfill] = '\0';
|
set_char_at(hfill1, hfill, char_nul);
|
||||||
hfill2[hfill] = '\0';
|
set_char_at(hfill2, hfill, char_nul);
|
||||||
hpl = 0;
|
hpl = 0;
|
||||||
hpr = 0;
|
hpr = 0;
|
||||||
if (hfill == 1) {
|
if (hfill == 1) {
|
||||||
@ -914,15 +980,15 @@ int output_box(const sentry_t *thebox)
|
|||||||
}
|
}
|
||||||
hfill += opt.design->padding[BLEF] + opt.design->padding[BRIG];
|
hfill += opt.design->padding[BLEF] + opt.design->padding[BRIG];
|
||||||
}
|
}
|
||||||
hfill1[hpl] = '\0';
|
set_char_at(hfill1, hpl, char_nul);
|
||||||
hfill2[hpr] = '\0';
|
set_char_at(hfill2, hpr, char_nul);
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
fprintf(stderr, "Alignment: hfill %d hpl %d hpr %d, vfill %d vfill1 %d vfill2 %d.\n",
|
fprintf(stderr, "Alignment: hfill %d hpl %d hpr %d, vfill %d vfill1 %d vfill2 %d.\n",
|
||||||
(int) hfill, (int) hpl, (int) hpr, (int) vfill, (int) vfill1, (int) vfill2);
|
(int) hfill, (int) hpl, (int) hpr, (int) vfill, (int) vfill1, (int) vfill2);
|
||||||
fprintf(stderr, " hfill1 = \"%s\"; hfill2 = \"%s\"; indentspc = \"%s\";\n",
|
fprintf(stderr, " hfill1 = \"%s\"; hfill2 = \"%s\"; indentspc = \"%s\";\n",
|
||||||
hfill1, hfill2, indentspc);
|
u32_strconv_to_output(hfill1), u32_strconv_to_output(hfill2), u32_strconv_to_output(indentspc));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out if and how many leading or trailing blank lines must be
|
* Find out if and how many leading or trailing blank lines must be
|
||||||
@ -948,21 +1014,28 @@ int output_box(const sentry_t *thebox)
|
|||||||
/*
|
/*
|
||||||
* Generate actual output
|
* Generate actual output
|
||||||
*/
|
*/
|
||||||
|
bxstr_t *obuf = NULL; /* final output string */
|
||||||
|
uint32_t *restored_indent;
|
||||||
|
uint32_t *empty_string = new_empty_string32();
|
||||||
for (j = skip_start; j < nol - skip_end; ++j) {
|
for (j = skip_start; j < nol - skip_end; ++j) {
|
||||||
|
|
||||||
if (j < thebox[BTOP].height) { /* box top */
|
if (j < thebox[BTOP].height) { /* box top */
|
||||||
restored_indent = tabbify_indent(0, indentspc, indentspclen);
|
restored_indent = tabbify_indent(0, indentspc, indentspclen);
|
||||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
obuf = bxs_concat(4, restored_indent,
|
||||||
skip_left ? "" : thebox[BLEF].chars[j], thebox[BTOP].chars[j],
|
skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
|
||||||
thebox[BRIG].chars[j]);
|
thebox[BTOP].mbcs[j]->memory,
|
||||||
|
thebox[BRIG].mbcs[j]->memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (vfill1) { /* top vfill */
|
else if (vfill1) { /* top vfill */
|
||||||
restored_indent = tabbify_indent(0, indentspc, indentspclen);
|
restored_indent = tabbify_indent(0, indentspc, indentspclen);
|
||||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
uint32_t *wspc = u32_nspaces(thebox[BTOP].width);
|
||||||
skip_left ? "" : thebox[BLEF].chars[j], nspaces(thebox[BTOP].width),
|
obuf = bxs_concat(4, restored_indent,
|
||||||
thebox[BRIG].chars[j]);
|
skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
|
||||||
|
wspc,
|
||||||
|
thebox[BRIG].mbcs[j]->memory);
|
||||||
--vfill1;
|
--vfill1;
|
||||||
|
BFREE(wspc);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (j < nol - thebox[BBOT].height) {
|
else if (j < nol - thebox[BBOT].height) {
|
||||||
@ -971,46 +1044,52 @@ int output_box(const sentry_t *thebox)
|
|||||||
int shift = justify_line(input.lines + ti, hpr - hpl);
|
int shift = justify_line(input.lines + ti, hpr - hpl);
|
||||||
restored_indent = tabbify_indent(ti, indentspc, indentspclen);
|
restored_indent = tabbify_indent(ti, indentspc, indentspclen);
|
||||||
uint32_t *mbtext_shifted = advance32(input.lines[ti].mbtext, shift < 0 ? (size_t) (-shift) : 0);
|
uint32_t *mbtext_shifted = advance32(input.lines[ti].mbtext, shift < 0 ? (size_t) (-shift) : 0);
|
||||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 8, restored_indent,
|
uint32_t *spc1 = empty_string;
|
||||||
skip_left ? "" : thebox[BLEF].chars[j], hfill1,
|
if (ti >= 0 && shift > 0) {
|
||||||
ti >= 0 && shift > 0 ? nspaces(shift) : "",
|
spc1 = u32_nspaces(shift);
|
||||||
ti >= 0 ? u32_strconv_to_output(mbtext_shifted) : "",
|
}
|
||||||
hfill2, nspaces(input.maxline - input.lines[ti].len - shift),
|
uint32_t *spc2 = u32_nspaces(input.maxline - input.lines[ti].len - shift);
|
||||||
thebox[BRIG].chars[j]);
|
obuf = bxs_concat(8, restored_indent,
|
||||||
|
skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory, hfill1, spc1,
|
||||||
|
ti >= 0 ? mbtext_shifted : empty_string, hfill2, spc2,
|
||||||
|
thebox[BRIG].mbcs[j]->memory);
|
||||||
|
if (spc1 != empty_string) {
|
||||||
|
BFREE(spc1);
|
||||||
|
}
|
||||||
|
BFREE(spc2);
|
||||||
}
|
}
|
||||||
else { /* bottom vfill */
|
else { /* bottom vfill */
|
||||||
restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
|
restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
|
||||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
uint32_t *spc = u32_nspaces(thebox[BTOP].width);
|
||||||
skip_left ? "" : thebox[BLEF].chars[j], nspaces(thebox[BTOP].width),
|
obuf = bxs_concat(4, restored_indent,
|
||||||
thebox[BRIG].chars[j]);
|
skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
|
||||||
|
spc,
|
||||||
|
thebox[BRIG].mbcs[j]->memory);
|
||||||
|
BFREE(spc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else { /* box bottom */
|
else { /* box bottom */
|
||||||
restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
|
restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
|
||||||
concat_strings(obuf, LINE_MAX_BYTES + 1, 4, restored_indent,
|
obuf = bxs_concat(4, restored_indent,
|
||||||
skip_left ? "" : thebox[BLEF].chars[j],
|
skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
|
||||||
thebox[BBOT].chars[j - (nol - thebox[BBOT].height)],
|
thebox[BBOT].mbcs[j - (nol - thebox[BBOT].height)]->memory,
|
||||||
thebox[BRIG].chars[j]);
|
thebox[BRIG].mbcs[j]->memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
obuf_len = strlen(obuf);
|
bxstr_t *obuf_trimmed = bxs_rtrim(obuf);
|
||||||
|
fprintf(opt.outfile, "%s%s", bxs_to_output(obuf_trimmed),
|
||||||
|
(input.final_newline || j < nol - skip_end - 1 ? opt.eol : ""));
|
||||||
|
|
||||||
if (obuf_len > LINE_MAX_BYTES) {
|
bxs_free(obuf);
|
||||||
size_t newlen = LINE_MAX_BYTES;
|
bxs_free(obuf_trimmed);
|
||||||
btrim(obuf, &newlen);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
btrim(obuf, &obuf_len);
|
|
||||||
}
|
|
||||||
if (opt.tabexp == 'k') {
|
if (opt.tabexp == 'k') {
|
||||||
BFREE (restored_indent);
|
BFREE(restored_indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(opt.outfile, "%s%s", obuf, (input.final_newline || j < nol - skip_end - 1 ? opt.eol : ""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BFREE (indentspc);
|
BFREE (indentspc);
|
||||||
|
BFREE (empty_string);
|
||||||
BFREE (hfill1);
|
BFREE (hfill1);
|
||||||
BFREE (hfill2);
|
BFREE (hfill2);
|
||||||
return 0; /* all clear */
|
return 0; /* all clear */
|
||||||
@ -1018,4 +1097,4 @@ int output_box(const sentry_t *thebox)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*EOF*/ /* vim: set sw=4: */
|
/* vim: set cindent sw=4: */
|
||||||
|
53
src/tools.c
53
src/tools.c
@ -242,6 +242,27 @@ char *concat_strings_alloc(size_t count, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char *repeat(char *s, size_t count)
|
||||||
|
{
|
||||||
|
if (s == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char *result = (char *) malloc(count * len + 1);
|
||||||
|
if (result != NULL) {
|
||||||
|
char *dest = result;
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
strcpy(dest, s);
|
||||||
|
dest += len;
|
||||||
|
}
|
||||||
|
*dest = '\0';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int empty_line(const line_t *line)
|
int empty_line(const line_t *line)
|
||||||
/*
|
/*
|
||||||
* Return true if line is empty.
|
* Return true if line is empty.
|
||||||
@ -484,26 +505,10 @@ size_t my_strrspn(const char *s, const char *accept)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentspc_len)
|
uint32_t *tabbify_indent(const size_t lineno, uint32_t *indentspc, const size_t indentspc_len)
|
||||||
/*
|
|
||||||
* Checks if tab expansion mode is "keep", and if so, calculates a new
|
|
||||||
* indentation string based on the one given. The new string contains
|
|
||||||
* tabs in their original positions.
|
|
||||||
*
|
|
||||||
* lineno index of the input line we are referring to
|
|
||||||
* indentspc previously calculated "space-only" indentation string
|
|
||||||
* (may be NULL). This is only used when opt.tabexp != 'k',
|
|
||||||
* in which case it will be used as the function result.
|
|
||||||
* indentspc_len desired result length, measured in spaces only
|
|
||||||
*
|
|
||||||
* RETURNS: if successful and opt.tabexp == 'k': new string
|
|
||||||
* on error (invalid input or out of memory): NULL
|
|
||||||
*
|
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
char *result;
|
uint32_t *result;
|
||||||
size_t result_len;
|
size_t result_len;
|
||||||
|
|
||||||
if (opt.tabexp != 'k') {
|
if (opt.tabexp != 'k') {
|
||||||
@ -513,16 +518,16 @@ char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentsp
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (indentspc_len == 0) {
|
if (indentspc_len == 0) {
|
||||||
return (char *) strdup("");
|
return new_empty_string32();
|
||||||
}
|
}
|
||||||
|
|
||||||
result = (char *) malloc(indentspc_len + 1);
|
result = (uint32_t *) malloc((indentspc_len + 1) * sizeof(uint32_t));
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
perror(PROJECT);
|
perror(PROJECT);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(result, (int) ' ', indentspc_len);
|
u32_set(result, char_space, indentspc_len);
|
||||||
result[indentspc_len] = '\0';
|
set_char_at(result, indentspc_len, char_nul);
|
||||||
result_len = indentspc_len;
|
result_len = indentspc_len;
|
||||||
|
|
||||||
for (i = 0; i < input.lines[lineno].tabpos_len && input.lines[lineno].tabpos[i] < indentspc_len; ++i) {
|
for (i = 0; i < input.lines[lineno].tabpos_len && input.lines[lineno].tabpos[i] < indentspc_len; ++i) {
|
||||||
@ -531,9 +536,9 @@ char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentsp
|
|||||||
if (tpos + nspc > input.indent) {
|
if (tpos + nspc > input.indent) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result[tpos] = '\t';
|
set_char_at(result, tpos, char_tab);
|
||||||
result_len -= nspc - 1;
|
result_len -= nspc - 1;
|
||||||
result[result_len] = '\0';
|
set_char_at(result, result_len, char_nul);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
32
src/tools.h
32
src/tools.h
@ -59,8 +59,8 @@ char *my_strnrstr(const char *s1, const char *s2, const size_t s2_len, int skip)
|
|||||||
/**
|
/**
|
||||||
* Calculates the length (in bytes) of the segment at the end of `s` which consists entirely of bytes in `accept`.
|
* Calculates the length (in bytes) of the segment at the end of `s` which consists entirely of bytes in `accept`.
|
||||||
* This is like `strspn()`, but from the end of the string.
|
* This is like `strspn()`, but from the end of the string.
|
||||||
* @param <s> the string to search
|
* @param s the string to search
|
||||||
* @param <accept> acceptable characters that form the trailing segment
|
* @param accept acceptable characters that form the trailing segment
|
||||||
* @return the number of bytes found as described above
|
* @return the number of bytes found as described above
|
||||||
*/
|
*/
|
||||||
size_t my_strrspn(const char *s, const char *accept);
|
size_t my_strrspn(const char *s, const char *accept);
|
||||||
@ -75,9 +75,9 @@ int strisno(const char *s);
|
|||||||
/**
|
/**
|
||||||
* Concatenate variable number of strings into one. This would normally be achieved via snprintf(), but that's not
|
* Concatenate variable number of strings into one. This would normally be achieved via snprintf(), but that's not
|
||||||
* available on all platforms where boxes is compiled.
|
* available on all platforms where boxes is compiled.
|
||||||
* @param <count> number of strings given in the following
|
* @param count number of strings given in the following
|
||||||
* @param <...> the strings
|
* @param <...> the strings
|
||||||
* @returns a new string, for which new memory was allocated
|
* @return a new string, for which new memory was allocated
|
||||||
*/
|
*/
|
||||||
char *concat_strings_alloc(size_t count, ...);
|
char *concat_strings_alloc(size_t count, ...);
|
||||||
|
|
||||||
@ -85,7 +85,27 @@ char *concat_strings_alloc(size_t count, ...);
|
|||||||
void concat_strings(char *dst, int max_len, int count, ...);
|
void concat_strings(char *dst, int max_len, int count, ...);
|
||||||
|
|
||||||
|
|
||||||
char *tabbify_indent(const size_t lineno, char *indentspc, const size_t indentspc_len);
|
/**
|
||||||
|
* Repeat the string `s` `count` times.
|
||||||
|
* @param s the string to repeat
|
||||||
|
* @param count the number of times the string should be repeated
|
||||||
|
* @return a new string, for which new memory was allocated, or NULL if `s` was NULL or out of memory
|
||||||
|
*/
|
||||||
|
char *repeat(char *s, size_t count);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if tab expansion mode is "keep", and if so, calculates a new indentation string based on the one given.
|
||||||
|
* The new string contains tabs in their original positions.
|
||||||
|
*
|
||||||
|
* @param lineno index of the input line we are referring to
|
||||||
|
* @param indentspc previously calculated "space-only" indentation string (may be NULL). This is only used when
|
||||||
|
* opt.tabexp != 'k', in which case it will be used as the function result.
|
||||||
|
* @param indentspc_len desired result length, measured in spaces only
|
||||||
|
* @return if successful and opt.tabexp == 'k': new string;
|
||||||
|
* on error (invalid input or out of memory): NULL
|
||||||
|
*/
|
||||||
|
uint32_t *tabbify_indent(const size_t lineno, uint32_t *indentspc, const size_t indentspc_len);
|
||||||
|
|
||||||
|
|
||||||
char *nspaces(const size_t n);
|
char *nspaces(const size_t n);
|
||||||
@ -208,4 +228,4 @@ FILE *bx_fopen(char *pathname, char *mode);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*EOF*/ /* vim: set cindent sw=4: */
|
/* vim: set cindent sw=4: */
|
||||||
|
@ -318,4 +318,20 @@ char *to_utf8(uint32_t *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*EOF*/ /* vim: set sw=4: */
|
|
||||||
|
uint32_t *u32_nspaces(const size_t n)
|
||||||
|
{
|
||||||
|
uint32_t *result = (uint32_t *) malloc((n + 1) * sizeof(uint32_t));
|
||||||
|
if (result == NULL) {
|
||||||
|
perror(PROJECT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (n > 0) {
|
||||||
|
u32_set(result, char_space, n);
|
||||||
|
}
|
||||||
|
set_char_at(result, n, char_nul);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* vim: set cindent sw=4: */
|
||||||
|
@ -146,6 +146,7 @@ uint32_t *advance_next32(const uint32_t *s, size_t *invis);
|
|||||||
* Determine a new position in the given string s with the given offset of visible characters.
|
* Determine a new position in the given string s with the given offset of visible characters.
|
||||||
* If the character right in front of the target character is invisible, then the pointer is moved to the start of
|
* If the character right in front of the target character is invisible, then the pointer is moved to the start of
|
||||||
* that invisible sequence. The purpose is to catch any escape sequences which would for example color the character.
|
* that invisible sequence. The purpose is to catch any escape sequences which would for example color the character.
|
||||||
|
* CHECK This is redundant, bxstrings can do this better.
|
||||||
*
|
*
|
||||||
* @param s The pointer to the start position. Is assumed to point either at the ESC at the start of an escape
|
* @param s The pointer to the start position. Is assumed to point either at the ESC at the start of an escape
|
||||||
* sequence, or to be positioned outside an escape sequence.
|
* sequence, or to be positioned outside an escape sequence.
|
||||||
@ -218,6 +219,14 @@ const char *check_encoding(const char *manual_encoding, const char *system_encod
|
|||||||
char *to_utf8(uint32_t *src);
|
char *to_utf8(uint32_t *src);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new string of `n` spaces.
|
||||||
|
* @param n number of spaces
|
||||||
|
* @return a new string of length `n`, for which new memory was allocated
|
||||||
|
*/
|
||||||
|
uint32_t *u32_nspaces(const size_t n);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*EOF*/ /* vim: set cindent sw=4: */
|
/*EOF*/ /* vim: set cindent sw=4: */
|
||||||
|
@ -317,10 +317,8 @@ void test_ansi_unicode_broken_escapes(void **state)
|
|||||||
* "\x1b[" (broken, counts as invisible, and belonging to the previous 'b')
|
* "\x1b[" (broken, counts as invisible, and belonging to the previous 'b')
|
||||||
*/
|
*/
|
||||||
uint32_t *ustr32 = u32_strconv_from_arg("\x1b[38;5;203 XX \x1b[0m__\x1b[38;5;203mb\x1b[", "ASCII");
|
uint32_t *ustr32 = u32_strconv_from_arg("\x1b[38;5;203 XX \x1b[0m__\x1b[38;5;203mb\x1b[", "ASCII");
|
||||||
fprintf(stderr, "BOO\n");
|
|
||||||
assert_non_null(ustr32);
|
assert_non_null(ustr32);
|
||||||
bxstr_t *actual = bxs_from_unicode(ustr32);
|
bxstr_t *actual = bxs_from_unicode(ustr32);
|
||||||
fprintf(stderr, "BAA\n");
|
|
||||||
|
|
||||||
assert_non_null(actual);
|
assert_non_null(actual);
|
||||||
assert_non_null(actual->memory);
|
assert_non_null(actual->memory);
|
||||||
@ -1059,4 +1057,63 @@ void test_bxs_free_null(void **state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void test_bxs_concat(void **state)
|
||||||
|
{
|
||||||
|
UNUSED(state);
|
||||||
|
|
||||||
|
bxstr_t *actual = bxs_concat(0);
|
||||||
|
assert_non_null(actual);
|
||||||
|
assert_string_equal("", actual->ascii);
|
||||||
|
assert_int_equal(0, actual->num_chars);
|
||||||
|
|
||||||
|
uint32_t *s1 = u32_strconv_from_arg("\x1b[38;5;203mX\x1b[0m", "ASCII");
|
||||||
|
uint32_t *s2 = u32_strconv_from_arg("---", "ASCII");
|
||||||
|
uint32_t *s3 = u32_strconv_from_arg("ÄÖÜ\x1b[38;5;203m!\x1b[0m", "UTF-8");
|
||||||
|
uint32_t *s4 = u32_strconv_from_arg(" ", "ASCII");
|
||||||
|
actual = bxs_concat(5, s1, s2, s3, s4, s4);
|
||||||
|
|
||||||
|
assert_non_null(actual);
|
||||||
|
assert_string_equal("X---xxx! ", actual->ascii);
|
||||||
|
assert_int_equal(12, actual->num_chars_visible);
|
||||||
|
assert_int_equal(30, actual->num_chars_invisible);
|
||||||
|
assert_int_equal(42, actual->num_chars);
|
||||||
|
assert_int_equal(4, actual->trailing);
|
||||||
|
assert_int_equal(0, actual->indent);
|
||||||
|
assert_int_equal(12, actual->num_columns);
|
||||||
|
|
||||||
|
BFREE(s1);
|
||||||
|
BFREE(s2);
|
||||||
|
BFREE(s3);
|
||||||
|
BFREE(s4);
|
||||||
|
bxs_free(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void test_bxs_concat_nullarg(void **state)
|
||||||
|
{
|
||||||
|
UNUSED(state);
|
||||||
|
|
||||||
|
uint32_t *s1 = u32_strconv_from_arg("\x1b[38;5;203mAB", "ASCII");
|
||||||
|
uint32_t *s2 = u32_strconv_from_arg("-CD-", "ASCII");
|
||||||
|
uint32_t *s3 = u32_strconv_from_arg("-EF\x1b[0m", "ASCII");
|
||||||
|
bxstr_t *actual = bxs_concat(4, s1, s2, NULL, s3);
|
||||||
|
|
||||||
|
assert_non_null(actual);
|
||||||
|
assert_string_equal("AB-CD-(NULL)-EF", actual->ascii);
|
||||||
|
assert_int_equal(15, actual->num_chars_visible);
|
||||||
|
assert_int_equal(15, actual->num_chars_invisible);
|
||||||
|
assert_int_equal(30, actual->num_chars);
|
||||||
|
assert_int_equal(0, actual->trailing);
|
||||||
|
assert_int_equal(0, actual->indent);
|
||||||
|
assert_int_equal(15, actual->num_columns);
|
||||||
|
|
||||||
|
BFREE(s1);
|
||||||
|
BFREE(s2);
|
||||||
|
BFREE(s3);
|
||||||
|
bxs_free(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* vim: set cindent sw=4: */
|
/* vim: set cindent sw=4: */
|
||||||
|
@ -79,6 +79,9 @@ void test_bxs_valid_in_filename_error(void **state);
|
|||||||
|
|
||||||
void test_bxs_free_null(void **state);
|
void test_bxs_free_null(void **state);
|
||||||
|
|
||||||
|
void test_bxs_concat(void **state);
|
||||||
|
void test_bxs_concat_nullarg(void **state);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -105,7 +105,8 @@ int main(void)
|
|||||||
cmocka_unit_test(test_is_ascii_id_valid),
|
cmocka_unit_test(test_is_ascii_id_valid),
|
||||||
cmocka_unit_test(test_is_ascii_id_invalid),
|
cmocka_unit_test(test_is_ascii_id_invalid),
|
||||||
cmocka_unit_test(test_is_ascii_id_strict_valid),
|
cmocka_unit_test(test_is_ascii_id_strict_valid),
|
||||||
cmocka_unit_test(test_is_ascii_id_strict_invalid)
|
cmocka_unit_test(test_is_ascii_id_strict_invalid),
|
||||||
|
cmocka_unit_test(test_repeat)
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct CMUnitTest unicode_tests[] = {
|
const struct CMUnitTest unicode_tests[] = {
|
||||||
@ -157,11 +158,12 @@ int main(void)
|
|||||||
cmocka_unit_test_setup(test_bxs_is_visible_char, beforeTest),
|
cmocka_unit_test_setup(test_bxs_is_visible_char, beforeTest),
|
||||||
cmocka_unit_test_setup(test_bxs_filter_visible, beforeTest),
|
cmocka_unit_test_setup(test_bxs_filter_visible, beforeTest),
|
||||||
cmocka_unit_test_setup(test_bxs_filter_visible_none, beforeTest),
|
cmocka_unit_test_setup(test_bxs_filter_visible_none, beforeTest),
|
||||||
|
|
||||||
cmocka_unit_test_setup(test_bxs_strcmp, beforeTest),
|
cmocka_unit_test_setup(test_bxs_strcmp, beforeTest),
|
||||||
cmocka_unit_test_setup(test_bxs_valid_anywhere_error, beforeTest),
|
cmocka_unit_test_setup(test_bxs_valid_anywhere_error, beforeTest),
|
||||||
cmocka_unit_test_setup(test_bxs_valid_in_filename_error, beforeTest),
|
cmocka_unit_test_setup(test_bxs_valid_in_filename_error, beforeTest),
|
||||||
cmocka_unit_test_setup(test_bxs_free_null, beforeTest)
|
cmocka_unit_test_setup(test_bxs_free_null, beforeTest),
|
||||||
|
cmocka_unit_test_setup(test_bxs_concat, beforeTest),
|
||||||
|
cmocka_unit_test_setup(test_bxs_concat_nullarg, beforeTest)
|
||||||
};
|
};
|
||||||
|
|
||||||
int num_failed = 0;
|
int num_failed = 0;
|
||||||
|
@ -261,4 +261,25 @@ void test_is_ascii_id_strict_invalid(void **state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test_repeat(void **state)
|
||||||
|
{
|
||||||
|
(void) state; /* unused */
|
||||||
|
|
||||||
|
char *actual = repeat(NULL, 1);
|
||||||
|
assert_null(actual);
|
||||||
|
|
||||||
|
actual = repeat("x", 0);
|
||||||
|
assert_string_equal("", actual);
|
||||||
|
BFREE(actual);
|
||||||
|
|
||||||
|
actual = repeat("x", 3);
|
||||||
|
assert_string_equal("xxx", actual);
|
||||||
|
BFREE(actual);
|
||||||
|
|
||||||
|
actual = repeat("abc", 3);
|
||||||
|
assert_string_equal("abcabcabc", actual);
|
||||||
|
BFREE(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* vim: set cindent sw=4: */
|
/* vim: set cindent sw=4: */
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unit tests of the 'tools' module
|
* Unit tests of the 'tools' module.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TOOLS_TEST_H
|
#ifndef TOOLS_TEST_H
|
||||||
@ -37,7 +37,9 @@ void test_is_ascii_id_invalid(void **state);
|
|||||||
void test_is_ascii_id_strict_valid(void **state);
|
void test_is_ascii_id_strict_valid(void **state);
|
||||||
void test_is_ascii_id_strict_invalid(void **state);
|
void test_is_ascii_id_strict_invalid(void **state);
|
||||||
|
|
||||||
|
void test_repeat(void **state);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*EOF*/ /* vim: set cindent sw=4: */
|
/* vim: set cindent sw=4: */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user