[BACK]Return to gplt_x11.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/gplt_x11.c, Revision 1.1.1.2

1.1       maekawa     1: #ifndef lint
1.1.1.2 ! maekawa     2: static char *RCSid = "$Id: gplt_x11.c,v 1.16.2.4 1999/10/15 16:04:50 lhecking Exp $";
1.1       maekawa     3: #endif
                      4:
                      5: /* GNUPLOT - gplt_x11.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37:
                     38: /* lph changes:
                     39:  * (a) make EXPORT_SELECTION the default and specify NOEXPORT to undefine
                     40:  * (b) append X11 terminal number to resource name
                     41:  * (c) change cursor for active terminal
                     42:  */
                     43:
                     44: /*-----------------------------------------------------------------------------
                     45:  *   gnuplot_x11 - X11 outboard terminal driver for gnuplot 3.3
                     46:  *
                     47:  *   Requires installation of companion inboard x11 driver in gnuplot/term.c
                     48:  *
                     49:  *   Acknowledgements:
                     50:  *      Chris Peterson (MIT)
                     51:  *      Dana Chee (Bellcore)
                     52:  *      Arthur Smith (Cornell)
                     53:  *      Hendri Hondorp (University of Twente, The Netherlands)
                     54:  *      Bill Kucharski (Solbourne)
                     55:  *      Charlie Kline (University of Illinois)
                     56:  *      Yehavi Bourvine (Hebrew University of Jerusalem, Israel)
                     57:  *      Russell Lang (Monash University, Australia)
                     58:  *      O'Reilly & Associates: X Window System - Volumes 1 & 2
                     59:  *
                     60:  *   This code is provided as is and with no warranties of any kind.
                     61:  *
                     62:  * drd: change to allow multiple windows to be maintained independently
                     63:  *
                     64:  * There is a mailing list for gnuplot users. Note, however, that the
                     65:  * newsgroup
                     66:  *     comp.graphics.apps.gnuplot
                     67:  * is identical to the mailing list (they
                     68:  * both carry the same set of messages). We prefer that you read the
                     69:  * messages through that newsgroup, to subscribing to the mailing list.
                     70:  * (If you can read that newsgroup, and are already on the mailing list,
                     71:  * please send a message to majordomo@dartmouth.edu, asking to be
                     72:  * removed from the mailing list.)
                     73:  *
                     74:  * The address for mailing to list members is
                     75:  *        info-gnuplot@dartmouth.edu
                     76:  * and for mailing administrative requests is
                     77:  *        majordomo@dartmouth.edu
                     78:  * The mailing list for bug reports is
                     79:  *        bug-gnuplot@dartmouth.edu
                     80:  * The list of those interested in beta-test versions is
                     81:  *        info-gnuplot-beta@dartmouth.edu
                     82:  *---------------------------------------------------------------------------*/
                     83:
                     84: /* drd : export the graph via ICCCM primary selection. well... not quite
                     85:  * ICCCM since we dont support full list of targets, but this
                     86:  * is a start.  define EXPORT_SELECTION if you want this feature
                     87:  */
                     88:
                     89: /*lph: add a "feature" to undefine EXPORT_SELECTION
                     90:    The following makes EXPORT_SELECTION the default and
                     91:    defining NOEXPORT over-rides the default
                     92:  */
                     93:
                     94: #ifdef HAVE_CONFIG_H
                     95: # include "config.h"
                     96: #endif
                     97:
                     98: #ifdef EXPORT_SELECTION
                     99: # undef EXPORT_SELECTION
                    100: #endif /* EXPORT SELECTION */
                    101: #ifndef NOEXPORT
                    102: # define EXPORT_SELECTION XA_PRIMARY
                    103: #endif /* NOEXPORT */
                    104:
                    105:
                    106: #if !(defined(VMS) || defined(CRIPPLED_SELECT))
                    107: # define DEFAULT_X11
                    108: #endif
                    109:
                    110: #if defined(VMS) && defined(CRIPPLED_SELECT)
                    111: Error. Incompatible options.
                    112: #endif
                    113:
                    114:
                    115: #include <X11/Xos.h>
                    116: #include <X11/Xlib.h>
                    117: #include <X11/Xresource.h>
                    118: #include <X11/Xutil.h>
                    119: #include <X11/Xatom.h>
                    120: #include <X11/keysym.h>
                    121:
                    122: #include <signal.h>
                    123:
                    124: #ifdef HAVE_SYS_BSDTYPES_H
                    125: # include <sys/bsdtypes.h>
                    126: #endif /* HAVE_SYS_BSDTYPES_H */
                    127:
                    128: #ifdef __EMX__
                    129: /* for gethostname ... */
                    130: # include <netdb.h>
                    131: #endif
                    132:
                    133: #if defined(HAVE_SYS_SELECT_H) && !defined(VMS)
                    134: # include <sys/select.h>
                    135: #endif /* HAVE_SYS_SELECT_H && !VMS */
                    136:
                    137: #ifndef FD_SET
                    138: # define FD_SET(n, p)    ((p)->fds_bits[0] |= (1 << ((n) % 32)))
                    139: # define FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1 << ((n) % 32)))
                    140: # define FD_ISSET(n, p)  ((p)->fds_bits[0] & (1 << ((n) % 32)))
                    141: # define FD_ZERO(p)      memset((char *)(p),'\0',sizeof(*(p)))
                    142: #endif /* not FD_SET */
                    143:
                    144: #include "plot.h"
                    145:
                    146: #if defined(HAVE_SYS_SYSTEMINFO_H) && defined(HAVE_SYSINFO)
                    147: # include <sys/systeminfo.h>
                    148: # define SYSINFO_METHOD "sysinfo"
                    149: # define GP_SYSTEMINFO(host) sysinfo (SI_HOSTNAME, (host), MAXHOSTNAMELEN)
                    150: #else
                    151: # define SYSINFO_METHOD "gethostname"
                    152: # define GP_SYSTEMINFO(host) gethostname ((host), MAXHOSTNAMELEN)
                    153: #endif /* HAVE_SYS_SYSTEMINFO_H && HAVE_SYSINFO */
                    154:
                    155: #ifdef VMS
                    156: # ifdef __DECC
                    157: #  include <starlet.h>
                    158: # endif                                /* __DECC */
                    159: # define EXIT(status) sys$delprc(0,0)  /* VMS does not drop itself */
                    160: #else
                    161: # define EXIT(status) exit(status)
                    162: #endif
                    163:
                    164: #ifdef OSK
                    165: # define EINTR E_ILLFNC
                    166: #endif
                    167:
                    168: /* information about one window/plot */
                    169:
                    170: typedef struct plot_struct {
                    171:     Window window;
                    172:     Pixmap pixmap;
                    173:     unsigned int posn_flags;
                    174:     int x, y;
                    175:     unsigned int width, height;        /* window size */
                    176:     unsigned int px, py;       /* pointsize */
                    177:     int ncommands, max_commands;
                    178:     char **commands;
                    179: } plot_struct;
                    180:
                    181: void store_command __PROTO((char *line, plot_struct * plot));
                    182: void prepare_plot __PROTO((plot_struct * plot, int term_number));
                    183: void delete_plot __PROTO((plot_struct * plot));
                    184:
                    185: int record __PROTO((void));
                    186: void process_event __PROTO((XEvent * event));  /* from Xserver */
                    187:
                    188: void mainloop __PROTO((void));
                    189:
                    190: void display __PROTO((plot_struct * plot));
                    191:
                    192: void reset_cursor __PROTO((void));
                    193:
                    194: void preset __PROTO((int argc, char *argv[]));
                    195: char *pr_GetR __PROTO((XrmDatabase db, char *resource));
                    196: void pr_color __PROTO((void));
                    197: void pr_dashes __PROTO((void));
                    198: void pr_font __PROTO((void));
                    199: void pr_geometry __PROTO((void));
                    200: void pr_pointsize __PROTO((void));
                    201: void pr_width __PROTO((void));
                    202: Window pr_window __PROTO((unsigned int flags, int x, int y, unsigned int width, unsigned height));
                    203: void pr_raise __PROTO((void));
                    204: void pr_persist __PROTO((void));
                    205:
                    206: #ifdef EXPORT_SELECTION
                    207: void export_graph __PROTO((plot_struct * plot));
                    208: void handle_selection_event __PROTO((XEvent * event));
                    209: #endif
                    210:
                    211: #define FallbackFont "fixed"
                    212:
                    213: #define Ncolors 13
                    214: unsigned long colors[Ncolors];
                    215:
                    216: #define Nwidths 10
                    217: unsigned int widths[Nwidths] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    218:
                    219: #define Ndashes 10
                    220: char dashes[Ndashes][5];
                    221:
                    222: #define MAX_WINDOWS 16
                    223:
                    224: #define XC_crosshair 34
                    225:
                    226:
                    227: struct plot_struct plot_array[MAX_WINDOWS];
                    228:
                    229:
                    230: Display *dpy;
                    231: int scr;
                    232: Window root;
                    233: Visual *vis;
                    234: GC gc = (GC) 0;
                    235: XFontStruct *font;
                    236: int do_raise = 1, persist = 0;
                    237: KeyCode q_keycode;
                    238: Cursor cursor;
                    239:
                    240: int windows_open = 0;
                    241:
                    242: int gX = 100, gY = 100;
                    243: unsigned int gW = 640, gH = 450;
                    244: unsigned int gFlags = PSize;
                    245:
                    246: unsigned int BorderWidth = 2;
                    247: unsigned int D;                        /* depth */
                    248:
                    249: Bool Mono = 0, Gray = 0, Rv = 0, Clear = 0;
                    250: char Name[64] = "gnuplot";
                    251: char Class[64] = "Gnuplot";
                    252:
                    253: int cx = 0, cy = 0, vchar;
                    254: double xscale, yscale, pointsize;
                    255: #define X(x) (int) ((x) * xscale)
                    256: #define Y(y) (int) ((4095-(y)) * yscale)
                    257:
                    258: #define Nbuf 1024
                    259: char buf[Nbuf], **commands = (char **) 0;
