xref: /plan9/sys/src/cmd/spin/ps_msc.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** spin: ps_msc.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier /* The Postscript generation code below was written by Gerard J. Holzmann */
137dd7cddfSDavid du Colombier /* in June 1997. Parts of the prolog template are based on similar boiler */
147dd7cddfSDavid du Colombier /* plate in the Tcl/Tk distribution. This code is used to support Spin's  */
15*00d97012SDavid du Colombier /* option -M for generating a Postscript file from a simulation run.      */
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier #include "spin.h"
187dd7cddfSDavid du Colombier #include "version.h"
197dd7cddfSDavid du Colombier 
20*00d97012SDavid du Colombier /* extern void free(void *); */
21312a1df1SDavid du Colombier 
227dd7cddfSDavid du Colombier static char *PsPre[] = {
237dd7cddfSDavid du Colombier 	"%%%%Pages: (atend)",
247dd7cddfSDavid du Colombier 	"%%%%PageOrder: Ascend",
257dd7cddfSDavid du Colombier 	"%%%%DocumentData: Clean7Bit",
267dd7cddfSDavid du Colombier 	"%%%%Orientation: Portrait",
277dd7cddfSDavid du Colombier 	"%%%%DocumentNeededResources: font Courier-Bold",
287dd7cddfSDavid du Colombier 	"%%%%EndComments",
297dd7cddfSDavid du Colombier 	"",
307dd7cddfSDavid du Colombier 	"%%%%BeginProlog",
317dd7cddfSDavid du Colombier 	"50 dict begin",
327dd7cddfSDavid du Colombier 	"",
337dd7cddfSDavid du Colombier 	"/baseline 0 def",
347dd7cddfSDavid du Colombier 	"/height 0 def",
357dd7cddfSDavid du Colombier 	"/justify 0 def",
367dd7cddfSDavid du Colombier 	"/lineLength 0 def",
377dd7cddfSDavid du Colombier 	"/spacing 0 def",
387dd7cddfSDavid du Colombier 	"/stipple 0 def",
397dd7cddfSDavid du Colombier 	"/strings 0 def",
407dd7cddfSDavid du Colombier 	"/xoffset 0 def",
417dd7cddfSDavid du Colombier 	"/yoffset 0 def",
427dd7cddfSDavid du Colombier 	"",
437dd7cddfSDavid du Colombier 	"/ISOEncode {",
447dd7cddfSDavid du Colombier 	"    dup length dict begin",
457dd7cddfSDavid du Colombier 	"	{1 index /FID ne {def} {pop pop} ifelse} forall",
467dd7cddfSDavid du Colombier 	"	/Encoding ISOLatin1Encoding def",
477dd7cddfSDavid du Colombier 	"	currentdict",
487dd7cddfSDavid du Colombier 	"    end",
497dd7cddfSDavid du Colombier 	"    /Temporary exch definefont",
507dd7cddfSDavid du Colombier 	"} bind def",
517dd7cddfSDavid du Colombier 	"",
527dd7cddfSDavid du Colombier 	"/AdjustColor {",
537dd7cddfSDavid du Colombier 	"    CL 2 lt {",
547dd7cddfSDavid du Colombier 	"	currentgray",
557dd7cddfSDavid du Colombier 	"	CL 0 eq {",
567dd7cddfSDavid du Colombier 	"	    .5 lt {0} {1} ifelse",
577dd7cddfSDavid du Colombier 	"	} if",
587dd7cddfSDavid du Colombier 	"	setgray",
597dd7cddfSDavid du Colombier 	"    } if",
607dd7cddfSDavid du Colombier 	"} bind def",
617dd7cddfSDavid du Colombier 	"",
627dd7cddfSDavid du Colombier 	"/DrawText {",
637dd7cddfSDavid du Colombier 	"    /stipple exch def",
647dd7cddfSDavid du Colombier 	"    /justify exch def",
657dd7cddfSDavid du Colombier 	"    /yoffset exch def",
667dd7cddfSDavid du Colombier 	"    /xoffset exch def",
677dd7cddfSDavid du Colombier 	"    /spacing exch def",
687dd7cddfSDavid du Colombier 	"    /strings exch def",
697dd7cddfSDavid du Colombier 	"    /lineLength 0 def",
707dd7cddfSDavid du Colombier 	"    strings {",
717dd7cddfSDavid du Colombier 	"	stringwidth pop",
727dd7cddfSDavid du Colombier 	"	dup lineLength gt {/lineLength exch def} {pop} ifelse",
737dd7cddfSDavid du Colombier 	"	newpath",
747dd7cddfSDavid du Colombier 	"    } forall",
757dd7cddfSDavid du Colombier 	"    0 0 moveto (TXygqPZ) false charpath",
767dd7cddfSDavid du Colombier 	"    pathbbox dup /baseline exch def",
777dd7cddfSDavid du Colombier 	"    exch pop exch sub /height exch def pop",
787dd7cddfSDavid du Colombier 	"    newpath",
797dd7cddfSDavid du Colombier 	"    translate",
807dd7cddfSDavid du Colombier 	"    lineLength xoffset mul",
817dd7cddfSDavid du Colombier 	"    strings length 1 sub spacing mul height add yoffset mul translate",
827dd7cddfSDavid du Colombier 	"    justify lineLength mul baseline neg translate",
837dd7cddfSDavid du Colombier 	"    strings {",
847dd7cddfSDavid du Colombier 	"	dup stringwidth pop",
857dd7cddfSDavid du Colombier 	"	justify neg mul 0 moveto",
867dd7cddfSDavid du Colombier 	"	stipple {",
877dd7cddfSDavid du Colombier 	"	    gsave",
887dd7cddfSDavid du Colombier 	"	    /char (X) def",
897dd7cddfSDavid du Colombier 	"	    {",
907dd7cddfSDavid du Colombier 	"		char 0 3 -1 roll put",
917dd7cddfSDavid du Colombier 	"		currentpoint",
927dd7cddfSDavid du Colombier 	"		gsave",
937dd7cddfSDavid du Colombier 	"		char true charpath clip StippleText",
947dd7cddfSDavid du Colombier 	"		grestore",
957dd7cddfSDavid du Colombier 	"		char stringwidth translate",
967dd7cddfSDavid du Colombier 	"		moveto",
977dd7cddfSDavid du Colombier 	"	    } forall",
987dd7cddfSDavid du Colombier 	"	    grestore",
997dd7cddfSDavid du Colombier 	"	} {show} ifelse",
1007dd7cddfSDavid du Colombier 	"	0 spacing neg translate",
1017dd7cddfSDavid du Colombier 	"    } forall",
1027dd7cddfSDavid du Colombier 	"} bind def",
1037dd7cddfSDavid du Colombier 	"%%%%EndProlog",
1047dd7cddfSDavid du Colombier 	"%%%%BeginSetup",
1057dd7cddfSDavid du Colombier 	"/CL 2 def",
1067dd7cddfSDavid du Colombier 	"%%%%IncludeResource: font Courier-Bold",
1077dd7cddfSDavid du Colombier 	"%%%%EndSetup",
1087dd7cddfSDavid du Colombier 	0,
1097dd7cddfSDavid du Colombier };
1107dd7cddfSDavid du Colombier 
111*00d97012SDavid du Colombier static int MH  = 600;	/* page height - can be scaled */
112*00d97012SDavid du Colombier static int oMH = 600;	/* page height - not scaled */
1137dd7cddfSDavid du Colombier #define MW	500	/* page width */
1147dd7cddfSDavid du Colombier #define LH	100	/* bottom margin */
1157dd7cddfSDavid du Colombier #define RH	100	/* right margin */
1167dd7cddfSDavid du Colombier #define WW	 50	/* distance between process lines */
1177dd7cddfSDavid du Colombier #define HH	  8	/* vertical distance between steps */
1187dd7cddfSDavid du Colombier #define PH	 14	/* height of process-tag headers */
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier static FILE	*pfd;
1217dd7cddfSDavid du Colombier static char	**I;		/* initial procs */
1227dd7cddfSDavid du Colombier static int	*D,*R;		/* maps between depth and ldepth */
1237dd7cddfSDavid du Colombier static short	*M;		/* x location of each box at index y */
1247dd7cddfSDavid du Colombier static short	*T;		/* y index of match for each box at index y */
1257dd7cddfSDavid du Colombier static char	**L;		/* text labels */
1267dd7cddfSDavid du Colombier static char	*ProcLine;	/* active processes */
1277dd7cddfSDavid du Colombier static int	pspno = 0;	/* postscript page */
1287dd7cddfSDavid du Colombier static int	ldepth = 1;
129312a1df1SDavid du Colombier static int	maxx, TotSteps = 2*4096; /* max nr of steps, about 40 pages */
1307dd7cddfSDavid du Colombier static float	Scaler = (float) 1.0;
1317dd7cddfSDavid du Colombier 
132312a1df1SDavid du Colombier extern int	ntrail, s_trail, pno, depth;
1337dd7cddfSDavid du Colombier extern Symbol	*oFname;
1347dd7cddfSDavid du Colombier extern void	exit(int);
1357dd7cddfSDavid du Colombier void putpages(void);
1367dd7cddfSDavid du Colombier void spitbox(int, int, int, char *);
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier void
putlegend(void)1397dd7cddfSDavid du Colombier putlegend(void)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier 	fprintf(pfd, "gsave\n");
1427dd7cddfSDavid du Colombier 	fprintf(pfd, "/Courier-Bold findfont 8 scalefont ");
1437dd7cddfSDavid du Colombier 	fprintf(pfd, "ISOEncode setfont\n");
1447dd7cddfSDavid du Colombier 	fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
1457dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d [\n", MW/2, LH+oMH+ 5*HH);
1467dd7cddfSDavid du Colombier 	fprintf(pfd, "    (%s -- %s -- MSC -- %d)\n] 10 -0.5 0.5 0 ",
147*00d97012SDavid du Colombier 		SpinVersion, oFname?oFname->name:"", pspno);
1487dd7cddfSDavid du Colombier 	fprintf(pfd, "false DrawText\ngrestore\n");
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier 
1517dd7cddfSDavid du Colombier void
startpage(void)1527dd7cddfSDavid du Colombier startpage(void)
1537dd7cddfSDavid du Colombier {	int i;
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 	pspno++;
1567dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%Page: %d %d\n", pspno, pspno);
1577dd7cddfSDavid du Colombier 	putlegend();
1587dd7cddfSDavid du Colombier 
159312a1df1SDavid du Colombier 	for (i = TotSteps-1; i >= 0; i--)
1607dd7cddfSDavid du Colombier 	{	if (!I[i]) continue;
1617dd7cddfSDavid du Colombier 		spitbox(i, RH, -PH, I[i]);
1627dd7cddfSDavid du Colombier 	}
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier 	fprintf(pfd, "save\n");
1657dd7cddfSDavid du Colombier 	fprintf(pfd, "10 %d moveto\n", LH+oMH+5);
1667dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH+oMH+5);
1677dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH);
1687dd7cddfSDavid du Colombier 	fprintf(pfd, "10 %d lineto\n", LH);
1697dd7cddfSDavid du Colombier 	fprintf(pfd, "closepath clip newpath\n");
1707dd7cddfSDavid du Colombier 	fprintf(pfd, "%f %f translate\n",
1717dd7cddfSDavid du Colombier 		(float) RH, (float) LH);
1727dd7cddfSDavid du Colombier 	memset(ProcLine, 0, 256*sizeof(char));
1737dd7cddfSDavid du Colombier 	if (Scaler != 1.0)
1747dd7cddfSDavid du Colombier 		fprintf(pfd, "%f %f scale\n", Scaler, Scaler);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier void
putprelude(void)1787dd7cddfSDavid du Colombier putprelude(void)
1797dd7cddfSDavid du Colombier {	char snap[256]; FILE *fd;
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier 	sprintf(snap, "%s.ps", oFname?oFname->name:"msc");
182*00d97012SDavid du Colombier 	if (!(pfd = fopen(snap, MFLAGS)))
1837dd7cddfSDavid du Colombier 		fatal("cannot create file '%s'", snap);
1847dd7cddfSDavid du Colombier 
1857dd7cddfSDavid du Colombier 	fprintf(pfd, "%%!PS-Adobe-2.0\n");
186*00d97012SDavid du Colombier 	fprintf(pfd, "%%%%Creator: %s\n", SpinVersion);
1877dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%Title: MSC %s\n", oFname?oFname->name:"--");
1887dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%BoundingBox: 119 154 494 638\n");
1897dd7cddfSDavid du Colombier 	ntimes(pfd, 0, 1, PsPre);
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier 	if (s_trail)
1927dd7cddfSDavid du Colombier 	{	if (ntrail)
193312a1df1SDavid du Colombier 		sprintf(snap, "%s%d.trail", oFname?oFname->name:"msc", ntrail);
1947dd7cddfSDavid du Colombier 		else
195312a1df1SDavid du Colombier 		sprintf(snap, "%s.trail", oFname?oFname->name:"msc");
1967dd7cddfSDavid du Colombier 		if (!(fd = fopen(snap, "r")))
1977dd7cddfSDavid du Colombier 		{	snap[strlen(snap)-2] = '\0';
1987dd7cddfSDavid du Colombier 			if (!(fd = fopen(snap, "r")))
1997dd7cddfSDavid du Colombier 				fatal("cannot open trail file", (char *) 0);
2007dd7cddfSDavid du Colombier 		}
2017dd7cddfSDavid du Colombier 		TotSteps = 1;
2027dd7cddfSDavid du Colombier 		while (fgets(snap, 256, fd)) TotSteps++;
2037dd7cddfSDavid du Colombier 		fclose(fd);
2047dd7cddfSDavid du Colombier 	}
205*00d97012SDavid du Colombier 	TotSteps += 10;
2067dd7cddfSDavid du Colombier 	R = (int   *) emalloc(TotSteps * sizeof(int));
2077dd7cddfSDavid du Colombier 	D = (int   *) emalloc(TotSteps * sizeof(int));
2087dd7cddfSDavid du Colombier 	M = (short *) emalloc(TotSteps * sizeof(short));
2097dd7cddfSDavid du Colombier 	T = (short *) emalloc(TotSteps * sizeof(short));
2107dd7cddfSDavid du Colombier 	L = (char **) emalloc(TotSteps * sizeof(char *));
211312a1df1SDavid du Colombier 	I = (char **) emalloc(TotSteps * sizeof(char *));
212312a1df1SDavid du Colombier 	ProcLine = (char *) emalloc(1024 * sizeof(char));
2137dd7cddfSDavid du Colombier 	startpage();
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier void
putpostlude(void)2177dd7cddfSDavid du Colombier putpostlude(void)
2187dd7cddfSDavid du Colombier {	putpages();
2197dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%Trailer\n");
2207dd7cddfSDavid du Colombier 	fprintf(pfd, "end\n");
2217dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%Pages: %d\n", pspno);
2227dd7cddfSDavid du Colombier 	fprintf(pfd, "%%%%EOF\n");
2237dd7cddfSDavid du Colombier 	fclose(pfd);
2247dd7cddfSDavid du Colombier 	/* stderr, in case user redirected output */
2257dd7cddfSDavid du Colombier 	fprintf(stderr, "spin: wrote %d pages into '%s.ps'\n",
2267dd7cddfSDavid du Colombier 		pspno, oFname?oFname->name:"msc");
2277dd7cddfSDavid du Colombier 	exit(0);
2287dd7cddfSDavid du Colombier }
229*00d97012SDavid du Colombier 
2307dd7cddfSDavid du Colombier void
psline(int x0,int iy0,int x1,int iy1,float r,float g,float b,int w)2317dd7cddfSDavid du Colombier psline(int x0, int iy0, int x1, int iy1, float r, float g, float b, int w)
232312a1df1SDavid du Colombier {	int y0 = MH-iy0;
2337dd7cddfSDavid du Colombier 	int y1 = MH-iy1;
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier 	if (y1 > y0) y1 -= MH;
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier 	fprintf(pfd, "gsave\n");
2387dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d moveto\n", x0*WW, y0);
2397dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", x1*WW, y1);
2407dd7cddfSDavid du Colombier 	fprintf(pfd, "%d setlinewidth\n", w);
2417dd7cddfSDavid du Colombier 	fprintf(pfd, "0 setlinecap\n");
2427dd7cddfSDavid du Colombier 	fprintf(pfd, "1 setlinejoin\n");
2437dd7cddfSDavid du Colombier 	fprintf(pfd, "%f %f %f setrgbcolor AdjustColor\n", r,g,b);
2447dd7cddfSDavid du Colombier 	fprintf(pfd, "stroke\ngrestore\n");
2457dd7cddfSDavid du Colombier }
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier void
colbox(int x,int y,int w,int h,float r,float g,float b)2487dd7cddfSDavid du Colombier colbox(int x, int y, int w, int h, float r, float g, float b)
2497dd7cddfSDavid du Colombier {	fprintf(pfd, "%d %d moveto\n", x - w, y-h);
2507dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", x + w, y-h);
2517dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", x + w, y+h);
2527dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", x - w, y+h);
2537dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", x - w, y-h);
2547dd7cddfSDavid du Colombier 	fprintf(pfd, "%f %f %f setrgbcolor AdjustColor\n", r,g,b);
2557dd7cddfSDavid du Colombier 	fprintf(pfd, "closepath fill\n");
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier void
putgrid(int p)2597dd7cddfSDavid du Colombier putgrid(int p)
2607dd7cddfSDavid du Colombier {	int i;
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier 	for (i = p ; i >= 0; i--)
263*00d97012SDavid du Colombier 	{	if (!ProcLine[i])
264*00d97012SDavid du Colombier 		{	psline(i, 0, i, MH-1, (float) (0.4), (float) (0.4), (float) (1.0), 1);
2657dd7cddfSDavid du Colombier 			ProcLine[i] = 1;
266*00d97012SDavid du Colombier 	}	}
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier void
putarrow(int from,int to)270312a1df1SDavid du Colombier putarrow(int from, int to)
271312a1df1SDavid du Colombier {
272312a1df1SDavid du Colombier 	T[D[from]] = D[to];
273312a1df1SDavid du Colombier }
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier void
stepnumber(int i)2767dd7cddfSDavid du Colombier stepnumber(int i)
2777dd7cddfSDavid du Colombier {	int y = MH-(i*HH)%MH;
2787dd7cddfSDavid du Colombier 
2797dd7cddfSDavid du Colombier 	fprintf(pfd, "gsave\n");
2807dd7cddfSDavid du Colombier 	fprintf(pfd, "/Courier-Bold findfont 6 scalefont ");
2817dd7cddfSDavid du Colombier 	fprintf(pfd, "ISOEncode setfont\n");
2827dd7cddfSDavid du Colombier 	fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
2837dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d [\n", -40, y);
2847dd7cddfSDavid du Colombier 	fprintf(pfd, "    (%d)\n] 10 -0.5 0.5 0 ", R[i]);
2857dd7cddfSDavid du Colombier 	fprintf(pfd, "false DrawText\ngrestore\n");
2867dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d moveto\n", -20, y);
2877dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d lineto\n", M[i]*WW, y);
2887dd7cddfSDavid du Colombier 	fprintf(pfd, "1 setlinewidth\n0 setlinecap\n1 setlinejoin\n");
2897dd7cddfSDavid du Colombier 	fprintf(pfd, "0.92 0.92 0.92 setrgbcolor AdjustColor\n");
2907dd7cddfSDavid du Colombier 	fprintf(pfd, "stroke\n");
2917dd7cddfSDavid du Colombier }
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier void
spitbox(int x,int dx,int y,char * s)2947dd7cddfSDavid du Colombier spitbox(int x, int dx, int y, char *s)
2957dd7cddfSDavid du Colombier {	float r,g,b, bw; int a; char d[256];
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	if (!dx)
2987dd7cddfSDavid du Colombier 	{	stepnumber(y);
2997dd7cddfSDavid du Colombier 		putgrid(x);
3007dd7cddfSDavid du Colombier 	}
3017dd7cddfSDavid du Colombier 	bw = (float)2.7*(float)strlen(s);
3027dd7cddfSDavid du Colombier 	colbox(x*WW+dx, MH-(y*HH)%MH, (int) (bw+1.0),
3037dd7cddfSDavid du Colombier 		5, (float) 0.,(float) 0.,(float) 0.);
3047dd7cddfSDavid du Colombier 	if (s[0] == '~')
3057dd7cddfSDavid du Colombier 	{	switch (s[1]) {
3067dd7cddfSDavid du Colombier 		case 'B': r = (float) 0.2; g = (float) 0.2; b = (float) 1.;
3077dd7cddfSDavid du Colombier 			  break;
3087dd7cddfSDavid du Colombier 		case 'G': r = (float) 0.2; g = (float) 1.; b = (float) 0.2;
3097dd7cddfSDavid du Colombier 			  break;
3107dd7cddfSDavid du Colombier 		case 'R':
3117dd7cddfSDavid du Colombier 		default : r = (float) 1.; g = (float) 0.2; b = (float) 0.2;
3127dd7cddfSDavid du Colombier 			  break;
3137dd7cddfSDavid du Colombier 		}
3147dd7cddfSDavid du Colombier 		s += 2;
3157dd7cddfSDavid du Colombier 	} else if (strchr(s, '!'))
3167dd7cddfSDavid du Colombier 	{	r = (float) 1.; g = (float) 1.; b = (float) 1.;
3177dd7cddfSDavid du Colombier 	} else if (strchr(s, '?'))
3187dd7cddfSDavid du Colombier 	{	r = (float) 0.; g = (float) 1.; b = (float) 1.;
3197dd7cddfSDavid du Colombier 	} else
3207dd7cddfSDavid du Colombier 	{	r = (float) 1.; g = (float) 1.; b = (float) 0.;
3217dd7cddfSDavid du Colombier 		if (!dx
322*00d97012SDavid du Colombier 		&&  sscanf(s, "%d:%250s", &a, d) == 2	/* was &d */
323312a1df1SDavid du Colombier 		&&  a >= 0 && a < TotSteps)
3247dd7cddfSDavid du Colombier 		{	if (!I[a]
3257dd7cddfSDavid du Colombier 			||  strlen(I[a]) <= strlen(s))
326312a1df1SDavid du Colombier 				I[a] = emalloc((int) strlen(s)+1);
3277dd7cddfSDavid du Colombier 			strcpy(I[a], s);
3287dd7cddfSDavid du Colombier 	}	}
3297dd7cddfSDavid du Colombier 	colbox(x*WW+dx, MH-(y*HH)%MH, (int) bw, 4, r,g,b);
3307dd7cddfSDavid du Colombier 	fprintf(pfd, "gsave\n");
3317dd7cddfSDavid du Colombier 	fprintf(pfd, "/Courier-Bold findfont 8 scalefont ");
3327dd7cddfSDavid du Colombier 	fprintf(pfd, "ISOEncode setfont\n");
3337dd7cddfSDavid du Colombier 	fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
3347dd7cddfSDavid du Colombier 	fprintf(pfd, "%d %d [\n", x*WW+dx, MH-(y*HH)%MH);
3357dd7cddfSDavid du Colombier 	fprintf(pfd, "    (%s)\n] 10 -0.5 0.5 0 ", s);
3367dd7cddfSDavid du Colombier 	fprintf(pfd, "false DrawText\ngrestore\n");
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier 
3397dd7cddfSDavid du Colombier void
putpages(void)3407dd7cddfSDavid du Colombier putpages(void)
3417dd7cddfSDavid du Colombier {	int i, lasti=0; float nmh;
3427dd7cddfSDavid du Colombier 
3437dd7cddfSDavid du Colombier 	if (maxx*WW > MW-RH/2)
3447dd7cddfSDavid du Colombier 	{	Scaler = (float) (MW-RH/2) / (float) (maxx*WW);
3457dd7cddfSDavid du Colombier 		fprintf(pfd, "%f %f scale\n", Scaler, Scaler);
3467dd7cddfSDavid du Colombier 		nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
3477dd7cddfSDavid du Colombier 	}
3487dd7cddfSDavid du Colombier 
349312a1df1SDavid du Colombier 	for (i = TotSteps-1; i >= 0; i--)
3507dd7cddfSDavid du Colombier 	{	if (!I[i]) continue;
3517dd7cddfSDavid du Colombier 		spitbox(i, 0, 0, I[i]);
3527dd7cddfSDavid du Colombier 	}
3537dd7cddfSDavid du Colombier 	if (ldepth >= TotSteps) ldepth = TotSteps-1;
3547dd7cddfSDavid du Colombier 	for (i = 0; i <= ldepth; i++)
3557dd7cddfSDavid du Colombier 	{	if (!M[i] && !L[i]) continue;	/* no box here */
3567dd7cddfSDavid du Colombier 		if (6+i*HH >= MH*pspno)
3577dd7cddfSDavid du Colombier 		{ fprintf(pfd, "showpage\nrestore\n"); startpage(); }
3587dd7cddfSDavid du Colombier 		if (T[i] > 0)	/* red arrow */
3597dd7cddfSDavid du Colombier 		{	int reali = i*HH;
3607dd7cddfSDavid du Colombier 			int realt = T[i]*HH;
3617dd7cddfSDavid du Colombier 			int topop = (reali)/MH; topop *= MH;
3627dd7cddfSDavid du Colombier 			reali -= topop;  realt -= topop;
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier 			if (M[i] == M[T[i]] && reali == realt)
3657dd7cddfSDavid du Colombier 				/* an rv handshake */
3667dd7cddfSDavid du Colombier 				psline( M[lasti], reali+2-3*HH/2,
3677dd7cddfSDavid du Colombier 					M[i], reali,
3687dd7cddfSDavid du Colombier 					(float) 1.,(float) 0.,(float) 0., 2);
3697dd7cddfSDavid du Colombier 			else
3707dd7cddfSDavid du Colombier 				psline(	M[i],    reali,
3717dd7cddfSDavid du Colombier 					M[T[i]], realt,
3727dd7cddfSDavid du Colombier 					(float) 1.,(float) 0.,(float) 0., 2);
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier 			if (realt >= MH) T[T[i]] = -i;
3757dd7cddfSDavid du Colombier 
3767dd7cddfSDavid du Colombier 		} else if (T[i] < 0)	/* arrow from prev page */
3777dd7cddfSDavid du Colombier 		{	int reali = (-T[i])*HH;
3787dd7cddfSDavid du Colombier 			int realt = i*HH;
3797dd7cddfSDavid du Colombier 			int topop = (realt)/MH; topop *= MH;
3807dd7cddfSDavid du Colombier 			reali -= topop;  realt -= topop;
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier 			psline(	M[-T[i]], reali,
3837dd7cddfSDavid du Colombier 				M[i],     realt,
3847dd7cddfSDavid du Colombier 				(float) 1., (float) 0., (float) 0., 2);
3857dd7cddfSDavid du Colombier 		}
3867dd7cddfSDavid du Colombier 		if (L[i])
3877dd7cddfSDavid du Colombier 		{	spitbox(M[i], 0, i, L[i]);
388*00d97012SDavid du Colombier 			/* free(L[i]); */
3897dd7cddfSDavid du Colombier 			lasti = i;
3907dd7cddfSDavid du Colombier 		}
3917dd7cddfSDavid du Colombier 	}
3927dd7cddfSDavid du Colombier 	fprintf(pfd, "showpage\nrestore\n");
3937dd7cddfSDavid du Colombier }
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier void
putbox(int x)3967dd7cddfSDavid du Colombier putbox(int x)
3977dd7cddfSDavid du Colombier {
3987dd7cddfSDavid du Colombier 	if (ldepth >= TotSteps)
399*00d97012SDavid du Colombier 	{	fprintf(stderr, "max length of %d steps exceeded - ps file truncated\n",
4007dd7cddfSDavid du Colombier 			TotSteps);
401*00d97012SDavid du Colombier 		putpostlude();
4027dd7cddfSDavid du Colombier 	}
4037dd7cddfSDavid du Colombier 	M[ldepth] = x;
4047dd7cddfSDavid du Colombier 	if (x > maxx) maxx = x;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier 
4077dd7cddfSDavid du Colombier void
pstext(int x,char * s)4087dd7cddfSDavid du Colombier pstext(int x, char *s)
409312a1df1SDavid du Colombier {	char *tmp = emalloc((int) strlen(s)+1);
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier 	strcpy(tmp, s);
4127dd7cddfSDavid du Colombier 	if (depth == 0)
4137dd7cddfSDavid du Colombier 		I[x] = tmp;
4147dd7cddfSDavid du Colombier 	else
4157dd7cddfSDavid du Colombier 	{	putbox(x);
416312a1df1SDavid du Colombier 		if (depth >= TotSteps || ldepth >= TotSteps)
417312a1df1SDavid du Colombier 		{	fprintf(stderr, "max nr of %d steps exceeded\n",
418312a1df1SDavid du Colombier 				TotSteps);
419312a1df1SDavid du Colombier 			fatal("aborting", (char *) 0);
420312a1df1SDavid du Colombier 		}
421312a1df1SDavid du Colombier 
4227dd7cddfSDavid du Colombier 		D[depth] = ldepth;
4237dd7cddfSDavid du Colombier 		R[ldepth] = depth;
4247dd7cddfSDavid du Colombier 		L[ldepth] = tmp;
4257dd7cddfSDavid du Colombier 		ldepth += 2;
4267dd7cddfSDavid du Colombier 	}
4277dd7cddfSDavid du Colombier }
4287dd7cddfSDavid du Colombier 
4297dd7cddfSDavid du Colombier void
dotag(FILE * fd,char * s)4307dd7cddfSDavid du Colombier dotag(FILE *fd, char *s)
431312a1df1SDavid du Colombier {	extern int columns, notabs; extern RunList *X;
4327dd7cddfSDavid du Colombier 	int i = (!strncmp(s, "MSC: ", 5))?5:0;
4337dd7cddfSDavid du Colombier 	int pid = s_trail ? pno : (X?X->pid:0);
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier 	if (columns == 2)
4367dd7cddfSDavid du Colombier 		pstext(pid, &s[i]);
4377dd7cddfSDavid du Colombier 	else
438312a1df1SDavid du Colombier 	{	if (!notabs)
439312a1df1SDavid du Colombier 		{	printf("  ");
440312a1df1SDavid du Colombier 			for (i = 0; i <= pid; i++)
441312a1df1SDavid du Colombier 				printf("    ");
442312a1df1SDavid du Colombier 		}
4437dd7cddfSDavid du Colombier 		fprintf(fd, "%s", s);
444312a1df1SDavid du Colombier 		fflush(fd);
4457dd7cddfSDavid du Colombier 	}
4467dd7cddfSDavid du Colombier }
447