[net.sources] Tek ditroff previewer again

slaney@uiucme.uiucme (12/05/85)

This is a reposting of the ditroff previewer made a awhile back.  The
difference with this one is that all control characters have been removed.

I was informed that when this went out all special characters were lost.  Please
excuse my ignorance and my regrets for all those who tried to run it and saw
that the checksum was off.

A quick repeat of what this program does.  tk allows any ditroff output to be
processed for Tektronix terminals 4107, 4109, 4113.  Other Tek terminals will
work but modifications are needed, either software or in viewing.  

See the actual code below for more details.

Jeff  at the University of Illinois Urbana-Champaign Mechanical Engineering
	[ihnp4,pur-ee]uiucdcs!uiucme!slaney	217)333-9044

To make "make tk".

#-------------CUT HERE---------------CUT HERE------------------------------
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	tk.c
#	tk.lib.c
#	makefile
sed 's/^X//' << 'SHAR_EOF' > tk.c
X/* Naturally when this goes "public" there is that little disclaimer about how
X   I would like my name to go with it on its adventures.  It was not written for
X   monetary gain, only as a personal convenience.  
X
X		Written by Jeff Slaney November 1985 
X				helped by Philip Gross
X*/
X
X/* man page - To get to the next page wait for the bell then hit carriage
X   return.  Same goes for the end of the program.  It will clear when finished.
X   Zoom and pan are permitted.  All pages are drawn as retained segment 1.  
X   It may also be necessary to turn off the dialog area.  This is especially
X   true on the 4112 and 4113.  Turn it back on at completion.   Also
X   if the program is killed it leaves the terminal in graphics mode.  It will
X   need to be reset.  Hopefully, there exists a proper host reset.  If not all
X   that's needed is to be in setup mode and set the code to ansi 
X   ( *code ansi).
X
X	To use: ditroff | tk  -or-   cat <file> | tk
X
X   Please feel free to make additions and corrections.  If you make 
X   changes please ship a copy off to me, ihnp4!uiucdcs!uiucme!slaney.
X*/
X
X
X/* Program to allow ditroff output to be processed on any of the following
X   Tektronix terminals:  
X			  4107, 4109, 4113.
X   The following terminals will work but for harware reasons lose certain
X   features:
X			  4105 - no retained segments, 8 colors
X			  4112 - black and white
X   This program should work on the 4111 and the 4115, however ....
X
X   The features of this program are:
X
X		complete device independence.  All output from ditroff is
X		capable of being processed independent of what device it was
X		intended for.  Naturally somethings aren't perfect.  That's why
X		this is called a previewer.  It is not intended for
X		publications purposes.  Only to give a good indication of
X		correct form.  It provides a very convenient method of checking
X		for widows at the top of pages.  
X
X		complete character point size mapping.  This exceeds some
X		previewers in capability.
X
X		font changes are enabled by changing the color and displaying
X		the ascii equivalent.
X
X		currently only line drawing.  The routine for arcs/circles is
X		in the library included but draws circles starting from the
X		right and proceeding counterclockwise.  ditroff likes it from
X		the left.  It may take some playing with.
X
X		character slant is also possible.  The tek routine is included.
X		Needs to be played with.
X
X  Areas lacking for this program are:
X		
X		spline fits
X
X		special characters other than underline
X
X		forward and reverse paging
X*/
X
X/*
Xoutput language from ditroff:
Xall numbers are character strings
X
Xsn	size in points
Xfn	font as number from 1-n
Xcx	ascii character x
XCxyz	funny char xyz. terminated by white space
XHn	go to absolute horizontal position n
XVn	go to absolute vertical position n (down is positive)
Xhn	go n units horizontally (relative)
Xvn	ditto vertically
Xnnc	move right nn, then print c (exactly 2 digits!)
X		(this wart is an optimization that shrinks output file size
X		 about 35% and run-time about 15% while preserving ascii-ness)
XDt ...\n	draw operation 't':
X	Dl x y		line from here by x,y
X	Dc d		circle of diameter d with left side here
X	De x y		ellipse of axes x,y with left side here
X	Da x y r	arc counter-clockwise by x,y of radius r
X	D~ x y x y ...	wiggly line by x,y then x,y ...
Xnb a	end of line (information only -- no action needed)
X	b = space before line, a = after
Xp	new page begins -- set v to 0
X#...\n	comment
Xx ...\n	device control functions:
X	x i	init
X	x T s	name of device is s
X	x r n h v	resolution is n/inch
X		h = min horizontal motion, v = min vert
X	x p	pause (can restart)
X	x s	stop -- done for ever
X	x t	generate trailer
X	x f n s	font position n contains font s
X	x H n	set character height to n
X	x S n	set slant to N
X
X	Subcommands like "i" are often spelled out like "init".
X*/
X
X#define TOP 3132
X#define ESC 27
X#define EOL 10
X
X#include <stdio.h>
X#include <ctype.h>
X
Xchar c;
Xint i;
Xint currentx, currenty;
Xint absx, absy;
Xint point_size, raster_size;
Xint char_width;
Xint resolution;
Xfloat rasters_per_point;
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	/* initialize */
X	currentx = 0;
X	currenty = 0;
X	rasters_per_point = .6591;  /* set initially for a phototypesetter */
X
X	/* initialize the terminal */
X		/* put in tek mode */
X		select_code(0);
X		/* set the window */
X		set_window(0,0,4095,TOP);
X		page();
X		/* set the graphtext precision to stroke */
X		graphtx_prec(2);
X
X	while ((c = getchar()) != EOF)
X		switch(c){
X
X		case 'p':
X			/* close off all open segments for next page */
X			if (ctoi() != 1) {
X				end_segment();
X				printf("%c",7);		/* signal end of page */
X				fflush(stdout);
X				readch();
X			} /* if not first page */
X			/* erase retained segments */
X			del_segment(-1);
X			page();
X			/* don't clear screen: leave dialog area alone */
X			/* open retained segment 1 */
X			begin_seg(1);
X			/* draw a line down the right margin */
X			move(2420,0);
X			draw(2420,TOP);
X			move(currentx,currenty);
X			break;
X
X		case 's':
X			/* point size */
X
X			/*  The font size is determined only by the terminal
X			being used.  The device formatted for does not enter
X			in.   A simple conversion is all that is needed.
X			72(points/inch) * 11(inches/page) = 792(points/page)
X			3132(rasters/page) * 1/792(page/points) =
X							3.95(rasters/point)
X				point size 1 = raster size 3.95
X			*/
X
X			point_size = ctoi();
X			raster_size = point_size * 3.95;
X			char_width = raster_size * .5; /* it looks good */
X			graphtx_size(char_width,raster_size,raster_size);
X			break;
X
X		case 'f':	/* font change */
X			text_index(ctoi());		/* just change color */
X			break;
X
X		case 'h':	/* relative horizontal move */
X			absx = absx + ctoi();
X			currentx = absx * rasters_per_point;
X			move(currentx,currenty);
X			break;
X
X		case 'v':	/* relative move vertical */
X			absy = absy + ctoi();
X			currenty = TOP - absy * rasters_per_point;
X			move(currentx,currenty);
X			break;
X
X		case 'H':
X			/* absolute horizontal move */
X			absx = ctoi();
X			currentx = absx * rasters_per_point;
X			move (currentx,currenty);
X			break;
X
X		case 'V':
X			/* absolute vertical */
X			absy = ctoi();
X			currenty = TOP - absy * rasters_per_point;
X			move(currentx,currenty);
X			break;
X
X		case 'c':
X			/* character */
X			/* display next character */
X			c = getchar();
X			printf("%cLT1%c",ESC,c);
X			break;
X
X		case 'C':
X			/* special character */
X			switch(getchar()){
X				case 'r':
X					if (getchar() == 'u') printf("%cLT1_",ESC);
X					break;
X				default:
X					while ((c = getchar()) != EOL );
X					break;
X			}
X			break;
X
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X			/* horizontal relative displacement */
X			absx = absx + (c - '0') * 10 + getchar() - '0';
X			currentx = absx * rasters_per_point;
X			move(currentx,currenty);
X			printf("%cLT1%c",ESC,getchar());
X			break;
X
X		case 'x':
X			c=getchar(); /* this should be a blank */
X			switch(getchar()){
X				case 'r':  /* set the resolution translation
X						factor */
X				   /* there are 3 numbers on this line.  they
X				   are (1) resolution in points per inch
X				       (2) minimum horizontal motion
X				       (3) minimum vertical motion
X				   Only concerned with the resolution in points
X				   per inch.  Call the term "resolution".
X
X				   How to determine the mapping from ANY device
X				   to the Tek terminal.
X
X		resolution(points/inch) * 11(inches/page) = (points/page)
X
X		3132(rasters/page) * (page/points) = (rasters/point)
X
X		motion of 1 point equals X rasters on the Tek.
X
X				   */
X
X				   while(isalpha(c=getchar()));
X				   resolution = ctoi();
X				   rasters_per_point = 3132.0 / (11.0 * resolution);
X				   while ((c = getchar()) != EOL );
X				       /* ignore the rest of line */
X				   break;
X
X				default:
X				/* ignore all other device control for now */
X				while ((c = getchar()) != EOL );
X				break;
X				} /* switch */
X			break;
X
X		case 'D':
X			switch(getchar()){
X				case 'l':
X					/* draw line from current to x,y */
X					move(currentx,currenty);
X					absx = absx + ctoi();
X				currentx = absx * rasters_per_point;
X					absy = absy + ctoi();
X				currenty = TOP - absy * rasters_per_point;
X					draw(currentx,currenty);
X					while ((c = getchar()) != EOL );
X					break;
X
X				default:
X					break;
X				}	/* switch */
X
X			break;
X
X		case 'n':
X			while ((c = getchar()) != EOL );
X			break;
X
X		default:
X			break;
X
X	} /* switch */
X
X/* set terminal back */
Xfflush(stdout);
Xend_segment();		/* close out segments */
Xprintf("%c",7);		/* signal at the end with a bell (control G) */
Xfflush(stdout);
Xc = readch();
Xdel_segment(-1); 	/* erase retained segments */
Xselect_code(1);		/* put in ansi mode */
X} /* tk */
X
X
Xctoi()
X{
X	int i, n , sign;
X	char s;
X
X	s = ' ';
X	for (i = 0; s == ' ' || s == '\n' || s == '\t'; i++)
X		s = getchar();	/* skip white space */
X	sign = 1;
X	if (s == '+' || s == '-') {	/* sign */
X		sign = (s == '+') ? 1 : -1;
X		s = getchar();
X	}
X	for (n = 0; s >= '0' && s <= '9'; i++){
X		n = 10 * n + s - '0';
X		s = getchar();
X	}
X	ungetc(s,stdin);
X	return(sign * n);
X}
X
X
Xreadch(){
X	char c;
X	if (read(2,&c,1)<1) c = 0;
X	return(c);
X}
SHAR_EOF
echo 'Orignal Sum -> 55137 9 tk.c'
echo 'Current Sum -> \c'
sum tk.c
sed 's/^X//' << 'SHAR_EOF' > tk.lib.c
X/* Naturally when this goes "public" there is that little disclaimer about how
X   I would like my name to go with it on its adventures.  It was not written for
X   monetary gain, only as a personal convenience.  
X
X		Written by Jeff Slaney November 1985 
X				helped by Phil Gross
X*/
X
X#define ESC 27
X
X/* Tektronix 4110 Series Command Reference, p. 7-191, 2/29/84, phg */
Xselect_code(mode)
Xint mode;
X{
X	if (mode == 0)
X		printf("%c%%\!0",ESC);
X	else if (mode == 1)
X		printf("%c%%\!1",ESC);
X	else
X		printf("%c%%\!2",ESC);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-360, 2/29/84, phg */
Xtext_index(text)
Xint text;
X{
X	printf("%cMT",ESC);
X	trans_int(text);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-276, 2/29/84, phg */
Xgraphtx_size(width, height, space)
Xint width, height, space;
X{
X	printf("%cMC",ESC);
X	trans_int(width);
X	trans_int(height);
X	trans_int(space);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-277, 2/29/84, phg */
Xgraphtx_slnt(angle)
Xfloat angle;
X{
X	printf("%cMA",ESC);
X	trans_real(angle);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-270, 2/29/84, phg */
Xgraphtx_font(font)
Xint font;
X{
X	printf("%cMF",ESC);
X	trans_int(font);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-274, 2/29/84, phg */
Xgraphtx_prec(precision)
Xint precision;
X{
X	printf("%cMQ",ESC);
X	trans_int(precision);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-275, 2/29/84, phg */
Xgraphtx_rot(angle)
Xfloat angle;
X{
X	printf("%cMR",ESC);
X	trans_real(angle);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-91, 2/29/84, phg */
Xend_segment()
X{
X	printf("%cSC",ESC);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-55, 2/29/84, phg */
Xdel_segment(segment)
Xint segment;
X{
X	printf("%cSK",ESC);
X	trans_int(segment);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-23, 2/28/84, phg */
Xbegin_seg(segment_num)
Xint segment_num;
X{
X	printf("%cSO",ESC);
X	trans_int(segment_num);
X}
X
X/* Tektronix 4110 Series Command Reference, p. 7-140, 2/29/84, phg */
Xpage()
X{
X	printf("%c%c",ESC,12);  /* ESCAPE and a CONTROL L */
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-370, 2/29/84, phg */
Xset_window(llx, lly, urx, ury)
Xint llx, lly, urx, ury;
X{
X	printf("%cRW",ESC);
X	trans_xy(llx, lly);
X	trans_xy(urx, ury);
X}
X
X
X#include <math.h>
Xfloat torads();
Xarc(x, y, r, st, sp, point)
Xint x, y, r, point;
Xfloat st, sp;
X/* x and y are the center of the circle
X * r is the radius of the arc
X * st is the starting degree angle of the arc
X * sp is the stopping degree angle of the arc
X * point is how many points along the arc are plotted
X */
X{
X	int t1, t2;
X	float k, inc;
X	t1 = x + (r * cos(torads(st)));
X	t2 = y + (r * sin(torads(st)));
X	move(t1, t2);
X	inc = (sp - st)/ point;
X	for ( k = inc; k < (sp - st); k += inc) {
X		t1 = (x + r * cos(torads(st + k)));
X		t2 = (y + r * sin(torads(st + k)));
X		draw(t1, t2);
X	}
X	t1 = (x + r * cos(torads(sp)));
X	t2 = (y + r * sin(torads(sp)));
X	draw(t1, t2);
X}
X
X/* converts degrees to radians */
Xfloat torads(coord)
Xfloat coord;
X{
X	return(3.1415962/180.0 * coord);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-137, 2/29/84, phg */
Xmove(x, y)
Xint x, y;
X{
X	printf("%cLF",ESC);
X	trans_xy(x, y);
X}
X
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-72, 2/29/84, phg */
Xdraw(x, y)
Xint x, y;
X{
X	printf("%cLG",ESC);
X	trans_xy(x, y);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-391, 2/29/84, phg */
X/* translate coords to something the tek likes */
Xtrans_xy(x, y)
Xint x, y;
X{
X	int t, arr[5];
X	arr[0] = 0040 | getbits(y, 11, 5);
X	arr[1] = 0140 | (getbits(y, 1, 2) << 2) | getbits(x, 1, 2);
X	arr[2] = 0140 | getbits(y, 6, 5);
X	arr[3] = 0040 | getbits(x, 11, 5);
X	arr[4] = 0100 | getbits(x, 6, 5);
X	for (t = 0; t <= 4; t++)
X		printf("%c", arr[t]);
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-160, 3/19/84, phg */
Xtrans_real(decimal)
Xfloat decimal;
X{
X	float epsilon = 0.00006104;
X	float temp;
X	int trunc, neg_flag, mantissa, exponent;
X	temp = decimal;
X	neg_flag = 0;
X	if (temp < 0) {
X		neg_flag = -1;
X		temp = neg_flag * temp;
X	}
X	trunc = temp / 1;
X	while ( temp > (trunc + epsilon) && trunc < 16383) {
X		temp = temp * 2.0;
X		exponent--;
X		trunc = temp / 1;
X	}
X	while (temp > 32767.0) {
X		temp = temp / 2.0;
X		exponent++;
X	}
X	mantissa = (temp + 0.5) / 1;
X	if (neg_flag == -1)
X		mantissa = -mantissa;
X	trans_int(mantissa);
X	trans_int(exponent);
X}
X
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-129, 3/19/84, phg */
X/* prints a tek translated integer */
Xtrans_int(x)
Xint x;
X{
X	int t, arr[3];
X	if ((t = getbits(x, 31, 1)) == 1) {
X		x = ~x + 0001;
X		arr[2] = 0040 | getbits(x, 3, 4);
X	}
X	else
X		arr[2] = 0060 | getbits(x, 3, 4);
X	arr[0] = 0100 | getbits(x, 15, 6);
X	arr[1] = 0100 | getbits(x, 9, 6);
X	if (arr[0] != '@') {
X		putchar(arr[0]);
X		putchar(arr[1]);
X		putchar(arr[2]);
X	}
X	else if (arr[1] != '@') {
X		putchar(arr[1]);
X		putchar(arr[2]);
X	}
X	else if (arr[2] != '@')
X		putchar(arr[2]);
X}
X
X
X
X/* This routine returns the value of n bits beginning with the p'th bit of x */
X/*
X *	t = getbits(57, 5, 3)
X *	(x = 57
X *	x = 01110111
X *	p = 5, n = 3
X *	x = 00000110
X *	x = 6)
X *	t = 6
X */
Xgetbits(x, p, n)
Xunsigned x, p, n;
X{
X	return((x >> (p+1-n)) & ~(~0 << n));
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-6, 3/19/84, phg */
X/* prints a character string after printing a count */
X#include <stdio.h>
Xchar	*rmtb;
X
Xtrans_char(string)
Xchar string[];
X{
X	int char_len;
X	int i;
X
X	rmtb = string;
X	i = strlen(string) - 1;
X	while (rmtb[i] == ' ')
X		i--;
X	rmtb[++i] = '\0';
X	trans_int(i);
X	printf("%s", rmtb);
X}
SHAR_EOF
echo 'Orignal Sum -> 18336 6 tk.lib.c'
echo 'Current Sum -> \c'
sum tk.lib.c
sed 's/^X//' << 'SHAR_EOF' > makefile
Xtkfiles: tk.c tk.lib.c
Xtkofiles: tk.o tk.lib.o
X.c.o:
X	cc -c $<
Xtk: tkofiles
X	cc -O tk.o tk.lib.o -lm -o tk
SHAR_EOF
echo 'Orignal Sum -> 8463 1 makefile'
echo 'Current Sum -> \c'
sum makefile
exit