• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ascii-boxes / boxes / 9430086843

08 Jun 2024 04:28PM UTC coverage: 87.159% (-0.2%) from 87.366%
9430086843

push

github

tsjensen
logg

3597 of 4567 branches covered (78.76%)

Branch coverage included in aggregate %.

14 of 16 new or added lines in 1 file covered. (87.5%)

2 existing lines in 1 file now uncovered.

5295 of 5635 relevant lines covered (93.97%)

169640.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.82
/src/generate.c
1
/*
2
 * boxes - Command line filter to draw/remove ASCII boxes around text
3
 * Copyright (c) 1999-2024 Thomas Jensen and the boxes contributors
4
 *
5
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
6
 * License, version 3, as published by the Free Software Foundation.
7
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
8
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
9
 * details.
10
 * You should have received a copy of the GNU General Public License along with this program.
11
 * If not, see <https://www.gnu.org/licenses/>.
12
 *
13
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
14
 */
15

16
/*
17
 * Box generation, i.e. the drawing of boxes
18
 */
19

20
#include "config.h"
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <stdint.h>
24
#include <string.h>
25

26
#include <unistr.h>
27

28
#include "shape.h"
29
#include "boxes.h"
30
#include "tools.h"
31
#include "unicode.h"
32
#include "generate.h"
33

34

35

36
static int horiz_precalc(const sentry_t *sarr,
260✔
37
                         size_t *topiltf, size_t *botiltf, size_t *hspace)
260✔
38
/*
39
 *  Calculate data for horizontal box side generation.
40
 *
41
 *  sarr     Array of shapes from the current design
42
 *
43
 *  topiltf  RESULT: individual lines (columns) to fill by shapes 1, 2, and 3
44
 *  botiltf          in top part of box (topiltf) and bottom part of box
45
 *  hspace   RESULT: number of columns excluding corners (sum over iltf)
46
 *
47
 *  RETURNS:  == 0   on success  (result values are set)
48
 *            != 0   on error
49
 *
50
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
51
 */
52
{
53
    int tnumsh;               /* number of existent shapes in top part */
54
    int bnumsh;
55
    size_t twidth;            /* current hspace for top side */
56
    size_t bwidth;            /* current hspace for bottom side */
57
    int i;
58
    size_t target_width;      /* assumed text width for minimum box size */
59
    int btoggle, ttoggle;     /* for case 3 w/ 2 elastics */
60

61
    /*
62
     *  Initialize future result values
63
     */
64
    memset(topiltf, 0, (SHAPES_PER_SIDE - 2) * sizeof(size_t));
260✔
65
    memset(botiltf, 0, (SHAPES_PER_SIDE - 2) * sizeof(size_t));
520✔
66
    *hspace = 0;
520✔
67

260✔
68
    /*
69
     *  Ensure minimum width for the insides of a box in order to ensure
70
     *  minimum box size required by current design
71
     */
72
    if (input.maxline >= (opt.design->minwidth - sarr[north_side[0]].width -
520✔
73
            sarr[north_side[SHAPES_PER_SIDE - 1]].width)) {
520✔
74
        target_width = input.maxline;
286✔
75
    }
52✔
76
    else {
77
        target_width = opt.design->minwidth - sarr[north_side[0]].width -
468✔
78
                sarr[north_side[SHAPES_PER_SIDE - 1]].width;
468✔
79
    }
234✔
80

81
    /*
82
     *  Compute number of existent shapes in top and in bottom part
83
     */
84
    tnumsh = 0;
260✔
85
    bnumsh = 0;
520✔
86
    for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
1,300✔
87
        if (!isempty(sarr + north_side[i])) {
1,820✔
88
            tnumsh++;
1,149✔
89
        }
738✔
90
        if (!isempty(sarr + south_side[i])) {
780✔
91
            bnumsh++;
1,138✔
92
        }
716✔
93
    }
780✔
94

95
#ifdef DEBUG
96
    fprintf (stderr, "in horiz_precalc:\n    ");
260!
97
    fprintf (stderr, "opt.design->minwidth %d, input.maxline %d, target_width"
98
            " %d, tnumsh %d, bnumsh %d\n", (int) opt.design->minwidth,
99
             (int) input.maxline, (int) target_width, tnumsh, bnumsh);
100
#endif
101

102
    twidth = 0;
260✔
103
    bwidth = 0;
520✔
104

260✔
105
    btoggle = 1;                         /* can be 1 or 3 */
260✔
106
    ttoggle = 1;
520✔
107

260✔
108
    do {
260✔
109
        shape_t *seite;                  /* ptr to north_side or south_side */
110
        size_t *iltf;                    /* ptr to botiltf or topiltf */
111
        size_t *res_hspace;              /* ptr to bwidth or twidth */
112
        int *stoggle;                    /* ptr to btoggle or ttoggle */
113
        int numsh;                       /* either bnumsh or tnumsh */
114

115
        /*
116
         *  Set pointers to the side which is currently shorter,
117
         *  so it will be advanced in this step.
118
         */
119
        if (twidth > bwidth) {           /* south (bottom) is behind */
26,623✔
120
            seite = south_side;
39,966✔
121
            iltf = botiltf;
26,686✔
122
            res_hspace = &bwidth;
26,686✔
123
            numsh = bnumsh;
26,686✔
124
            stoggle = &btoggle;
26,686✔
125
        }
26,686✔
126
        else {                           /* north (top) is behind */
127
            seite = north_side;
13,280✔
128
            iltf = topiltf;
26,560✔
129
            res_hspace = &twidth;
26,560✔
130
            numsh = tnumsh;
26,560✔
131
            stoggle = &ttoggle;
26,560✔
132
        }
13,280✔
133

134
        switch (numsh) {
26,623!
135

26,623!
136
            case 1:
137
                /*
22,327✔
138
                 *  only one shape -> it must be elastic
139
                 */
140
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
44,654!
141
                    if (!isempty(&(sarr[seite[i]]))) {
89,308✔
142
                        if (iltf[i - 1] == 0 ||
66,994!
143
                                *res_hspace < target_width ||
44,266✔
144
                                twidth != bwidth) {
21,952✔
145
                            iltf[i - 1] += sarr[seite[i]].width;
22,340!
146
                            *res_hspace += sarr[seite[i]].width;
44,654✔
147
                        }
44,654✔
148
                        break;
22,327✔
149
                    }
22,327✔
150
                }
22,327✔
151
                break;
22,327✔
152

22,327✔
153
            case 2:
154
                /*
2,019✔
155
                 *  two shapes -> one must be elastic, the other must not
156
                 */
157
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
7,949✔
158
                    if (!isempty(sarr + seite[i]) && !(sarr[seite[i]].elastic)) {
13,936✔
159
                        if (iltf[i - 1] == 0) {
8,006✔
160
                            iltf[i - 1] += sarr[seite[i]].width;
2,076✔
161
                            *res_hspace += sarr[seite[i]].width;
114✔
162
                            break;
114✔
163
                        }
57✔
164
                    }
1,962✔
165
                }
