v04i091: simple formatting filter for text editors
chad at anasaz.UUCP
chad at anasaz.UUCP
Sun Sep 25 11:29:37 AEST 1988
Posting-number: Volume 4, Issue 91
Submitted-by: "A. Nonymous" <chad at 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 at 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! |
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
More information about the Comp.sources.misc
mailing list