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