5,930✔
166
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
4,038!
167
                    if (!isempty(sarr + seite[i]) && sarr[seite[i]].elastic) {
8,076✔
168
                        if (iltf[i - 1] == 0 ||
6,057✔
169
                                *res_hspace < target_width ||
3,981✔
170
                                twidth != bwidth) {
1,962!
171
                            iltf[i - 1] += sarr[seite[i]].width;
2,019!
172
                            *res_hspace += sarr[seite[i]].width;
4,038✔
173
                        }
4,038✔
174
                        break;
2,019✔
175
                    }
2,019✔
176
                }
2,019✔
177
                break;
2,019✔
178

2,019✔
179
            case 3:
180
                /*
2,277✔
181
                 *  three shapes -> one or two of them must be elastic
182
                 *  If two are elastic, they are the two outer ones.
183
                 */
184
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
9,108✔
185
                    if (!(sarr[seite[i]].elastic) && iltf[i - 1] == 0) {
15,939✔
186
                        iltf[i - 1] += sarr[seite[i]].width;
6,940✔
187
                        *res_hspace += sarr[seite[i]].width;
218✔
188
                    }
218✔
189
                }
6,831✔
190
                if (sarr[seite[1]].elastic && sarr[seite[3]].elastic) {
2,277!
191
                    if (iltf[*stoggle - 1] == 0 ||
3,844!
192
                            *res_hspace < target_width ||
3,052✔
193
                            twidth != bwidth) {
1,485!
194
                        *res_hspace += sarr[seite[*stoggle]].width;
1,567!
195
                        iltf[*stoggle - 1] += sarr[seite[*stoggle]].width;
3,134✔
196
                    }
3,134✔
197
                    *stoggle = *stoggle == 1 ? 3 : 1;
1,567✔
198
                }
3,134✔
199
                else {
200
                    for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
1,420!
201
                        if (sarr[seite[i]].elastic) {
2,840✔
202
                            if (iltf[i - 1] == 0 ||
2,130!
203
                                    *res_hspace < target_width ||
1,386✔
204
                                    twidth != bwidth) {
676!
205
                                iltf[i - 1] += sarr[seite[i]].width;
710!
206
                                *res_hspace += sarr[seite[i]].width;
1,420✔
207
                            }
1,420✔
208
                            break;
710✔
209
                        }
710✔
210
                    }
710✔
211
                }
212
                break;
2,277✔
213

2,277✔
214
            default:
UNCOV
215
                fprintf(stderr, "%s: internal error in horiz_precalc()\n", PROJECT);
×
NEW
216
                return 1;
×
217
        }
218
    } while (twidth != bwidth || twidth < target_width || bwidth < target_width);
26,623✔
219

26,623!
220
    *hspace = twidth;                    /* return either one */
260✔
221

260✔
222
    return 0;                            /* all clear */
260✔
223
}
520✔
224

225

226

227
static int vert_precalc(const sentry_t *sarr,
260✔
228
                        size_t *leftiltf, size_t *rightiltf, size_t *vspace)
260✔
229
/*
230
 *  Calculate data for vertical box side generation.
231
 *
232
 *  sarr      Array of shapes from the current design
233
 *
234
 *  leftiltf  RESULT: individual lines to fill by shapes 1, 2, and 3
235
 *  rightiltf         in left part of box (leftiltf) and right part of box
236
 *  vspace    RESULT: number of columns excluding corners (sum over iltf)
237
 *
238
 *  RETURNS:  == 0   on success  (result values are set)
239
 *            != 0   on error
240
 *
241
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
242
 */
243
{
244
    int lnumsh;               /* number of existent shapes in top part */
245
    int rnumsh;
246
    size_t lheight;           /* current vspace for top side */
247
    size_t rheight;           /* current vspace for bottom side */
248
    int i;
249
    size_t target_height;     /* assumed text height for minimum box size */
250
    int rtoggle, ltoggle;     /* for case 3 w/ 2 elastics */
251

252
    /*
253
     *  Initialize future result values
254
     */
255
    memset(leftiltf, 0, (SHAPES_PER_SIDE - 2) * sizeof(size_t));
260✔
256
    memset(rightiltf, 0, (SHAPES_PER_SIDE - 2) * sizeof(size_t));
520✔
257
    *vspace = 0;
520✔
258

260✔
259
    /*
260
     *  Ensure minimum height for insides of box in order to ensure
261
     *  minimum box size required by current design
262
     */
263
    if (input.num_lines >= (opt.design->minheight - sarr[west_side[0]].height -
520✔
264
            sarr[west_side[SHAPES_PER_SIDE - 1]].height)) {
520✔
265
        target_height = input.num_lines;
410✔
266
    }
300✔
267
    else {
268
        target_height = opt.design->minheight - sarr[west_side[0]].height -
220✔
269
                sarr[west_side[SHAPES_PER_SIDE - 1]].height;
220✔
270
    }
110✔
271

272
    /*
273
     *  Compute number of existent shapes in left and right part (1..3)
274
     */
275
    lnumsh = 0;
260✔
276
    rnumsh = 0;
520✔
277
    for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
1,300✔
278
        if (!isempty(sarr + west_side[i])) {
1,820✔
279
            lnumsh++;
1,084✔
280
        }
608✔
281
        if (!isempty(sarr + east_side[i])) {
780✔
282
            rnumsh++;
1,084✔
283
        }
608✔
284
    }
780✔
285

286
    lheight = 0;
260✔
287
    rheight = 0;
520✔
288

260✔
289
    rtoggle = 1;                         /* can be 1 or 3 */
260✔
290
    ltoggle = 1;
520✔
291

