[net.sources] A program to generate carriage control chars

abcscnuk@csun.UUCP (Naoto Kimura) (04/20/87)

    Here's a program I have found to be quite useful if you happen to
want to print a file on a line printer that uses carriage control
characters in column 1.  It's also useful if your printer doesn't allow
the char-backspace-char sequences to generate overstrike.  Of course,
you won't get overstrike by using this program, but the overstrike stuff
will be visible when you print it.  If you happen to have a printer that
allows you to print overstrike by sending CR without LF between lines,
this program should help, since it will separate out the
char-backspace-char into multiple lines, which then you can put a CR
between to get overstrike.  Although I am not finished with writing
this program (I haven't gotten around to writing the code that takes out
blank lines at the end of a page, or the code to take multiple blank
lines and condense it to a series of triple-space and double-space
control chars), but what I have now should still come in handy.

    For those unfamiliar with carriage control characters, they are
characters found in column 1 ( or 0 if you happen to prefer numbering
from 0 ) that are used by a printer to control spacing of lines.
Here is a list of the carriage control characters:

    1	form feed
    SP	single space
    0	double space
    -	triple space
    +	overstrike

    I should warn you about a really silly thing I've done in this
program, which I used to trick getopt into doing something that it
normally doesn't do, like accept something like -l66w80 and parse
it as - l 66 w 80, instead of - l 66w80.   What I've done will most
likely not work with all implementations of getopt.   I've marked that
part of the code with the comment /* kludgy stuff */ .  If you can
think of a better way, without writing another implementation of getopt,
please inform me.

--- cut here -------- cut here -------- cut here -------- cut here ---
#include <stdio.h>
#include <ctype.h>
#include <bool.h>

#define SH_TRUE		1
#define SH_FALSE	0

#define NEWPAGE		'1'
#define OVRSTRK		'+'
#define SNG_SPC		' '
#define DBL_SPC		'0'
#define TRP_SPC		'-'
#define TABLENGTH	8
#define PAGELENGTH	66

char	*pname;
int	tablength = TABLENGTH,
	pglength  = PAGELENGTH,
	cctrl;

usage()
{
    fprintf(stderr,"usage: %s [-t#] [ file1 [ file2 .. filen ] ]\n",
	    pname);
    fprintf(stderr,"\t-t#  -- tabstops at multiples of #\n");
    exit(SH_FALSE);
}

main(argc,argv)
int	argc;
char	**argv;
{
    extern char	*optarg;
    extern int	optind, opterr;
    FILE	*f;
    int		errflg = FALSE,
		tmp,
		c;
    char	*sp;

    pname=*argv;

    while ( (c=getopt(argc,argv,"l:t:")) != EOF )
	switch(c) {
	    case 'l':	errflg=(errflg || sscanf(optarg,"%d",&tmp)!=1 || tmp<0);
			if (! errflg) {
			    pglength = tmp;
			    while(isdigit(*optarg))	/* kludgy stuff */
				optarg++;
			    if (*optarg != '\0') {	/* kludgy stuff */
				argv[--optind]  = optarg - 1;
				argv[optind][0] = '-';
			    }
			}
			break;
	    case 't':	errflg=(errflg || sscanf(optarg,"%d",&tmp)!=1 || tmp<0);
			if (! errflg) {
			    tablength = tmp;
			    while(isdigit(*optarg))	/* kludgy stuff */
				optarg++;
			    if (*optarg != '\0') {	/* kludgy stuff */
				argv[--optind]  = optarg - 1;
				argv[optind][0] = '-';
			    }
			}
			break;
	    default:	errflg = TRUE;
			break;
	}

    argc -= optind;
    argv = &(argv[optind]);

    if (errflg)
	usage();

    if (argc==0) {
	cctrl = NEWPAGE;
	mkcc(stdin);
    } else {
	while (argc--) {
	    if ((f=fopen(*argv,"r")) == NULL) {
		fprintf(stderr,"%s: cannot open file \"%s\".\n",pname,*argv);
		exit(SH_FALSE);
	    } else {
		cctrl = NEWPAGE;
		mkcc(f);
		fclose(f);
	    }
	    argv++;
	}
    }
    exit(SH_TRUE);
}

/**********************************************************************
 *                                                                    *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

#define max(x,y)	((x)>(y) ? (x) : (y))

#define BUFCOLS	2048
#define BUFROWS	  16

static char	buffer[BUFROWS][BUFCOLS];
static int	lines,
		width[BUFROWS],
		bufc,
		bufr[BUFCOLS],
		buftouched;

mkcc(f)
FILE *f;
{
    int	c;

    initbuf();

    while ((c=getc(f))!= EOF) {
	buftouched = TRUE;
	switch(c) {
	    case '\r' :	printout();
			cctrl = OVRSTRK;
			break;
	    case '\f' :	printout();
			cctrl = NEWPAGE;
			break;
	    case '\n' :	printout();
			cctrl = SNG_SPC;
			break;
	    case '\b' :	bufc--;
			break;
	    case ' ' :	bufc++;
			break;
	    case '\t' : if (tablength > 0)
			    bufc += tablength - (bufc % tablength);
			break;
	    default:	if isprint(c)  {
			    buffer[bufr[bufc]][bufc]=c;
			    width[bufr[bufc]]
				=max(width[bufr[bufc]],bufc+1);
			    bufr[bufc]++;
			    lines=max(lines,bufr[bufc]);
			    bufc++;
			} else {
			    fprintf(stderr,
				"%s: can't handle control characters.\n",
				pname);
			    exit(SH_FALSE);
			}
			break;
	}
    }
    printout();
}

printout()
{
    int	i,
	j;

    if (buftouched) {
	putchar(cctrl);
	for (i=0; i<lines; i++) {
	    if (i)
		printf("\n%c",OVRSTRK);
	    for (j=0; j<width[i]; j++)
		if (i<bufr[j])
		    putchar(buffer[i][j]);
		else
		    putchar(' ');
	}
	initbuf();
	putchar('\n');
    }
}


initbuf()
{
    for (bufc=0; bufc<BUFCOLS; bufc++)
	bufr[bufc] = 0;
    for (lines=0; lines<BUFROWS; lines++)
        width[lines] = 0;
    bufc  = 0;
    lines = 0;
    buftouched = FALSE;
}
--- cut here -------- cut here -------- cut here -------- cut here ---
							Naoto Kimura
                //-n-\\					(csun!abcscnuk)
        _____---=======---_____
    ====____\   /.. ..\   /____====
  //         ---\__O__/---        \\	Enterprise... Surrender or we'll
  \_\                            /_/	send back your *&^$% tribbles !!!