Extract list_designs functionality into its own, new 'list' module #78

This commit is contained in:
Thomas Jensen 2021-04-14 21:16:52 +02:00
parent 9203a76ed6
commit 2cc2bc1021
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
4 changed files with 455 additions and 376 deletions

View File

@ -28,9 +28,9 @@ GEN_HDR = parser.h boxes.h lex.yy.h
GEN_SRC = parser.c lex.yy.c
GEN_FILES = $(GEN_SRC) $(GEN_HDR)
ORIG_HDRCL = boxes.in.h config.h
ORIG_HDR = $(ORIG_HDRCL) cmdline.h discovery.h generate.h lexer.h parsecode.h parsing.h regulex.h remove.h shape.h tools.h unicode.h
ORIG_HDR = $(ORIG_HDRCL) cmdline.h discovery.h generate.h list.h parsecode.h parsing.h regulex.h remove.h shape.h tools.h unicode.h
ORIG_GEN = lexer.l parser.y
ORIG_NORM = boxes.c cmdline.c discovery.c generate.c parsecode.c parsing.c regulex.c remove.c shape.c tools.c unicode.c
ORIG_NORM = boxes.c cmdline.c discovery.c generate.c list.c parsecode.c parsing.c regulex.c remove.c shape.c tools.c unicode.c
ORIG_SRC = $(ORIG_GEN) $(ORIG_NORM)
ORIG_FILES = $(ORIG_SRC) $(ORIG_HDR)
@ -86,12 +86,13 @@ parser.c parser.h: parser.y lex.yy.h | check_dir
lex.yy.c lex.yy.h: lexer.l | check_dir
$(LEX) --header-file=lex.yy.h $<
boxes.o: boxes.c boxes.h discovery.h regulex.h shape.h tools.h unicode.h generate.h remove.h config.h | check_dir
boxes.o: boxes.c boxes.h cmdline.h discovery.h regulex.h shape.h tools.h unicode.h generate.h list.h remove.h config.h | check_dir
cmdline.o: cmdline.c cmdline.h boxes.h tools.h config.h | check_dir
discovery.o: discovery.c discovery.h boxes.h tools.h config.h | check_dir
generate.o: generate.c generate.h boxes.h shape.h tools.h unicode.h config.h | check_dir
getopt.o: misc/getopt.c misc/getopt.h | check_dir
lex.yy.o: lex.yy.c parser.h boxes.h parsing.h tools.h shape.h config.h | check_dir
list.o: list.c list.h boxes.h parsing.h tools.h config.h | check_dir
parsecode.o: parsecode.c parser.h boxes.h tools.h lex.yy.h regulex.h unicode.h config.h | check_dir
parser.o: parser.c boxes.h lex.yy.h parser.h parsing.h tools.h shape.h discovery.h config.h | check_dir
parsing.o: parsing.c parsing.h parser.h lex.yy.h boxes.h tools.h config.h | check_dir

View File