260✔
292
    do {
260✔
293
        shape_t *seite;                  /* ptr to west_side or east_side */
294
        size_t *iltf;                    /* ptr to rightiltf or leftiltf */
295
        size_t *res_vspace;              /* ptr to rheight or lheight */
296
        int *stoggle;                    /* ptr to rtoggle or ltoggle */
297
        int numsh;                       /* either rnumsh or lnumsh */
298

299
        /*
300
         *  Set pointers to the side which is currently shorter,
301
         *  so it will be advanced in this step.
302
         */
303
        if (lheight > rheight) {         /* east (right) is behind */
2,827✔
304
            seite = east_side;
4,243✔
305
            iltf = rightiltf;
2,832✔
306
            res_vspace = &rheight;
2,832✔
307
            numsh = rnumsh;
2,832✔
308
            stoggle = &rtoggle;
2,832✔
309
        }
2,832✔
310
        else {                           /* west (left) is behind */
311
            seite = west_side;
1,411✔
312
            iltf = leftiltf;
2,822✔
313
            res_vspace = &lheight;
2,822✔
314
            numsh = lnumsh;
2,822✔
315
            stoggle = &ltoggle;
2,822✔
316
        }
1,411✔
317

318
        switch (numsh) {
2,827!
319

2,827!
320
            case 1:
321
                /*
2,665✔
322
                 *  only one shape -> it must be elastic
323
                 */
324
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
5,330!
325
                    if (!isempty(&(sarr[seite[i]]))) {
10,660✔
326
                        if (iltf[i - 1] == 0 ||
8,000!
327
                                *res_vspace < target_height ||
4,872✔
328
                                lheight != rheight) {
2,212✔
329
                            iltf[i - 1] += sarr[seite[i]].height;
2,670!
330
                            *res_vspace += sarr[seite[i]].height;
5,330✔
331
                        }
5,330✔
332
                        break;
2,665✔
333
                    }
2,665✔
334
                }
2,665✔
335
                break;
2,665✔
336

2,665✔
337
            case 2:
338
                /*
130✔
339
                 *  two shapes -> one must be elastic, the other must not
340
                 */
341
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
448✔
342
                    if (!isempty(sarr + seite[i]) && !(sarr[seite[i]].elastic)) {
802✔
343
                        if (iltf[i - 1] == 0) {
484✔
344
                            iltf[i - 1] += sarr[seite[i]].height;
166✔
345
                            *res_vspace += sarr[seite[i]].height;
72✔
346
                            break;
72✔
347
                        }
36✔
348
                    }
94✔
349
                }
318✔
350
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
260!
351
                    if (!isempty(sarr + seite[i]) && sarr[seite[i]].elastic) {
520✔
352
                        if (iltf[i - 1] == 0 ||
390✔
353
                                *res_vspace < target_height ||
224✔
354
                                lheight != rheight) {
94!
355
                            iltf[i - 1] += sarr[seite[i]].height;
130!
356
                            *res_vspace += sarr[seite[i]].height;
260✔
357
                        }
260✔
358
                        break;
130✔
359
                    }
130✔
360
                }
130✔
361
                break;
130✔
362

130✔
363
            case 3:
364
                /*
32✔
365
                 *  three shapes -> one or two of them must be elastic
366
                 *  If two are elastic, they are the two outer ones.
367
                 */
368
                for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
128✔
369
                    if (!(sarr[seite[i]].elastic) && iltf[i - 1] == 0) {
224✔
370
                        iltf[i - 1] += sarr[seite[i]].height;
148✔
371
                        *res_vspace += sarr[seite[i]].height;
104✔
372
                    }
104✔
373
                }
96✔
374
                if (sarr[seite[1]].elastic && sarr[seite[3]].elastic) {
32!
375
                    if (iltf[*stoggle - 1] == 0 ||
32!
376
                            *res_vspace < target_height ||
×
377
                            lheight != rheight) {
×
378
                        *res_vspace += sarr[seite[*stoggle]].height;
×
379
                        iltf[*stoggle - 1] += sarr[seite[*stoggle]].height;
×
380
                    }
×
381
                    *stoggle = *stoggle == 1 ? 3 : 1;
382
                }
×
383
                else {
384
                    for (i = 1; i < SHAPES_PER_SIDE - 1; ++i) {
64!
385
                        if (sarr[seite[i]].elastic) {
128✔
386
                            if (iltf[i - 1] == 0 ||
96!
387
                                    *res_vspace < target_height ||
38✔
388
                                    lheight != rheight) {
6!
389
                                iltf[i - 1] += sarr[seite[i]].height;
32!
390
                                *res_vspace += sarr[seite[i]].height;
64✔
391
                            }
64✔
392
                            break;
32✔
393
                        }
32✔
394
                    }
32✔
395
                }
396
                break;
32✔
397

32✔
398
            default:
UNCOV
399
                fprintf(stderr, "%s: internal error in vert_precalc()\n", PROJECT);
×
NEW
400
                return 1;
×
401
        }
402
    } while (lheight != rheight || lheight < target_height || rheight < target_height);
2,827✔
403

2,827!
404
    *vspace = lheight;                   /* return either one */
260✔
405

260✔
406
    return 0;                            /* all clear */
260✔
407
}
520✔
408

409

410

411
/**
412
 * Calculate the maximum number of characters in a line of a horizontal side (top or bottom). This excludes corners,
413
 * which always belong to the vertical sides. This is needed for allocating space for the assembled sides, which will
414
 * include shapes multiple times, and also include invisible characters.
415
 * @param sarr all shapes of the current design
416
 * @param side the side to calculate (`north_side` or `south_side`)
417
 * @param iltf the numbers of times that a shape shall appear (array of *three* values)
418
 * @param target_width the number of columns we must reach
419
 * @param target_height the number of lines of the side
420
 * @return the number of characters(!), visible plus invisible, that suffice to store every line of that side
421
 */
422
static size_t horiz_chars_required(const sentry_t *sarr, const shape_t *side, size_t *iltf, size_t target_width,
520✔
423
    size_t target_height)