1.1.1.2 ! maekawa   260: static int buffered_input_available = 0;
1.1       maekawa   261:
                    262: FILE *X11_ipc;
                    263: char X11_ipcpath[32];
                    264:
                    265: /* when using an ICCCM-compliant window manager, we can ask it
                    266:  * to send us an event when user chooses 'close window'. We do this
                    267:  * by setting WM_DELETE_WINDOW atom in property WM_PROTOCOLS
                    268:  */
                    269:
                    270: Atom WM_PROTOCOLS, WM_DELETE_WINDOW;
                    271:
                    272: XPoint Diamond[5], Triangle[4];
                    273: XSegment Plus[2], Cross[2], Star[4];
                    274:
                    275: /*-----------------------------------------------------------------------------
                    276:  *   main program
                    277:  *---------------------------------------------------------------------------*/
                    278:
1.1.1.2 ! maekawa   279: int
        !           280: main(argc, argv)
1.1       maekawa   281: int argc;
                    282: char *argv[];
                    283: {
                    284:
                    285:
                    286: #ifdef OSK
                    287:     /* malloc large blocks, otherwise problems with fragmented mem */
                    288:     _mallocmin(102400);
                    289: #endif
                    290: #ifdef __EMX__
                    291:     /* close open file handles */
                    292:     fcloseall();
                    293: #endif
                    294:
                    295:     FPRINTF((stderr, "gnuplot_X11 starting up\n"));
                    296:
                    297:     preset(argc, argv);
                    298:
                    299: /* set up the alternative cursor */
                    300:     cursor = XCreateFontCursor(dpy, XC_crosshair);
                    301:
                    302:     mainloop();
                    303:
                    304:     if (persist) {
1.1.1.2 ! maekawa   305:        FPRINTF((stderr, "waiting for %d windows\n", windows_open));
1.1       maekawa   306:        /* read x events until all windows have been quit */
                    307:        while (windows_open > 0) {
                    308:            XEvent event;
                    309:            XNextEvent(dpy, &event);
                    310:            process_event(&event);
                    311:        }
                    312:     }
                    313:     XCloseDisplay(dpy);
                    314:
                    315:     FPRINTF((stderr, "exiting\n"));
                    316:
                    317:     EXIT(0);
                    318: }
                    319:
                    320: /*-----------------------------------------------------------------------------
                    321:  *   mainloop processing - process X events and input from gnuplot
                    322:  *
                    323:  *   Three different versions of main loop processing are provided to support
                    324:  *   three different platforms.
                    325:  *
                    326:  *   DEFAULT_X11:     use select() for both X events and input on stdin
                    327:  *                    from gnuplot inboard driver
                    328:  *
                    329:  *   CRIPPLED_SELECT: use select() to service X events and check during
                    330:  *                    select timeout for temporary plot file created
                    331:  *                    by inboard driver
                    332:  *
                    333:  *   VMS:             use XNextEvent to service X events and AST to
                    334:  *                    service input from gnuplot inboard driver on stdin
                    335:  *---------------------------------------------------------------------------*/
                    336:
                    337:
                    338: #ifdef DEFAULT_X11
                    339: /*-----------------------------------------------------------------------------
                    340:  *    DEFAULT_X11 mainloop
                    341:  *---------------------------------------------------------------------------*/
                    342:
1.1.1.2 ! maekawa   343: void
        !           344: mainloop()
1.1       maekawa   345: {
1.1.1.2 ! maekawa   346:     int nf, cn = ConnectionNumber(dpy), in;
        !           347:     fd_set_size_t nfds;
        !           348:     struct timeval timeout, *timer = (struct timeval *) 0;
        !           349:     fd_set tset;
1.1       maekawa   350:
                    351:     X11_ipc = stdin;
                    352:     in = fileno(X11_ipc);
                    353:
                    354: #ifdef ISC22
                    355: /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
                    356:     timeout.tv_sec = 0;                /* select() in ISC2.2 needs timeout */
                    357:     timeout.tv_usec = 300000;  /* otherwise input from gnuplot is */
                    358:     timer = &timeout;          /* suspended til next X event. */
                    359: #endif /* ISC22   (0.3s are short enough not to be noticed */
                    360:
                    361:     while (1) {
                    362:
                    363:        /* XNextEvent does an XFlush() before waiting. But here.
                    364:         * we must ensure that the queue is flushed, since we
                    365:         * dont call XNextEvent until an event arrives. (I have
                    366:         * twice wasted quite some time over this issue, so now
                    367:         * I am making sure of it !
                    368:         */
                    369:
                    370:        XFlush(dpy);
                    371:
1.1.1.2 ! maekawa   372:        FD_ZERO(&tset);
        !           373:        FD_SET(cn, &tset);
        !           374:
        !           375:        /* Don't wait for events if we know that input is
        !           376:         * already sitting in a buffer.  Also don't wait for
        !           377:         * input to become available.
        !           378:        */
        !           379:        if (buffered_input_available) {
        !           380:            timeout.tv_sec  = 0;
        !           381:            timeout.tv_usec = 0;
        !           382:            timer = &timeout;
        !           383:        } else {
        !           384:            timer = (struct timeval *) 0;
        !           385:            FD_SET(in, &tset);
        !           386:        }
        !           387:
        !           388:        nfds = (cn > in) ? cn + 1 : in + 1;
        !           389:
        !           390:        nf = select(nfds, SELECT_FD_SET_CAST &tset, 0, 0, timer);
        !           391:
1.1       maekawa   392:        if (nf < 0) {
                    393:            if (errno == EINTR)
                    394:                continue;
                    395:            fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
                    396:            EXIT(1);
                    397:        }
1.1.1.2 ! maekawa   398:
1.1       maekawa   399:        if (nf > 0)
                    400:            XNoOp(dpy);
                    401:
                    402:        if (FD_ISSET(cn, &tset)) {
                    403:            /* used to use CheckMaskEvent() but that cannot receive
                    404:             * maskable events such as ClientMessage. So now we do
                    405:             * one event, then return to the select.
                    406:             * And that almost works, except that under some Xservers
                    407:             * running without a window manager (e.g. Hummingbird Exceed under Win95)
                    408:             * a bogus ConfigureNotify is sent followed by a valid ConfigureNotify
                    409:             * when the window is maximized.  The two events are queued, apparently
                    410:             * in a single I/O because select() above doesn't see the second, valid
                    411:             * event.  This little loop fixes the problem by flushing the
                    412:             * event queue completely.
                    413:             */
                    414:            XEvent xe;
                    415:            do {
                    416:                XNextEvent(dpy, &xe);
                    417:                process_event(&xe);
                    418:            } while (XPending(dpy));
                    419:        }
1.1.1.2 ! maekawa   420:
        !           421:        if (FD_ISSET(in, &tset) || buffered_input_available) {
        !           422:            if (!record())      /* end of input */
1.1       maekawa   423:                return;
                    424:        }
                    425:     }
                    426: }
                    427:
                    428:
1.1.1.2 ! maekawa   429: #elif defined(CRIPPLED_SELECT)
1.1       maekawa   430: /*-----------------------------------------------------------------------------
                    431:  *    CRIPPLED_SELECT mainloop
                    432:  *---------------------------------------------------------------------------*/
                    433:
1.1.1.2 ! maekawa   434: void
        !           435: mainloop()
1.1       maekawa   436: {
1.1.1.2 ! maekawa   437:     fd_set_size_t nf, nfds, cn = ConnectionNumber(dpy);
1.1       maekawa   438:     struct timeval timeout, *timer;
1.1.1.2 ! maekawa   439:     fd_set tset;
1.1       maekawa   440:     unsigned long all = (unsigned long) (-1L);
                    441:     XEvent xe;
                    442:
                    443:     timeout.tv_sec = 1;
                    444:     timeout.tv_usec = 0;
                    445:     timer = &timeout;
                    446:     sprintf(X11_ipcpath, "/tmp/Gnuplot_%d", getppid());
                    447:     nfds = cn + 1;
                    448:
                    449:     while (1) {
                    450:        XFlush(dpy);            /* see above */
1.1.1.2 ! maekawa   451:
        !           452:        FD_ZERO(&tset);
        !           453:        FD_SET(cn, &tset);
        !           454:
        !           455:        /* Don't wait for events if we know that input is
        !           456:         * already sitting in a buffer.  Also don't wait for
        !           457:         * input to become available.
        !           458:        */
        !           459:        if (buffered_input_available) {
        !           460:            timeout.tv_sec  = 0;
        !           461:            timeout.tv_usec = 0;
        !           462:            timer = &timeout;
        !           463:        } else {
        !           464:            timer = (struct timeval *) 0;
        !           465:            FD_SET(in, &tset);
        !           466:        }
        !           467:
        !           468:        nfds = (cn > in) ? cn + 1 : in + 1;
        !           469:
        !           470:        nf = select(nfds, SELECT_FD_SET_CAST &tset, 0, 0, timer);
        !           471:
1.1       maekawa   472:        if (nf < 0) {
                    473:            if (errno == EINTR)
                    474:                continue;
                    475:            fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
                    476:            EXIT(1);
                    477:        }
1.1.1.2 ! maekawa   478:
        !           479:        if (nf > 0)
        !           480:            XNoOp(dpy);
        !           481:
1.1       maekawa   482:        if (FD_ISSET(cn, &tset)) {
                    483:            while (XCheckMaskEvent(dpy, all, &xe)) {
                    484:                process_event(&xe);
                    485:            }
                    486:        }
                    487:        if ((X11_ipc = fopen(X11_ipcpath, "r"))) {
                    488:            unlink(X11_ipcpath);
                    489:            record();
                    490:            fclose(X11_ipc);
                    491:        }
                    492:     }
                    493: }
                    494:
                    495:
1.1.1.2 ! maekawa   496: #elif defined(VMS)
1.1       maekawa   497: /*-----------------------------------------------------------------------------
                    498:  *    VMS mainloop - Yehavi Bourvine - YEHAVI@VMS.HUJI.AC.IL
                    499:  *---------------------------------------------------------------------------*/
                    500:
                    501: /*  In VMS there is no decent Select(). hence, we have to loop inside
                    502:  *  XGetNextEvent for getting the next X window event. In order to get input
                    503:  *  from the master we assign a channel to SYS$INPUT and use AST's in order to
1.1.1.2 ! maekawa   504:  *  receive data. In order to exit the mainloop, we need to somehow make
        !           505:  *  XNextEvent return from within the ast. We do this with a XSendEvent() to
        !           506:  *  ourselves !
1.1       maekawa   507:  *  This needs a window to send the message to, so we create an unmapped window
                    508:  *  for this purpose. Event type XClientMessage is perfect for this, but it
1.1.1.2 ! maekawa   509:  *  appears that such messages come from elsewhere (motif window manager,
        !           510:  *  perhaps ?) So we need to check fairly carefully that it is the ast event
        !           511:  *  that has been received.
1.1       maekawa   512:  */
                    513:
                    514: #include <iodef.h>
                    515: char STDIIN[] = "SYS$INPUT:";
                    516: short STDIINchannel, STDIINiosb[4];
1.1.1.2 ! maekawa   517: struct {
        !           518:     short size, type;
        !           519:     char *address;
        !           520: } STDIINdesc;
1.1       maekawa   521: char STDIINbuffer[64];
                    522: int status;
                    523:
                    524: ast()
                    525: {
                    526:     int status = sys$qio(0, STDIINchannel, IO$_READVBLK, STDIINiosb, record,
1.1.1.2 ! maekawa   527:                         0, STDIINbuffer, sizeof(STDIINbuffer) - 1, 0, 0, 0, 0);
1.1       maekawa   528:     if ((status & 0x1) == 0)
                    529:        EXIT(status);
                    530: }
                    531:
                    532: Window message_window;
                    533:
1.1.1.2 ! maekawa   534: void
        !           535: mainloop()
1.1       maekawa   536: {
                    537:     /* dummy unmapped window for receiving internally-generated terminate
                    538:      * messages
                    539:      */
                    540:     message_window = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 1, 0, 0);
                    541:
                    542:     STDIINdesc.size = strlen(STDIIN);
                    543:     STDIINdesc.type = 0;
                    544:     STDIINdesc.address = STDIIN;
                    545:     status = sys$assign(&STDIINdesc, &STDIINchannel, 0, 0, 0);
                    546:     if ((status & 0x1) == 0)
                    547:        EXIT(status);
                    548:     ast();
                    549:
                    550:     for (;;) {
                    551:        XEvent xe;
                    552:        XNextEvent(dpy, &xe);
                    553:        if (xe.type == ClientMessage && xe.xclient.window == message_window) {
                    554:            if (xe.xclient.message_type == None &&
                    555:                xe.xclient.format == 8 &&
                    556:                strcmp(xe.xclient.data.b, "die gnuplot die") == 0) {
                    557:                FPRINTF((stderr, "quit message from ast\n"));
                    558:                return;
                    559:            } else {
                    560:                FPRINTF((stderr, "Bogus XClientMessage event from window manager ?\n"));
                    561:            }
                    562:        }
                    563:        process_event(&xe);
                    564:     }
                    565: }
1.1.1.2 ! maekawa   566: #else /* !(DEFAULT_X11 || CRIPPLED_SELECT || VMS */
        !           567: You lose. No mainloop.
        !           568: #endif                         /* !(DEFAULT_X11 || CRIPPLED_SELECT || VMS */
1.1       maekawa   569:
                    570: /* delete a window / plot */
                    571:
1.1.1.2 ! maekawa   572: void
        !           573: delete_plot(plot)
1.1       maekawa   574: plot_struct *plot;
                    575: {
                    576:     int i;
                    577:
                    578:     FPRINTF((stderr, "Delete plot %d\n", plot - plot_array));
                    579:
                    580:     for (i = 0; i < plot->ncommands; ++i)
                    581:        free(plot->commands[i]);
                    582:     plot->ncommands = 0;
                    583:
                    584:     if (plot->window) {
                    585:        FPRINTF((stderr, "Destroy window 0x%x\n", plot->window));
                    586:        XDestroyWindow(dpy, plot->window);
                    587:        plot->window = None;
                    588:        --windows_open;
                    589:     }
                    590:     if (plot->pixmap) {
                    591:        XFreePixmap(dpy, plot->pixmap);
                    592:        plot->pixmap = None;
                    593:     }
                    594:     /* but preserve geometry */
                    595: }
                    596:
                    597:
                    598: /* prepare the plot structure */
                    599:
1.1.1.2 ! maekawa   600: void
        !           601: prepare_plot(plot, term_number)
1.1       maekawa   602: plot_struct *plot;
                    603: int term_number;
                    604: {
                    605:     int i;
                    606:     char *term_name;
                    607:
                    608:     for (i = 0; i < plot->ncommands; ++i)
                    609:        free(plot->commands[i]);
                    610:     plot->ncommands = 0;
                    611:
                    612:     if (!plot->posn_flags) {
                    613:        /* first time this window has been used - use default or -geometry
                    614:         * settings
                    615:         */
                    616:        plot->posn_flags = gFlags;
                    617:        plot->x = gX;
                    618:        plot->y = gY;
                    619:        plot->width = gW;
                    620:        plot->height = gH;
                    621:     }
                    622:     if (!plot->window) {
                    623:        plot->window = pr_window(plot->posn_flags, plot->x, plot->y, plot->width, plot->height);
                    624:        ++windows_open;
                    625:
                    626:        /* append the X11 terminal number (if greater than zero) */
                    627:
                    628:        if (term_number) {
                    629:            char new_name[60];
                    630:            XFetchName(dpy, plot->window, &term_name);
                    631:            FPRINTF((stderr, "Window title is %s\n", term_name));
                    632:
                    633:            sprintf(new_name, "%.55s%3d", term_name, term_number);
                    634:            FPRINTF((stderr, "term_number  is %d\n", term_number));
                    635:
                    636:            XStoreName(dpy, plot->window, new_name);
                    637:
                    638:            sprintf(new_name, "gplt%3d", term_number);
                    639:            XSetIconName(dpy, plot->window, new_name);
                    640:        }
                    641:     }
                    642: /* We don't know that it is the same window as before, so we reset the
                    643:  * cursors for all windows and then define the cursor for the active
                    644:  * window
                    645:  */
                    646:     reset_cursor();
                    647:     XDefineCursor(dpy, plot->window, cursor);
                    648:
                    649: }
                    650:
                    651: /* store a command in a plot structure */
                    652:
1.1.1.2 ! maekawa   653: void
        !           654: store_command(buffer, plot)
1.1       maekawa   655: char *buffer;
                    656: plot_struct *plot;
                    657: {
                    658:     char *p;
                    659:
                    660:     FPRINTF((stderr, "Store in %d : %s", plot - plot_array, buffer));
                    661:
                    662:     if (plot->ncommands >= plot->max_commands) {
                    663:        plot->max_commands = plot->max_commands * 2 + 1;
                    664:        plot->commands = (plot->commands)
                    665:            ? (char **) realloc(plot->commands, plot->max_commands * sizeof(char *))
                    666:        : (char **) malloc(sizeof(char *));
                    667:     }
                    668:     p = (char *) malloc((unsigned) strlen(buffer) + 1);
                    669:     if (!plot->commands || !p) {
                    670:        fputs("gnuplot: can't get memory. X11 aborted.\n", stderr);
                    671:        EXIT(1);
                    672:     }
                    673:     plot->commands[plot->ncommands++] = strcpy(p, buffer);
                    674: }
                    675:
                    676: #ifndef VMS
1.1.1.2 ! maekawa   677:
        !           678: /* Handle input.  Use read instead of fgets because stdio buffering
        !           679: * causes trouble when combined with calls to select.
        !           680: */
        !           681: int
        !           682: read_input ()
        !           683: {
        !           684:     static int rdbuf_size = 10*Nbuf;
        !           685:     static char rdbuf[10*Nbuf-1];
        !           686:     static int total_chars;
        !           687:     static int rdbuf_offset;
        !           688:     static int buf_offset;
        !           689:     static int partial_read = 0;
        !           690:     int fd = fileno (X11_ipc);
        !           691:
        !           692:     if (! partial_read)
        !           693:        buf_offset = 0;
        !           694:
        !           695:     if (! buffered_input_available) {
        !           696:        total_chars = read (fd, rdbuf, rdbuf_size);
        !           697:        buffered_input_available = 1;
        !           698:        partial_read = 0;
        !           699:        rdbuf_offset = 0;
        !           700:        if (total_chars < 0)
        !           701:            return -1;
        !           702:     }
        !           703:
        !           704:     if (rdbuf_offset < total_chars) {
        !           705:        while (rdbuf_offset < total_chars && buf_offset < Nbuf) {
        !           706:            char c = rdbuf[rdbuf_offset++];
        !           707:            buf[buf_offset++] = c;
        !           708:            if (c == '\n')
        !           709:                break;
        !           710:        }
        !           711:
        !           712:        if (buf_offset == Nbuf) {
        !           713:            fputs("\
        !           714: \n\
        !           715: gnuplot: buffer overflow in read_input!\n\
        !           716: gnuplot: X11 aborted.\n", stderr);
        !           717:            EXIT(1);
        !           718:        } else
        !           719:            buf[buf_offset] = NUL;
        !           720:     }
        !           721:
        !           722:     if (rdbuf_offset == total_chars) {
        !           723:        buffered_input_available = 0;
        !           724:        if (buf[buf_offset-1] != '\n')
        !           725:            partial_read = 1;
        !           726:     }
        !           727:
        !           728:     return partial_read;
        !           729: }
        !           730:
        !           731:
1.1       maekawa   732: /*-----------------------------------------------------------------------------
                    733:  *   record - record new plot from gnuplot inboard X11 driver (Unix)
                    734:  *---------------------------------------------------------------------------*/
                    735:
1.1.1.2 ! maekawa   736: int
        !           737: record()
