chad@anasaz.UUCP (09/25/88)
Posting-number: Volume 4, Issue 91 Submitted-by: "A. Nonymous" <chad@anasaz.UUCP> Archive-name: fill This is another simple filter to make it easier to enter and revise text from within vi or some other editor. It provides centering, filling and justification on selectable margins. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: fill.c fill.1 Makefile test_file # Wrapped by chad@dcfinc on Sat Sep 24 01:29:59 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'fill.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fill.c'\" else echo shar: Extracting \"'fill.c'\" \(8314 characters\) sed "s/^X//" >'fill.c' <<'END_OF_FILE' X/* fill.c - Simple text formatter - 1.7 */ X X/* X** fill is a simple text formatter meant to be used from within X** your editor to provide the same functionality as the ^B command X** in WordStar. This presumes your editor can pipe an object through X** a filter. In vi, you would do something like "!}fill" to word wrap X** a paragraph. Of course, you may, in the spirit of Unix, find other X** uses for it. For example, fill has the side-effect of de-tabifying X** lines passed to it. X** Usage: fill [-c | -j] [-l n] [-o n] X** -c center the lines X** -j justify the right margin X** -r n set right margin to "n", defaults to 72 X** -l n set left margin to "n", defaults to 1 X*/ X X/* X** Author: X** Chad R. Larson This program is placed in the X** DCF, Inc. Public Domain. You may do with X** 14623 North 49th Place it as you please. X** Scottsdale, AZ 85254 X*/ X X/* X** Programming note: functions from the string library were used X** wherever logical, under the assumption that they are more optimized X** (or assemblerized) than whatever I built would be. On my C library X** this is true, your milage may vary. Buffer pointers were generally X** avoided for readability (this doesn't have to blaze, after all). X*/ X X/* maximum length of a line (for centering only) */ X#define LINE_MAX 512 X X/* maximum length of a word */ X#define WORD_MAX 128 X X/* the default right margin */ X#define DEF_MARGIN 72 X X#include <stdio.h> X#include <string.h> X#include <memory.h> X X/* forward references */ Xvoid j_line(); /* justify a line */ Xvoid exit(); Xchar *malloc(); X X X/* main program */ Xvoid main(argc, argv) Xint argc; Xchar *argv[]; X{ X int c; /* a generic character */ X int center = 0; /* center text flag */ X int justify = 0; /* justify right margin flag */ X int w_length; /* length of current word */ X int l_length = 0; /* length of current line */ X int l_margin = 1; /* left margin */ X int r_margin = DEF_MARGIN; /* right margin */ X int wrap_point; /* max chars allowed on a line */ X char *margin; /* points to left margin string */ X char *out_line; /* points to the output line */ X char word[WORD_MAX]; /* the current word */ X char *bp; /* a buffer pointer for centering */ X extern char *optarg; /* option argument pointer X X /* parse the command line */ X while ((c = getopt(argc, argv, "cjr:l:")) != EOF) X switch (c) { X case 'c': X center++; X break; X case 'j': X justify++; X break; X case 'r': X r_margin = atoi(optarg); X break; X case 'l': X l_margin = atoi(optarg); X break; X case '?': X (void)fprintf(stderr, X "Usage: %s [-c | -j] [-l n] [-o n]\n", argv[0]); X exit(-1); X } X X /* validate command line inputs */ X if ( justify && center ) { X (void)fputs("Center and Justify are mutually exclusive.\n", stderr); X exit(1); X } X if (l_margin >= r_margin || l_margin < 1) { X (void)fputs("Illogical margin setting.\n", stderr); X exit(2); X } X X /* Center the text if requested. Will exit without filling. */ X if (center) { X if ( (out_line = malloc(LINE_MAX)) == NULL ) { X (void)fputs("Unable to allocate centering buffer.\n", stderr); X exit(3); X } X while ( fgets(out_line, LINE_MAX, stdin) != NULL ) { X bp = out_line; X while (*bp == ' ' || *bp == '\t') /* strip leading spaces */ X bp++; X l_length = strlen(bp); X l_length--; /* back over new-line */ X while (bp[l_length - 1] == ' ' || bp[l_length - 1] == '\t') X l_length--; /* strip trailing space */ X bp[l_length] = '\0'; X center = (r_margin - l_length) / 2; X while (center--) X (void)putc(' ', stdout); X (void)puts(bp); X } X exit(0); X } X X /* create the left margin string */ X if ( (margin = malloc( (unsigned)l_margin) ) == NULL ) { X (void)fputs("Unable to allocate space for margin.\n", stderr); X exit(4); X } X (void)memset(margin, ' ', l_margin - 1); X margin[l_margin - 1] = '\0'; X X /* create the output line buffer */ X wrap_point = r_margin - l_margin + 1; X if ((out_line = malloc( (unsigned)wrap_point + 3) ) == NULL) { X (void)fputs("Unable to allocate space for line buffer.\n", stderr); X exit(5); X } X X /* move words from the input to the output */ X while ( (w_length = get_word(word) ) != 0 ) { X if ( (l_length + w_length) > wrap_point ) { /* line wrap? */ X while (out_line[l_length - 1] == ' ') /* trailing space strip */ X l_length--; X out_line[l_length] = '\0'; X if (justify) /* justify the line? */ X j_line(out_line, wrap_point); X (void)fputs(margin, stdout); /* set any offset */ X (void)puts(out_line); /* put the line to stdout */ X *out_line = '\0'; /* reset the output line */ X l_length = 0; X } X (void)strcat(out_line, word); X (void)strcat(out_line, " "); X l_length = l_length + w_length + 1; X if ( (c = word[w_length - 1]) == '.' || c == '?' || c == '!' ) { X (void)strcat(out_line, " "); /* end-of-sentence handling */ X l_length++; X } X } X X /* clean up and exit */ X if (l_length) { /* residual to flush */ X while (out_line[l_length - 1] == ' ') X l_length--; X out_line[l_length] = '\0'; X (void)fputs(margin, stdout); X (void)puts(out_line); X } X exit(0); X} X X/* X** get_word - a routine to return the next word from the standard input. X** Copies the next word from the input stream to the location pointed to X** by its argument. The word will be null terminated. A word is any X** string of characters delimited by whitespace. Returns the length X** of the word. X*/ X Xint get_word(Word) Xchar *Word; X{ X register int c; /* generic character */ X register int i; /* a counter */ X X /* first strip any leading whitespace */ X while ((c = getchar()) == ' ' || c == '\n' || c == '\t' || c == '\f') ; X if (c == EOF) { X *Word = '\0'; X return 0; X } else X (void)ungetc(c, stdin); X X /* copy the word */ X i = 0; X while ((c = getchar()) != ' ' && c != '\n' X && c != '\t' && c != '\f' && c != EOF) { X *Word++ = c; X if (++i >= WORD_MAX) { X (void)fputs("Encountered word too large.\n", stderr); X exit(6); X } X } X *Word = '\0'; X return i; X} X X/* X** Routine to justify a line. X*/ Xvoid j_line(buffer, margin) Xchar *buffer; Xint margin; X{ X static unsigned direction = 0; /* which end to we fill from? */ X static char *work = NULL; /* working storage */ X int insert; /* count of places to insert */ X int spaces; /* count of spaces to insert */ X int multi; /* spaces to insert each chance */ X int extra; /* count of extra spaces needed */ X int count; /* loop counter */ X int loop; /* loop counter */ X char *Ibp; /* Input buffer pointer */ X char *Obp; /* Output buffer pointer */ X X /* X ** Allocate a working storage large enough to hold the line. We X ** only do this once (and only if we are justifing). X */ X if (work == NULL) X if ((work = malloc( (unsigned)margin + 1 )) == NULL) { X (void)fputs("Unable to allocate work buffer.\n", stderr); X exit(7); X } X X /* how many spaces do we have to insert? */ X loop = strlen(buffer); X spaces = margin - loop; X if (spaces == 0) X return; X X /* find how many opportunities there are for space stuffing */ X Ibp = buffer; X insert = 0; X while (loop--) { X if ( (*Ibp++ == ' ') && (*Ibp != ' ') ) X insert++; X } X if (insert == 0) X return; X X /* how many spaces do we have to stuff per chance? */ X extra = spaces % insert; /* extra spaces needed */ X multi = spaces / insert; /* spaces per slot to insert */ X X /* copy the buffer contents, inserting spaces */ X direction = ~direction; /* flip end to fill from */ X (void)strcpy(work, buffer); /* make a working copy */ X if (direction) { X Ibp = work; X Obp = buffer; X loop = strlen(buffer) + 1; X while (loop--) { X *Obp++ = *Ibp++; /* move a character */ X if ((*(Ibp - 1) == ' ') && (*(Ibp - 2) != ' ')) { X if (extra) { X extra--; X *Obp++ = ' '; X } X for (count = multi; count; count--) X *Obp++ = ' '; X } X } X } else { X loop = strlen(buffer); X Ibp = work + loop; X Obp = buffer + loop + spaces; X *(Obp + 1) = '\0'; X while (loop--) { X *Obp-- = *Ibp--; X if ((*(Ibp + 1) == ' ') && (*(Ibp + 2) != ' ')) { X if (extra) { X extra--; X *Obp-- = ' '; X } X for (count = multi; count; count--) X *Obp-- = ' '; X } X } X } X} END_OF_FILE if test 8314 -ne `wc -c <'fill.c'`; then echo shar: \"'fill.c'\" unpacked with wrong size! fi # end of 'fill.c' fi if test -f 'fill.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fill.1'\" else echo shar: Extracting \"'fill.1'\" \(1177 characters\) sed "s/^X//" >'fill.1' <<'END_OF_FILE' X.TH FILL 1 local X.SH NAME Xfill - a simple text formatter X.SH SYNOPSIS Xfill [-c | -j] [-r n] [-l n] X.SH DESCRIPTION X.I Fill Xis a simple text formatter meant to be used from within Xyour editor to provide the same functionality as the ^B command Xin WordStar. This presumes your editor can pipe an object through Xa filter. In vi, you would do something like "!}fill" to word wrap Xa paragraph. Of course, you may, in the spirit of Unix, find other Xuses for it. For example, X.I fill Xhas the side-effect of de-tabifying Xlines passed to it. X.PP XThe following options pertain: X.nf X -c center the lines X -j justify the right margin X -r n set right margin to "n", defaults to 72 X -l n set left margin to "n", defaults to 1 X.fi X.SH CAVEATS XThis ability is built in to emacs (but then, what isn't). It is Xrumored a similar program exists in the Berkely world. X.SH FEATURES X.I Fill Xhas no pracical limit on line lengths (except when centering). X.SH BUGS XThe justification algorithm is a little crude. X.br X.I Fill Xmakes no attempt to preserve existing indentations or blank Xlines (this could be construed as a feature). X.SH AUTHOR XChad R. Larson X.SH "SEE ALSO" Xpr(1), nroff(1), troff(1) END_OF_FILE if test 1177 -ne `wc -c <'fill.1'`; then echo shar: \"'fill.1'\" unpacked with wrong size! fi # end of 'fill.1' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(243 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for fill, a simple text formatter X# X# Last changed 9/23/88 X# X XBINDIR = /usr/local/bin X Xfill: fill.c X $(CC) $(CFLAGS) -o fill fill.c X Xinstall: fill X strip fill X -ln fill $(BINDIR) X touch install X XLint: fill.c X lint -p fill.c >Lint END_OF_FILE if test 243 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'test_file' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'test_file'\" else echo shar: Extracting \"'test_file'\" \(852 characters\) sed "s/^X//" >'test_file' <<'END_OF_FILE' XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. XThis is just a silly file of words to see if fill wraps them properly. END_OF_FILE if test 852 -ne `wc -c <'test_file'`; then echo shar: \"'test_file'\" unpacked with wrong size! fi # end of 'test_file' fi echo shar: End of shell archive. exit 0 --------------- "I read the news today, oh boy!" --John Lennon =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | DCF, Inc. | UUCP: ...ncar!noao!nud!anasaz!dcfinc!chad | | 14623 North 49th Place | Ma Bell: (602) 953-1392 | | Scottsdale, AZ 85254 | Loran: N-33deg37min20sec W-111deg58min26sec | =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | Disclaimer: These ARE the opinions of my employer! | =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=