520✔
424
{
425
    size_t *lens = (size_t *) calloc(target_height, sizeof(size_t));
520✔
426
    size_t *iltf_copy = (size_t *) malloc(3 * sizeof(size_t));
1,040✔
427
    memcpy(iltf_copy, iltf, 3 * sizeof(size_t));
1,040✔
428

520✔
429
    int cshape = (side == north_side) ? 0 : 2;
520✔
430
    for (size_t j = 0; j < target_width; j += sarr[side[cshape + 1]].width) {
27,829✔
431
        while (iltf_copy[cshape] == 0) {
54,717✔
432
            cshape += (side == north_side) ? 1 : -1;
28,027✔
433
        }
619✔
434
        for (size_t line = 0; line < target_height; ++line) {
70,013✔
435
            lens[line] += sarr[side[cshape + 1]].mbcs[line]->num_chars;
113,237✔
436
        }
86,448✔
437
        iltf_copy[cshape] -= sarr[side[cshape + 1]].width;
26,789✔
438
    }
53,578✔
439

440
    size_t result = 0;
520✔
441
    for (size_t i = 0; i < target_height; i++) {
2,050✔
442
        if (lens[i] > result) {
2,540✔
443
            result = lens[i];
1,530✔
444
        }
1,040✔
445
    }
1,010✔
446

447
    BFREE(lens);
520!
448
    BFREE(iltf_copy);
1,040!
449
    #ifdef DEBUG
520!
450
        fprintf (stderr, "%s side required characters: %d\n", (side == north_side) ? "Top": "Bottom", (int) result);
520✔
451
    #endif
452
    return result;
1,040✔
453
}
454

455

456

457
static int vert_assemble(const sentry_t *sarr, const shape_t *seite,
1,040✔
458
                         size_t *iltf, sentry_t *result)
459
/*
460
 *  RETURNS:  == 0   on success  (result values are set)
461
 *            != 0   on error
462
 *
463
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
464
 */
465
{
466
    size_t j;
467
    size_t line;
468
    int cshape;                      /* current shape (idx to iltf) */
469

470
    size_t max_chars = horiz_chars_required(sarr, seite, iltf, result->width, result->height);
1,040✔
471
    uint32_t **mbcs_tmp = (uint32_t **) calloc(result->height, sizeof(uint32_t *));
1,040✔
472

473
    for (line = 0; line < result->height; ++line) {
3,060✔
474
        result->chars[line] = (char *) calloc(1, result->width + 1);
2,020✔
475
        if (result->chars[line] == NULL) {
2,020✔
476
            perror(PROJECT);
×
477
            if ((long) --line >= 0) {
×
478
                do {
479
                    BFREE (mbcs_tmp[line]);
×
480
                    BFREE (result->chars[line--]);
×
481
                } while ((long) line >= 0);
×
482
            }
483
            BFREE(mbcs_tmp);
×
484
            return 1;                    /* out of memory */
×
485
        }
486
        mbcs_tmp[line] = (uint32_t *) calloc(max_chars + 1, sizeof(uint32_t));
2,020✔
487
    }
1,010✔
488

489
    cshape = (seite == north_side) ? 0 : 2;
1,040✔
490

491
    for (j = 0; j < result->width; j += sarr[seite[cshape + 1]].width) {
54,618✔
492
        while (iltf[cshape] == 0) {
54,816✔
493
            cshape += (seite == north_side) ? 1 : -1;
1,238✔
494
        }
495
        for (line = 0; line < result->height; ++line) {
140,026✔
496
            strcat(result->chars[line], sarr[seite[cshape + 1]].chars[line]);
86,448✔
497
            u32_strcat(mbcs_tmp[line], sarr[seite[cshape + 1]].mbcs[line]->memory);
86,448✔
498
        }
43,224✔
499
        iltf[cshape] -= sarr[seite[cshape + 1]].width;
53,578✔
500
    }
26,789✔
501

502
    for (line = 0; line < result->height; ++line) {
3,060✔
503
        result->mbcs[line] = bxs_from_unicode(mbcs_tmp[line]);
2,020✔
504
    }
1,010✔
505

506
    BFREE(mbcs_tmp);
1,040✔
507
    return 0;                            /* all clear */
1,040✔
508
}
520✔
509

510

511

512
static void horiz_assemble(const sentry_t *sarr, const shape_t *seite,
1,040✔
513
                           size_t *iltf, sentry_t *result)
514
{
515
    size_t j;
516
    size_t sc;                       /* index to shape chars (lines) */
517
    int cshape;                      /* current shape (idx to iltf) */
518
    shape_t ctop, cbottom;
519

520
    if (seite == east_side) {
1,040✔
521
        ctop = seite[0];
520✔
522
        cbottom = seite[SHAPES_PER_SIDE - 1];
520✔
523
        cshape = 0;
520✔
524
    }
260✔
525
    else {
526
        ctop = seite[SHAPES_PER_SIDE - 1];
520✔
527
        cbottom = seite[0];
520✔
528
        cshape = 2;
520✔
529
    }
530

531
    for (j = 0; j < sarr[ctop].height; ++j) {
3,040✔
532
        result->chars[j] = sarr[ctop].chars[j];
2,000✔
533
        result->mbcs[j] = sarr[ctop].mbcs[j];
2,000✔
534
    }
1,000✔
535
    for (j = 0; j < sarr[cbottom].height; ++j) {
3,080✔
536
        result->chars[result->height - sarr[cbottom].height + j] = sarr[cbottom].chars[j];
2,040✔
537
        result->mbcs[result->height - sarr[cbottom].height + j] = sarr[cbottom].mbcs[j];
2,040✔
538
    }
1,020✔
539

540
    sc = 0;
1,040✔
541
    for (j = sarr[ctop].height; j < result->height - sarr[cbottom].height; ++j) {
7,476✔
542
        while (iltf[cshape] == 0) {
7,536✔
543
            if (seite == east_side) {
1,100✔
544
                ++cshape;
550✔
545
            } else {
275✔
546
                --cshape;
550✔
547
            }
548
            sc = 0;
1,100✔
549
        }
550
        if (sc == sarr[seite[cshape + 1]].height) {
6,436✔
551
            sc = 0;
4,614✔
552
        }
2,307✔
553
        result->chars[j] = sarr[seite[cshape + 1]].chars[sc];
6,436✔
554
        result->mbcs[j] = sarr[seite[cshape + 1]].mbcs[sc];
6,436✔
555
        ++sc;
6,436✔
556
        iltf[cshape] -= 1;
6,436✔
557
    }
3,218✔
558
}
1,040✔
559

560

561

562
static int horiz_generate(sentry_t *tresult, sentry_t *bresult)
520✔
563
/*
564
 *  Generate top and bottom parts of box (excluding corners).
565
 *
566
 *  RETURNS:  == 0  if successful (resulting char array is stored in [bt]result)
567
 *            != 0  on error
568
 *
569
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
570
 */