1.1       maekawa   738: {
                    739:     static plot_struct *plot = plot_array;
                    740:
1.1.1.2 ! maekawa   741:     while (1) {
        !           742:        int status = read_input ();
        !           743:        if (status != 0)
        !           744:            return status;
        !           745:
1.1       maekawa   746:        switch (*buf) {
                    747:        case 'G':               /* enter graphics mode */
                    748:            {
1.1.1.2 ! maekawa   749:                int plot_number = atoi(buf + 1);    /* 0 if none specified */
1.1       maekawa   750:
                    751:                if (plot_number < 0 || plot_number >= MAX_WINDOWS)
                    752:                    plot_number = 0;
                    753:
                    754:                FPRINTF((stderr, "plot for window number %d\n", plot_number));
                    755:                plot = plot_array + plot_number;
                    756:                prepare_plot(plot, plot_number);
                    757:                continue;
                    758:            }
                    759:        case 'E':               /* leave graphics mode / suspend */
                    760:            display(plot);
                    761:            return 1;
                    762:        case 'R':               /* leave x11 mode */
                    763:            reset_cursor();
                    764:            return 0;
                    765:        default:
                    766:            store_command(buf, plot);
                    767:            continue;
                    768:        }
                    769:     }
                    770: }
                    771:
                    772: #else /* VMS */
                    773: /*-----------------------------------------------------------------------------
                    774:  *   record - record new plot from gnuplot inboard X11 driver (VMS)
                    775:  *---------------------------------------------------------------------------*/
                    776:
                    777: record()
                    778: {
                    779:     static plot_struct *plot = plot_array;
                    780:
                    781:     int status;
                    782:
                    783:     if ((STDIINiosb[0] & 0x1) == 0)
                    784:        EXIT(STDIINiosb[0]);
                    785:     STDIINbuffer[STDIINiosb[1]] = '\0';
                    786:     strcpy(buf, STDIINbuffer);
                    787:
                    788:     switch (*buf) {
                    789:     case 'G':                  /* enter graphics mode */
                    790:        {
                    791:            int plot_number = atoi(buf + 1);    /* 0 if none specified */
                    792:            if (plot_number < 0 || plot_number >= MAX_WINDOWS)
                    793:                plot_number = 0;
                    794:            FPRINTF((stderr, "plot for window number %d\n", plot_number));
                    795:            plot = plot_array + plot_number;
                    796:            prepare_plot(plot, plot_number);
                    797:            break;
                    798:        }
                    799:     case 'E':                  /* leave graphics mode */
                    800:        display(plot);
                    801:        break;
                    802:     case 'R':                  /* exit x11 mode */
                    803:        FPRINTF((stderr, "received R - sending ClientMessage\n"));
                    804:        reset_cursor();
                    805:        sys$cancel(STDIINchannel);
                    806:        /* this is ridiculous - cook up an event to ourselves,
                    807:         * in order to get the mainloop() out of the XNextEvent() call
                    808:         * it seems that window manager can also send clientmessages,
                    809:         * so put a checksum into the message
                    810:         */
                    811:        {
                    812:            XClientMessageEvent event;
                    813:            event.type = ClientMessage;
                    814:            event.send_event = True;
                    815:            event.display = dpy;
                    816:            event.window = message_window;
                    817:            event.message_type = None;
                    818:            event.format = 8;
                    819:            strcpy(event.data.b, "die gnuplot die");
                    820:            XSendEvent(dpy, message_window, False, 0, (XEvent *) & event);
                    821:            XFlush(dpy);
                    822:        }
                    823:        return;                 /* no ast */
                    824:     default:
                    825:        store_command(buf, plot);
                    826:        break;
                    827:     }
                    828:     ast();
                    829: }
                    830: #endif /* VMS */
                    831:
                    832:
                    833: /*-----------------------------------------------------------------------------
                    834:  *   display - display a stored plot
                    835:  *---------------------------------------------------------------------------*/
                    836:
1.1.1.2 ! maekawa   837: void
        !           838: display(plot)
