[net.sources] Tek ditroff previewer

slaney@uiucme.uiucme (11/24/85)

After numerous requests, all filled and many rebounding back.  I have decided
to post this program here.  Enclosed is a ditroff previewer for the Tektronix 
terminals 4105, 4107, 4109, 4112, 4113.  The escape codes are completely 
different from those used in tc.  Notes about it are included at the beginning 
of the program.  Please make additions to the program.  I have left lots of 
hooks for enhancements.  Please note the numerous features in the included 
library that are not used.  When done ship me off a copy.  I'll consolidate 
them.  Currently, I have not had time to put all the nifty features in.  
Theses are due Dec 16 and this program only has the features I need to preview 
my work.

This should also work with a few changes on a 4115.  The original exchange of
messages concerning this took place in net.graphics.

Thanks to moloch!tony and Phil Gross.

Oh yes, I know I'm using the term raster incorrectly. 

To make: make tk.

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


-----Cut Here-----Cut Here-----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 of program.   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 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("");
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("LT1%c",c);
X			break;
X
X		case 'C':
X			/* special character */
X			switch(getchar()){
X				case 'r':
X					if (getchar() == 'u') printf("LT1_");
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("LT1%c",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 verticle 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("");
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 -> 47788 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.  Naturally don't use it then
X   claim it.
X
X		Written by Jeff Slaney November 1985 
X				helped by Phil Gross
X*/
X
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("%%\!0");
X	else if (mode == 1)
X		printf("%%\!1");
X	else
X		printf("%%\!2");
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-360, 2/29/84, phg */
Xtext_index(text)
Xint text;
X{
X	printf("MT");
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("MC");
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("MA");
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("MF");
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("MQ");
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("MR");
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("SC");
X}
X
X
X/* Tektronix 4110 Series Command Reference, p. 7-55, 2/29/84, phg */
Xdel_segment(segment)
Xint segment;
X{
X	printf("SK");
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("SO");
X	trans_int(segment_num);
X}
X
X/* Tektronix 4110 Series Command Reference, p. 7-140, 2/29/84, phg */
Xpage()
X{
X	printf("");
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("RW");
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("LF");
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("LG");
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 -> 12641 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