diff --git a/src/Makefile b/src/Makefile index 79d4bce..f41d699 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/boxes.c b/src/boxes.c index 2559342..8485f47 100644 --- a/src/boxes.c +++ b/src/boxes.c @@ -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); } diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..53c7966 --- /dev/null +++ b/src/list.c @@ -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 +#include +#include + +#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: */ diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..655f310 --- /dev/null +++ b/src/list.h @@ -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: */