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