Source for text justify fragment
utzoo!decvax!harpo!seismo!hao!csu-cs!silver
utzoo!decvax!harpo!seismo!hao!csu-cs!silver
Wed Feb 16 13:07:37 AEST 1983
/*
* justify lines (part of fmt.c for testing)
* compile with -DDEBUG for extra output
*/
#include <stdio.h>
#define LENGTH 72 /* definitions from fmt.c */
int pfx;
char *outp;
main () /* test routine */
{
char buf[BUFSIZ];
int left, right;
while (gets (buf) != NULL) {
for (left = 0; (left < LENGTH) && (buf[left] == ' '); left++);
for (right = left; buf[right]; right++);
justify (buf, left, right-1, LENGTH);
puts (buf);
}
}
/*
* Right-justify one line by padding with blanks:
* Also sets global outp past new end of buffer.
*/
#define MAXBLANKS BUFSIZ/2 /* most blank fields on line */
struct blank {
int pos; /* where blank is in buf */
int size; /* contiguous blanks in field */
int score; /* total surrounding nonblanks */
int insert; /* blanks to insert here */
};
justify (buf, left, right, margin)
char *buf; /* line to justify */
int left; /* leftmost nonblank character */
int right; /* rightmost character of any kind */
int margin; /* to justify against, base one */
{
struct blank blank[MAXBLANKS]; /* one per blank field in buf */
struct blank *bpa[MAXBLANKS]; /* one per blank[] entry */
struct blank *bp; /* temp pointer */
int blanks = 0; /* valid entries in blank[] */
int b; /* index into bpa */
int c, oldc; /* positions in buf */
int ins, need; /* number to insert, needed */
int to, from; /* for copying characters */
int compare();
if (left >= --margin) /* adjust margin to base zero */
return; /* can't do anything */
/*
* set right = last nonblank:
*/
while ((right > left) && (buf[right] == ' '))
right--;
if ((right == left) || (right >= margin))
return; /* can't do anything */
#ifdef DEBUG
printf ("%s\nleft:%3d right:%3d margin:%3d need:%3d\n",
buf, left, right, margin, margin-right);
#endif
/*
* scan buf to set up blank[] and bpa[]:
*/
for (c = oldc = left; c <= right; c++)
if (buf[c] == ' ') {
if (blanks) /* finish previous blank */
blank[blanks-1].score += c-oldc;
bp = &blank[blanks];
bp->pos = c;
bp->score = c-oldc; /* nonblanks to left */
bp->insert = 0; /* for now */
oldc = c; /* count and skip blanks */
while (buf[++c] == ' ')
;
bp->size = c-oldc; /* number of blanks in field */
bpa[blanks++] = bp; /* save & each blank[] */
oldc = c; /* for next word */
}
if (!blanks) return; /* no blanks on line */
bp->score += c-oldc; /* finish last entry */
/*
* sort array of pointers to blank[] entries, by values in blank[]:
*/
qsort (bpa, blanks, sizeof (bpa[0]), compare);
/*
* assign number of blanks to insert at each field, by going through the
* sorted pointer array, first adding one blank to those fields with only
* one blank, then those with one or two, etc:
*/
need = margin - right; /* total to insert */
for (ins = 1; need > 0; ins++) { /* number to insert this pass */
b = 0;
while
( (b < blanks) /* more places to insert */
&& ((bpa[b]->size + bpa[b]->insert) == ins) /* same level */
&& need--) /* more blanks needed */
bpa[b++]->insert++;
}
#ifdef DEBUG
for (b = 0; b < blanks; b++)
printf ("field:%3d pos:%3d size:%3d score:%3d ins:%3d\n",
bpa[b]-blank, bpa[b]->pos, bpa[b]->size,
bpa[b]->score, bpa[b]->insert);
#endif
/*
* insert blanks in buf:
*/
from = right; /* copy from */
to = margin; /* copy to */
bp = &blank[blanks-1]; /* rightmost blank field */
while (to > from) { /* more to insert */
buf[to--] = buf[from--]; /* copy one char */
if (from == bp->pos) { /* at blank field */
while (bp->insert--) /* insert as many as needed */
buf[to--] = ' ';
bp--; /* previous field */
}
}
outp = buf + LENGTH; /* past new end of buffer */
return; /* we're done! */
}
/*
* Compare two blank[] elements via bpa[] to sort bpa[] by size, ascending,
* then score, descending:
* (return > 0) means elements are swapped.
* Multiply by BUFSIZ gives size priority over score.
*/
int
compare (lp, rp)
struct blank **lp, **rp;
{
return (BUFSIZ * ((**lp).size - (**rp).size) +
((**rp).score - (**lp).score));
}
More information about the Comp.sources.unix
mailing list