#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <io.h>
//#include <process.h>
//#include <dir.h>
/* Documentation
This utility will format any list into a column based output.
The original order of the list will be kept and each column will
follow the previous column in that order. That is, the order of the
columns will be such that if the second column were added to the
bottom of the first column, the order of the the items in the newly
formed column would match the original order of the input items.
The default number of columns is three, and columns are always
seperated by at least one space.
the options are as follows :
-w<N> sets the width of the page to N characters, 80 is the default.
-m tells the program to use as many columns as will fit on the page
without losing any information ( m stands for "maximize" )
-n<N> tells the program to use N columns. If this is used with
the "-m" option, the -m option will override this option. If
the "-m" option is not used with this option, any entries which
are longer than the columns are wide will be truncated to fit.
The default number of columns is three.
If a filename is not given on the command line, then a single dash
as in "-" must be given to indicate that the input should be read from
standard input, however if no dash("-") is given and no filename
is given, the program will assume that it should read from standard
input.
There is a maximum of 200 columns, however, the real limit on columns
is the number of files which may be opened at the same time.
*/
#define TRUE 1
#define FALSE 0
int countlines(char *);
void showhelp(void);
int g_cmin; /* the minimum width the columns must be in order to not truncate any entries. set in countlines. */
int gcols; /* number of columns asked for by the "-n" option. */
int g_max; /* used as a boolean, set to TRUE IFF the "-m" option is used */
int g_width; /* the width of the page, set by the "-w" option, default is 80*/
int usestdin; /* used as a boolean, tells if reading from stdin or a file */
main( int argc, char **argv)
{
char filename[200];
int K;
char line[200];
FILE * col[200];
int i,j,n; /* ubiquitous counting variables */
int maxwidth; /* contains the calculated width if the columns */
char temp[200];
char format[20];
char *tname;
char **args;
g_max = FALSE; /* initialize default values */
gcols = 3;
g_width = 80;
usestdin = TRUE;
args = argv; /* done only to defeat Borlands
"code has no effect" warning */
if ( argc == 1 ) {
printf("%s%s%s",
"Usage : columns [-w<N>] [-n<N>] [-m] <[-]|[filename]>\n",
"OR - \n",
"columns -? OR columns -h OR columns -H will give a help page.\n");
exit(1);
}
/*
This option checking has some holes in it, for example, does not
prevent the user from using two mutually exclusive options
( such as read from stdin and a filename at the same time ) results
will be unpredictable, although generally the last option set will
override the other.
*/
*args++;
while ( *args != NULL ) {
if ( (strncmp("-w",*args,2)) == 0 ) {
strcpy(temp,*args++);
g_width = atoi(&(temp[2]));
} else if ( ( strcmp("-m",*args) ) == 0 ) {
g_max = TRUE;
*args++;
} else if ( (strncmp("-n", *args,2)) == 0 ) {
strcpy(temp,*args++);
gcols = atoi(&(temp[2]));
} else if ( (strcmp("-",*args)) == 0 ) {
usestdin = TRUE;
tname = mktemp("tmpXXXXXX");
strcpy(filename,tname);
*args++;
} else if ( (strcmp("-?",*args)) == 0 ) {
showhelp();
*args++;
} else if ( (strcmp("-h",*args)) == 0 ) {
showhelp();
*args++;
} else if ( (strcmp("-H",*args)) == 0 ) {
showhelp();
*args++;
} else if ( (strcmp("-U",*args)) == 0 ) {
showhelp();
*args++;
} else if ( (strcmp("-u",*args)) == 0 ) {
showhelp();
*args++;
} else {
strcpy(filename,*args++);
usestdin = FALSE;
}
}
/*
*determine the number of lines in the input, and set the g_cmin global
*/
K = countlines(filename);
/*
*determine width and number of columns
*/
if ( g_max == TRUE ) { /* maximize the # of columns */
gcols = ((g_width ) / g_cmin );
maxwidth = g_cmin;
while ( ((maxwidth * gcols) + (gcols-1)) < g_width ) {
maxwidth += 1;
}
} else { /* just use the asked for number of columns */
/* determine the width of the columns */
/* divide the width of the page by the number of columns*/
maxwidth = g_width / gcols;
/* add room for a single space between each column */
/* ( make the columns narrower ) */
while ((gcols * maxwidth + (gcols - 1)) > g_width) maxwidth --;
}
/* determin how many lines in each column */
/* divide the number of lines by the number of columns */
if ( (K % gcols) == 0 ) {
K = K / gcols;
} else {
K = (K / gcols) +1;
}
for ( i = 0; i < gcols; i++ ) {
if ( (col[i] = fopen(filename,"rt")) == NULL ) {
printf("Unable to open file descriptor for col %d.\n",i);
exit(1);
}
/* space each file descriptor in to the head of its column*/
for ( j = 0; j < ( K * i ); j++ ) fgets(line,200,col[i]);
}
printf("\n\n\n\n\n\n"); /* a few blank lines at top of first page */
sprintf(format,"%%-%ds",maxwidth);
for ( i = 0; i < K; i++ ) {
for ( j = 0; j < gcols ; j++ ) {
line[0] = NULL;
fgets(line,200,col[j]);
line[(strlen(line))-1] = NULL; /* remove trailing \n */
/* if the length of this string exceeds maxwidth,
truncate it */
/* remove trailing blanks */
for (n = (strlen(line) -2); ((n > 0)&&(line[n] == ' ')); n--) {
line[n] = NULL;
}
if ( (strlen(line)) > maxwidth ) {
line[maxwidth-1] = NULL;
}
printf(format,line);
}
printf("\n");
}
for ( i = 0; i < gcols; i++ ) {
fclose (col[i]);
}
if ( usestdin == TRUE ) {
if ( (unlink(filename)) != 0 ) {
printf("Error : unable to delete temp file %s.\n",
filename);
}
}
return(0);
}
int countlines(char *name)
{
int i;
int n;
char line[200];
FILE *fin; /* file descriptor to read IN on - fIN */
FILE *fout; /* file descriptor to write OUT on - fOUT */
n = 0;
g_cmin = 0;
/* if we are reading from stdin, then set fin to stream 0 and */
/* open a temp file to save the text in */
if ( usestdin == TRUE ) {
fin = fdopen(0,"rt");
if ( fin == NULL ) {
printf("Unable to open standard input for reading.\n");
exit(1);
}
if ( ( fout = fopen(name,"wt") ) == NULL ) {
printf("unable to open %s to save text.\n",name);
exit(1);
}
} else {
if ( ( fin = fopen(name,"rt") ) == NULL ) {
printf("unable to open %s to count lines.\n",name);
exit(1);
}
}
while ( ( fgets(line,200,fin)) != NULL ) {
/* remove trailing blanks */
for (i = (strlen(line) -2); ((i > 0)&&(line[i] == ' ')); i--) {
line[i] = NULL;
}
if ( ( strlen(line) ) > g_cmin ) {
g_cmin = strlen(line);
}
if ( (line[strlen(line)-1]) == '\n' ) {
line[strlen(line)-1] = NULL;
}
if ( usestdin == TRUE ) {
fprintf(fout,"%s\n",line);
}
n++;
}
fclose(fout);
fclose(fin);
return(n);
}
void showhelp(void)
{
printf("\n");
printf(" Documentation for the columns program\n");
printf("\n");
printf("\n");
printf(" This utility will format any list into a column based output.\n");
printf(" The original order of the list will be kept and each column will \n");
printf(" follow the previous column in that order. That is, the order of the\n");
printf(" columns will be such that if the second column were added to the \n");
printf(" bottom of the first column, the order of the the items in the newly\n");
printf(" formed column would match the original order of the input items.\n");
printf(" The default number of columns is three, and columns are always \n");
printf(" seperated by at least one space.\n");
printf("\n");
printf(" the options are as follows :\n");
printf(" -w<N> sets the width of the page to N characters, 80 is the default.\n");
printf("\n");
printf(" -m tells the program to use as many columns as will fit on the page\n");
printf(" without losing any information ( m stands for 'maximize' )\n");
printf("\n");
printf(" -n<N> tells the program to use N columns. If this is used with \n");
printf(" the \"-m\" option, the -m option will override this option. If\n");
printf(" the \"-m\" option is not used with this option, any entries which\n");
printf(" are longer than the columns are wide will be truncated to fit.\n");
printf(" The default number of columns is three.\n");
printf("\n");
printf(" If a filename is not given on the command line, then a single dash\n");
printf(" as in \"-\" must be given to indicate that the input should be read from\n");
printf(" standard input, however if no dash(\"-\") is given and no filename\n");
printf(" is given, the program will assume that it should read from standard\n");
printf(" input.\n");
printf("\n");
printf(" There is a maximum of 200 columns, however, the real limit on columns \n");
printf(" is the number of files which may be opened at the same time.\n");
printf("\n");
printf(" to print a list on epson fx-286 in condesned mode use :\n");
printf(" columns -w140 -m listfile\n");
}