571
{
572
    size_t biltf[SHAPES_PER_SIDE - 2];     /* individual lines to fill (bottom) */
573
    size_t tiltf[SHAPES_PER_SIDE - 2];     /* individual lines to fill (top) */
574
    int rc;                                /* received return code */
575

576
    tresult->height = highest(opt.design->shape,
520✔
577
                              SHAPES_PER_SIDE, NW, NNW, N, NNE, NE);
578
    bresult->height = highest(opt.design->shape,
520✔
579
                              SHAPES_PER_SIDE, SW, SSW, S, SSE, SE);
580

581
    rc = horiz_precalc(opt.design->shape, tiltf, biltf, &(tresult->width));
520✔
582
    if (rc) {
520!
583
        return rc;
×
584
    }
585
    bresult->width = tresult->width;
520✔
586

587
    #ifdef DEBUG
260!
588
        fprintf (stderr, "Top side box rect width %d, height %d.\n",
589
                (int) tresult->width, (int) tresult->height);
590
        fprintf (stderr, "Top columns to fill: %s %d, %s %d, %s %d.\n",
591
                shape_name[north_side[1]], (int) tiltf[0],
592
                shape_name[north_side[2]], (int) tiltf[1],
593
                shape_name[north_side[3]], (int) tiltf[2]);
594
        fprintf (stderr, "Bottom side box rect width %d, height %d.\n",
595
                (int) bresult->width, (int) bresult->height);
596
        fprintf (stderr, "Bottom columns to fill: %s %d, %s %d, %s %d.\n",
597
                shape_name[south_side[1]], (int) biltf[0],
598
                shape_name[south_side[2]], (int) biltf[1],
599
                shape_name[south_side[3]], (int) biltf[2]);
600
    #endif
601

602
    tresult->chars = (char **) calloc(tresult->height, sizeof(char *));
520✔
603
    tresult->mbcs = (bxstr_t **) calloc(tresult->height, sizeof(bxstr_t *));
520✔
604
    bresult->chars = (char **) calloc(bresult->height, sizeof(char *));
520✔
605
    bresult->mbcs = (bxstr_t **) calloc(bresult->height, sizeof(bxstr_t *));
520✔
606
    if (tresult->chars == NULL || bresult->chars == NULL) {
520!
607
        return 1;
×
608
    }
609

610
    rc = vert_assemble(opt.design->shape, north_side, tiltf, tresult);
520✔
611
    if (rc) {
520!
612
        return rc;
×
613
    }
614
    rc = vert_assemble(opt.design->shape, south_side, biltf, bresult);
520✔
615
    if (rc) {
520✔
616
        return rc;
×
617
    }
618

619
    #ifdef DEBUG
620
    {
621
        /*
622
         *  Debugging code - Output horizontal sides of box
260!
623
         */
624
        size_t j;
625
        fprintf(stderr, "TOP SIDE:\n");
×
626
        for (j = 0; j < tresult->height; ++j) {
627
            fprintf(stderr, "  %2d: \'%s\' - \'%s\'\n", (int) j,
628
                            bxs_to_output(tresult->mbcs[j]), tresult->chars[j]);
×
629
        }
630
        fprintf(stderr, "BOTTOM SIDE:\n");
631
        for (j = 0; j < bresult->height; ++j) {
×
632
            fprintf(stderr, "  %2d: \'%s\' - '%s'\n", (int) j,
633
                            bxs_to_output(bresult->mbcs[j]), bresult->chars[j]);
634
        }
×
635
    }
636
    #endif
637

260✔
638
    return 0;                            /* all clear */
260✔
639
}
260✔
640

641

642

260✔
643
static int vert_generate(sentry_t *lresult, sentry_t *rresult)
260✔
644
/*
645
 *  Generate vertical sides of box.
646
 *
647
 *  RETURNS:  == 0   on success  (resulting char array is stored in [rl]result)
648
 *            != 0   on error
649
 *
650
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
651
 */
652
{
260✔
653
    size_t vspace = 0;
260✔
654
    size_t leftiltf[SHAPES_PER_SIDE - 2];  /* individual lines to fill */
655
    size_t rightiltf[SHAPES_PER_SIDE - 2]; /* individual lines to fill */
656
    int rc;                                /* received return code */
657

260✔
658
    lresult->width = widest(opt.design->shape,
260✔
659
                            SHAPES_PER_SIDE, SW, WSW, W, WNW, NW);
260✔
660
    rresult->width = widest(opt.design->shape,
260✔
661
                            SHAPES_PER_SIDE, SE, ESE, E, ENE, NE);
662

260✔
663
    rc = vert_precalc(opt.design->shape, leftiltf, rightiltf, &vspace);
520!
664
    if (rc) {
260!
665
        return rc;
666
    }
667

260✔
668
    lresult->height = vspace +
1,040✔
669
            opt.design->shape[NW].height + opt.design->shape[SW].height;
780✔
670
    rresult->height = vspace +
1,040✔
671
            opt.design->shape[NE].height + opt.design->shape[SE].height;
520✔
672

260!
673
    #ifdef DEBUG
674
        fprintf(stderr, "Left side box rect width %d, height %d, vspace %d.\n",
675
                (int) lresult->width, (int) lresult->height, (int) vspace);
676
        fprintf(stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n",
677
                shape_name[west_side[1]], (int) leftiltf[0],
678
                shape_name[west_side[2]], (int) leftiltf[1],
679
                shape_name[west_side[3]], (int) leftiltf[2]);
680
        fprintf(stderr, "Right side box rect width %d, height %d, vspace %d.\n",
681
                (int) rresult->width, (int) rresult->height, (int) vspace);
682
        fprintf(stderr, "Right lines to fill: %s %d, %s %d, %s %d.\n",
683
                shape_name[east_side[1]], (int) rightiltf[0],
684
                shape_name[east_side[2]], (int) rightiltf[1],
685
                shape_name[east_side[3]], (int) rightiltf[2]);
686
    #endif
687

260✔
688
    lresult->chars = (char **) calloc(lresult->height, sizeof(char *));
520!
689
    if (lresult->chars == NULL) {
260!
690
        return 1;
691
    }
260✔
692
    lresult->mbcs = (bxstr_t **) calloc(lresult->height, sizeof(bxstr_t *));
520!
693
    if (lresult->mbcs == NULL) {
260!
694
        return 1;
695
    }
260✔
696
    rresult->chars = (char **) calloc(rresult->height, sizeof(char *));
520!
697
    if (rresult->chars == NULL) {
260!
698
        return 1;
699
    }
260✔
700
    rresult->mbcs = (bxstr_t **) calloc(rresult->height, sizeof(bxstr_t *));
520!
701
    if (rresult->mbcs == NULL) {
260!
702
        return 1;
703
    }
704

260✔
705
    horiz_assemble(opt.design->shape, west_side, leftiltf, lresult);
520✔
706
    horiz_assemble(opt.design->shape, east_side, rightiltf, rresult);
260✔
707

708
    #if defined(DEBUG) && 1
709
        {
710
            /*
260!
711
            *  Debugging code - Output left and right side of box
712
            */
713
            size_t j;
×
714
            fprintf(stderr, "LEFT SIDE:\n");
715
            for (j = 0; j < lresult->height; ++j) {
716
                fprintf(stderr, "  %2d: \'%s\' - \'%s\'\n", (int) j,
×
717
                                bxs_to_output(lresult->mbcs[j]), lresult->chars[j]);
718
            }
719
            fprintf(stderr, "RIGHT SIDE:\n");
×
720
            for (j = 0; j < rresult->height; ++j) {
721
                fprintf(stderr, "  %2d: \'%s\' - \'%s\'\n", (int) j,
722
                                bxs_to_output(rresult->mbcs[j]), rresult->chars[j]);
×
723
            }
724
        }
725
    #endif
260✔
726

727
    return 0;                            /* all clear */
260✔
728
}
260✔
729