@ -34,6 +34,7 @@
#include "boxes.h"
#include "cmdline.h"
#include "list.h"
#include "shape.h"
#include "tools.h"
#include "discovery.h"
@ -45,12 +46,6 @@
typedef struct {
char *tag;
size_t count;
} tagstats_t;
/* _\|/_
(o o)
+----oOO-{_}-OOo------------------------------------------------------------+
@ -172,77 +167,6 @@ static int build_design(design_t **adesigns, const char *cld)
static char *escape(const char *org, const int pLength)
{
char *result = (char *) calloc(1, 2 * strlen(org) + 1);
int orgIdx, resultIdx;
for (orgIdx = 0, resultIdx = 0; orgIdx < pLength; ++orgIdx, ++resultIdx) {
if (org[orgIdx] == '\\' || org[orgIdx] == '"') {
result[resultIdx++] = '\\';
}
result[resultIdx] = org[orgIdx];
}
result[resultIdx] = '\0';
return result;
}
static int style_sort(const void *p1, const void *p2)
{
return strcasecmp((const char *) ((*((design_t **) p1))->name),
(const char *) ((*((design_t **) p2))->name));
}
/**
* Create a string listing all the names of a design, for example `"ada-cmt alias lua-cmt, sql-cmt"`.
* @param design pointer to the design
* @return the string of names, for which memory was allocated
*/
static char *names(design_t *design)
{
size_t siz = strlen(design->name);
size_t num_aliases = 0;
while(design->aliases[num_aliases] != NULL) {
siz += strlen(design->aliases[num_aliases]);
if (num_aliases > 0) {
siz += 2; // ", "
}
++num_aliases;
}
if (num_aliases > 0) {
siz += 7; // " alias "
}
char *result = (char *) malloc (siz + 1);
if (result == NULL) {
perror(PROJECT);
return NULL;
}
strcpy(result, design->name);
if (num_aliases > 0) {
char *p = result + strlen(design->name);
strcpy(p, " alias ");
p += 7;
for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) {
strcpy(p, design->aliases[aidx]);
p += strlen(design->aliases[aidx]);
if (aidx < num_aliases - 1) {
strcpy(p, ", ");
p += 2;
}
}
}
return result;
}
int query_is_undoc()
{
return opt.query != NULL && strcmp(opt.query[0], QUERY_UNDOC) == 0 && opt.query[1] == NULL;
@ -288,300 +212,6 @@ static int filter_by_tag(char **tags)
static void count_tag(char *tag, tagstats_t **tagstats, size_t *num_tags)
{
if (*tagstats != NULL) {
for (size_t i = 0; i < (*num_tags); ++i) {
if (strcasecmp((*tagstats)[i].tag, tag) == 0) {
++((*tagstats)[i].count);
return;
}
}
}
++(*num_tags);
*tagstats = realloc(*tagstats, (*num_tags) * sizeof(tagstats_t));
(*tagstats)[(*num_tags) - 1].tag = tag;
(*tagstats)[(*num_tags) - 1].count = 1;
}
static int tagstats_sort(const void *p1, const void *p2)
{
return strcasecmp(((tagstats_t *) p1)->tag, ((tagstats_t *) p2)->tag);
}
static void print_tags(tagstats_t *tagstats, size_t num_tags)
{
if (tagstats != NULL) {
qsort(tagstats, num_tags, sizeof(tagstats_t), tagstats_sort);
for (size_t tidx = 0; tidx < num_tags; ++tidx) {
if (tidx > 0) {
fprintf(opt.outfile, " | ");
}
fprintf(opt.outfile, "%s (%d)", tagstats[tidx].tag, (int) tagstats[tidx].count);
}
fprintf(opt.outfile, "%s", opt.eol);
}
}
/**
* Create a sorted shallow copy of the design array.
* @returns a new array, for which memory was allocated. All pointers in the array point to the original data.
* Returns `NULL` when out of memory.
*/
static design_t **sort_designs_by_name()
{
design_t **result = (design_t **) malloc(anz_designs * sizeof(design_t *));
if (result != NULL) {
for (int i = 0; i < anz_designs; ++i) {
result[i] = &(designs[i]);
}
qsort(result, anz_designs, sizeof(design_t *), style_sort);
}
else {
perror(PROJECT);
}
return result;
}
/**
* Generate sorted listing of available box styles.
* Uses design name from BOX spec and sample picture plus author.
* @returns != 0 on error (out of memory);
* == 0 on success
*/
static int list_styles()
{
int i;
if (opt.design_choice_by_user) {
design_t *d = opt.design;
int sstart = 0;
size_t w = 0;
char space[LINE_MAX_BYTES + 1];
memset(&space, ' ', LINE_MAX_BYTES);
space[LINE_MAX_BYTES] = '\0';
fprintf(opt.outfile, "Complete Design Information for \"%s\":%s", d->name, opt.eol);
fprintf(opt.outfile, "-----------------------------------");
for (i = strlen(d->name); i > 0; --i) {
fprintf(opt.outfile, "-");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Alias Names: ");
size_t aidx = 0;
while(d->aliases[aidx] != NULL) {
fprintf(opt.outfile, "%s%s", aidx > 0 ? ", " : "", d->aliases[aidx]);
++aidx;
}
if (aidx == 0) {
fprintf(opt.outfile, "none");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Author: %s%s",
d->author ? d->author : "(unknown author)", opt.eol);
fprintf(opt.outfile, "Original Designer: %s%s",
d->designer ? d->designer : "(unknown artist)", opt.eol);
fprintf(opt.outfile, "Creation Date: %s%s",
d->created ? d->created : "(unknown)", opt.eol);
fprintf(opt.outfile, "Current Revision: %s%s%s%s",
d->revision ? d->revision : "",
d->revision && d->revdate ? " as of " : "",
d->revdate ? d->revdate : (d->revision ? "" : "(unknown)"), opt.eol);
fprintf(opt.outfile, "Configuration File: %s%s", d->defined_in, opt.eol);
fprintf(opt.outfile, "Indentation Mode: ");
switch (d->indentmode) {
case 'b':
fprintf(opt.outfile, "box (indent box)%s", opt.eol);
break;
case 't':
fprintf(opt.outfile, "text (retain indentation inside of box)%s", opt.eol);
break;
default:
fprintf(opt.outfile, "none (discard indentation)%s", opt.eol);
break;
}
fprintf(opt.outfile, "Replacement Rules: ");
if (d->anz_reprules > 0) {
for (i = 0; i < (int) d->anz_reprules; ++i) {
fprintf(opt.outfile, "%d. (%s) \"%s\" WITH \"%s\"%s", i + 1,
d->reprules[i].mode == 'g' ? "glob" : "once",
d->reprules[i].search, d->reprules[i].repstr, opt.eol);
if (i < (int) d->anz_reprules - 1) {
fprintf(opt.outfile, " ");
}
}
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Reversion Rules: ");
if (d->anz_revrules > 0) {
for (i = 0; i < (int) d->anz_revrules; ++i) {
fprintf(opt.outfile, "%d. (%s) \"%s\" TO \"%s\"%s", i + 1,
d->revrules[i].mode == 'g' ? "glob" : "once",
d->revrules[i].search, d->revrules[i].repstr, opt.eol);
if (i < (int) d->anz_revrules - 1) {
fprintf(opt.outfile, " ");
}
}
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Minimum Box Dimensions: %d x %d (width x height)%s",
(int) d->minwidth, (int) d->minheight, opt.eol);
fprintf(opt.outfile, "Default Padding: ");
if (d->padding[BTOP] || d->padding[BRIG]
|| d->padding[BBOT] || d->padding[BLEF]) {
if (d->padding[BLEF]) {
fprintf(opt.outfile, "left %d", d->padding[BLEF]);
if (d->padding[BTOP] || d->padding[BRIG] || d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BTOP]) {
fprintf(opt.outfile, "top %d", d->padding[BTOP]);
if (d->padding[BRIG] || d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BRIG]) {
fprintf(opt.outfile, "right %d", d->padding[BRIG]);
if (d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BBOT]) {
fprintf(opt.outfile, "bottom %d", d->padding[BBOT]);
}
fprintf(opt.outfile, "%s", opt.eol);
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Default Killblank: %s%s",
empty_side(opt.design->shape, BTOP) && empty_side(opt.design->shape, BBOT) ? "no" : "yes", opt.eol);
fprintf(opt.outfile, "Tags: ");
size_t tidx = 0;
while(d->tags[tidx] != NULL) {
fprintf(opt.outfile, "%s%s", tidx > 0 ? ", " : "", d->tags[tidx]);
++tidx;
}
if (tidx == 0) {
fprintf(opt.outfile, "none");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Elastic Shapes: ");
sstart = 0;
for (i = 0; i < ANZ_SHAPES; ++i) {
if (isempty(d->shape + i)) {
continue;
}
if (d->shape[i].elastic) {
fprintf(opt.outfile, "%s%s", sstart ? ", " : "", shape_name[i]);
sstart = 1;
}
}
fprintf(opt.outfile, "%s", opt.eol);
/*
* Display all shapes
*/
if (query_is_undoc()) {
fprintf(opt.outfile, "Sample:%s%s%s", opt.eol, d->sample, opt.eol);
}
else {
int first_shape = 1;
for (i = 0; i < ANZ_SHAPES; ++i) {
if (isdeepempty(d->shape + i)) {
continue;
}
for (w = 0; w < d->shape[i].height; ++w) {
char *escaped_line = escape(d->shape[i].chars[w], d->shape[i].width);
fprintf(opt.outfile, "%-24s%3s%c \"%s\"%c%s",
(first_shape == 1 && w == 0 ? "Defined Shapes:" : ""),
(w == 0 ? shape_name[i] : ""), (w == 0 ? ':' : ' '),
escaped_line,
(w < d->shape[i].height - 1 ? ',' : ' '),
opt.eol
);
BFREE (escaped_line);
}
first_shape = 0;
}
}
}
else {
tagstats_t *tagstats = NULL;
size_t num_tags = 0;
design_t **list = sort_designs_by_name(); /* temp list for sorting */
if (list == NULL) {
return 1;
}
print_design_list_header();
for (i = 0; i < anz_designs; ++i) {
char *all_names = names(list[i]);
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
fprintf(opt.outfile, "%s%s%s, coded by %s:%s%s%s%s%s", all_names, opt.eol,
list[i]->designer, list[i]->author, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else if (list[i]->designer) {
fprintf(opt.outfile, "%s%s%s:%s%s%s%s%s", all_names, opt.eol,
list[i]->designer, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else if (list[i]->author) {
fprintf(opt.outfile, "%s%sunknown artist, coded by %s:%s%s%s%s%s", all_names, opt.eol,
list[i]->author, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else {
fprintf(opt.outfile, "%s:%s%s%s%s%s", all_names, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
BFREE(all_names);
for (size_t tidx = 0; list[i]->tags[tidx] != NULL; ++tidx) {
count_tag(list[i]->tags[tidx], &tagstats, &num_tags);
}
}
BFREE(list);
print_tags(tagstats, num_tags);
BFREE(tagstats);
}
return 0;
}
static int query_by_tag()
{
design_t **list = sort_designs_by_name(); /* temp list for sorting */
@ -1028,10 +658,10 @@ int main(int argc, char *argv[])
opt.design = designs;
/*
* If "-l" option was given, list styles and exit.
* If "-l" option was given, list designs and exit.
*/
if (opt.l) {
rc = list_styles();
rc = list_designs();
exit(rc);
}

400
src/list.c Normal file
View File

@ -0,0 +1,400 @@
/*
* boxes - Command line filter to draw/remove ASCII boxes around text
* Copyright (c) 1999-2021 Thomas Jensen and the boxes contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License, version 2, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* List design information about a single design or about all designs.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include "boxes.h"
#include "parsing.h"
#include "tools.h"
#include "list.h"
typedef struct {
char *tag;
size_t count;
} tagstats_t;
static void analyze_names(design_t *design, size_t *r_num_aliases, size_t *r_num_chars)
{
size_t siz = strlen(design->name);
size_t num_aliases = 0;
while(design->aliases[num_aliases] != NULL) {
siz += strlen(design->aliases[num_aliases]);
if (num_aliases > 0) {
siz += 2; // ", "
}
++num_aliases;
}
if (num_aliases > 0) {
siz += 7; // " alias "
}
*r_num_aliases = num_aliases;
*r_num_chars = siz;
}
/**
* Create a string listing all the names of a design, for example `"ada-cmt alias lua-cmt, sql-cmt"`.
* @param design pointer to the design
* @return the string of names, for which memory was allocated
*/
static char *names(design_t *design)
{
size_t siz;
size_t num_aliases;
analyze_names(design, &num_aliases, &siz);
char *result = (char *) malloc (siz + 1);
if (result == NULL) {
perror(PROJECT);
return NULL;
}
strcpy(result, design->name);
if (num_aliases > 0) {
char *p = result + strlen(design->name);
strcpy(p, " alias ");
p += 7; // " alias "
for (size_t aidx = 0; design->aliases[aidx] != NULL; ++aidx) {
strcpy(p, design->aliases[aidx]);
p += strlen(design->aliases[aidx]);
if (aidx < num_aliases - 1) {
strcpy(p, ", ");
p += 2; // ", "
}
}
}
return result;
}
static int style_sort(const void *p1, const void *p2)
{
return strcasecmp((const char *) ((*((design_t **) p1))->name),
(const char *) ((*((design_t **) p2))->name));
}
design_t **sort_designs_by_name()
{
design_t **result = (design_t **) malloc(anz_designs * sizeof(design_t *));
if (result != NULL) {
for (int i = 0; i < anz_designs; ++i) {
result[i] = &(designs[i]);
}
qsort(result, anz_designs, sizeof(design_t *), style_sort);
}
else {
perror(PROJECT);
}
return result;
}
static void count_tag(char *tag, tagstats_t **tagstats, size_t *num_tags)
{
if (*tagstats != NULL) {
for (size_t i = 0; i < (*num_tags); ++i) {
if (strcasecmp((*tagstats)[i].tag, tag) == 0) {
++((*tagstats)[i].count);
return;
}
}
}
++(*num_tags);
*tagstats = realloc(*tagstats, (*num_tags) * sizeof(tagstats_t));
(*tagstats)[(*num_tags) - 1].tag = tag;
(*tagstats)[(*num_tags) - 1].count = 1;
}
static int tagstats_sort(const void *p1, const void *p2)
{
return strcasecmp(((tagstats_t *) p1)->tag, ((tagstats_t *) p2)->tag);
}
static void print_tags(tagstats_t *tagstats, size_t num_tags)
{
if (tagstats != NULL) {
qsort(tagstats, num_tags, sizeof(tagstats_t), tagstats_sort);
for (size_t tidx = 0; tidx < num_tags; ++tidx) {
if (tidx > 0) {
fprintf(opt.outfile, " | ");
}
fprintf(opt.outfile, "%s (%d)", tagstats[tidx].tag, (int) tagstats[tidx].count);
}
fprintf(opt.outfile, "%s", opt.eol);
}
}
static char *escape(const char *org, const int pLength)
{
char *result = (char *) calloc(1, 2 * strlen(org) + 1);
int orgIdx, resultIdx;
for (orgIdx = 0, resultIdx = 0; orgIdx < pLength; ++orgIdx, ++resultIdx) {
if (org[orgIdx] == '\\' || org[orgIdx] == '"') {
result[resultIdx++] = '\\';
}
result[resultIdx] = org[orgIdx];
}
result[resultIdx] = '\0';
return result;
}
static void print_design_details(design_t *d)
{
fprintf(opt.outfile, "Complete Design Information for \"%s\":%s", d->name, opt.eol);
fprintf(opt.outfile, "-----------------------------------");
for (int i = strlen(d->name); i > 0; --i) {
fprintf(opt.outfile, "-");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Alias Names: ");
size_t aidx = 0;
while(d->aliases[aidx] != NULL) {
fprintf(opt.outfile, "%s%s", aidx > 0 ? ", " : "", d->aliases[aidx]);
++aidx;
}
if (aidx == 0) {
fprintf(opt.outfile, "none");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Author: %s%s", d->author ? d->author : "(unknown author)", opt.eol);
fprintf(opt.outfile, "Original Designer: %s%s", d->designer ? d->designer : "(unknown artist)", opt.eol);
fprintf(opt.outfile, "Creation Date: %s%s", d->created ? d->created : "(unknown)", opt.eol);
fprintf(opt.outfile, "Current Revision: %s%s%s%s",
d->revision ? d->revision : "",
d->revision && d->revdate ? " as of " : "",
d->revdate ? d->revdate : (d->revision ? "" : "(unknown)"), opt.eol);
fprintf(opt.outfile, "Configuration File: %s%s", d->defined_in, opt.eol);
fprintf(opt.outfile, "Indentation Mode: ");
switch (d->indentmode) {
case 'b':
fprintf(opt.outfile, "box (indent box)%s", opt.eol);
break;
case 't':
fprintf(opt.outfile, "text (retain indentation inside of box)%s", opt.eol);
break;
default:
fprintf(opt.outfile, "none (discard indentation)%s", opt.eol);
break;
}
fprintf(opt.outfile, "Replacement Rules: ");
if (d->anz_reprules > 0) {
for (int i = 0; i < (int) d->anz_reprules; ++i) {
fprintf(opt.outfile, "%d. (%s) \"%s\" WITH \"%s\"%s", i + 1,
d->reprules[i].mode == 'g' ? "glob" : "once",
d->reprules[i].search, d->reprules[i].repstr, opt.eol);
if (i < (int) d->anz_reprules - 1) {
fprintf(opt.outfile, " ");
}
}
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Reversion Rules: ");
if (d->anz_revrules > 0) {
for (int i = 0; i < (int) d->anz_revrules; ++i) {
fprintf(opt.outfile, "%d. (%s) \"%s\" TO \"%s\"%s", i + 1,
d->revrules[i].mode == 'g' ? "glob" : "once",
d->revrules[i].search, d->revrules[i].repstr, opt.eol);
if (i < (int) d->anz_revrules - 1) {
fprintf(opt.outfile, " ");
}
}
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Minimum Box Dimensions: %d x %d (width x height)%s",
(int) d->minwidth, (int) d->minheight, opt.eol);
fprintf(opt.outfile, "Default Padding: ");
if (d->padding[BTOP] || d->padding[BRIG] || d->padding[BBOT] || d->padding[BLEF]) {
if (d->padding[BLEF]) {
fprintf(opt.outfile, "left %d", d->padding[BLEF]);
if (d->padding[BTOP] || d->padding[BRIG] || d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BTOP]) {
fprintf(opt.outfile, "top %d", d->padding[BTOP]);
if (d->padding[BRIG] || d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BRIG]) {
fprintf(opt.outfile, "right %d", d->padding[BRIG]);
if (d->padding[BBOT]) {
fprintf(opt.outfile, ", ");
}
}
if (d->padding[BBOT]) {
fprintf(opt.outfile, "bottom %d", d->padding[BBOT]);
}
fprintf(opt.outfile, "%s", opt.eol);
}
else {
fprintf(opt.outfile, "none%s", opt.eol);
}
fprintf(opt.outfile, "Default Killblank: %s%s",
empty_side(opt.design->shape, BTOP) && empty_side(opt.design->shape, BBOT) ? "no" : "yes", opt.eol);
fprintf(opt.outfile, "Tags: ");
size_t tidx = 0;
while(d->tags[tidx] != NULL) {
fprintf(opt.outfile, "%s%s", tidx > 0 ? ", " : "", d->tags[tidx]);
++tidx;
}
if (tidx == 0) {
fprintf(opt.outfile, "none");
}
fprintf(opt.outfile, "%s", opt.eol);
fprintf(opt.outfile, "Elastic Shapes: ");
int sstart = 0;
for (int i = 0; i < ANZ_SHAPES; ++i) {
if (isempty(d->shape + i)) {
continue;
}
if (d->shape[i].elastic) {
fprintf(opt.outfile, "%s%s", sstart ? ", " : "", shape_name[i]);
sstart = 1;
}
}
fprintf(opt.outfile, "%s", opt.eol);
/*
* Display all shapes
*/
if (query_is_undoc()) {
fprintf(opt.outfile, "Sample:%s%s%s", opt.eol, d->sample, opt.eol);
}
else {
int first_shape = 1;
for (int i = 0; i < ANZ_SHAPES; ++i) {
if (isdeepempty(d->shape + i)) {
continue;
}
for (size_t w = 0; w < d->shape[i].height; ++w) {
char *escaped_line = escape(d->shape[i].chars[w], d->shape[i].width);
fprintf(opt.outfile, "%-24s%3s%c \"%s\"%c%s",
(first_shape == 1 && w == 0 ? "Defined Shapes:" : ""),
(w == 0 ? shape_name[i] : ""), (w == 0 ? ':' : ' '),
escaped_line,
(w < d->shape[i].height - 1 ? ',' : ' '),
opt.eol
);
BFREE (escaped_line);
}
first_shape = 0;
}
}
}
int list_designs()
{
if (opt.design_choice_by_user) {
print_design_details(opt.design);
}
else {
tagstats_t *tagstats = NULL;
size_t num_tags = 0;
design_t **list = sort_designs_by_name(); /* temp list for sorting */
if (list == NULL) {
return 1;
}
print_design_list_header();
for (int i = 0; i < anz_designs; ++i) {
char *all_names = names(list[i]);
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
fprintf(opt.outfile, "%s%s%s, coded by %s:%s%s%s%s%s", all_names, opt.eol,
list[i]->designer, list[i]->author, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else if (list[i]->designer) {
fprintf(opt.outfile, "%s%s%s:%s%s%s%s%s", all_names, opt.eol,
list[i]->designer, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else if (list[i]->author) {
fprintf(opt.outfile, "%s%sunknown artist, coded by %s:%s%s%s%s%s", all_names, opt.eol,
list[i]->author, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
else {
fprintf(opt.outfile, "%s:%s%s%s%s%s", all_names, opt.eol, opt.eol,
list[i]->sample, opt.eol, opt.eol);
}
BFREE(all_names);
for (size_t tidx = 0; list[i]->tags[tidx] != NULL; ++tidx) {
count_tag(list[i]->tags[tidx], &tagstats, &num_tags);
}
}
BFREE(list);
print_tags(tagstats, num_tags);
BFREE(tagstats);
}
return 0;
}
/*EOF*/ /* vim: set sw=4: */

48
src/list.h Normal file
View File

@ -0,0 +1,48 @@
/*
* boxes - Command line filter to draw/remove ASCII boxes around text
* Copyright (c) 1999-2021 Thomas Jensen and the boxes contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License, version 2, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* List design information about a single design or about all designs.
*/
#ifndef LIST_H
#define LIST_H
/**
* Create a sorted shallow copy of the global design array.
* @returns a new array, for which memory was allocated. All pointers in the array point to the original data.
* Returns `NULL` when out of memory.
*/
design_t **sort_designs_by_name();
/**
* Print a sorted listing of available box designs.
* Uses design name from BOX spec and sample picture plus author.
* @returns != 0 on error (out of memory);
* == 0 on success
*/
int list_designs();
#endif
/*EOF*/ /* vim: set cindent sw=4: */