Back to index

tetex-bin  3.0
psdps.c
Go to the documentation of this file.
00001 /*========================================================================*\
00002 
00003 Copyright (c) 1994-2004  Paul Vojta
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to
00007 deal in the Software without restriction, including without limitation the
00008 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00009 sell copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018 PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
00019 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00020 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00021 OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 NOTES:
00024        This code was originally written by Ricardo Telichevesky
00025        (ricardo@rle-vlsi-mit.edu) and Luis Miguel Silveira
00026        (lms@rle-vlsi-mit.edu).
00027        It was largely influenced by similar code in the SeeTeX/XTeX
00028        package by Dirk Grunwald (grunwald@colorado.edu).
00029 
00030 \*========================================================================*/
00031 
00032 #ifdef PS_DPS /* entire file */
00033 
00034 
00035 #include <setjmp.h>
00036 #include <signal.h>
00037 #include <X11/X.h>
00038 #include <X11/Xlib.h>
00039 #include <DPS/XDPSlib.h>
00040 #include <DPS/dpsXclient.h>
00041 #include <DPS/dpsexcept.h>
00042 #include <DPS/dpsclient.h>
00043 
00044 #include "xdvi-config.h"
00045 #include "xdvi.h"
00046 
00047 #ifdef X_NOT_STDC_ENV
00048 extern int    errno;
00049 #endif
00050 
00051 #if defined(sun) || defined(__sun)
00052 #ifndef SUNHACK
00053 #define       SUNHACK       1
00054 #endif
00055 #endif
00056 
00057 
00058 #include "dvi-init.h"
00059 #include "dvi-draw.h"
00060 #include "events.h"
00061 
00062 /*
00063  * This string reads chunks (delimited by %%xdvimark).
00064  * The first character of a chunk tells whether a given chunk
00065  * is to be done within save/restore or not.
00066  * The `H' at the end tells it that the first group is a
00067  * header; i.e., no save/restore.
00068  */
00069 #if !SUNHACK
00070 static char preamble[] =
00071     "/xdvi$line 81 string def "
00072     "/xdvi$run {{$error null ne {$error /newerror false put}if "
00073     " currentfile cvx stopped "
00074     " $error null eq {false} {$error /newerror get} ifelse and "
00075     " {handleerror} if} stopped pop} def "
00076     "/xdvi$dslen countdictstack def "
00077     "{currentfile read not {exit} if 72 eq "
00078     " {xdvi$run} "
00079     " {/xdvi$sav save def xdvi$run "
00080     "  clear countdictstack xdvi$dslen sub {end} repeat xdvi$sav restore} "
00081     " ifelse "
00082     " {(%%xdvimark) currentfile xdvi$line {readline} stopped "
00083     "  {clear} {pop eq {exit} if} ifelse }loop "
00084     " (xdvi$Ack\n) print flush "
00085     "}loop\nH";
00086 #else /* SUNHACK */
00087 static char preamble[] =
00088     "/xdvi$line 81 string def "
00089     "/xdvi$run {{$error null ne {$error /newerror false put}if "
00090     "currentfile cvx stopped "
00091     "$error null eq {false} {$error /newerror get} ifelse and "
00092     "{handleerror} if} stopped pop} def "
00093     "/xdvi$dslen countdictstack def "
00094     "/xdvi$ack {{(%%xdvimark) currentfile xdvi$line {readline} stopped "
00095     "  {clear} {pop eq {exit} if} ifelse }loop "
00096     "  (xdvi$Ack\n) print flush} bind def "
00097     "errordict begin /interrupt{(xdvi$Int\n) print flush stop}bind def "
00098     "end "
00099     "{{currentfile read not {exit} if 72 eq "
00100     "   {xdvi$run} "
00101     "   {/xdvi$sav save def xdvi$run "
00102     "    clear countdictstack xdvi$dslen sub {end} repeat xdvi$sav restore} "
00103     "  ifelse "
00104     " xdvi$ack "
00105     " }loop "
00106     "xdvi$ack "
00107     "}loop\nH";
00108 #endif /* SUNHACK */
00109 
00110 extern const char psheader[];
00111 extern unsigned psheaderlen;
00112 
00113 
00114 /* global procedures (besides initDPS) */
00115 
00116 static void toggleDPS(int flag);
00117 static void destroyDPS(void);
00118 static void interruptDPS(void);
00119 static void endpageDPS(void);
00120 static void drawbeginDPS(int, int, const char *);
00121 static void drawbeginDPS_box(int, int, const char *);
00122 static void drawrawDPS(const char *);
00123 static void drawfileDPS(const char *, FILE *);
00124 static void drawendDPS(const char *);
00125 static void beginheaderDPS(void);
00126 static void endheaderDPS(void);
00127 static void newdocDPS(void);
00128 
00129 static struct psprocs dps_procs = {
00130     /* toggle */ toggleDPS,
00131     /* destroy */ destroyDPS,
00132     /* interrupt */ interruptDPS,
00133     /* endpage */ endpageDPS,
00134     /* drawbegin */ drawbeginDPS,
00135     /* drawraw */ drawrawDPS,
00136     /* drawfile */ drawfileDPS,
00137     /* drawend */ drawendDPS,
00138     /* beginheader */ beginheaderDPS,
00139     /* endheader */ endheaderDPS,
00140     /* newdoc */ newdocDPS
00141 };
00142 
00143 #define       DPS_MASK_NORMAL      EV_GE_NEWPAGE
00144 #define       DPS_MASK_HEADER      EV_GE_PS_TOGGLE
00145 #define       DPS_MASK_INIT (EV_GE_TERM | EV_PS_TOGGLE)
00146 
00147 static DPSContext DPS_ctx = NULL;
00148 static DPSSpace DPS_space = NULL;
00149 static int DPS_mag;  /* magnification currently in use */
00150 static int DPS_shrink;      /* shrink factor currently in use */
00151 static Boolean DPS_active;  /* if we've started a page */
00152 static int DPS_pending;     /* number of ack's we're expecting */
00153 static Boolean DPS_in_header;      /* if we're sending a header */
00154 static Boolean DPS_in_doc;  /* if we've sent header information */
00155 
00156 static int DPS_ev_mask = DPS_MASK_NORMAL; /* events for which we'll stop */
00157 
00158 
00159 #if    0
00160 static void DPSErrorProcHandler();
00161 #else
00162 #define       DPSErrorProcHandler  DPSDefaultErrorProc
00163 #endif
00164 
00165 
00166 static char ackstr[] = "xdvi$Ack\n";
00167 #if SUNHACK
00168 static char intstr[] = "xdvi$Int\n";
00169 static char intstr2[] = "xdvi$In2\n";
00170 #endif
00171 
00172 #define       LINELEN       81
00173 #define       BUFLEN (LINELEN + sizeof ackstr)
00174 static char line[BUFLEN + 1];
00175 static char *linepos = line;
00176 
00177 static void
00178 TextProc(DPSContext ctxt, char *buf, unsigned long count)
00179 {
00180     int i;
00181     char *p;
00182     char *p0;
00183 
00184     while (count > 0) {
00185        i = line + BUFLEN - linepos;
00186        if (i > count)
00187            i = count;
00188        (void)bcopy(buf, linepos, i);
00189        linepos += i;
00190        buf += i;
00191        count -= i;
00192        p0 = line;
00193        for (;;) {
00194            if (p0 >= linepos) {
00195               linepos = line;
00196               break;
00197            }
00198            p = memchr(p0, '\n', linepos - p0);
00199            if (p == NULL) {
00200               if (p0 != line) {
00201                   (void)bcopy(p0, line, linepos - p0);
00202                   linepos -= p0 - line;
00203               }
00204               else if (linepos == line + BUFLEN) {
00205                   char c;
00206 
00207                   c = line[LINELEN];
00208                   line[LINELEN] = '\0';
00209                   printf("DPS: %s\n", line);
00210                   line[LINELEN] = c;
00211                   linepos -= LINELEN;
00212                   (void)bcopy(line + LINELEN, line, linepos - line);
00213               }
00214               break;
00215            }
00216            if (p >= p0 + 8 && memcmp(p - 8, ackstr, 9) == 0) {
00217               --DPS_pending;
00218               if (DPS_pending == 0)
00219                   globals.ev.flags |= EV_ACK;
00220               if (globals.debug & DBG_PS)
00221                   printf("Got DPS ack; %d pending.\n", DPS_pending);
00222               ++p;
00223               (void)bcopy(p, p - 9, linepos - p);
00224               linepos -= 9;
00225               continue;
00226            }
00227 #if SUNHACK
00228            if (p >= p0 + 8 && memcmp(p - 8, intstr, 9) == 0) {
00229               if (globals.debug & DBG_PS)
00230                   puts("Got DPS int.");
00231               ++p;
00232               (void)bcopy(p, p - 9, linepos - p);
00233               linepos -= 9;
00234               globals.ev.flags |= EV_ACK;
00235               continue;
00236            }
00237            if (p >= p0 + 8 && memcmp(p - 8, intstr2, 9) == 0) {
00238               if (globals.debug & DBG_PS)
00239                   puts("Got DPS int 2.");
00240               ++p;
00241               (void)bcopy(p, p - 9, linepos - p);
00242               linepos -= 9;
00243               DPS_pending = 3;
00244 
00245               continue;
00246            }
00247 #endif /* SUNHACK */
00248            *p = '\0';
00249            printf("DPS: %s\n", p0);
00250            p0 = p + 1;
00251        }
00252     }
00253 }
00254 
00255 
00256 /*---------------------------------------------------------------------------*
00257   waitack()
00258 
00259   Arguments: none.
00260 
00261   Returns: (void)
00262 
00263   Description:
00264   Waits until the requisite number of acknowledgements has been received from
00265   the context.
00266 
00267 +----------------------------------------------------------------------------*/
00268 
00269 #if SUNHACK
00270 static void   DPS_alarm ARGS((struct xtimer *));
00271 
00272 static struct xtimer DPS_timer     = {NULL, {0, 0}, DPS_alarm};
00273 static Boolean              DPS_timer_set;
00274 
00275 static void DPS_alarm(struct xtimer *arg)
00276 {
00277     if (globals.debug & DBG_PS)
00278        puts("Received DPS alarm");
00279 
00280     DPS_timer_set = False;
00281     globals.ev.flags |= EV_ACK;
00282 }
00283 #endif /* SUNHACK */
00284 
00285 static void
00286 waitack(void)
00287 {
00288     if (DPS_pending <= 0)
00289        return;
00290 
00291     DPSFlushContext(DPS_ctx);
00292     if (read_events(DPS_ev_mask | EV_ACK) & EV_ACK) {
00293        globals.ev.flags &= ~EV_ACK;
00294        return;
00295     }
00296 
00297     if (globals.debug & DBG_PS)
00298        printf("Interrupting DPS in waitack(); code is now %d %x\n",
00299               XDPSGetContextStatus(DPS_ctx), globals.ev.flags);
00300 
00301     DPS_active = DPS_in_header = DPS_in_doc = False;
00302     DPS_ev_mask = DPS_MASK_NORMAL;
00303 
00304     /*
00305      * I would really like to use DPSInterruptContext() here, but (at least
00306      * on an RS6000) I can't get it to work.
00307      */
00308 
00309 #if SUNHACK
00310 
00311     /*
00312      * On the other hand, under OpenWindows 3.3 (at least), destroying and
00313      * re-creating contexts has a nasty habit of crashing the server.
00314      */
00315 
00316     DPS_pending = 32767;
00317     DPSInterruptContext(DPS_ctx);
00318     DPSFlushContext(DPS_ctx);
00319     (void) read_events(EV_GE_TERM | EV_ACK);
00320     globals.ev.flags &= ~EV_ACK;
00321 
00322     XSync(DISP, False);
00323     DPSPrintf(DPS_ctx, " stop\n%%%%xdvimark\n stop\n%%%%xdvimark\n");
00324     DPSPrintf(DPS_ctx, " (xdvi$In2\n) print flush stop\n%%%%xdvimark\n");
00325     DPSPrintf(DPS_ctx, " stop\n%%%%xdvimark\n stop\n%%%%xdvimark\n");
00326     DPSFlushContext(DPS_ctx);
00327 
00328     if (globals.debug & DBG_PS)
00329        puts("Setting DPS timer");
00330 
00331     DPS_timer_set = True;
00332     set_timer(&DPS_timer, 500);
00333     (void) read_events(EV_GE_TERM | EV_ACK);
00334     globals.ev.flags &= ~EV_ACK;
00335 
00336     if (DPS_pending <= 0) {
00337        if (DPS_timer_set) {
00338            cancel_timer(&DPS_timer);
00339        }
00340 
00341        return;
00342     }
00343 
00344     /*
00345      * However, under Solaris 2.6 (at least), sometimes interrupting the
00346      * context leaves it in an uncommunicative state, so destruction
00347      * is the only alternative.
00348      */
00349 
00350     if (globals.debug & DBG_PS)
00351        puts("Plan B:  Destroying DPS context");
00352 
00353 #endif /* SUNHACK */
00354 
00355     DPSDestroyContext(DPS_ctx);
00356     DPS_ctx = NULL;
00357     DPS_pending = 0;
00358 }
00359 
00360 
00361 /*---------------------------------------------------------------------------*
00362   initDPS()
00363 
00364   Arguments: (none)
00365   Returns: (void)
00366   Side-Effects: DPS_ctx may be set as well as other static variables.
00367 
00368   Description:
00369   Initializes variables from the application main loop.  Checks to see if
00370   a connection to the DPS server can be opened.
00371 
00372 +----------------------------------------------------------------------------*/
00373 
00374 static int
00375 get_shift(Pixel mask)
00376 {
00377     int k;
00378 
00379     for (k = 0; (mask & 1) == 0; ++k)
00380        mask >>= 1;
00381     return k;
00382 }
00383 
00384 Boolean initDPS(void)
00385 {
00386 
00387     /* Try to create a context */
00388 
00389 #if GREY
00390 
00391     if (G_colormap == DefaultColormapOfScreen(SCRN))
00392        DPS_ctx = XDPSCreateSimpleContext(DISP, mane.win, globals.gc.copy, 0, 0,
00393                                      TextProc, DPSDefaultErrorProc, NULL);
00394     else {
00395        static XStandardColormap *ccube = NULL;
00396        static XStandardColormap *grayramp = NULL;
00397        int shift;
00398 
00399        if (grayramp == NULL) {
00400            grayramp = XAllocStandardColormap();
00401            if (grayramp == NULL)
00402               return False;
00403        }
00404 
00405        if (ccube == NULL) {
00406            ccube = XAllocStandardColormap();
00407            if (ccube == NULL)
00408               return False;
00409        }
00410 
00411        shift = get_shift(G_visual->red_mask);
00412        ccube->red_max = G_visual->red_mask >> shift;
00413        ccube->red_mult = 1 << shift;
00414 
00415        shift = get_shift(G_visual->green_mask);
00416        ccube->green_max = G_visual->green_mask >> shift;
00417        ccube->green_mult = 1 << shift;
00418 
00419        shift = get_shift(G_visual->blue_mask);
00420        ccube->blue_max = G_visual->blue_mask >> shift;
00421        ccube->blue_mult = 1 << shift;
00422 
00423        grayramp->red_max = ccube->red_max & ccube->green_max & ccube->blue_max;
00424        grayramp->red_mult = ccube->red_mult + ccube->green_mult
00425            + ccube->blue_mult;
00426 
00427        ccube->colormap = grayramp->colormap = G_colormap;
00428        ccube->visualid = grayramp->visualid = G_visual->visualid;
00429 
00430        DPS_ctx = XDPSCreateContext(DISP, mane.win, globals.gc.copy, 0, 0,
00431                                 0, grayramp, ccube,
00432                                 /* actual */
00433                                 (ccube->red_max + 1) * (ccube->green_max +
00434                                                      1) *
00435                                 (ccube->blue_max + 1), TextProc,
00436                                 DPSDefaultErrorProc, NULL);
00437     }
00438 
00439 #else /* not GREY */
00440 
00441     DPS_ctx = XDPSCreateSimpleContext(DISP, mane.win, globals.gc.copy, 0, 0,
00442                                   TextProc, DPSDefaultErrorProc, NULL);
00443 
00444 #endif /* not GREY */
00445 
00446     if (DPS_ctx == NULL)
00447        return False;
00448 
00449     DPS_mag = DPS_shrink = -1;
00450     DPS_active = False;
00451     DPS_pending = 1;
00452 
00453     DPS_space = DPSSpaceFromContext(DPS_ctx);
00454     DPSWritePostScript(DPS_ctx, preamble, (sizeof preamble) - 1);
00455     DPSWritePostScript(DPS_ctx, (char *)psheader, psheaderlen);
00456     DPSPrintf(DPS_ctx, "matrix setmatrix stop\n%%%%xdvimark\n");
00457     DPSFlushContext(DPS_ctx);
00458 
00459     psp = dps_procs;
00460     return True;
00461 }
00462 
00463 
00464 /*---------------------------------------------------------------------------*
00465   toggleDPS(int flag)
00466 
00467   Arguments: flag for toggling PostScript
00468   Returns: (void)
00469   Side-Effects: psp.drawbegin is changed.
00470 
00471   Description:
00472   Used to toggle the rendering of PostScript by the DPS server
00473   This routine may be called from within read_events().
00474 
00475 +----------------------------------------------------------------------------*/
00476 
00477 static void
00478 toggleDPS(int flag)
00479 {
00480     if (globals.debug & DBG_PS)
00481        Puts("Toggling DPS to %d", flag);
00482 
00483     switch (flag) {
00484     case 0:
00485        psp.drawbegin = drawbegin_none;
00486        break;
00487     case 1:
00488        psp.drawbegin = drawbeginDPS;
00489        break;
00490     default:
00491        psp.drawbegin = drawbeginDPS_box;
00492        break;
00493     }
00494 }
00495 
00496 
00497 /*---------------------------------------------------------------------------*
00498   destroyDPS()
00499 
00500   Arguments: none
00501   Returns: (void)
00502   Side-Effects: the context is nulled out and destroyed.
00503 
00504   Description:
00505   Close the connection to the DPS server; used when rendering is terminated
00506   in any way.
00507 
00508 +----------------------------------------------------------------------------*/
00509 
00510 static void
00511 destroyDPS(void)
00512 {
00513     if (globals.debug & DBG_PS)
00514        puts("Calling destroyDPS()");
00515     if (linepos > line) {
00516        *linepos = '\0';
00517        printf("DPS: %s\n", line);
00518     }
00519     if (DPS_space != NULL)
00520        DPSDestroySpace(DPS_space);
00521     psp = no_ps_procs;
00522     scanned_page = scanned_page_ps = scanned_page_reset;
00523 }
00524 
00525 
00526 /*---------------------------------------------------------------------------*
00527   interruptDPS()
00528 
00529   Arguments: none
00530   Returns: (void)
00531   Side-Effects: the context may be nulled out and destroyed.
00532 
00533   Description:
00534   Close the connection to the DPS server; used when rendering is terminated
00535   because of an interruption in the viewing of the current page.
00536 
00537 +----------------------------------------------------------------------------*/
00538 
00539 static void
00540 interruptDPS(void)
00541 {
00542     if (globals.debug & DBG_PS)
00543        puts("Running interruptDPS()");
00544 
00545     if (DPS_pending <= 0)
00546        return;       /* nothing to do */
00547 
00548     if (DPS_active) {
00549        DPSPrintf(DPS_ctx, "stop\n%%%%xdvimark\n");
00550        DPS_active = False;
00551     }
00552 
00553     waitack();
00554 }
00555 
00556 
00557 /*---------------------------------------------------------------------------*
00558   endpageDPS()
00559 
00560   Arguments: none
00561   Returns: (void)
00562   Side-Effects: the DPS_active variable is cleared.
00563 
00564   Description:
00565   Should be called at the end of a page to end this chunk for the DPS server.
00566 
00567 +----------------------------------------------------------------------------*/
00568 
00569 static void
00570 endpageDPS(void)
00571 {
00572     if (DPS_active) {
00573        if (globals.debug & DBG_PS)
00574            puts("Endpage sent to context");
00575        DPSPrintf(DPS_ctx, "stop\n%%%%xdvimark\n");
00576        DPS_active = False;
00577        waitack();
00578     }
00579 }
00580 
00581 
00582 /*
00583  *     checkDPS - Check that the DPS interpreter is still running.
00584  *     Return True for success, False for failure.
00585  */
00586 
00587 static Boolean
00588 checkDPS(void)
00589 {
00590     /* static char faulty_display_vs[]
00591      * ="DECWINDOWS DigitalEquipmentCorporation UWS4.2LA"; */
00592 
00593     if (DPS_ctx == NULL) {
00594        DPS_ctx = XDPSCreateSimpleContext(DISP, mane.win, globals.gc.copy, 0, 0,
00595               TextProc, DPSErrorProcHandler, DPS_space);
00596        if (DPS_ctx == NULL) {
00597            psp = no_ps_procs;
00598            draw_bbox();
00599            return False;
00600        }
00601        DPSWritePostScript(DPS_ctx, preamble, (sizeof preamble) - 1);
00602        /* it already has psheader */
00603        DPSPrintf(DPS_ctx, "matrix setmatrix stop\n%%%%xdvimark\n");
00604        DPS_mag = DPS_shrink = -1;
00605        DPS_active = False;
00606        DPS_pending = 1;
00607     }
00608 
00609     return True;
00610 }
00611 
00612 
00613 /*---------------------------------------------------------------------------*
00614   drawbeginDPS  ()
00615 
00616   Arguments: xul, yul - coordinates of the upper left corner of the figure
00617              cp - string with the bounding box line data
00618   Returns: (void)
00619   Side-Effects: DPS_ctx is set is set and connection to DPS server is
00620                 opened.
00621 
00622   Description:
00623   Opens a connection to the DPS server and send in the preamble and the
00624   bounding box information after correctly computing resolution factors.
00625   In case no rendering is to be done, outlines the figure.
00626   An outline is also generated whenever the a context cannot be allocated
00627 
00628 +----------------------------------------------------------------------------*/
00629 
00630 static void
00631 drawbeginDPS(int xul, int yul, const char *cp)
00632 {
00633     if (globals.debug & DBG_PS)
00634        printf("Begin drawing at xul= %d, yul= %d.\n", xul, yul);
00635 
00636     if (!checkDPS()) return;
00637 
00638     if (!DPS_active) {
00639        /* send initialization to context */
00640        if (magnification != DPS_mag) {
00641            DPSPrintf(DPS_ctx, "H TeXDict begin /DVImag %d 1000 div def "
00642                     "end stop\n%%%%xdvimark\n", DPS_mag = magnification);
00643            ++DPS_pending;
00644        }
00645        if (mane.shrinkfactor != DPS_shrink) {
00646            DPSPrintf(DPS_ctx, "H TeXDict begin %d %d div dup "
00647                     "/Resolution X /VResolution X "
00648                     "end stop\n%%%%xdvimark\n", resource.pixels_per_inch, DPS_shrink = mane.shrinkfactor);
00649            ++DPS_pending;
00650        }
00651        DPSPrintf(DPS_ctx, " TeXDict begin\n");
00652        DPS_active = True;
00653        ++DPS_pending;
00654     }
00655 
00656     if (globals.ev.flags & DPS_MASK_NORMAL)
00657        longjmp(globals.ev.canit, 1);
00658 
00659     DPSPrintf(DPS_ctx, "%d %d moveto\n", xul, yul);
00660     DPSPrintf(DPS_ctx, "%s\n", cp);
00661 }
00662 
00663 static void
00664 drawbeginDPS_box(int xul, int yul, const char *cp)
00665 {
00666     drawbeginDPS(int xul, int yul, const char *cp);
00667     draw_bbox();
00668 }
00669 
00670 /*---------------------------------------------------------------------------*
00671 
00672   drawrawDPS()
00673 
00674   Arguments: cp - the raw string to be sent to the postscript interpreter
00675   Returns: (void)
00676   Side-Effects: (none)
00677 
00678   Description:
00679   If there is a valid postscript context, just send the string to the
00680   interpreter, else leave.
00681 
00682 +----------------------------------------------------------------------------*/
00683 
00684 static void
00685 drawrawDPS(const char *cp)
00686 {
00687     if (!DPS_active || (globals.ev.flags & DPS_ev_mask))
00688        return;
00689 
00690     if (globals.debug & DBG_PS)
00691        printf("Sending raw PS to context: %s\n", cp);
00692 
00693     DPSPrintf(DPS_ctx, "%s\n", cp);
00694 }
00695 
00696 
00697 /*---------------------------------------------------------------------------*
00698   drawfileDPS()
00699 
00700   Arguments: cp - string with the postscript file pathname
00701             psfile - opened file pointer
00702   Returns: (void)
00703   Side-Effects: none
00704 
00705   Description:
00706   Postscript file containing the figure is opened and sent to the DPS server.
00707 
00708 +----------------------------------------------------------------------------*/
00709 
00710 static void
00711 drawfileDPS(const char *cp, FILE *psfile)
00712 {
00713     char buffer[1025];
00714     int blen;
00715 
00716     if (DPS_active && !(read_events(EV_NOWAIT) & DPS_ev_mask)) {
00717        if (globals.debug & DBG_PS)
00718            printf("sending file %s\n", cp);
00719        for (;;) {
00720            blen = fread(buffer, sizeof(char), 1024, psfile);
00721            if (blen == 0) break;
00722            DPSWritePostScript(DPS_ctx, buffer, blen);
00723            if (read_events(EV_NOWAIT) & DPS_ev_mask) {
00724               /* ||| stop at a good place */
00725               if (globals.debug & DBG_PS)
00726                   puts("Interrupting in drawfileDPS");
00727               break;
00728            }
00729        }
00730     }
00731 
00732     fclose(psfile);
00733 
00734     if (globals.ev.flags & DPS_ev_mask)
00735        longjmp(globals.ev.canit, 1);
00736 }
00737 
00738 
00739 /*---------------------------------------------------------------------------*
00740   drawendDPS()
00741 
00742   Arguments: cp - string with indication of the end of the special
00743   Returns: (void)
00744   Side-Effects: none
00745 
00746   Description:
00747   Sends the indication of end of the figure PostScript code.
00748 
00749 +----------------------------------------------------------------------------*/
00750 
00751 static void
00752 drawendDPS(const char *cp)
00753 {
00754     if (!DPS_active || (globals.ev.flags & DPS_MASK_NORMAL))
00755        return;
00756 
00757     if (globals.debug & DBG_PS)
00758        printf("End PS: %s\n", cp);
00759     DPSPrintf(DPS_ctx, "%s\n", cp);
00760 }
00761 
00762 
00763 /*---------------------------------------------------------------------------*
00764   beginheaderDPS()
00765 
00766   Arguments: none
00767   Returns: (void)
00768 
00769   Description:
00770   Prepares the PostScript interpreter for receipt of header code.
00771 
00772 +----------------------------------------------------------------------------*/
00773 
00774 static void
00775 beginheaderDPS(void)
00776 {
00777     if (globals.ev.flags & DPS_MASK_HEADER || !checkDPS())
00778        return;
00779 
00780     if (globals.debug & DBG_PS)
00781        puts("Running beginheaderDPS()");
00782 
00783     if (DPS_active) {
00784        if (!DPS_in_header)
00785            XDVI_FATAL((stderr, "Internal error in beginheaderDPS()."));
00786        return;
00787     }
00788 
00789     DPS_in_header = True;
00790     DPS_ev_mask = DPS_MASK_HEADER;
00791 
00792     if (DPS_in_doc)
00793        DPSPrintf(DPS_ctx, "H");
00794     else {
00795        DPSPrintf(DPS_ctx, "Hsave /xdvi$doc exch def\n");
00796        DPS_in_doc = True;
00797     }
00798     DPS_active = True;
00799     ++DPS_pending;
00800 }
00801 
00802 
00803 /*---------------------------------------------------------------------------*
00804   endheaderDPS()
00805 
00806   Arguments: none
00807   Returns: (void)
00808 
00809   Description:
00810   Prepares the PostScript interpreter for receipt of header code.
00811 
00812 +----------------------------------------------------------------------------*/
00813 
00814 static void
00815 endheaderDPS(void)
00816 {
00817     if (globals.debug & DBG_PS)
00818        puts("Running endheaderDPS()");
00819 
00820     if (DPS_active) {
00821        DPSPrintf(DPS_ctx, "stop\n%%%%xdvimark\n");
00822        DPS_active = False;
00823        waitack();
00824        DPS_in_header = False;
00825        DPS_ev_mask = DPS_MASK_NORMAL;
00826     }
00827 }
00828 
00829 
00830 /*---------------------------------------------------------------------------*
00831   newdocDPS()
00832 
00833   Arguments: none
00834   Returns: (void)
00835 
00836   Description:
00837   Clears out headers stored from the previous document.
00838 
00839 +----------------------------------------------------------------------------*/
00840 
00841 static void
00842 newdocDPS(void)
00843 {
00844     if (globals.debug & DBG_PS)
00845        puts("Running newdocDPS()");
00846 
00847     if (DPS_in_doc) {
00848        DPSPrintf(DPS_ctx, "H xdvi$doc restore stop\n%%%%xdvimark\n");
00849        ++DPS_pending;
00850        DPS_mag = DPS_shrink = -1;
00851        DPS_in_doc = False;
00852     }
00853 }
00854 
00855 #else
00856 /* silence `empty compilation unit' warnings */
00857 static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
00858 #endif /* PS_DPS */