diff --git a/src/boxes.c b/src/boxes.c index a108b2f..d7ef24d 100644 --- a/src/boxes.c +++ b/src/boxes.c @@ -3,7 +3,7 @@ * Date created: March 18, 1999 (Thursday, 15:09h) * Author: Thomas Jensen * tsjensen@stud.informatik.uni-erlangen.de - * Version: $Id: boxes.c,v 1.3 1999/03/30 09:36:23 tsjensen Exp tsjensen $ + * Version: $Id: boxes.c,v 1.4 1999/03/30 13:30:19 tsjensen Exp tsjensen $ * Language: ANSI C * Platforms: sunos5/sparc, for now * World Wide Web: http://home.pages.de/~jensen/boxes/ @@ -14,6 +14,10 @@ * Revision History: * * $Log: boxes.c,v $ + * Revision 1.4 1999/03/30 13:30:19 tsjensen + * Added minimum width/height for a design. Fixed screwed tiny boxes. + * Did not handle zero input. + * * Revision 1.3 1999/03/30 09:36:23 tsjensen * ... still programming ... * (removed setlocale() call and locale.h include) @@ -42,7 +46,7 @@ extern char *optarg; /* for getopt() */ extern int optind, opterr, optopt; /* for getopt() */ -#ident "$Id: boxes.c,v 1.3 1999/03/30 09:36:23 tsjensen Exp tsjensen $" +#ident "$Id: boxes.c,v 1.4 1999/03/30 13:30:19 tsjensen Exp tsjensen $" extern FILE *yyin; /* lex input file */ @@ -785,155 +789,16 @@ size_t widest (const sentry_t *sarr, const int n, ...) } -#if 0 -static int shape_to_use (const shape_t s, shape_t *result) -/* - * Determine shape to use for a particular shape. - * This is only interesting if shape is not defined. :-) - * - * The resulting shape may not be elastic! Should be checked by caller. - * - * RETURNS: == 0 on success (result points to the shape to use) - * != 0 on error (result is undefined) - * -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ -{ - shape_t *seite; - int i; - shape_t cand1, cand2; /* candidate shapes */ - int dist1, dist2; /* distances of cands to corner */ - int idx; /* index of shape in side */ - if (isempty (&(opt.design->shape[s]))) - { - seite = on_side (s, 0); - - if (iscorner(s)) - { - if (seite[0] == s) { - for (i=1; ishape[seite[i]]))) { - cand1 = seite[i]; - break; - } - } - } - else { - for (i=SHAPES_PER_SIDE-2; i>=0; --i) { - if (!isempty(&(opt.design->shape[seite[i]]))) { - cand1 = seite[i]; - break; - } - } - } - - seite = on_side (s, 1); - if (seite[0] == s) { - for (i=1; ishape[seite[i]]))) { - cand2 = seite[i]; - break; - } - } - } - else { - for (i=SHAPES_PER_SIDE-2; i>=0; --i) { - if (!isempty(&(opt.design->shape[seite[i]]))) { - cand2 = seite[i]; - break; - } - } - } - } - - else { - for (i=0; ishape[seite[i]]))) { - cand1 = seite[i]; - break; - } - } - for (i=idx-1; i>=0; --i) { - if (!isempty(&(opt.design->shape[seite[i]]))) { - cand2 = seite[i]; - break; - } - } - - if (cand1 == s && cand2 != s) { - *result = cand2; - return 0; - } - if (cand1 != s && cand2 == s) { - *result = cand1; - return 0; - } - } - - if (opt.design->shape[cand1].elastic - && !(opt.design->shape[cand2].elastic)) { - *result = cand1; - return 0; - } - if (opt.design->shape[cand2].elastic - && !(opt.design->shape[cand1].elastic)) { - *result = cand2; - return 0; - } - /* - * at this point, both candidates must be elastic unless we - * have an error in the parser's sensibility checks - */ - dist1 = shape_distance (s, cand1); - dist2 = shape_distance (s, cand2); - if (dist1 < dist2) { - *result = cand1; - return 0; - } - else if (dist1 > dist2) { - *result = cand2; - return 0; - } - if (shapecmp (&(opt.design->shape[cand1]), - &(opt.design->shape[cand2])) == 0) { - *result = cand1; /* either one */ - return 0; - } - else { - /* - * Two different elastic shapes at the same distance to - * the corner -> no way we can say which one to use. - */ - return 1; - } - } - - else { - *result = s; - return 0; /* it is there, so use it */ - } -} -#endif - - - -static int vert_precalc (const sentry_t *sarr, const shape_t *seite, - size_t *iltf, size_t *hspace) +static int horiz_precalc (const sentry_t *sarr, + size_t *topiltf, size_t *botiltf, size_t *hspace) /* * Calculate data for horizontal box side generation. * * sarr Array of shapes from the current design - * seite the side to work on (e.g. north_side) - * iltf RESULT: individual lines (columns) to fill by shapes 1, 2, and 3 + * + * topiltf RESULT: individual lines (columns) to fill by shapes 1, 2, and 3 + * botiltf in top part of box (topiltf) and bottom part of box * hspace RESULT: number of columns excluding corners (sum over iltf) * * RETURNS: == 0 on success (result values are set) @@ -942,128 +807,183 @@ static int vert_precalc (const sentry_t *sarr, const shape_t *seite, * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { - int numshapes = 0; - size_t res_hspace = 0; + int tnumsh; /* number of existent shapes in top part */ + int bnumsh; + size_t twidth; /* current hspace for top side */ + size_t bwidth; /* current hspace for bottom side */ int i; - size_t j; - size_t target_width; + size_t target_width; /* assumed text width for minimum box size */ + int btoggle, ttoggle; /* for case 3 w/ 2 elastics */ - memset (iltf, 0, (SHAPES_PER_SIDE-2) * sizeof(size_t)); + /* + * Initialize future result values + */ + memset (topiltf, 0, (SHAPES_PER_SIDE-2) * sizeof(size_t)); + memset (botiltf, 0, (SHAPES_PER_SIDE-2) * sizeof(size_t)); *hspace = 0; - if (input.maxline >= (opt.design->minwidth - sarr[seite[0]].width - - sarr[seite[SHAPES_PER_SIDE-1]].width)) { + /* + * Ensure minimum width for the insides of a box in order to ensure + * minimum box size required by current design + */ + if (input.maxline >= (opt.design->minwidth - sarr[north_side[0]].width - + sarr[north_side[SHAPES_PER_SIDE-1]].width)) { target_width = input.maxline; } else { - target_width = opt.design->minwidth - sarr[seite[0]].width - - sarr[seite[SHAPES_PER_SIDE-1]].width; + target_width = opt.design->minwidth - sarr[north_side[0]].width - + sarr[north_side[SHAPES_PER_SIDE-1]].width; } - for (i=1; i it must be elastic - */ - for (i=1; i one must be elastic, the other must not - */ - for (i=1; i one or two of them must be elastic - * If two are elastic, they are the two outer ones. - */ - for (i=1; i target_width) - space_to_fill = 0; - else - space_to_fill = target_width - res_hspace; - for (j=0,vtmp=0; !j||vtmp bwidth) { /* south (bottom) is behind */ + seite = south_side; + iltf = botiltf; + res_hspace = &bwidth; + numsh = bnumsh; + stoggle = &btoggle; + } + else { /* north (top) is behind */ + seite = north_side; + iltf = topiltf; + res_hspace = &twidth; + numsh = tnumsh; + stoggle = &ttoggle; + } + + switch (numsh) { + + case 1: + /* + * only one shape -> it must be elastic + */ for (i=1; i one must be elastic, the other must not + */ + for (i=1; i one or two of them must be elastic + * If two are elastic, they are the two outer ones. + */ + for (i=1; i= (opt.design->minheight - sarr[seite[0]].height - - sarr[seite[SHAPES_PER_SIDE-1]].height)) - text_height = input.anz_lines; + /* + * Ensure minimum height for insides of box in order to ensure + * minimum box size required by current design + */ + if (input.anz_lines >= (opt.design->minheight - sarr[west_side[0]].height - + sarr[west_side[SHAPES_PER_SIDE-1]].height)) { + target_height = input.anz_lines; + } else { - text_height = opt.design->minheight - sarr[seite[0]].height - - sarr[seite[SHAPES_PER_SIDE-1]].height; + target_height = opt.design->minheight - sarr[west_side[0]].height - + sarr[west_side[SHAPES_PER_SIDE-1]].height; } - for (i=1; i it must be elastic - */ - for (i=1; i one must be elastic, the other must not - */ - for (i=1; i one or two of them must be elastic - * If two are elastic, they are the two outer ones. - */ - for (i=1; i text_height) - space_to_fill = 0; - else - space_to_fill = text_height - res_vspace; - for (j=0,vtmp=0; !j||vtmp rheight) { /* east (right) is behind */ + seite = east_side; + iltf = rightiltf; + res_vspace = &rheight; + numsh = rnumsh; + stoggle = &rtoggle; + } + else { /* west (left) is behind */ + seite = west_side; + iltf = leftiltf; + res_vspace = &lheight; + numsh = lnumsh; + stoggle = <oggle; + } + + switch (numsh) { + + case 1: + /* + * only one shape -> it must be elastic + */ for (i=1; i one must be elastic, the other must not + */ + for (i=1; i one or two of them must be elastic + * If two are elastic, they are the two outer ones. + */ + for (i=1; iheight = highest (opt.design->shape, + SHAPES_PER_SIDE, NW, NNW, N, NNE, NE); + bresult->height = highest (opt.design->shape, + SHAPES_PER_SIDE, SW, SSW, S, SSE, SE); + + rc = horiz_precalc (opt.design->shape, tiltf, biltf, &(tresult->width)); + if (rc) return rc; + bresult->width = tresult->width; + + #ifdef DEBUG + fprintf (stderr, "Top side box rect width %d, height %d.\n", + tresult->width, tresult->height); + fprintf (stderr, "Top columns to fill: %s %d, %s %d, %s %d.\n", + shape_name[north_side[1]], tiltf[0], + shape_name[north_side[2]], tiltf[1], + shape_name[north_side[3]], tiltf[2]); + fprintf (stderr, "Bottom side box rect width %d, height %d.\n", + bresult->width, bresult->height); + fprintf (stderr, "Bottom columns to fill: %s %d, %s %d, %s %d.\n", + shape_name[south_side[1]], biltf[0], + shape_name[south_side[2]], biltf[1], + shape_name[south_side[3]], biltf[2]); + #endif + + tresult->chars = (char **) calloc (tresult->height, sizeof(char *)); + bresult->chars = (char **) calloc (bresult->height, sizeof(char *)); + if (tresult->chars == NULL || bresult->chars == NULL) return 1; + + rc = vert_assemble (opt.design->shape, north_side, tiltf, tresult); + if (rc) return rc; + rc = vert_assemble (opt.design->shape, south_side, biltf, bresult); + if (rc) return rc; + + #if defined(DEBUG) && 1 + { + /* + * Debugging code - Output horizontal sides of box + */ + size_t j; + fprintf (stderr, "TOP SIDE:\n"); + for (j=0; jheight; ++j) { + fprintf (stderr, " %2d: \'%s\'\n", j, + tresult->chars[j]? tresult->chars[j] : "(null)"); + } + fprintf (stderr, "BOTTOM SIDE:\n"); + for (j=0; jheight; ++j) { + fprintf (stderr, " %2d: \'%s\'\n", j, + bresult->chars[j]? bresult->chars[j] : "(null)"); + } + } + #endif + + return 0; /* all clear */ +} + + + +static int vert_generate (sentry_t *lresult, sentry_t *rresult) +/* + * Generate vertical sides of box. + * + * RETURNS: == 0 on success (resulting char array is stored in [rl]result) * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t vspace = 0; - size_t iltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ + size_t leftiltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ + size_t rightiltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ int rc; /* received return code */ - result->width = widest (opt.design->shape, + lresult->width = widest (opt.design->shape, SHAPES_PER_SIDE, SW, WSW, W, WNW, NW); - - rc = horiz_precalc (opt.design->shape, west_side, iltf, &vspace); - if (rc) return rc; - - result->height = vspace + - opt.design->shape[NW].height + opt.design->shape[SW].height; - - #ifdef DEBUG - fprintf (stderr, "Left side box rect width %d, height %d, vspace %d.\n", - result->width, result->height, vspace); - fprintf (stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n", - shape_name[west_side[1]], iltf[0], - shape_name[west_side[2]], iltf[1], - shape_name[west_side[3]], iltf[2]); - #endif - - result->chars = (char **) calloc (result->height, sizeof(char *)); - if (result->chars == NULL) return 1; - - horiz_assemble (opt.design->shape, west_side, iltf, result); - - #if defined(DEBUG) && 1 - { - /* - * Debugging code - Output left side of box - */ - size_t j; - fprintf (stderr, "LEFT SIDE:\n"); - for (j=0; jheight; ++j) { - fprintf (stderr, " %2d: \'%s\'\n", j, - result->chars[j]? result->chars[j] : "(null)"); - } - } - #endif - - return 0; /* all clear */ -} - - - -static int generate_mtop (sentry_t *result) -/* - * Generate top part of box (excluding corners). - * - * RETURNS: == 0 if successful (resulting char array is stored in result) - * != 0 on error - * -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ -{ - size_t iltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ - int rc; /* received return code */ - - result->height = highest (opt.design->shape, - SHAPES_PER_SIDE, NW, NNW, N, NNE, NE); - - rc = vert_precalc (opt.design->shape, north_side, iltf, &(result->width)); - if (rc) return rc; - - #ifdef DEBUG - fprintf (stderr, "Top side box rect width %d, height %d.\n", - result->width, result->height); - fprintf (stderr, "Top lines to fill: %s %d, %s %d, %s %d.\n", - shape_name[north_side[1]], iltf[0], - shape_name[north_side[2]], iltf[1], - shape_name[north_side[3]], iltf[2]); - #endif - - result->chars = (char **) calloc (result->height, sizeof(char *)); - if (result->chars == NULL) return 1; - - rc = vert_assemble (opt.design->shape, north_side, iltf, result); - if (rc) return rc; - - #if defined(DEBUG) && 1 - { - /* - * Debugging code - Output top side of box - */ - size_t j; - fprintf (stderr, "TOP SIDE:\n"); - for (j=0; jheight; ++j) { - fprintf (stderr, " %2d: \'%s\'\n", j, - result->chars[j]? result->chars[j] : "(null)"); - } - } - #endif - - return 0; /* all clear */ -} - - - -static int generate_right (sentry_t *result) -/* - * Generate right side of box. - * - * RETURNS: == 0 if successful - * != 0 on error - * -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ -{ - size_t vspace = 0; - size_t iltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ - int rc; /* received return code */ - - result->width = widest (opt.design->shape, + rresult->width = widest (opt.design->shape, SHAPES_PER_SIDE, SE, ESE, E, ENE, NE); - rc = horiz_precalc (opt.design->shape, east_side, iltf, &vspace); + rc = vert_precalc (opt.design->shape, leftiltf, rightiltf, &vspace); if (rc) return rc; - result->height = vspace + + lresult->height = vspace + + opt.design->shape[NW].height + opt.design->shape[SW].height; + rresult->height = vspace + opt.design->shape[NE].height + opt.design->shape[SE].height; #ifdef DEBUG + fprintf (stderr, "Left side box rect width %d, height %d, vspace %d.\n", + lresult->width, lresult->height, vspace); + fprintf (stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n", + shape_name[west_side[1]], leftiltf[0], + shape_name[west_side[2]], leftiltf[1], + shape_name[west_side[3]], leftiltf[2]); fprintf (stderr, "Right side box rect width %d, height %d, vspace %d.\n", - result->width, result->height, vspace); + rresult->width, rresult->height, vspace); fprintf (stderr, "Right lines to fill: %s %d, %s %d, %s %d.\n", - shape_name[east_side[1]], iltf[0], - shape_name[east_side[2]], iltf[1], - shape_name[east_side[3]], iltf[2]); + shape_name[east_side[1]], rightiltf[0], + shape_name[east_side[2]], rightiltf[1], + shape_name[east_side[3]], rightiltf[2]); #endif - result->chars = (char **) calloc (result->height, sizeof(char *)); - if (result->chars == NULL) return 1; + lresult->chars = (char **) calloc (lresult->height, sizeof(char *)); + if (lresult->chars == NULL) return 1; + rresult->chars = (char **) calloc (rresult->height, sizeof(char *)); + if (rresult->chars == NULL) return 1; - horiz_assemble (opt.design->shape, east_side, iltf, result); + horiz_assemble (opt.design->shape, west_side, leftiltf, lresult); + horiz_assemble (opt.design->shape, east_side, rightiltf, rresult); #if defined(DEBUG) && 1 { /* - * Debugging code - Output right side of box + * Debugging code - Output left and right side of box */ size_t j; - fprintf (stderr, "RIGHT SIDE:\n"); - for (j=0; jheight; ++j) { + fprintf (stderr, "LEFT SIDE:\n"); + for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, - result->chars[j]? result->chars[j] : "(null)"); + lresult->chars[j]? lresult->chars[j] : "(null)"); } - } - #endif - - return 0; /* all clear */ -} - - - -static int generate_mbottom (sentry_t *result) -/* - * Generate bottom part of box (excluding corners). - * - * RETURNS: == 0 if successful - * != 0 on error - * -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ -{ - size_t iltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ - int rc; /* received return code */ - - result->height = highest (opt.design->shape, - SHAPES_PER_SIDE, SW, SSW, S, SSE, SE); - - rc = vert_precalc (opt.design->shape, south_side, iltf, &(result->width)); - if (rc) return rc; - - #ifdef DEBUG - fprintf (stderr, "Bottom side box rect width %d, height %d.\n", - result->width, result->height); - fprintf (stderr, "Bottom lines to fill: %s %d, %s %d, %s %d.\n", - shape_name[south_side[1]], iltf[0], - shape_name[south_side[2]], iltf[1], - shape_name[south_side[3]], iltf[2]); - #endif - - result->chars = (char **) calloc (result->height, sizeof(char *)); - if (result->chars == NULL) { - perror (PROJECT); - return 1; - } - - rc = vert_assemble (opt.design->shape, south_side, iltf, result); - if (rc) return rc; - - #if defined(DEBUG) && 1 - { - /* - * Debugging code - Output bottom side of box - */ - size_t j; - fprintf (stderr, "BOTTOM SIDE:\n"); - for (j=0; jheight; ++j) { + fprintf (stderr, "RIGHT SIDE:\n"); + for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, - result->chars[j]? result->chars[j] : "(null)"); + rresult->chars[j]? rresult->chars[j] : "(null)"); } } #endif @@ -1503,16 +1401,10 @@ static int generate_box (sentry_t *thebox) int rc; int i; - rc = generate_mtop (&(thebox[0])); + rc = horiz_generate (&(thebox[0]), &(thebox[2])); if (rc) goto err; - rc = generate_right (&(thebox[1])); - if (rc) goto err; - - rc = generate_mbottom (&(thebox[2])); - if (rc) goto err; - - rc = generate_left (&(thebox[3])); + rc = vert_generate (&(thebox[3]), &(thebox[1])); if (rc) goto err; return 0; /* all clear */