Back to index

tetex-bin  3.0
next.c
Go to the documentation of this file.
00001 /* next.c: display interface for the NeXT, joe@rilgp.tamri.com.
00002 
00003 This device code requires a second program ("DrawingServant") to
00004 act as the interface between sm and the WindowServer.  The second program
00005 just serves to listen for commands on a pipe, but otherwise
00006 send everything else with a DPSPrintf to the WindowServer.  The servant can
00007 also do things like implement it's own event loop and handle things
00008 like printing, saving .eps  and the like.  This seems (to me) to be the
00009 best way to put a multiplatform program into a NeXT application.
00010 
00011 You can get DrawingServant from sonata.cc.purdue.edu.
00012 */
00013 
00014 /* with not too much work, the client side of things probably 
00015 could be on another machine */
00016 #define EXTERN extern
00017 #include "../mfd.h"
00018 
00019 #ifdef NEXTWIN              /* the whole file */
00020 #define DRAWSERVER "DrawingServant"
00021 #define DEFWIDTH 400 /* default width and height */
00022 #define DEFHEIGHT 500
00023 
00024 /*these default values are taken from plain.mf
00025 and are used if we can't see anything better */
00026 static int nextheight=DEFHEIGHT;
00027 static int nextwidth=DEFWIDTH;
00028 static int outpipe[2],inpipe[2];
00029 static int pid;
00030 static int nextscreenlooksOK = 0;
00031 char outstring[1024];       /* the longest string pushed though a pipe */
00032 /* these are used a lot, so macro-ize these two lines */
00033 #define SENDPS write(outpipe[1],outstring,strlen(outstring)+1)
00034 #define GETACK do{\
00035               read(inpipe[0],outstring,sizeof(outstring)-1);\
00036               } while(strncmp(outstring,"Ok",2))
00037 #ifdef read
00038 #undef read
00039 #endif
00040 
00041 int mf_next_initscreen()
00042 {
00043        int i;
00044        void mf_next_closescreen();
00045        /* strings for height, width, in and out pipes */
00046        char hstr[20],wstr[20],instr[20],outstr[20];
00047        
00048        /* I should figure out how to use screen_rows and screen_cols
00049        to size the window. what I think I need is one of leftcol,rightcol
00050        toprow and botrow.  Let's find the first which is non-zero,
00051        at least until someone tells me what the real answer is.*/
00052 
00053        for(i=0;i<16;i++) {
00054               if((leftcol[i]-rightcol[i]) && (toprow[i]-botrow[i])) {
00055                      nextwidth = rightcol[i]-leftcol[i];
00056                      nextheight = botrow[i]-toprow[i];
00057                      break;
00058               }
00059        }
00060 
00061        /* fork a process and assign some pipes.  return if unsuccessful */
00062        if( pipe(outpipe)== -1)
00063                      return 0;
00064        if( pipe(inpipe)== -1)
00065                      return 0;
00066        if( (pid=fork())== -1)
00067                      return 0;
00068 
00069        if(pid==0) {
00070               /* things done by the child. we pass it height,width and
00071               input and output pipes */
00072               sprintf(hstr,"h %d ",nextheight);
00073               sprintf(wstr,"w %d ",nextwidth);
00074               sprintf(outstr,"i %d",outpipe[0]);
00075               sprintf(instr,"o %d",inpipe[1]);
00076               execl(DRAWSERVER,DRAWSERVER,hstr,wstr,instr,outstr,0);
00077               exit(0);
00078        }
00079        sprintf(outstring,"initgraphics\n");
00080        SENDPS;
00081        GETACK;
00082        nextscreenlooksOK = 1;
00083 
00084        /* The prior version used a hacked version of uexit to kill the
00085        server...at the urging of karl berry, here is a more legit way to
00086        kill the server */
00087        atexit(*mf_next_closescreen);
00088 
00089        return 1;
00090 }
00091 /*
00092  *     void updatescreen;
00093  *     does nothing
00094  *
00095  */
00096 void mf_next_updatescreen()
00097 {
00098 }
00099 /*
00100  *     void blankrectangle(int left,int right,int top,int bottom);
00101  *
00102  *            blank out a port of the screen.
00103  */
00104 void mf_next_blankrectangle P4C(screencol, left,
00105                                 screencol, right,
00106                                 screenrow, top,
00107                                 screenrow, bottom)
00108 {
00109 
00110        if(left==0 && top==nextheight && right==nextwidth && bottom==0 ) {
00111                /* clear and forgets PS strings */
00112               sprintf(outstring,"DSclear");
00113        } else {
00114               sprintf(outstring,
00115                      " 1 setgray %d %d %d %d rectfill 0 setgray \n",
00116                      left+1,top+1,right,bottom+1);
00117        }
00118               SENDPS;
00119               GETACK;
00120 }
00121 
00122 /*
00123  *     void paintrow(int row,int init_color,int transition_vector,
00124  *                                        int vector_size);
00125  *
00126  *            Paint "row" starting with color "init_color", up to next
00127  *            transition specified by "transition_vector", switch colors,
00128  *            and continue for "vector_size" transitions.
00129  */
00130 void mf_next_paintrow P4C(screenrow,   row,
00131                           pixelcolor,  init_color,
00132                           transspec,   transition_vector,
00133                           screencol,   vector_size)
00134 {
00135        int i,whereami;
00136        if(init_color) {
00137               init_color = 1;
00138        } else {
00139               init_color = 0;
00140        }
00141        whereami = 0;
00142 
00143        for(i=0;i<vector_size;i++) {
00144               if(init_color) {
00145                      sprintf(outstring+whereami,
00146                             "newpath %d %d moveto %d %d lineto stroke ",
00147                                    transition_vector[i],nextheight-row,
00148                                    transition_vector[i+1],nextheight-row);
00149                      whereami = strlen(outstring);
00150                      /* buffering is good.  perhaps. */
00151                      if(whereami > 500) {
00152                             SENDPS;
00153                             GETACK;
00154                             *outstring = 0;
00155                             whereami = 0;
00156                      }
00157               }
00158               init_color = 1-init_color;
00159        }
00160        if(whereami) {
00161               SENDPS;
00162               GETACK;
00163        }
00164 }
00165 /* this isn't part of the online display routines.  We need it to
00166 kill DrawingServant.  This is called during exit */
00167 void mf_next_closescreen()
00168 {
00169        if(nextscreenlooksOK) {
00170               sprintf(outstring,"DSquit");
00171               SENDPS;
00172        }
00173 }
00174 
00175 #else
00176 int next_dummy;
00177 #endif /* NEXTWIN */