730

260✔
731

732
int generate_box(sentry_t *thebox)
260✔
733
/*
734
 *
735
 *  RETURNS:  == 0  if successful  (thebox is set)
736
 *            != 0  on error
737
 *
738
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
739
 */
740
{
741
    int rc;
742
    int i;
260✔
743

260!
744
    rc = horiz_generate(&(thebox[0]), &(thebox[2]));
260✔
745
    if (rc) {
260!
746
        goto err;
747
    }
260✔
748

260!
749
    rc = vert_generate(&(thebox[3]), &(thebox[1]));
260✔
750
    if (rc) {
260!
751
        goto err;
752
    }
260✔
753

754
    return 0;                            /* all clear */
260✔
755

×
756
    err:
×
757
    for (i = 0; i < NUM_SIDES; ++i) {
×
758
        if (!isempty(&(thebox[i]))) {
×
759
            BFREE (thebox[i].chars);     /* free only pointer array */
×
760
            memset(thebox + i, 0, sizeof(sentry_t));
761
        }
×
762
    }
763
    return rc;                           /* error */
764
}
260✔
765

766

1,347✔
767

768
static int justify_line(line_t *line, int skew)
1,347✔
769
/*
770
 *  Justify input line according to specified justification
771
 *
772
 *     line   line to justify
773
 *     skew   difference in spaces right/left of text block (hpr-hpl)
774
 *
775
 *  line is assumed to be already free of trailing whitespace.
776
 *
777
 *  RETURNS:  number of space characters which must be added to (> 0)
778
 *            or removed from (< 0) the beginning of the line
779
 *            A return value of 0 means "nothing to do".
780
 *
781
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
782
 */
1,347✔
783
{
40✔
784
    if (empty_line(line)) {
1,347✔
785
        return 0;
1,347✔
786
    }
1,059✔
787
    if (opt.justify == '\0') {
1,307✔
788
        return 0;
1,059✔
789
    }
248!
790

791
    #if defined(DEBUG) || 0
792
        char *outtext = bxs_to_output(line->text);
793
        fprintf(stderr, "justify_line(%c):  Input: real: (%02d) \"%s\", text: (%02d) \"%s\", invisible=%d, skew=%d",
794
                opt.justify ? opt.justify : '0', (int) line->text->num_chars, outtext, (int) line->text->num_columns,
×
795
                line->text->ascii, (int) line->text->num_chars_invisible, skew);
×
796
        BFREE(outtext);
797
    #endif
798

248✔
799
    int result = 0;
496✔
800
    size_t initial_space_size = line->text->indent;
496✔
801
    size_t newlen = line->text->num_columns - initial_space_size;
248✔
802
    size_t shift;
803

248!
804
    switch (opt.justify) {
248!
805

57✔
806
        case 'l':
57!
807
            if (opt.design->indentmode == 't') {
57!
808
                /* text indented inside of box */
809
                result = (int) input.indent - (int) initial_space_size;
810
            }
811
            else {
57✔
812
                result = -1 * (int) initial_space_size;
57✔
813
            }
57✔
814
            break;
57✔
815

102✔
816
        case 'c':
102!
817
            if (opt.design->indentmode == 't') {
102!
818
                /* text indented inside of box */
819
                shift = (input.maxline - input.indent - newlen) / 2 + input.indent;
×
820
                skew -= input.indent;
×
821
                if ((input.maxline - input.indent - newlen) % 2 && skew == 1) {
×
822
                    ++shift;
823
                }
824
            }
825
            else {
102✔
826
                shift = (input.maxline - newlen) / 2;
204✔
827
                if ((input.maxline - newlen) % 2 && skew == 1) {
103✔
828
                    ++shift;
1✔
829
                }
1✔
830
            }
102✔
831
            result = (int) shift - (int) initial_space_size;
204✔
832
            break;
102✔
833

89✔
834
        case 'r':
89✔
835
            shift = input.maxline - newlen;
178✔
836
            result = (int) shift - (int) initial_space_size;
178✔
837
            break;
89✔
838

839
        default:
840
            fprintf(stderr, "%s: internal error (unknown justify option: %c)\n", PROJECT, opt.justify);
×
841
            result = 0;
842
    }
843

248✔
844
    #if defined(DEBUG) || 0
248✔
845
        fprintf (stderr, " -> %d\n", result);
846
    #endif
847
    return result;
248✔
848
}
1,347✔
849

260✔
850

851

852
int output_box(const sentry_t *thebox)
260✔
853
/*
854
 *  Generate final output using the previously generated box parts.
855
 *
856
 *    thebox    Array of four shapes which contain the previously generated
857
 *              box parts in the following order: BTOP, BRIG, BBOT, BLEF
858
 *
859
 *  RETURNS:  == 0  if successful
860
 *            != 0  on error
861
 *
862
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
863
 */
