1 
2 static char rcsid[] = "@(#)$Id: prlong.c,v 1.4 1996/03/14 17:30:11 wfp5p Exp $";
3 
4 /*******************************************************************************
5  *  The Elm Mail System  -  $Revision: 1.4 $
6  *
7  *                      Copyright (c) 1988-1995 USENET Community Trust
8  * 			Copyright (c) 1986,1987 Dave Taylor
9  *******************************************************************************
10  * Bug reports, patches, comments, suggestions should be sent to:
11  *
12  *      Bill Pemberton, Elm Coordinator
13  *      flash@virginia.edu
14  *
15  *******************************************************************************
16  * $Log: prlong.c,v $
17  * Revision 1.4  1996/03/14  17:30:11  wfp5p
18  * Alpha 9
19  *
20  * Revision 1.3  1995/09/29  17:42:47  wfp5p
21  * Alpha 8 (Chip's big changes)
22  *
23  * Revision 1.2  1995/04/20  21:02:09  wfp5p
24  * Added the showreply feature and emacs key bindings.
25  *
26  * Revision 1.1.1.1  1995/04/19  20:38:41  wfp5p
27  * Initial import of elm 2.4 PL0 as base for elm 2.5.
28  *
29  ******************************************************************************/
30 
31 
32 /*
33  * Format large amounts of output, folding across multiple lines.
34  *
35  * Input is read in a line at a time, and the input records are joined
36  * together into output records up to a maximum line width.  A field
37  * seperator is placed between every input record, and a configurable
38  * leader is printed at the front of each line.  The default field
39  * seperator is a single space.  The default output leader is an empty
40  * string for the first output line, and a single tab for all subsequent
41  * lines.
42  *
43  * Usage:
44  *
45  *	prlong [-w wid] [-1 first_leader] [-l leader] [-f sep] < data
46  *
47  * Options:
48  *
49  *	-w wid		Maximum output line width.
50  *	-1 leader	Leader for the first line of output.
51  *	-l leader	Leader for all subsequent lines of output.
52  *	-f sep		Field seperator.
53  *
54  * Example:
55  *
56  *    $ elmalias -en friends | /usr/lib/elm/prlong -w40
57  *    tom@sleepy.acme.com (Tom Smith)
58  *	    dick@dopey.acme.com (Dick Jones)
59  *	    harry@grumpy.acme.com
60  *    $ elmalias -en friends | /usr/lib/elm/prlong -w40 -1 "To: " -f ", "
61  *    To: tom@sleepy.acme.com (Tom Smith),
62  *	    dick@dopey.acme.com (Dick Jones),
63  *	    harry@grumpy.acme.com
64  */
65 
66 
67 #include "elm_defs.h"
68 
69 #define MAXWID		78	/* default maximum line width		*/
70 #define ONE_LDR		""	/* default leader for first line	*/
71 #define DFLT_LDR	"\t"	/* default leader for other lines	*/
72 #define FLDSEP		" "	/* default field seperator		*/
73 
74 char inbuf[1024];		/* space to hold an input record	*/
75 char outbuf[4096];		/* space to accumulate output record	*/
76 
77 int calc_col();			/* calculate output column position	*/
78 
79 
usage_error(prog)80 void usage_error(prog)
81 char *prog;
82 {
83     fprintf(stderr,
84 	"usage: %s [-w wid] [-1 first_leader] [-l leader] [-f sep]\n", prog);
85     exit(1);
86 }
87 
88 
main(argc,argv)89 main(argc, argv)
90 int argc;
91 char *argv[];
92 {
93     char *one_ldr;		/* output leader to use on first line	*/
94     char *dflt_ldr;		/* output leader for subsequent lines	*/
95     char *fld_sep;		/* selected field seperator		*/
96     char *curr_sep;		/* text to output before next field	*/
97     int maxwid;			/* maximum output line width		*/
98     int outb_col;		/* current column pos in output rec	*/
99     int outb_len;		/* current length of output record	*/
100     int i;
101     extern int optind;
102     extern char *optarg;
103 
104     /*
105      * Initialize defaults.
106      */
107     maxwid = MAXWID;
108     one_ldr = ONE_LDR;
109     dflt_ldr = DFLT_LDR;
110     fld_sep = FLDSEP;
111 
112     /*
113      * Crack command line.
114      */
115     while ((i = getopt(argc, argv, "w:1:l:f:")) != EOF) {
116 	switch (i) {
117 	    case 'w':	maxwid = atoi(optarg);	break;
118 	    case '1':	one_ldr = optarg;	break;
119 	    case 'l':	dflt_ldr = optarg;	break;
120 	    case 'f':	fld_sep = optarg;	break;
121 	    default:	usage_error(argv[0]);
122 	}
123     }
124     if (optind != argc)
125 	usage_error(argv[0]);
126 
127     /*
128      * Initialize output buffer.
129      */
130     (void) strfcpy(outbuf, one_ldr, sizeof(outbuf));
131     outb_col = calc_col(0, one_ldr);
132     outb_len = strlen(one_ldr);
133     curr_sep = "";
134 
135     /*
136      * Process the input a line at a time.
137      */
138     while (fgets(inbuf, sizeof(inbuf), stdin) != NULL) {
139 
140 	/*
141 	 * Trim trailing space.  Skip blank lines.
142 	 */
143 	for (i = strlen(inbuf) - 1 ; i >= 0 && isspace(inbuf[i]) ; --i)
144 		;
145 	inbuf[i+1] = '\0';
146 	if (inbuf[0] == '\0')
147 		continue;
148 
149 	/*
150 	 * If this text exceeds the line length then print the stored
151 	 * info and reset the line.
152 	 */
153 	if (calc_col(calc_col(outb_col, curr_sep), inbuf) >= maxwid) {
154 	    printf("%s%s\n", outbuf, curr_sep);
155 	    curr_sep = dflt_ldr;
156 	    outb_col = 0;
157 	    outb_len = 0;
158 	    outbuf[0] = '\0';
159 	}
160 
161 	/*
162 	 * Append the current field seperator to the stored info.
163 	 */
164 	(void) strfcpy(outbuf+outb_len, curr_sep, sizeof(outbuf)-outb_len);
165 	outb_col = calc_col(outb_col, outbuf+outb_len);
166 	outb_len += strlen(outbuf+outb_len);
167 
168 	/*
169 	 * Append the text to the stored info.
170 	 */
171 	(void) strfcpy(outbuf+outb_len, inbuf, sizeof(outbuf)-outb_len);
172 	outb_col = calc_col(outb_col, outbuf+outb_len);
173 	outb_len += strlen(outbuf+outb_len);
174 
175 	/*
176 	 * Enable the field seperator.
177 	 */
178 	curr_sep = fld_sep;
179 
180     }
181 
182     if (*outbuf != '\0')
183 	puts(outbuf);
184     exit(0);
185 }
186 
187 
calc_col(col,s)188 int calc_col(col, s)
189 register int col;
190 register char *s;
191 {
192     while (*s != '\0') {
193 	switch (*s) {
194 	    case '\b':	--col;			break;
195 	    case '\r':	col = 0;		break;
196 	    case '\t':	col = ((col + 8) & ~7);	break;
197 	    default:	++col;			break;
198 	}
199 	++s;
200     }
201     return col;
202 }
203 
204