1.1       maekawa   839: plot_struct *plot;
                    840: {
                    841:     int n, x, y, sw, sl, lt = 0, width, type, point, px, py;
                    842:     int user_width = 1;                /* as specified by plot...linewidth */
                    843:     char *buffer, *str;
                    844:     enum JUSTIFY jmode;
                    845:
                    846:     FPRINTF((stderr, "Display %d ; %d commands\n", plot - plot_array, plot->ncommands));
                    847:
                    848:     if (plot->ncommands == 0)
                    849:        return;
                    850:
                    851:     /* set scaling factor between internal driver & window geometry */
                    852:     xscale = plot->width / 4096.0;
                    853:     yscale = plot->height / 4096.0;
                    854:
                    855:     /* initial point sizes, until overridden with P7xxxxyyyy */
                    856:     px = (int) (xscale * pointsize);
                    857:     py = (int) (yscale * pointsize);
                    858:
                    859:     /* create new pixmap & GC */
                    860:     if (gc)
                    861:        XFreeGC(dpy, gc);
                    862:
                    863:     if (!plot->pixmap) {
1.1.1.2 ! maekawa   864:        FPRINTF((stderr, "Create pixmap %d : %dx%dx%d\n", plot - plot_array, plot->width,
        !           865:                 plot->height, D));
1.1       maekawa   866:        plot->pixmap = XCreatePixmap(dpy, root, plot->width, plot->height, D);
                    867:     }
                    868:     gc = XCreateGC(dpy, plot->pixmap, 0, (XGCValues *) 0);
                    869:
                    870:     XSetFont(dpy, gc, font->fid);
                    871:
                    872:     /* set pixmap background */
                    873:     XSetForeground(dpy, gc, colors[0]);
                    874:     XFillRectangle(dpy, plot->pixmap, gc, 0, 0, plot->width, plot->height);
                    875:     XSetBackground(dpy, gc, colors[0]);
                    876:
                    877:     if (!plot->window) {
                    878:        plot->window = pr_window(plot->posn_flags, plot->x, plot->y, plot->width, plot->height);
                    879:        ++windows_open;
                    880:     }
                    881:     /* top the window but don't put keyboard or mouse focus into it. */
                    882:     if (do_raise)
                    883:        XMapRaised(dpy, plot->window);
                    884:
                    885:     /* momentarily clear the window first if requested */
                    886:     if (Clear) {
                    887:        XClearWindow(dpy, plot->window);
                    888:        XFlush(dpy);
                    889:     }
                    890:     /* loop over accumulated commands from inboard driver */
                    891:     for (n = 0; n < plot->ncommands; n++) {
                    892:        buffer = plot->commands[n];
                    893:
                    894:        /*   X11_vector(x,y) - draw vector  */
                    895:        if (*buffer == 'V') {
                    896:            sscanf(buffer, "V%4d%4d", &x, &y);
                    897:            XDrawLine(dpy, plot->pixmap, gc, X(cx), Y(cy), X(x), Y(y));
                    898:            cx = x;
                    899:            cy = y;
                    900:        }
                    901:        /*   X11_move(x,y) - move  */
                    902:        else if (*buffer == 'M')
                    903:            sscanf(buffer, "M%4d%4d", &cx, &cy);
                    904:
                    905:        /*   X11_put_text(x,y,str) - draw text   */
                    906:        else if (*buffer == 'T') {
                    907:            sscanf(buffer, "T%4d%4d", &x, &y);
                    908:            str = buffer + 9;
                    909:            sl = strlen(str) - 1;
                    910:            sw = XTextWidth(font, str, sl);
                    911:
                    912:            switch (jmode) {
                    913:            case LEFT:
                    914:                sw = 0;
                    915:                break;
                    916:            case CENTRE:
                    917:                sw = -sw / 2;
                    918:                break;
                    919:            case RIGHT:
                    920:                sw = -sw;
                    921:                break;
                    922:            }
                    923:
                    924:            XSetForeground(dpy, gc, colors[2]);
                    925:            XDrawString(dpy, plot->pixmap, gc, X(x) + sw, Y(y) + vchar / 3, str, sl);
                    926:            XSetForeground(dpy, gc, colors[lt + 3]);
                    927:        } else if (*buffer == 'F') {    /* fill box */
                    928:            int style, xtmp, ytmp, w, h;
                    929:
                    930:            if (sscanf(buffer + 1, "%4d%4d%4d%4d%4d", &style, &xtmp, &ytmp, &w, &h) == 5) {
                    931:                /* gnuplot has origin at bottom left, but X uses top left
                    932:                 * There may be an off-by-one (or more) error here.
                    933:                 * style ignored here for the moment
                    934:                 */
1.1.1.2 ! maekawa   935:                ytmp += h;      /* top left corner of rectangle to be filled */
1.1       maekawa   936:                w *= xscale;
                    937:                h *= yscale;
                    938:                XSetForeground(dpy, gc, colors[0]);
                    939:                XFillRectangle(dpy, plot->pixmap, gc, X(xtmp), Y(ytmp), w, h);
                    940:                XSetForeground(dpy, gc, colors[lt + 3]);
                    941:            }
                    942:        }
                    943:        /*   X11_justify_text(mode) - set text justification mode  */
                    944:        else if (*buffer == 'J')
                    945:            sscanf(buffer, "J%4d", (int *) &jmode);
                    946:
                    947:        /*  X11_linewidth(width) - set line width */
                    948:        else if (*buffer == 'W')
                    949:            sscanf(buffer + 1, "%4d", &user_width);
                    950:
                    951:        /*   X11_linetype(type) - set line type  */
                    952:        else if (*buffer == 'L') {
                    953:            sscanf(buffer, "L%4d", &lt);
                    954:            lt = (lt % 8) + 2;
                    955:            /* default width is 0 {which X treats as 1} */
                    956:            width = widths[lt] ? user_width * widths[lt] : user_width;
                    957:            if (dashes[lt][0]) {
                    958:                type = LineOnOffDash;
                    959:                XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
                    960:            } else {
                    961:                type = LineSolid;
                    962:            }
                    963:            XSetForeground(dpy, gc, colors[lt + 3]);
                    964:            XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
                    965:        }
                    966:        /*   X11_point(number) - draw a point */
                    967:        else if (*buffer == 'P') {
                    968:            /* linux sscanf does not like %1d%4d%4d" with Oxxxxyyyy */
                    969:            /* sscanf(buffer, "P%1d%4d%4d", &point, &x, &y); */
                    970:            point = buffer[1] - '0';
                    971:            sscanf(buffer + 2, "%4d%4d", &x, &y);
                    972:            if (point == 7) {
                    973:                /* set point size */
                    974:                px = (int) (x * xscale * pointsize);
                    975:                py = (int) (y * yscale * pointsize);
                    976:            } else {
                    977:                if (type != LineSolid || width != 0) {  /* select solid line */
                    978:                    XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
                    979:                }
                    980:                switch (point) {
                    981:                case 0: /* dot */
                    982:                    XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
                    983:                    break;
                    984:                case 1: /* do diamond */
                    985:                    Diamond[0].x = (short) X(x) - px;
                    986:                    Diamond[0].y = (short) Y(y);
                    987:                    Diamond[1].x = (short) px;
                    988:                    Diamond[1].y = (short) -py;
                    989:                    Diamond[2].x = (short) px;
                    990:                    Diamond[2].y = (short) py;
                    991:                    Diamond[3].x = (short) -px;
                    992:                    Diamond[3].y = (short) py;
                    993:                    Diamond[4].x = (short) -px;
                    994:                    Diamond[4].y = (short) -py;
                    995:
                    996:                    /*
                    997:                     * Should really do a check with XMaxRequestSize()
                    998:                     */
                    999:                    XDrawLines(dpy, plot->pixmap, gc, Diamond, 5, CoordModePrevious);
                   1000:                    XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
                   1001:                    break;
                   1002:                case 2: /* do plus */
                   1003:                    Plus[0].x1 = (short) X(x) - px;
                   1004:                    Plus[0].y1 = (short) Y(y);
                   1005:                    Plus[0].x2 = (short) X(x) + px;
                   1006:                    Plus[0].y2 = (short) Y(y);
                   1007:                    Plus[1].x1 = (short) X(x);
                   1008:                    Plus[1].y1 = (short) Y(y) - py;
                   1009:                    Plus[1].x2 = (short) X(x);
                   1010:                    Plus[1].y2 = (short) Y(y) + py;
                   1011:
                   1012:                    XDrawSegments(dpy, plot->pixmap, gc, Plus, 2);
                   1013:                    break;
                   1014:                case 3: /* do box */
                   1015:                    XDrawRectangle(dpy, plot->pixmap, gc, X(x) - px, Y(y) - py, (px + px), (py + py));
                   1016:                    XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
                   1017:                    break;
                   1018:                case 4: /* do X */
                   1019:                    Cross[0].x1 = (short) X(x) - px;
                   1020:                    Cross[0].y1 = (short) Y(y) - py;
                   1021:                    Cross[0].x2 = (short) X(x) + px;
                   1022:                    Cross[0].y2 = (short) Y(y) + py;
                   1023:                    Cross[1].x1 = (short) X(x) - px;
                   1024:                    Cross[1].y1 = (short) Y(y) + py;
                   1025:                    Cross[1].x2 = (short) X(x) + px;
                   1026:                    Cross[1].y2 = (short) Y(y) - py;
                   1027:
                   1028:                    XDrawSegments(dpy, plot->pixmap, gc, Cross, 2);
                   1029:                    break;
                   1030:                case 5: /* do triangle */
                   1031:                    {
                   1032:                        short temp_x, temp_y;
                   1033:
                   1034:                        temp_x = (short) (1.33 * (double) px + 0.5);
                   1035:                        temp_y = (short) (1.33 * (double) py + 0.5);
                   1036:
                   1037:                        Triangle[0].x = (short) X(x);
                   1038:                        Triangle[0].y = (short) Y(y) - temp_y;
                   1039:                        Triangle[1].x = (short) temp_x;
                   1040:                        Triangle[1].y = (short) 2 *py;
                   1041:                        Triangle[2].x = (short) -(2 * temp_x);
                   1042:                        Triangle[2].y = (short) 0;
                   1043:                        Triangle[3].x = (short) temp_x;
                   1044:                        Triangle[3].y = (short) -(2 * py);
                   1045:
                   1046:                        XDrawLines(dpy, plot->pixmap, gc, Triangle, 4, CoordModePrevious);
                   1047:                        XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
                   1048:                    }
                   1049:                    break;
                   1050:                case 6: /* do star */
                   1051:                    Star[0].x1 = (short) X(x) - px;
                   1052:                    Star[0].y1 = (short) Y(y);
                   1053:                    Star[0].x2 = (short) X(x) + px;
                   1054:                    Star[0].y2 = (short) Y(y);
                   1055:                    Star[1].x1 = (short) X(x);
                   1056:                    Star[1].y1 = (short) Y(y) - py;
                   1057:                    Star[1].x2 = (short) X(x);
                   1058:                    Star[1].y2 = (short) Y(y) + py;
                   1059:                    Star[2].x1 = (short) X(x) - px;
                   1060:                    Star[2].y1 = (short) Y(y) - py;
                   1061:                    Star[2].x2 = (short) X(x) + px;
                   1062:                    Star[2].y2 = (short) Y(y) + py;
                   1063:                    Star[3].x1 = (short) X(x) - px;
                   1064:                    Star[3].y1 = (short) Y(y) + py;
                   1065:                    Star[3].x2 = (short) X(x) + px;
                   1066:                    Star[3].y2 = (short) Y(y) - py;
                   1067:
                   1068:                    XDrawSegments(dpy, plot->pixmap, gc, Star, 4);
                   1069:                    break;
                   1070:                }
                   1071:                if (type != LineSolid || width != 0) {  /* select solid line */
                   1072:                    XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
                   1073:                }
                   1074:            }
                   1075:        }
                   1076:     }
                   1077:
                   1078:     /* set new pixmap as window background */
                   1079:     XSetWindowBackgroundPixmap(dpy, plot->window, plot->pixmap);
                   1080:
                   1081:     /* trigger exposure of background pixmap */
                   1082:     XClearWindow(dpy, plot->window);
                   1083:
                   1084: #ifdef EXPORT_SELECTION
                   1085:     export_graph(plot);
                   1086: #endif
                   1087:
                   1088:     XFlush(dpy);
                   1089: }
                   1090:
                   1091: /*---------------------------------------------------------------------------
                   1092:  *  reset all cursors (since we dont have a record of the previous terminal #)
                   1093:  *---------------------------------------------------------------------------*/
                   1094:
1.1.1.2 ! maekawa  1095: void
        !          1096: reset_cursor()
1.1       maekawa  1097: {
                   1098:     int plot_number;
                   1099:     plot_struct *plot = plot_array;
                   1100:
                   1101:     for (plot_number = 0, plot = plot_array;
                   1102:         plot_number < MAX_WINDOWS;
                   1103:         ++plot_number, ++plot) {
                   1104:        if (plot->window) {
                   1105:            FPRINTF((stderr, "Window for plot %d exists\n", plot_number));
                   1106:            XUndefineCursor(dpy, plot->window);;
                   1107:        }
                   1108:     }
                   1109:
                   1110:     FPRINTF((stderr, "Cursors reset\n"));
                   1111:     return;
                   1112: }
                   1113:
                   1114: /*-----------------------------------------------------------------------------
                   1115:  *   resize - rescale last plot if window resized
                   1116:  *---------------------------------------------------------------------------*/
                   1117:
1.1.1.2 ! maekawa  1118: plot_struct *
        !          1119: find_plot(window)
1.1       maekawa  1120: Window window;
                   1121: {
                   1122:     int plot_number;
                   1123:     plot_struct *plot = plot_array;
                   1124:
                   1125:     for (plot_number = 0, plot = plot_array;
                   1126:         plot_number < MAX_WINDOWS;
                   1127:         ++plot_number, ++plot) {
                   1128:        if (plot->window == window) {
                   1129:            FPRINTF((stderr, "Event for plot %d\n", plot_number));
                   1130:            return plot;
                   1131:        }
                   1132:     }
                   1133:
                   1134:     FPRINTF((stderr, "Bogus window 0x%x in event !\n", window));
                   1135:     return NULL;
                   1136: }
                   1137:
1.1.1.2 ! maekawa  1138: void
        !          1139: process_event(event)
1.1       maekawa  1140: XEvent *event;
                   1141: {
                   1142:     FPRINTF((stderr, "Event 0x%x\n", event->type));
                   1143:
                   1144:     switch (event->type) {
                   1145:     case ConfigureNotify:
                   1146:        {
                   1147:            plot_struct *plot = find_plot(event->xconfigure.window);
                   1148:            if (plot) {
                   1149:                int w = event->xconfigure.width, h = event->xconfigure.height;
                   1150:
                   1151:                /* store settings in case window is closed then recreated */
                   1152:                plot->x = event->xconfigure.x;
                   1153:                plot->y = event->xconfigure.y;
                   1154:                plot->posn_flags = (plot->posn_flags & ~PPosition) | USPosition;
                   1155:
                   1156:                if (w > 1 && h > 1 && (w != plot->width || h != plot->height)) {
                   1157:                    plot->width = w;
                   1158:                    plot->height = h;
                   1159:                    plot->posn_flags = (plot->posn_flags & ~PSize) | USSize;
                   1160:                    if (plot->pixmap) {
                   1161:                        /* it is the wrong size now */
                   1162:                        FPRINTF((stderr, "Free pixmap %d\n", 0));
                   1163:                        XFreePixmap(dpy, plot->pixmap);
                   1164:                        plot->pixmap = None;
                   1165:                    }
                   1166:                    display(plot);
                   1167:                }
                   1168:            }
                   1169:            break;
                   1170:        }
                   1171:     case KeyPress:
                   1172:        if (event->xkey.keycode == q_keycode) {
                   1173:            plot_struct *plot = find_plot(event->xkey.window);
                   1174:            if (plot)
                   1175:                delete_plot(plot);
                   1176:        }
                   1177:        break;
                   1178:     case ClientMessage:
                   1179:        if (event->xclient.message_type == WM_PROTOCOLS &&
                   1180:            event->xclient.format == 32 &&
                   1181:            event->xclient.data.l[0] == WM_DELETE_WINDOW) {
                   1182:            plot_struct *plot = find_plot(event->xclient.window);
                   1183:            if (plot)
                   1184:                delete_plot(plot);
                   1185:        }
                   1186:        break;
                   1187: #ifdef EXPORT_SELECTION
                   1188:     case SelectionNotify:
                   1189:     case SelectionRequest:
                   1190:        handle_selection_event(event);
                   1191:        break;
                   1192: #endif
                   1193:     }
                   1194: }
                   1195:
                   1196: /*-----------------------------------------------------------------------------
                   1197:  *   preset - determine options, open display, create window
                   1198:  *---------------------------------------------------------------------------*/