260✔
864
{
865
    size_t j;
866
    size_t nol = thebox[BRIG].height;   /* number of output lines */
260✔
867
    size_t vfill, vfill1, vfill2;       /* empty lines/columns in box */
868
    size_t hfill;
869
    uint32_t *hfill1, *hfill2;          /* space before/after text */
870
    size_t hpl, hpr;
871
    size_t skip_start;                  /* lines to skip for box top */
872
    size_t skip_end;                    /* lines to skip for box bottom */
873
    size_t skip_left;                   /* true if left box part is to be skipped */
260✔
874
    size_t ntabs, nspcs;                /* needed for unexpand of tabs */
260✔
875

260✔
876
    #ifdef DEBUG
877
        fprintf (stderr, "Padding used: left %d, top %d, right %d, bottom %d\n",
878
                opt.design->padding[BLEF], opt.design->padding[BTOP],
879
                opt.design->padding[BRIG], opt.design->padding[BBOT]);
880
    #endif
260✔
881

260✔
882
    /*
260✔
883
     *  Create string of spaces for indentation
260!
884
     */
260✔
885
    uint32_t *indentspc = NULL;
265✔
886
    size_t indentspclen = 0;
265✔
887
    ntabs = nspcs = 0;
265✔
888
    if (opt.design->indentmode == 'b') {
260!
889
        if (opt.tabexp == 'u') {
260✔
890
            ntabs = input.indent / opt.tabstop;
260✔
891
            nspcs = input.indent % opt.tabstop;
5✔
892
            indentspclen = ntabs + nspcs;
5✔
893
        }
265✔
894
        else {
260!
895
            indentspclen = input.indent;
255✔
896
        }
897

898
        indentspc = (uint32_t *) malloc((indentspclen + 1) * sizeof(uint32_t));
260✔
899
        if (indentspc == NULL) {
520✔
900
            perror(PROJECT);
5✔
901
            return 1;
5✔
902
        }
903

904
        if (opt.tabexp == 'u') {
515✔
905
            u32_set(indentspc, char_tab, ntabs);
5✔
906
            u32_set(indentspc + ntabs, char_space, nspcs);
265✔
907
        }
5✔
908
        else {
909
            u32_set(indentspc, char_space, indentspclen);
255✔
910
        }
×
911
        set_char_at(indentspc, indentspclen, char_nul);
260✔
912
    }
260✔
913
    else {
914
        indentspc = new_empty_string32();
915
        if (indentspc == NULL) {
×
916
            perror(PROJECT);
917
            return 1;
918
        }
919
    }
260✔
920

260✔
921
    /*
260✔
922
     *  Compute number of empty lines in box (vfill).
38✔
923
     */
38✔
924
    vfill = nol - thebox[BTOP].height - thebox[BBOT].height - input.num_lines;
260✔
925
    vfill -= opt.design->padding[BTOP] + opt.design->padding[BBOT];
482✔
926
    if (opt.valign == 'c') {
274✔
927
        vfill1 = vfill / 2;
52✔
928
        vfill2 = vfill1 + (vfill % 2);
38✔
929
    }
38✔
930
    else if (opt.valign == 'b') {
430✔
931
        vfill1 = vfill;
222✔
932
        vfill2 = 0;
14✔
933
    }
274✔
934
    else {
260✔
935
        vfill1 = 0;
468✔
936
        vfill2 = vfill;
208✔
937
    }
938
    vfill1 += opt.design->padding[BTOP];
260✔
939
    vfill2 += opt.design->padding[BBOT];
260✔
940
    vfill += opt.design->padding[BTOP] + opt.design->padding[BBOT];
520✔
941

260✔
942
    /*
260✔
943
     *  Provide strings for horizontal text alignment.
260!
944
     */
945
    hfill = thebox[BTOP].width - input.maxline;
260✔
946
    hfill1 = (uint32_t *) malloc((hfill + 1) * sizeof(uint32_t));
260✔
947
    hfill2 = (uint32_t *) malloc((hfill + 1) * sizeof(uint32_t));
520✔
948
    if (!hfill1 || !hfill2) {
520!
949
        perror(PROJECT);
260✔
950
        return 1;
260✔
951
    }
260✔
952
    u32_set(hfill1, char_space, hfill);
520✔
953
    u32_set(hfill2, char_space, hfill);
520✔
954
    set_char_at(hfill1, hfill, char_nul);
284!
955
    set_char_at(hfill2, hfill, char_nul);
284✔
956
    hpl = 0;
281✔
957
    hpr = 0;
281✔
958
    if (hfill == 1) {
260✔
959
        if (opt.halign == 'r'
24✔
960
                || opt.design->padding[BLEF] > opt.design->padding[BRIG]) {
27!
961
            hpl = 1;
24✔
962
            hpr = 0;
21✔
963
        }
21✔
964
        else {
965
            hpl = 0;
239✔
966
            hpr = 1;
239✔
967
        }
24✔
968
    }
48✔
969
    else {
970
        hfill -= opt.design->padding[BLEF] + opt.design->padding[BRIG];
448✔
971
        if (opt.halign == 'c') {
257✔
972
            hpl = hfill / 2 + opt.design->padding[BLEF];
45✔
973
            hpr = hfill / 2 + opt.design->padding[BRIG] + (hfill % 2);
24✔
974
        }
24✔
975
        else if (opt.halign == 'r') {
403✔
976
            hpl = hfill + opt.design->padding[BLEF];
212✔
977
            hpr = opt.design->padding[BRIG];
21✔
978
        }
257✔
979
        else {
980
            hpl = opt.design->padding[BLEF];
451✔
981
            hpr = hfill + opt.design->padding[BRIG];
451✔
982
        }
983
        hfill += opt.design->padding[BLEF] + opt.design->padding[BRIG];
496!
984
    }
985
    set_char_at(hfill1, hpl, char_nul);
260✔
986
    set_char_at(hfill2, hpr, char_nul);
260✔
987

988
    #if defined(DEBUG)
989
        fprintf(stderr, "Alignment: hfill %d hpl %d hpr %d, vfill %d vfill1 %d vfill2 %d.\n",
990
                (int) hfill, (int) hpl, (int) hpr, (int) vfill, (int) vfill1, (int) vfill2);
991
        fprintf(stderr, "           hfill1 = \"%s\";  hfill2 = \"%s\";  indentspc = \"%s\";\n",
×
992
                u32_strconv_to_output(hfill1), u32_strconv_to_output(hfill2), u32_strconv_to_output(indentspc));
×
993
    #endif
×
994

995
    /*
996
     *  Find out if and how many leading or trailing blank lines must be
997
     *  skipped because the corresponding box side was defined empty.
998
     */
999
    skip_start = 0;
260✔
1000
    skip_end = 0;
520✔
1001
    skip_left = 0;
520✔
1002
    if (empty_side(opt.design->shape, BTOP)) {
520✔
1003
        skip_start = opt.design->shape[NW].height;
289✔
1004
    }
58✔
1005
    if (empty_side(opt.design->shape, BBOT)) {
260✔
1006
        skip_end = opt.design->shape[SW].height;
287✔
1007
    }
54✔
1008
    if (empty_side(opt.design->shape, BLEF)) {
260✔
1009
        skip_left = opt.design->shape[NW].width;
266✔
1010
    } /* could simply be 1, though */
12✔
1011
    #if defined(DEBUG)
1012
        fprintf(stderr, "skip_start = %d;  skip_end = %d;  skip_left = %d;  nol = %d;\n",
260✔
1013
                (int) skip_start, (int) skip_end, (int) skip_left, (int) nol);
1014
    #endif
1015

1016
    /*
1017
     *  Generate actual output
1018
     */
260✔
1019
    bxstr_t *obuf = NULL;           /* final output string */
260✔
1020
    uint32_t *restored_indent;
260✔
1021
    uint32_t *empty_string = new_empty_string32();
3,083✔
1022
    for (j = skip_start; j < nol - skip_end; ++j) {
2,823✔
1023

2,563✔
1024
        if (j < thebox[BTOP].height) {   /* box top */
3,034✔
1025
            restored_indent = tabbify_indent(0, indentspc, indentspclen);
942✔
1026
            obuf = bxs_concat(4, restored_indent, 
1,397✔
1027
                            skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
942✔
1028
                            thebox[BTOP].mbcs[j]->memory,
942✔
1029
                            thebox[BRIG].mbcs[j]->memory);
471✔
1030
        }
471✔
1031

2,092✔
1032
        else if (vfill1) {               /* top vfill */
2,198✔
1033
            restored_indent = tabbify_indent(0, indentspc, indentspclen);
212✔
1034
            uint32_t *wspc = u32_nspaces(thebox[BTOP].width);
212✔
1035
            obuf = bxs_concat(4, restored_indent,
316✔
1036
                            skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
106✔
1037
                            wspc,
212✔
1038
                            thebox[BRIG].mbcs[j]->memory);
212✔
1039
            --vfill1;
212!
1040
            BFREE(wspc);
106!
1041
        }
106✔
1042

1,986✔
1043
        else if (j < nol - thebox[BBOT].height) {
3,489✔
1044
            long ti = j - thebox[BTOP].height - (vfill - vfill2);
3,006✔
1045
            if (ti < (long) input.num_lines) {      /* box content (lines) */
2,850✔
1046
                int shift = justify_line(input.lines + ti, hpr - hpl);
2,694✔
1047
                restored_indent = tabbify_indent(ti, indentspc, indentspclen);
2,694✔
1048
                bxstr_t *text_shifted = bxs_cut_front(input.lines[ti].text, shift < 0 ? (size_t) (-shift) : 0);
2,694✔
1049
                uint32_t *spc1 = empty_string;
2,694!
1050
                if (ti >= 0 && shift > 0) {
1,480!
1051
                    spc1 = u32_nspaces(shift);
133✔
1052
                }
1,480✔
1053
                uint32_t *spc2 = u32_nspaces(input.maxline - input.lines[ti].text->num_columns - shift);
4,019✔
1054
                obuf = bxs_concat(8, restored_indent,
4,019✔
1055
                                skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory, hfill1, spc1,
1,347✔
1056
                                ti >= 0 ? text_shifted->memory : empty_string, hfill2, spc2,
2,694!
1057
                                thebox[BRIG].mbcs[j]->memory);
2,694✔
1058
                bxs_free(text_shifted);
2,694✔
1059
                if (spc1 != empty_string) {
1,480✔
1060
                    BFREE(spc1);
133!
1061
                }
1,480!
1062
                BFREE(spc2);
1,347!
1063
            }
1,347✔
1064
            else {                       /* bottom vfill */
156✔
1065
                restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
312✔
1066
                uint32_t *spc = u32_nspaces(thebox[BTOP].width);
312✔
1067
                obuf = bxs_concat(4, restored_indent,
468✔
1068
                                skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
156!
1069
                                spc,
312!
1070
                                thebox[BRIG].mbcs[j]->memory);
312!
1071
                BFREE(spc);
156!
1072
            }
1073
        }
1,503✔
1074

1075
        else {                           /* box bottom */
483✔
1076
            restored_indent = tabbify_indent(input.num_lines - 1, indentspc, indentspclen);
966✔
1077
            obuf = bxs_concat(4, restored_indent,
1,433✔
1078
                            skip_left ? empty_string : thebox[BLEF].mbcs[j]->memory,
966✔
1079
                            thebox[BBOT].mbcs[j - (nol - thebox[BBOT].height)]->memory,
966✔
1080
                            thebox[BRIG].mbcs[j]->memory);
483✔
1081
        }
1082

2,563✔
1083
        bxstr_t *obuf_trimmed = bxs_rtrim(obuf);
5,126✔
1084
        fprintf(opt.outfile, "%s%s", bxs_to_output(obuf_trimmed),
7,689!
1085
                    (input.final_newline || j < nol - skip_end - 1 ? opt.eol : ""));
2,563!
1086

2,563✔
1087
        bxs_free(obuf);
5,126✔
1088
        bxs_free(obuf_trimmed);
5,126✔
1089
        if (opt.tabexp == 'k') {
2,578✔
1090
            BFREE(restored_indent);
15!
1091
        }
15✔
1092
    }
2,563✔
1093

260!
1094
    BFREE (indentspc);
520✔
1095
    BFREE (empty_string);
520✔
1096
    BFREE (hfill1);
520✔
1097
    BFREE (hfill2);
520!
1098
    return 0;                            /* all clear */
260✔
1099
}
260✔
1100

1101

1102

1103
/* vim: set cindent sw=4: */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc