/*
 * Multic : multi-column text formatter
 *
 *     by Joel Swank 1/3/89
 *
 */

#include <stdio.h>
#define FALSE 0
#define TRUE 1

/* page format parameters  */

/* user selected parms     */
int pagesize = 60;      /* Number of lines on a page        */
int columns = 2;        /* number of print columns          */
int linesize = 80;      /* size of output line              */
int skip = 0;           /* lines between pages, 0= do '\f'  */
int gap = 0;            /* space between columns            */

/* derived parms     */
int colsize;            /* size of each column */
int numptrs;            /* number of pointers needed */

/* stock of blanks for gap */
char blanks[] = "                                                                                                    ";
char *malloc(), *index();

char **pagebuf;        /* pointer to array of pointers for lines */

/****************************************************************/
/*         Main program starts here                             */
/****************************************************************/

main(argc,argv)
int argc;
char *argv[];
{
	int argindex;

	if (argc < 2)
		{
		usage();
		exit(1);
		}


	/* parse the command line and execute the parameters */

	argindex = 0;

	while(--argc > 0)
		{
		argindex++;
		do_parm(argv[argindex]);
		}


exit(0);
}

/*
 * do_file : process an input file
 */

do_file(filename)
char *filename;
{
	int curptr, ret, i, j, ptrsize;
	char *inbuf, *nlptr;
	FILE *in;
	int Eoflag = FALSE;

	in = fopen(filename,"r");
	if (in == NULL)
		{
		fprintf(stderr,"multic:cannot open %s\n",filename);
		exit(7);
		}

	/* calculate individual column size */
	colsize = ((linesize-(columns-1)*gap)/columns);

	inbuf = malloc(colsize+1); /* allocate the input buffer */
	if (!inbuf) memerr();

	/* allocate array of line pointers */
	numptrs = (columns-1)*pagesize;
	ptrsize = numptrs * sizeof(char *);
	if (numptrs)
		{
		pagebuf = (char **) malloc(ptrsize);
		setmem (pagebuf,ptrsize,'\0');
		}

	while (!Eoflag)	    /* do each page */
		{
		/* read in first columns-1 columns and store */
		curptr = 0;
		while (curptr < numptrs )
			{
			ret = fgets(inbuf,colsize+1,in);
			if (!ret) 
				{
				Eoflag = TRUE;
				break;
				}
			nlptr=index(inbuf,'\n');
			if (nlptr) *nlptr = '\0';
			pagebuf[curptr] = malloc(strlen(inbuf)+1);
			if (!pagebuf[curptr]) memerr();
			strcpy(pagebuf[curptr], inbuf);
			curptr++;
			}

		/* print out the page */
		for (i=0; i< pagesize; i++)     /* do each line */
			{
			for (j=0; j< columns-1; j++)   /* do each column */
				{
				curptr = i+j*pagesize;
				if (j == 0 && pagebuf[i] == NULL && skip == 0) goto filedun;
				if (pagebuf[curptr])
					{
			    	printf("%-*.*s", colsize, colsize,pagebuf[curptr]);
					free (pagebuf[curptr]);
					pagebuf[curptr] = NULL;
					if (gap) printf("%.*s",gap,blanks);
					}
				else break;
				}
			if (!Eoflag)
				{
				ret = fgets(inbuf,colsize+1,in);
				if (!ret) 
					{
					Eoflag = TRUE;
					if (columns == 1 && skip == 0) goto filedun;
					}
		    	else 
					{
					nlptr=index(inbuf,'\n');
					if (nlptr) *nlptr = '\0';
					printf("%.*s", colsize, inbuf);
					}
				}
			putchar('\n');
			}
  filedun:
		if (skip)
			for (i=0; i< skip; i++) putchar('\n');
		else putchar('\f');
		}	/* end while(!Eoflag) */

	fclose(in);
	free (inbuf);
	if (pagebuf) free (pagebuf);
}


/*
 * do_parm : process one parameter
 */

do_parm(parm)
unsigned char *parm;
{
	register int i,j;

	if (parm[0] == '-')
		{
		switch (parm[1])
			{
			case 'g':	/* set number of spaces between columns */
			  gap = atoi(&parm[2]);
			  if (gap <0 || gap > 100)
				{
			  	fprintf(stderr,"multic:Bad gap: %s\n",
				   parm);
				exit(6);
				}
			  break;
			case 's':	/* set number of lines between pages */
			  skip = atoi(&parm[2]);
			  if (skip <0 || skip > 100)
				{
			  	fprintf(stderr,"multic:Bad skip: %s\n",
				   parm);
				exit(6);
				}
			  break;
			case 'p':	/* set number of lines per page */
			  pagesize = atoi(&parm[2]);
			  if (pagesize <20 || pagesize > 500)
				{
			  	fprintf(stderr,"multic:Bad pagesize: %s\n",
				   parm);
				exit(6);
				}
			  break;
			case 'c':	/* set number of columns */
			  columns = atoi(&parm[2]);
			  if (columns <1 || columns > 9)
				{
			  	fprintf(stderr,"multic:Bad columns: %s\n",
				   parm);
				exit(6);
				}
			  break;
			case 'l':	/* set maximum line size */
			  linesize = atoi(&parm[2]);
			  if (linesize <20 || linesize > 999)
				{
			  	fprintf(stderr,"multic:Bad linesize: %s\n",
				   parm);
				exit(6);
				}
			  break;
			default:
			  fprintf(stderr,"multic:Bad flag: %s\n",parm);
			  usage();
			  exit(21);
			}	/* end switch */
	}else {
		/* not a flag, must be a filename, so print it */
		do_file(parm);
		}
}

/*
 * exit for lack of memory.
 */

memerr()
{
	fprintf(stderr,"Multic: Ran out of memory\n");
	exit(10);
}

usage()
{
fprintf(stderr,"Usage: multic: [[-cn] [-ln] [-pn] [-sn] [-gn] file ...] ...\n");
fprintf(stderr,"Format file into multiple columns - args:\n");
fprintf(stderr,"-cn   Format into n column output\n");
fprintf(stderr,"-ln   Output line is n chatacters\n");
fprintf(stderr,"-pn   Output page is n lines long\n");
fprintf(stderr,"-sn   Skip n lines between pages\n");
fprintf(stderr,"-gn   Skip n spaces between columns\n");
}