1.1.1.2 ! maekawa  1199: /*
1.1       maekawa  1200: #define On(v) ( !strcmp(v,"on") || !strcmp(v,"true") || \
                   1201:                 !strcmp(v,"On") || !strcmp(v,"True") || \
                   1202:                 !strcmp(v,"ON") || !strcmp(v,"TRUE") )
1.1.1.2 ! maekawa  1203: */
        !          1204: #define On(v) ( !strnicmp(v,"on",2) || !strnicmp(v,"true",4) )
1.1       maekawa  1205:
                   1206: #define AppDefDir "/usr/lib/X11/app-defaults"
                   1207: #ifndef MAXHOSTNAMELEN
                   1208: #define MAXHOSTNAMELEN 64
                   1209: #endif
                   1210:
                   1211: static XrmDatabase dbCmd, dbApp, dbDef, dbEnv, db = (XrmDatabase) 0;
                   1212:
                   1213: char *pr_GetR(), *getenv(), *type[20];
                   1214: XrmValue value;
                   1215:
                   1216: static XrmOptionDescRec options[] = {
                   1217:     {"-mono", ".mono", XrmoptionNoArg, (caddr_t) "on"},
                   1218:     {"-gray", ".gray", XrmoptionNoArg, (caddr_t) "on"},
                   1219:     {"-clear", ".clear", XrmoptionNoArg, (caddr_t) "on"},
                   1220:     {"-tvtwm", ".tvtwm", XrmoptionNoArg, (caddr_t) "on"},
                   1221:     {"-pointsize", ".pointsize", XrmoptionSepArg, (caddr_t) NULL},
                   1222:     {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
                   1223:     {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL},
                   1224:     {"-geometry", "*geometry", XrmoptionSepArg, (caddr_t) NULL},
                   1225:     {"-background", "*background", XrmoptionSepArg, (caddr_t) NULL},
                   1226:     {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL},
                   1227:     {"-foreground", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
                   1228:     {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
                   1229:     {"-bordercolor", "*bordercolor", XrmoptionSepArg, (caddr_t) NULL},
                   1230:     {"-bd", "*bordercolor", XrmoptionSepArg, (caddr_t) NULL},
                   1231:     {"-borderwidth", ".borderwidth", XrmoptionSepArg, (caddr_t) NULL},
                   1232:     {"-bw", ".borderwidth", XrmoptionSepArg, (caddr_t) NULL},
                   1233:     {"-font", "*font", XrmoptionSepArg, (caddr_t) NULL},
                   1234:     {"-fn", "*font", XrmoptionSepArg, (caddr_t) NULL},
                   1235:     {"-reverse", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"},
                   1236:     {"-rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"},
                   1237:     {"+rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "off"},
                   1238:     {"-iconic", "*iconic", XrmoptionNoArg, (caddr_t) "on"},
                   1239:     {"-synchronous", "*synchronous", XrmoptionNoArg, (caddr_t) "on"},
                   1240:     {"-xnllanguage", "*xnllanguage", XrmoptionSepArg, (caddr_t) NULL},
                   1241:     {"-selectionTimeout", "*selectionTimeout", XrmoptionSepArg, (caddr_t) NULL},
                   1242:     {"-title", ".title", XrmoptionSepArg, (caddr_t) NULL},
                   1243:     {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL},
                   1244:     {"-raise", "*raise", XrmoptionNoArg, (caddr_t) "on"},
                   1245:     {"-noraise", "*raise", XrmoptionNoArg, (caddr_t) "off"},
                   1246:     {"-persist", "*persist", XrmoptionNoArg, (caddr_t) "on"}
                   1247: };
                   1248:
                   1249: #define Nopt (sizeof(options) / sizeof(options[0]))
                   1250:
1.1.1.2 ! maekawa  1251: void
        !          1252: preset(argc, argv)
1.1       maekawa  1253: int argc;
                   1254: char *argv[];
                   1255: {
                   1256:     int Argc = argc;
                   1257:     char **Argv = argv;
                   1258:
                   1259: #ifdef VMS
                   1260:     char *ldisplay = (char *) 0;
                   1261: #else
                   1262:     char *ldisplay = getenv("DISPLAY");
                   1263: #endif
                   1264:     char *home = getenv("HOME");
                   1265:     char *server_defaults, *env, buffer[256];
                   1266:
                   1267:     /* avoid bus error when env vars are not set */
                   1268:     if (ldisplay == NULL)
                   1269:        ldisplay = "";
                   1270:     if (home == NULL)
                   1271:        home = "";
                   1272:
                   1273: /*---set to ignore ^C and ^Z----------------------------------------------*/
                   1274:
                   1275:     signal(SIGINT, SIG_IGN);
                   1276: #ifdef SIGTSTP
                   1277:     signal(SIGTSTP, SIG_IGN);
                   1278: #endif
                   1279:
                   1280: /*---prescan arguments for "-name"----------------------------------------*/
                   1281:
                   1282:     while (++Argv, --Argc > 0) {
                   1283:        if (!strcmp(*Argv, "-name") && Argc > 1) {
1.1.1.2 ! maekawa  1284:            strncpy(Name, Argv[1], sizeof(Name) - 1);
        !          1285:            strncpy(Class, Argv[1], sizeof(Class) - 1);
        !          1286:            /* just in case */
        !          1287:            Name[sizeof(Name)-1] = NUL;
        !          1288:            Class[sizeof(Class)-1] = NUL;
1.1       maekawa  1289:            if (Class[0] >= 'a' && Class[0] <= 'z')
                   1290:                Class[0] -= 0x20;
                   1291:        }
                   1292:     }
                   1293:     Argc = argc;
                   1294:     Argv = argv;
                   1295:
                   1296: /*---parse command line---------------------------------------------------*/
                   1297:
                   1298:     XrmInitialize();
                   1299:     XrmParseCommand(&dbCmd, options, Nopt, Name, &Argc, Argv);
                   1300:     if (Argc > 1) {
                   1301:        fprintf(stderr, "\n\
                   1302: gnuplot: bad option: %s\n\
                   1303: gnuplot: X11 aborted.\n", Argv[1]);
                   1304:        EXIT(1);
                   1305:     }
                   1306:     if (pr_GetR(dbCmd, ".display"))
                   1307:        ldisplay = (char *) value.addr;
                   1308:
                   1309: /*---open display---------------------------------------------------------*/
                   1310:
                   1311:     dpy = XOpenDisplay(ldisplay);
                   1312:     if (!dpy) {
                   1313:        fprintf(stderr, "\n\
                   1314: gnuplot: unable to open display '%s'\n\
                   1315: gnuplot: X11 aborted.\n", ldisplay);
                   1316:        EXIT(1);
                   1317:     }
                   1318:     scr = DefaultScreen(dpy);
                   1319:     vis = DefaultVisual(dpy, scr);
                   1320:     D = DefaultDepth(dpy, scr);
                   1321:     root = DefaultRootWindow(dpy);
                   1322:     server_defaults = XResourceManagerString(dpy);
                   1323:
                   1324: /*---get symcode for key q ---*/
                   1325:
                   1326:     q_keycode = XKeysymToKeycode(dpy, XK_q);
                   1327:
                   1328: /**** atoms we will need later ****/
                   1329:
                   1330:     WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
                   1331:     WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
                   1332:
                   1333:
                   1334: /*---get application defaults--(subset of Xt processing)------------------*/
                   1335:
                   1336: #ifdef VMS
                   1337:     strcpy(buffer, "DECW$USER_DEFAULTS:GNUPLOT_X11.INI");
1.1.1.2 ! maekawa  1338: #elif defined OS2
1.1       maekawa  1339: /* for Xfree86 ... */
                   1340:     {
                   1341:        char *appdefdir = "XFree86/lib/X11/app-defaults";
                   1342:        char *xroot = getenv("X11ROOT");
                   1343:        sprintf(buffer, "%s/%s/%s", xroot, appdefdir, "Gnuplot");
                   1344:     }
1.1.1.2 ! maekawa  1345: # else /* !OS/2 */
        !          1346:     strcpy(buffer, AppDefDir);
        !          1347:     strcat(buffer, "/");
        !          1348:     strcat(buffer, "Gnuplot");
1.1       maekawa  1349: #endif /* !VMS */
                   1350:
                   1351:     dbApp = XrmGetFileDatabase(buffer);
                   1352:     XrmMergeDatabases(dbApp, &db);
                   1353:
                   1354: /*---get server or ~/.Xdefaults-------------------------------------------*/
                   1355:
                   1356:     if (server_defaults)
                   1357:        dbDef = XrmGetStringDatabase(server_defaults);
                   1358:     else {
                   1359: #ifdef VMS
                   1360:        strcpy(buffer, "DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT");
                   1361: #else
1.1.1.2 ! maekawa  1362:        strcpy(buffer, home);
        !          1363:        strcat(buffer, ".Xdefaults");
1.1       maekawa  1364: #endif
                   1365:        dbDef = XrmGetFileDatabase(buffer);
                   1366:     }
                   1367:     XrmMergeDatabases(dbDef, &db);
                   1368:
                   1369: /*---get XENVIRONMENT or  ~/.Xdefaults-hostname---------------------------*/
                   1370:
                   1371: #ifndef VMS
                   1372:     if ((env = getenv("XENVIRONMENT")) != NULL)
                   1373:        dbEnv = XrmGetFileDatabase(env);
                   1374:     else {
                   1375:        char *p = NULL, host[MAXHOSTNAMELEN];
                   1376:
                   1377:        if (GP_SYSTEMINFO(host) < 0) {
                   1378:            fprintf(stderr, "gnuplot: %s failed. X11 aborted.\n", SYSINFO_METHOD);
                   1379:            EXIT(1);
                   1380:        }
                   1381:        if ((p = strchr(host, '.')) != NULL)
                   1382:            *p = '\0';
1.1.1.2 ! maekawa  1383:        strcpy(buffer, home);
        !          1384:        strcat(buffer, "/.Xdefaults-");
        !          1385:        strcat(buffer, host);
1.1       maekawa  1386:        dbEnv = XrmGetFileDatabase(buffer);
                   1387:     }
                   1388:     XrmMergeDatabases(dbEnv, &db);
                   1389: #endif /* not VMS */
                   1390:
                   1391: /*---merge command line options-------------------------------------------*/
                   1392:
                   1393:     XrmMergeDatabases(dbCmd, &db);
                   1394:
                   1395: /*---set geometry, font, colors, line widths, dash styles, point size-----*/
                   1396:
                   1397:     pr_geometry();
                   1398:     pr_font();
                   1399:     pr_color();
                   1400:     pr_width();
                   1401:     pr_dashes();
                   1402:     pr_pointsize();
                   1403:     pr_raise();
                   1404:     pr_persist();
                   1405: }
                   1406:
                   1407: /*-----------------------------------------------------------------------------
                   1408:  *   pr_GetR - get resource from database using "-name" option (if any)
                   1409:  *---------------------------------------------------------------------------*/
                   1410:
                   1411: char *
1.1.1.2 ! maekawa  1412: pr_GetR(xrdb, resource)
1.1       maekawa  1413: XrmDatabase xrdb;
                   1414: char *resource;
                   1415: {
                   1416:     char name[128], class[128], *rc;
                   1417:
                   1418:     strcpy(name, Name);
                   1419:     strcat(name, resource);
                   1420:     strcpy(class, Class);
                   1421:     strcat(class, resource);
                   1422:     rc = XrmGetResource(xrdb, name, class, type, &value)
1.1.1.2 ! maekawa  1423:     ? (char *) value.addr
        !          1424:     : (char *) 0;
1.1       maekawa  1425:     return (rc);
                   1426: }
                   1427:
                   1428: /*-----------------------------------------------------------------------------
                   1429:  *   pr_color - determine color values
                   1430:  *---------------------------------------------------------------------------*/
                   1431:
                   1432: char color_keys[Ncolors][30] = {
                   1433:     "background", "bordercolor", "text", "border", "axis",
                   1434:     "line1", "line2", "line3", "line4",
                   1435:     "line5", "line6", "line7", "line8"
                   1436: };
                   1437: char color_values[Ncolors][30] = {
                   1438:     "white", "black", "black", "black", "black",
                   1439:     "red", "green", "blue", "magenta",
                   1440:     "cyan", "sienna", "orange", "coral"
                   1441: };
                   1442: char gray_values[Ncolors][30] = {
                   1443:     "black", "white", "white", "gray50", "gray50",
                   1444:     "gray100", "gray60", "gray80", "gray40",
                   1445:     "gray90", "gray50", "gray70", "gray30"
                   1446: };
                   1447:
1.1.1.2 ! maekawa  1448: void
        !          1449: pr_color()
1.1       maekawa  1450: {
                   1451:     unsigned long black = BlackPixel(dpy, scr), white = WhitePixel(dpy, scr);
                   1452:     char option[20], color[30], *v, *ctype;
                   1453:     XColor xcolor;
                   1454:     Colormap cmap;
                   1455:     double intensity = -1;
                   1456:     int n;
                   1457:
                   1458:     pr_GetR(db, ".mono") && On(value.addr) && Mono++;
                   1459:     pr_GetR(db, ".gray") && On(value.addr) && Gray++;
                   1460:     pr_GetR(db, ".reverseVideo") && On(value.addr) && Rv++;
                   1461:
                   1462:     if (!Gray && (vis->class == GrayScale || vis->class == StaticGray))
                   1463:        Mono++;
                   1464:
                   1465:     if (!Mono) {
                   1466:        cmap = DefaultColormap(dpy, scr);
                   1467:        ctype = (Gray) ? "Gray" : "Color";
                   1468:
                   1469:        for (n = 0; n < Ncolors; n++) {
                   1470:            strcpy(option, ".");
                   1471:            strcat(option, color_keys[n]);
                   1472:            (n > 1) && strcat(option, ctype);
                   1473:            v = pr_GetR(db, option)
                   1474:                ? (char *) value.addr
                   1475:                : ((Gray) ? gray_values[n] : color_values[n]);
                   1476:
                   1477:            if (sscanf(v, "%30[^,],%lf", color, &intensity) == 2) {
                   1478:                if (intensity < 0 || intensity > 1) {
                   1479:                    fprintf(stderr, "\ngnuplot: invalid color intensity in '%s'\n",
                   1480:                            color);
                   1481:                    intensity = 1;
                   1482:                }
                   1483:            } else {
                   1484:                strcpy(color, v);
                   1485:                intensity = 1;
                   1486:            }
                   1487:
                   1488:            if (!XParseColor(dpy, cmap, color, &xcolor)) {
                   1489:                fprintf(stderr, "\ngnuplot: unable to parse '%s'. Using black.\n",
                   1490:                        color);
                   1491:                colors[n] = black;
                   1492:            } else {
                   1493:                xcolor.red *= intensity;
                   1494:                xcolor.green *= intensity;
                   1495:                xcolor.blue *= intensity;
                   1496:                if (XAllocColor(dpy, cmap, &xcolor)) {
                   1497:                    colors[n] = xcolor.pixel;
                   1498:                } else {
                   1499:                    fprintf(stderr, "\ngnuplot: can't allocate '%s'. Using black.\n",
                   1500:                            v);
                   1501:                    colors[n] = black;
                   1502:                }
                   1503:            }
                   1504:        }
                   1505:     } else {
                   1506:        colors[0] = (Rv) ? black : white;
                   1507:        for (n = 1; n < Ncolors; n++)
                   1508:            colors[n] = (Rv) ? white : black;
                   1509:     }
                   1510: }
                   1511:
                   1512: /*-----------------------------------------------------------------------------
                   1513:  *   pr_dashes - determine line dash styles
                   1514:  *---------------------------------------------------------------------------*/
                   1515:
                   1516: char dash_keys[Ndashes][10] = {
                   1517:     "border", "axis",
                   1518:     "line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8"
                   1519: };
                   1520:
                   1521: char dash_mono[Ndashes][10] = {
                   1522:     "0", "16",
                   1523:     "0", "42", "13", "44", "15", "4441", "42", "13"
                   1524: };
                   1525:
                   1526: char dash_color[Ndashes][10] = {
                   1527:     "0", "16",
                   1528:     "0", "0", "0", "0", "0", "0", "0", "0"
                   1529: };
                   1530:
1.1.1.2 ! maekawa  1531: void
        !          1532: pr_dashes()
1.1       maekawa  1533: {
                   1534:     int n, j, l, ok;
                   1535:     char option[20], *v;
                   1536:
                   1537:     for (n = 0; n < Ndashes; n++) {
                   1538:        strcpy(option, ".");
                   1539:        strcat(option, dash_keys[n]);
                   1540:        strcat(option, "Dashes");
                   1541:        v = pr_GetR(db, option)
                   1542:            ? (char *) value.addr
                   1543:            : ((Mono) ? dash_mono[n] : dash_color[n]);
                   1544:        l = strlen(v);
                   1545:        if (l == 1 && *v == '0') {
                   1546:            dashes[n][0] = (unsigned char) 0;
                   1547:            continue;
                   1548:        }
                   1549:        for (ok = 0, j = 0; j < l; j++) {
                   1550:            v[j] >= '1' && v[j] <= '9' && ok++;
                   1551:        }
                   1552:        if (ok != l || (ok != 2 && ok != 4)) {
                   1553:            fprintf(stderr, "gnuplot: illegal dashes value %s:%s\n", option, v);
                   1554:            dashes[n][0] = (unsigned char) 0;
                   1555:            continue;
                   1556:        }
                   1557:        for (j = 0; j < l; j++) {
                   1558:            dashes[n][j] = (unsigned char) (v[j] - '0');
                   1559:        }
                   1560:        dashes[n][l] = (unsigned char) 0;
                   1561:     }
                   1562: }
                   1563:
                   1564: /*-----------------------------------------------------------------------------
                   1565:  *   pr_font - determine font
                   1566:  *---------------------------------------------------------------------------*/
                   1567:
1.1.1.2 ! maekawa  1568: void
        !          1569: pr_font()
1.1       maekawa  1570: {
                   1571:     char *fontname = pr_GetR(db, ".font");
                   1572:
                   1573:     if (!fontname)
                   1574:        fontname = FallbackFont;
                   1575:     font = XLoadQueryFont(dpy, fontname);
                   1576:     if (!font) {
                   1577:        fprintf(stderr, "\ngnuplot: can't load font '%s'\n", fontname);
                   1578:        fprintf(stderr, "gnuplot: using font '%s' instead.\n", FallbackFont);
                   1579:        font = XLoadQueryFont(dpy, FallbackFont);
                   1580:        if (!font) {
                   1581:            fprintf(stderr, "\
                   1582: gnuplot: can't load font '%s'\n\
                   1583: gnuplot: no useable font - X11 aborted.\n", FallbackFont);
                   1584:            EXIT(1);
                   1585:        }
                   1586:     }
                   1587:     vchar = font->ascent + font->descent;
                   1588: }
                   1589:
                   1590: /*-----------------------------------------------------------------------------
                   1591:  *   pr_geometry - determine window geometry
                   1592:  *---------------------------------------------------------------------------*/
                   1593:
1.1.1.2 ! maekawa  1594: void
        !          1595: pr_geometry()
1.1       maekawa  1596: {
                   1597:     char *geometry = pr_GetR(db, ".geometry");
                   1598:     int x, y, flags;
                   1599:     unsigned int w, h;
                   1600:
                   1601:     if (geometry) {
                   1602:        flags = XParseGeometry(geometry, &x, &y, &w, &h);
                   1603:        if (flags & WidthValue)
                   1604:            gW = w;
                   1605:        if (flags & HeightValue)
                   1606:            gH = h;
                   1607:        if (flags & (WidthValue | HeightValue))
                   1608:            gFlags = (gFlags & ~PSize) | USSize;
                   1609:
                   1610:        if (flags & XValue)
                   1611:            gX = (flags & XNegative) ? x + DisplayWidth(dpy, scr) - gW - BorderWidth * 2 : x;
                   1612:
                   1613:        if (flags & YValue)
                   1614:            gY = (flags & YNegative) ? y + DisplayHeight(dpy, scr) - gH - BorderWidth * 2 : y;
                   1615:
                   1616:        if (flags & (XValue | YValue))
                   1617:            gFlags = (gFlags & ~PPosition) | USPosition;
                   1618:     }
                   1619: }
                   1620:
                   1621: /*-----------------------------------------------------------------------------
                   1622:  *   pr_pointsize - determine size of points for 'points' plotting style
                   1623:  *---------------------------------------------------------------------------*/
                   1624:
1.1.1.2 ! maekawa  1625: void
        !          1626: pr_pointsize()
1.1       maekawa  1627: {
                   1628:     if (pr_GetR(db, ".pointsize")) {
                   1629:        if (sscanf((char *) value.addr, "%lf", &pointsize) == 1) {
                   1630:            if (pointsize <= 0 || pointsize > 10) {
                   1631:                fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
                   1632:                pointsize = 1;
                   1633:            }
                   1634:        } else {
                   1635:            fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
                   1636:            pointsize = 1;
                   1637:        }
                   1638:     } else {
                   1639:        pointsize = 1;
                   1640:     }
                   1641: }
                   1642:
                   1643: /*-----------------------------------------------------------------------------
                   1644:  *   pr_width - determine line width values
                   1645:  *---------------------------------------------------------------------------*/
                   1646:
                   1647: char width_keys[Nwidths][30] = {
                   1648:     "border", "axis",
                   1649:     "line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8"
                   1650: };
                   1651:
1.1.1.2 ! maekawa  1652: void
        !          1653: pr_width()
1.1       maekawa  1654: {
                   1655:     int n;
                   1656:     char option[20], *v;
                   1657:
                   1658:     for (n = 0; n < Nwidths; n++) {
                   1659:        strcpy(option, ".");
                   1660:        strcat(option, width_keys[n]);
                   1661:        strcat(option, "Width");
                   1662:        if ((v = pr_GetR(db, option)) != NULL) {
                   1663:            if (*v < '0' || *v > '4' || strlen(v) > 1)
                   1664:                fprintf(stderr, "gnuplot: illegal width value %s:%s\n", option, v);
                   1665:            else
                   1666:                widths[n] = (unsigned int) atoi(v);
                   1667:        }
                   1668:     }
                   1669: }
                   1670:
                   1671: /*-----------------------------------------------------------------------------
                   1672:  *   pr_window - create window
                   1673:  *---------------------------------------------------------------------------*/
                   1674:
1.1.1.2 ! maekawa  1675: Window
        !          1676: pr_window(flags, x, y, width, height)
1.1       maekawa  1677: unsigned int flags;
                   1678: int x, y;
                   1679: unsigned int width, height;
                   1680: {
                   1681:     char *title = pr_GetR(db, ".title");
                   1682:     static XSizeHints hints;
                   1683:     int Tvtwm = 0;
                   1684:
                   1685:     Window win = XCreateSimpleWindow(dpy, root, x, y, width, height, BorderWidth,
                   1686:                                     colors[1], colors[0]);
                   1687:
                   1688:     /* ask ICCCM-compliant window manager to tell us when close window
                   1689:      * has been chosen, rather than just killing us
                   1690:      */
                   1691:
                   1692:     XChangeProperty(dpy, win, WM_PROTOCOLS, XA_ATOM, 32, PropModeReplace,
                   1693:                    (unsigned char *) &WM_DELETE_WINDOW, 1);
                   1694:
                   1695:     pr_GetR(db, ".clear") && On(value.addr) && Clear++;
                   1696:     pr_GetR(db, ".tvtwm") && On(value.addr) && Tvtwm++;
                   1697:
                   1698:     if (!Tvtwm) {
                   1699:        hints.flags = flags;
                   1700:     } else {
                   1701:        hints.flags = (flags & ~USPosition) | PPosition;        /* ? */
                   1702:     }
                   1703:     hints.x = gX;
                   1704:     hints.y = gY;
                   1705:     hints.width = width;
                   1706:     hints.height = height;
                   1707:
                   1708:     XSetNormalHints(dpy, win, &hints);
                   1709:
                   1710:     if (pr_GetR(db, ".iconic") && On(value.addr)) {
                   1711:        XWMHints wmh;
                   1712:
                   1713:        wmh.flags = StateHint;
                   1714:        wmh.initial_state = IconicState;
                   1715:        XSetWMHints(dpy, win, &wmh);
                   1716:     }
                   1717:     XStoreName(dpy, win, ((title) ? title : Class));
                   1718:
                   1719:     XSelectInput(dpy, win, KeyPressMask | StructureNotifyMask);
                   1720:     XMapWindow(dpy, win);
                   1721:
                   1722:     return win;
                   1723: }
                   1724:
                   1725:
                   1726: /***** pr_raise ***/
1.1.1.2 ! maekawa  1727: void
        !          1728: pr_raise()
1.1       maekawa  1729: {
                   1730:     if (pr_GetR(db, ".raise"))
                   1731:        do_raise = (On(value.addr));
                   1732: }
                   1733:
                   1734:
1.1.1.2 ! maekawa  1735: void
        !          1736: pr_persist()
1.1       maekawa  1737: {
                   1738:     if (pr_GetR(db, ".persist"))
                   1739:        persist = (On(value.addr));
                   1740: }
                   1741:
                   1742: /************ code to handle selection export *********************/
                   1743:
                   1744: #ifdef EXPORT_SELECTION
                   1745:
                   1746: /* bit of a bodge, but ... */
                   1747: static struct plot_struct *exported_plot;
                   1748:
1.1.1.2 ! maekawa  1749: void
        !          1750: export_graph(plot)
1.1       maekawa  1751: struct plot_struct *plot;
                   1752: {
                   1753:     FPRINTF((stderr, "export_graph(0x%x)\n", plot));
                   1754:
                   1755:     XSetSelectionOwner(dpy, EXPORT_SELECTION, plot->window, CurrentTime);
                   1756:     /* to check we have selection, we would have to do a
                   1757:      * GetSelectionOwner(), but if it failed, it failed - no big deal
                   1758:      */
                   1759:     exported_plot = plot;
                   1760: }
                   1761:
1.1.1.2 ! maekawa  1762: void
        !          1763: handle_selection_event(event)
1.1       maekawa  1764: XEvent *event;
                   1765: {
                   1766:     switch (event->type) {
                   1767:     case SelectionRequest:
                   1768:        {
                   1769:            XEvent reply;
                   1770:
                   1771:            static Atom XA_TARGETS = (Atom) 0;
                   1772:            if (XA_TARGETS == 0)
                   1773:                XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
                   1774:
                   1775:            reply.type = SelectionNotify;
                   1776:            reply.xselection.send_event = True;
                   1777:            reply.xselection.display = event->xselectionrequest.display;
                   1778:            reply.xselection.requestor = event->xselectionrequest.requestor;
                   1779:            reply.xselection.selection = event->xselectionrequest.selection;
                   1780:            reply.xselection.target = event->xselectionrequest.target;
                   1781:            reply.xselection.property = event->xselectionrequest.property;
                   1782:            reply.xselection.time = event->xselectionrequest.time;
                   1783:
                   1784:            FPRINTF((stderr, "selection request\n"));
                   1785:
                   1786:            if (reply.xselection.target == XA_TARGETS) {
1.1.1.2 ! maekawa  1787:                static Atom targets[] = { XA_PIXMAP, XA_COLORMAP };
1.1       maekawa  1788:
                   1789:                FPRINTF((stderr, "Targets request from %d\n", reply.xselection.requestor));
                   1790:
                   1791:                XChangeProperty(dpy, reply.xselection.requestor,
                   1792:                                reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
                   1793:                                (unsigned char *) targets, 2);
                   1794:            } else if (reply.xselection.target == XA_COLORMAP) {
                   1795:                Colormap cmap = DefaultColormap(dpy, 0);
                   1796:
                   1797:                FPRINTF((stderr, "colormap request from %d\n", reply.xselection.requestor));
                   1798:
                   1799:                XChangeProperty(dpy, reply.xselection.requestor,
                   1800:                                reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
                   1801:                                (unsigned char *) &cmap, 1);
                   1802:            } else if (reply.xselection.target == XA_PIXMAP) {
                   1803:
                   1804:                FPRINTF((stderr, "pixmap request from %d\n", reply.xselection.requestor));
                   1805:
                   1806:                XChangeProperty(dpy, reply.xselection.requestor,
                   1807:                                reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
1.1.1.2 ! maekawa  1808:                                (unsigned char *) &(exported_plot->pixmap), 1);
1.1       maekawa  1809:            } else {
                   1810:                reply.xselection.property = None;
                   1811:            }
                   1812:
                   1813:            XSendEvent(dpy, reply.xselection.requestor, False, 0L, &reply);
                   1814:            /* we never block on XNextEvent(), so must flush manually
                   1815:             * (took me *ages* to find this out !)
                   1816:             */
                   1817:
                   1818:            XFlush(dpy);
                   1819:        }
                   1820:        break;
                   1821:     }
                   1822: }
                   1823:
                   1824: #endif /* EXPORT_SELECTION */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>