1 /* next.c: display interface for the NeXT, joe@rilgp.tamri.com.
2 
3 This device code requires a second program ("DrawingServant") to
4 act as the interface between sm and the WindowServer.  The second program
5 just serves to listen for commands on a pipe, but otherwise
6 send everything else with a DPSPrintf to the WindowServer.  The servant can
7 also do things like implement it's own event loop and handle things
8 like printing, saving .eps  and the like.  This seems (to me) to be the
9 best way to put a multiplatform program into a NeXT application.
10 
11 You can get DrawingServant from sonata.cc.purdue.edu.
12 */
13 
14 /* with not too much work, the client side of things probably
15 could be on another machine */
16 #define EXTERN extern
17 #include "../mfd.h"
18 
19 #ifdef NEXTWIN		/* the whole file */
20 #define DRAWSERVER "DrawingServant"
21 #define DEFWIDTH 400	/* default width and height */
22 #define DEFHEIGHT 500
23 
24 /*these default values are taken from plain.mf
25 and are used if we can't see anything better */
26 static int nextheight=DEFHEIGHT;
27 static int nextwidth=DEFWIDTH;
28 static int outpipe[2],inpipe[2];
29 static int pid;
30 static int nextscreenlooksOK = 0;
31 char outstring[1024];	/* the longest string pushed though a pipe */
32 /* these are used a lot, so macro-ize these two lines */
33 #define SENDPS write(outpipe[1],outstring,strlen(outstring)+1)
34 #define GETACK do{\
35 		read(inpipe[0],outstring,sizeof(outstring)-1);\
36 		} while(strncmp(outstring,"Ok",2))
37 #ifdef read
38 #undef read
39 #endif
40 
41 #include <mfdisplay.h>
42 
mf_next_initscreen(void)43 int mf_next_initscreen(void)
44 {
45 	int i;
46 	void mf_next_closescreen();
47 	/* strings for height, width, in and out pipes */
48 	char hstr[20],wstr[20],instr[20],outstr[20];
49 
50 	/* I should figure out how to use screen_rows and screen_cols
51 	to size the window. what I think I need is one of leftcol,rightcol
52 	toprow and botrow.  Let's find the first which is non-zero,
53 	at least until someone tells me what the real answer is.*/
54 
55 	for(i=0;i<16;i++) {
56 		if((leftcol[i]-rightcol[i]) && (toprow[i]-botrow[i])) {
57 			nextwidth = rightcol[i]-leftcol[i];
58 			nextheight = botrow[i]-toprow[i];
59 			break;
60 		}
61 	}
62 
63 	/* fork a process and assign some pipes.  return if unsuccessful */
64 	if( pipe(outpipe)== -1)
65 			return 0;
66 	if( pipe(inpipe)== -1)
67 			return 0;
68 	if( (pid=fork())== -1)
69 			return 0;
70 
71 	if(pid==0) {
72 		/* things done by the child. we pass it height,width and
73 		input and output pipes */
74 		sprintf(hstr,"h %d ",nextheight);
75 		sprintf(wstr,"w %d ",nextwidth);
76 		sprintf(outstr,"i %d",outpipe[0]);
77 		sprintf(instr,"o %d",inpipe[1]);
78 		execl(DRAWSERVER,DRAWSERVER,hstr,wstr,instr,outstr,0);
79 		exit(0);
80 	}
81 	sprintf(outstring,"initgraphics\n");
82 	SENDPS;
83 	GETACK;
84 	nextscreenlooksOK = 1;
85 
86 	/* The prior version used a hacked version of uexit to kill the
87 	server...at the urging of karl berry, here is a more legit way to
88 	kill the server */
89 	atexit(*mf_next_closescreen);
90 
91 	return 1;
92 }
93 /*
94  *	void updatescreen;
95  * 	does nothing
96  *
97  */
mf_next_updatescreen(void)98 void mf_next_updatescreen(void)
99 {
100 }
101 /*
102  *	void blankrectangle(int left,int right,int top,int bottom);
103  *
104  *		blank out a port of the screen.
105  */
mf_next_blankrectangle(screencol left,screencol right,screenrow top,screenrow bottom)106 void mf_next_blankrectangle (screencol left,
107                              screencol right,
108                              screenrow top,
109                              screenrow bottom)
110 {
111 
112 	if(left==0 && top==nextheight && right==nextwidth && bottom==0 ) {
113 		 /* clear and forgets PS strings */
114 		sprintf(outstring,"DSclear");
115 	} else {
116 		sprintf(outstring,
117 			" 1 setgray %d %d %d %d rectfill 0 setgray \n",
118 			left+1,top+1,right,bottom+1);
119 	}
120 		SENDPS;
121 		GETACK;
122 }
123 
124 /*
125  *	void paintrow(int row,int init_color,int transition_vector,
126  *						int vector_size);
127  *
128  *		Paint "row" starting with color "init_color", up to next
129  *		transition specified by "transition_vector", switch colors,
130  *		and continue for "vector_size" transitions.
131  */
mf_next_paintrow(screenrow row,pixelcolor init_color,transspec transition_vector,screencol vector_size)132 void mf_next_paintrow (screenrow   row,
133                        pixelcolor  init_color,
134                        transspec   transition_vector,
135                        screencol   vector_size)
136 {
137 	int i,whereami;
138 	if(init_color) {
139 		init_color = 1;
140 	} else {
141 		init_color = 0;
142 	}
143 	whereami = 0;
144 
145 	for(i=0;i<vector_size;i++) {
146 		if(init_color) {
147 			sprintf(outstring+whereami,
148 				"newpath %d %d moveto %d %d lineto stroke ",
149 					transition_vector[i],nextheight-row,
150 					transition_vector[i+1],nextheight-row);
151 			whereami = strlen(outstring);
152 			/* buffering is good.  perhaps. */
153 			if(whereami > 500) {
154 				SENDPS;
155 				GETACK;
156 				*outstring = 0;
157 				whereami = 0;
158 			}
159 		}
160 		init_color = 1-init_color;
161 	}
162 	if(whereami) {
163 		SENDPS;
164 		GETACK;
165 	}
166 }
167 /* this isn't part of the online display routines.  We need it to
168 kill DrawingServant.  This is called during exit */
mf_next_closescreen(void)169 void mf_next_closescreen(void)
170 {
171 	if(nextscreenlooksOK) {
172 		sprintf(outstring,"DSquit");
173 		SENDPS;
174 	}
175 }
176 
177 #else
178 int next_dummy;
179 #endif	/* NEXTWIN */
180