Annotation of OpenXM_contrib/gnuplot/gplt_x11.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: gplt_x11.c,v 1.71 1998/04/14 00:15:22 drd Exp $";
! 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;
! 260:
! 261: FILE *X11_ipc;
! 262: char X11_ipcpath[32];
! 263:
! 264: /* when using an ICCCM-compliant window manager, we can ask it
! 265: * to send us an event when user chooses 'close window'. We do this
! 266: * by setting WM_DELETE_WINDOW atom in property WM_PROTOCOLS
! 267: */
! 268:
! 269: Atom WM_PROTOCOLS, WM_DELETE_WINDOW;
! 270:
! 271: XPoint Diamond[5], Triangle[4];
! 272: XSegment Plus[2], Cross[2], Star[4];
! 273:
! 274: /*-----------------------------------------------------------------------------
! 275: * main program
! 276: *---------------------------------------------------------------------------*/
! 277:
! 278: int main(argc, argv)
! 279: int argc;
! 280: char *argv[];
! 281: {
! 282:
! 283:
! 284: #ifdef OSK
! 285: /* malloc large blocks, otherwise problems with fragmented mem */
! 286: _mallocmin(102400);
! 287: #endif
! 288: #ifdef __EMX__
! 289: /* close open file handles */
! 290: fcloseall();
! 291: #endif
! 292:
! 293: FPRINTF((stderr, "gnuplot_X11 starting up\n"));
! 294:
! 295: preset(argc, argv);
! 296:
! 297: /* set up the alternative cursor */
! 298: cursor = XCreateFontCursor(dpy, XC_crosshair);
! 299:
! 300: mainloop();
! 301:
! 302: if (persist) {
! 303: FPRINTF((stderr, "waiting for %d windows\n, windows_open"));
! 304: /* read x events until all windows have been quit */
! 305: while (windows_open > 0) {
! 306: XEvent event;
! 307: XNextEvent(dpy, &event);
! 308: process_event(&event);
! 309: }
! 310: }
! 311: XCloseDisplay(dpy);
! 312:
! 313: FPRINTF((stderr, "exiting\n"));
! 314:
! 315: EXIT(0);
! 316: }
! 317:
! 318: /*-----------------------------------------------------------------------------
! 319: * mainloop processing - process X events and input from gnuplot
! 320: *
! 321: * Three different versions of main loop processing are provided to support
! 322: * three different platforms.
! 323: *
! 324: * DEFAULT_X11: use select() for both X events and input on stdin
! 325: * from gnuplot inboard driver
! 326: *
! 327: * CRIPPLED_SELECT: use select() to service X events and check during
! 328: * select timeout for temporary plot file created
! 329: * by inboard driver
! 330: *
! 331: * VMS: use XNextEvent to service X events and AST to
! 332: * service input from gnuplot inboard driver on stdin
! 333: *---------------------------------------------------------------------------*/
! 334:
! 335:
! 336: #ifdef DEFAULT_X11
! 337: /*-----------------------------------------------------------------------------
! 338: * DEFAULT_X11 mainloop
! 339: *---------------------------------------------------------------------------*/
! 340:
! 341: void mainloop()
! 342: {
! 343: int nf, nfds, cn = ConnectionNumber(dpy), in;
! 344: struct timeval *timer = (struct timeval *) 0;
! 345: #ifdef ISC22
! 346: struct timeval timeout;
! 347: #endif
! 348: fd_set rset, tset;
! 349:
! 350: X11_ipc = stdin;
! 351: in = fileno(X11_ipc);
! 352:
! 353: FD_ZERO(&rset);
! 354: FD_SET(cn, &rset);
! 355:
! 356: FD_SET(in, &rset);
! 357: nfds = (cn > in) ? cn + 1 : in + 1;
! 358:
! 359: #ifdef ISC22
! 360: /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
! 361: timeout.tv_sec = 0; /* select() in ISC2.2 needs timeout */
! 362: timeout.tv_usec = 300000; /* otherwise input from gnuplot is */
! 363: timer = &timeout; /* suspended til next X event. */
! 364: #endif /* ISC22 (0.3s are short enough not to be noticed */
! 365:
! 366: while (1) {
! 367:
! 368: /* XNextEvent does an XFlush() before waiting. But here.
! 369: * we must ensure that the queue is flushed, since we
! 370: * dont call XNextEvent until an event arrives. (I have
! 371: * twice wasted quite some time over this issue, so now
! 372: * I am making sure of it !
! 373: */
! 374:
! 375: XFlush(dpy);
! 376:
! 377: tset = rset;
! 378: nf = select((gp_nfds_t)nfds, gp_fd_set_p &tset, gp_fd_set_p 0,
! 379: gp_fd_set_p 0, gp_timeval_p timer);
! 380: if (nf < 0) {
! 381: if (errno == EINTR)
! 382: continue;
! 383: fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
! 384: EXIT(1);
! 385: }
! 386: if (nf > 0)
! 387: XNoOp(dpy);
! 388:
! 389: if (FD_ISSET(cn, &tset)) {
! 390: /* used to use CheckMaskEvent() but that cannot receive
! 391: * maskable events such as ClientMessage. So now we do
! 392: * one event, then return to the select.
! 393: * And that almost works, except that under some Xservers
! 394: * running without a window manager (e.g. Hummingbird Exceed under Win95)
! 395: * a bogus ConfigureNotify is sent followed by a valid ConfigureNotify
! 396: * when the window is maximized. The two events are queued, apparently
! 397: * in a single I/O because select() above doesn't see the second, valid
! 398: * event. This little loop fixes the problem by flushing the
! 399: * event queue completely.
! 400: */
! 401: XEvent xe;
! 402: do {
! 403: XNextEvent(dpy, &xe);
! 404: process_event(&xe);
! 405: } while (XPending(dpy));
! 406: }
! 407: if (FD_ISSET(in, &tset)) {
! 408: if (!record()) /* end of input */
! 409: return;
! 410: }
! 411: }
! 412: }
! 413:
! 414: #endif
! 415:
! 416:
! 417: #ifdef CRIPPLED_SELECT
! 418: /*-----------------------------------------------------------------------------
! 419: * CRIPPLED_SELECT mainloop
! 420: *---------------------------------------------------------------------------*/
! 421:
! 422: void mainloop()
! 423: {
! 424: int nf, nfds, cn = ConnectionNumber(dpy);
! 425: struct timeval timeout, *timer;
! 426: fd_set rset, tset;
! 427: unsigned long all = (unsigned long) (-1L);
! 428: XEvent xe;
! 429:
! 430: FD_ZERO(&rset);
! 431: FD_SET(cn, &rset);
! 432:
! 433: timeout.tv_sec = 1;
! 434: timeout.tv_usec = 0;
! 435: timer = &timeout;
! 436: sprintf(X11_ipcpath, "/tmp/Gnuplot_%d", getppid());
! 437: nfds = cn + 1;
! 438:
! 439: while (1) {
! 440: XFlush(dpy); /* see above */
! 441: tset = rset;
! 442: nf = select((gp_nfds_t)nfds, gp_fd_set_p &tset, gp_fd_set_p 0,
! 443: gp_fd_set_p 0, gp_timeval_p timer);
! 444: if (nf < 0) {
! 445: if (errno == EINTR)
! 446: continue;
! 447: fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
! 448: EXIT(1);
! 449: }
! 450: nf > 0 && XNoOp(dpy);
! 451: if (FD_ISSET(cn, &tset)) {
! 452: while (XCheckMaskEvent(dpy, all, &xe)) {
! 453: process_event(&xe);
! 454: }
! 455: }
! 456: if ((X11_ipc = fopen(X11_ipcpath, "r"))) {
! 457: unlink(X11_ipcpath);
! 458: record();
! 459: fclose(X11_ipc);
! 460: }
! 461: }
! 462: }
! 463: #endif /* CRIPPLED_SELECT */
! 464:
! 465:
! 466: #ifdef VMS
! 467: /*-----------------------------------------------------------------------------
! 468: * VMS mainloop - Yehavi Bourvine - YEHAVI@VMS.HUJI.AC.IL
! 469: *---------------------------------------------------------------------------*/
! 470:
! 471: /* In VMS there is no decent Select(). hence, we have to loop inside
! 472: * XGetNextEvent for getting the next X window event. In order to get input
! 473: * from the master we assign a channel to SYS$INPUT and use AST's in order to
! 474: * receive data. In order to exit the mainloop, we need to somehow make XNextEvent
! 475: * return from within the ast. We do this with a XSendEvent() to ourselves !
! 476: * This needs a window to send the message to, so we create an unmapped window
! 477: * for this purpose. Event type XClientMessage is perfect for this, but it
! 478: * appears that such messages come from elsewhere (motif window manager, perhaps ?)
! 479: * So we need to check fairly carefully that it is the ast event that has been received.
! 480: */
! 481:
! 482: #include <iodef.h>
! 483: char STDIIN[] = "SYS$INPUT:";
! 484: short STDIINchannel, STDIINiosb[4];
! 485: struct { short size, type; char *address; } STDIINdesc;
! 486: char STDIINbuffer[64];
! 487: int status;
! 488:
! 489: ast()
! 490: {
! 491: int status = sys$qio(0, STDIINchannel, IO$_READVBLK, STDIINiosb, record,
! 492: 0, STDIINbuffer, sizeof(STDIINbuffer) - 1, 0, 0, 0, 0);
! 493: if ((status & 0x1) == 0)
! 494: EXIT(status);
! 495: }
! 496:
! 497: Window message_window;
! 498:
! 499: void mainloop()
! 500: {
! 501: /* dummy unmapped window for receiving internally-generated terminate
! 502: * messages
! 503: */
! 504: message_window = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 1, 0, 0);
! 505:
! 506: STDIINdesc.size = strlen(STDIIN);
! 507: STDIINdesc.type = 0;
! 508: STDIINdesc.address = STDIIN;
! 509: status = sys$assign(&STDIINdesc, &STDIINchannel, 0, 0, 0);
! 510: if ((status & 0x1) == 0)
! 511: EXIT(status);
! 512: ast();
! 513:
! 514: for (;;) {
! 515: XEvent xe;
! 516: XNextEvent(dpy, &xe);
! 517: if (xe.type == ClientMessage && xe.xclient.window == message_window) {
! 518: if (xe.xclient.message_type == None &&
! 519: xe.xclient.format == 8 &&
! 520: strcmp(xe.xclient.data.b, "die gnuplot die") == 0) {
! 521: FPRINTF((stderr, "quit message from ast\n"));
! 522: return;
! 523: } else {
! 524: FPRINTF((stderr, "Bogus XClientMessage event from window manager ?\n"));
! 525: }
! 526: }
! 527: process_event(&xe);
! 528: }
! 529: }
! 530:
! 531: #endif /* VMS */
! 532:
! 533: /* delete a window / plot */
! 534:
! 535: void delete_plot(plot)
! 536: plot_struct *plot;
! 537: {
! 538: int i;
! 539:
! 540: FPRINTF((stderr, "Delete plot %d\n", plot - plot_array));
! 541:
! 542: for (i = 0; i < plot->ncommands; ++i)
! 543: free(plot->commands[i]);
! 544: plot->ncommands = 0;
! 545:
! 546: if (plot->window) {
! 547: FPRINTF((stderr, "Destroy window 0x%x\n", plot->window));
! 548: XDestroyWindow(dpy, plot->window);
! 549: plot->window = None;
! 550: --windows_open;
! 551: }
! 552: if (plot->pixmap) {
! 553: XFreePixmap(dpy, plot->pixmap);
! 554: plot->pixmap = None;
! 555: }
! 556: /* but preserve geometry */
! 557: }
! 558:
! 559:
! 560: /* prepare the plot structure */
! 561:
! 562: void prepare_plot(plot, term_number)
! 563: plot_struct *plot;
! 564: int term_number;
! 565: {
! 566: int i;
! 567: char *term_name;
! 568:
! 569: for (i = 0; i < plot->ncommands; ++i)
! 570: free(plot->commands[i]);
! 571: plot->ncommands = 0;
! 572:
! 573: if (!plot->posn_flags) {
! 574: /* first time this window has been used - use default or -geometry
! 575: * settings
! 576: */
! 577: plot->posn_flags = gFlags;
! 578: plot->x = gX;
! 579: plot->y = gY;
! 580: plot->width = gW;
! 581: plot->height = gH;
! 582: }
! 583:
! 584: if (!plot->window) {
! 585: plot->window = pr_window(plot->posn_flags, plot->x, plot->y, plot->width, plot->height);
! 586: ++windows_open;
! 587:
! 588: /* append the X11 terminal number (if greater than zero) */
! 589:
! 590: if (term_number) {
! 591: char new_name[60];
! 592: XFetchName(dpy, plot->window, &term_name);
! 593: FPRINTF((stderr, "Window title is %s\n", term_name));
! 594:
! 595: sprintf(new_name, "%.55s%3d", term_name, term_number);
! 596: FPRINTF((stderr, "term_number is %d\n", term_number));
! 597:
! 598: XStoreName(dpy, plot->window, new_name);
! 599:
! 600: sprintf(new_name, "gplt%3d", term_number);
! 601: XSetIconName(dpy, plot->window, new_name);
! 602: }
! 603: }
! 604: /* We don't know that it is the same window as before, so we reset the
! 605: * cursors for all windows and then define the cursor for the active
! 606: * window
! 607: */
! 608: reset_cursor();
! 609: XDefineCursor(dpy, plot->window, cursor);
! 610:
! 611: }
! 612:
! 613: /* store a command in a plot structure */
! 614:
! 615: void store_command(buffer, plot)
! 616: char *buffer;
! 617: plot_struct *plot;
! 618: {
! 619: char *p;
! 620:
! 621: FPRINTF((stderr, "Store in %d : %s", plot - plot_array, buffer));
! 622:
! 623: if (plot->ncommands >= plot->max_commands) {
! 624: plot->max_commands = plot->max_commands * 2 + 1;
! 625: plot->commands = (plot->commands)
! 626: ? (char **) realloc(plot->commands, plot->max_commands * sizeof(char *))
! 627: : (char **) malloc(sizeof(char *));
! 628: }
! 629: p = (char *) malloc((unsigned) strlen(buffer) + 1);
! 630: if (!plot->commands || !p) {
! 631: fputs("gnuplot: can't get memory. X11 aborted.\n", stderr);
! 632: EXIT(1);
! 633: }
! 634: plot->commands[plot->ncommands++] = strcpy(p, buffer);
! 635: }
! 636:
! 637: #ifndef VMS
! 638: /*-----------------------------------------------------------------------------
! 639: * record - record new plot from gnuplot inboard X11 driver (Unix)
! 640: *---------------------------------------------------------------------------*/
! 641:
! 642: int record()
! 643: {
! 644: static plot_struct *plot = plot_array;
! 645:
! 646: while (fgets(buf, Nbuf, X11_ipc)) {
! 647: switch (*buf) {
! 648: case 'G': /* enter graphics mode */
! 649: {
! 650: int plot_number = atoi(buf + 1); /* 0 if none specified */
! 651:
! 652: if (plot_number < 0 || plot_number >= MAX_WINDOWS)
! 653: plot_number = 0;
! 654:
! 655: FPRINTF((stderr, "plot for window number %d\n", plot_number));
! 656: plot = plot_array + plot_number;
! 657: prepare_plot(plot, plot_number);
! 658: continue;
! 659: }
! 660: case 'E': /* leave graphics mode / suspend */
! 661: display(plot);
! 662: return 1;
! 663: case 'R': /* leave x11 mode */
! 664: reset_cursor();
! 665: return 0;
! 666: default:
! 667: store_command(buf, plot);
! 668: continue;
! 669: }
! 670: }
! 671:
! 672: /* get here if fgets fails */
! 673:
! 674: #ifdef OSK
! 675: if (feof(X11_ipc)) /* On OS-9 sometimes while resizing the window, */
! 676: _cleareof(X11_ipc); /* and plotting data, the eof or error flag of */
! 677: if (ferror(X11_ipc)) /* X11_ipc stream gets set, while there is */
! 678: clearerr(X11_ipc); /* nothing wrong! Probably a bug in my select()? */
! 679: #else
! 680: if (feof(X11_ipc) || ferror(X11_ipc))
! 681: return 0;
! 682: #endif /* not OSK */
! 683:
! 684: return 1;
! 685: }
! 686:
! 687: #else /* VMS */
! 688: /*-----------------------------------------------------------------------------
! 689: * record - record new plot from gnuplot inboard X11 driver (VMS)
! 690: *---------------------------------------------------------------------------*/
! 691:
! 692: record()
! 693: {
! 694: static plot_struct *plot = plot_array;
! 695:
! 696: int status;
! 697:
! 698: if ((STDIINiosb[0] & 0x1) == 0)
! 699: EXIT(STDIINiosb[0]);
! 700: STDIINbuffer[STDIINiosb[1]] = '\0';
! 701: strcpy(buf, STDIINbuffer);
! 702:
! 703: switch (*buf) {
! 704: case 'G': /* enter graphics mode */
! 705: {
! 706: int plot_number = atoi(buf + 1); /* 0 if none specified */
! 707: if (plot_number < 0 || plot_number >= MAX_WINDOWS)
! 708: plot_number = 0;
! 709: FPRINTF((stderr, "plot for window number %d\n", plot_number));
! 710: plot = plot_array + plot_number;
! 711: prepare_plot(plot, plot_number);
! 712: break;
! 713: }
! 714: case 'E': /* leave graphics mode */
! 715: display(plot);
! 716: break;
! 717: case 'R': /* exit x11 mode */
! 718: FPRINTF((stderr, "received R - sending ClientMessage\n"));
! 719: reset_cursor();
! 720: sys$cancel(STDIINchannel);
! 721: /* this is ridiculous - cook up an event to ourselves,
! 722: * in order to get the mainloop() out of the XNextEvent() call
! 723: * it seems that window manager can also send clientmessages,
! 724: * so put a checksum into the message
! 725: */
! 726: {
! 727: XClientMessageEvent event;
! 728: event.type = ClientMessage;
! 729: event.send_event = True;
! 730: event.display = dpy;
! 731: event.window = message_window;
! 732: event.message_type = None;
! 733: event.format = 8;
! 734: strcpy(event.data.b, "die gnuplot die");
! 735: XSendEvent(dpy, message_window, False, 0, (XEvent *) & event);
! 736: XFlush(dpy);
! 737: }
! 738: return; /* no ast */
! 739: default:
! 740: store_command(buf, plot);
! 741: break;
! 742: }
! 743: ast();
! 744: }
! 745: #endif /* VMS */
! 746:
! 747:
! 748: /*-----------------------------------------------------------------------------
! 749: * display - display a stored plot
! 750: *---------------------------------------------------------------------------*/
! 751:
! 752: void display(plot)
! 753: plot_struct *plot;
! 754: {
! 755: int n, x, y, sw, sl, lt = 0, width, type, point, px, py;
! 756: int user_width = 1; /* as specified by plot...linewidth */
! 757: char *buffer, *str;
! 758: enum JUSTIFY jmode;
! 759:
! 760: FPRINTF((stderr, "Display %d ; %d commands\n", plot - plot_array, plot->ncommands));
! 761:
! 762: if (plot->ncommands == 0)
! 763: return;
! 764:
! 765: /* set scaling factor between internal driver & window geometry */
! 766: xscale = plot->width / 4096.0;
! 767: yscale = plot->height / 4096.0;
! 768:
! 769: /* initial point sizes, until overridden with P7xxxxyyyy */
! 770: px = (int) (xscale * pointsize);
! 771: py = (int) (yscale * pointsize);
! 772:
! 773: /* create new pixmap & GC */
! 774: if (gc)
! 775: XFreeGC(dpy, gc);
! 776:
! 777: if (!plot->pixmap) {
! 778: FPRINTF((stderr, "Create pixmap %d : %dx%dx%d\n", plot - plot_array, plot->width, plot->height, D));
! 779: plot->pixmap = XCreatePixmap(dpy, root, plot->width, plot->height, D);
! 780: }
! 781:
! 782: gc = XCreateGC(dpy, plot->pixmap, 0, (XGCValues *) 0);
! 783:
! 784: XSetFont(dpy, gc, font->fid);
! 785:
! 786: /* set pixmap background */
! 787: XSetForeground(dpy, gc, colors[0]);
! 788: XFillRectangle(dpy, plot->pixmap, gc, 0, 0, plot->width, plot->height);
! 789: XSetBackground(dpy, gc, colors[0]);
! 790:
! 791: if (!plot->window) {
! 792: plot->window = pr_window(plot->posn_flags, plot->x, plot->y, plot->width, plot->height);
! 793: ++windows_open;
! 794: }
! 795: /* top the window but don't put keyboard or mouse focus into it. */
! 796: if (do_raise)
! 797: XMapRaised(dpy, plot->window);
! 798:
! 799: /* momentarily clear the window first if requested */
! 800: if (Clear) {
! 801: XClearWindow(dpy, plot->window);
! 802: XFlush(dpy);
! 803: }
! 804: /* loop over accumulated commands from inboard driver */
! 805: for (n = 0; n < plot->ncommands; n++) {
! 806: buffer = plot->commands[n];
! 807:
! 808: /* X11_vector(x,y) - draw vector */
! 809: if (*buffer == 'V') {
! 810: sscanf(buffer, "V%4d%4d", &x, &y);
! 811: XDrawLine(dpy, plot->pixmap, gc, X(cx), Y(cy), X(x), Y(y));
! 812: cx = x;
! 813: cy = y;
! 814: }
! 815: /* X11_move(x,y) - move */
! 816: else if (*buffer == 'M')
! 817: sscanf(buffer, "M%4d%4d", &cx, &cy);
! 818:
! 819: /* X11_put_text(x,y,str) - draw text */
! 820: else if (*buffer == 'T') {
! 821: sscanf(buffer, "T%4d%4d", &x, &y);
! 822: str = buffer + 9;
! 823: sl = strlen(str) - 1;
! 824: sw = XTextWidth(font, str, sl);
! 825:
! 826: switch (jmode) {
! 827: case LEFT:
! 828: sw = 0;
! 829: break;
! 830: case CENTRE:
! 831: sw = -sw / 2;
! 832: break;
! 833: case RIGHT:
! 834: sw = -sw;
! 835: break;
! 836: }
! 837:
! 838: XSetForeground(dpy, gc, colors[2]);
! 839: XDrawString(dpy, plot->pixmap, gc, X(x) + sw, Y(y) + vchar / 3, str, sl);
! 840: XSetForeground(dpy, gc, colors[lt + 3]);
! 841: } else if (*buffer == 'F') { /* fill box */
! 842: int style, xtmp, ytmp, w, h;
! 843:
! 844: if (sscanf(buffer + 1, "%4d%4d%4d%4d%4d", &style, &xtmp, &ytmp, &w, &h) == 5) {
! 845: /* gnuplot has origin at bottom left, but X uses top left
! 846: * There may be an off-by-one (or more) error here.
! 847: * style ignored here for the moment
! 848: */
! 849: ytmp += h; /* top left corner of rectangle to be filled */
! 850: w *= xscale;
! 851: h *= yscale;
! 852: XSetForeground(dpy, gc, colors[0]);
! 853: XFillRectangle(dpy, plot->pixmap, gc, X(xtmp), Y(ytmp), w, h);
! 854: XSetForeground(dpy, gc, colors[lt + 3]);
! 855: }
! 856: }
! 857: /* X11_justify_text(mode) - set text justification mode */
! 858: else if (*buffer == 'J')
! 859: sscanf(buffer, "J%4d", (int *) &jmode);
! 860:
! 861: /* X11_linewidth(width) - set line width */
! 862: else if (*buffer == 'W')
! 863: sscanf(buffer + 1, "%4d", &user_width);
! 864:
! 865: /* X11_linetype(type) - set line type */
! 866: else if (*buffer == 'L') {
! 867: sscanf(buffer, "L%4d", <);
! 868: lt = (lt % 8) + 2;
! 869: /* default width is 0 {which X treats as 1} */
! 870: width = widths[lt] ? user_width * widths[lt] : user_width;
! 871: if (dashes[lt][0]) {
! 872: type = LineOnOffDash;
! 873: XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
! 874: } else {
! 875: type = LineSolid;
! 876: }
! 877: XSetForeground(dpy, gc, colors[lt + 3]);
! 878: XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
! 879: }
! 880: /* X11_point(number) - draw a point */
! 881: else if (*buffer == 'P') {
! 882: /* linux sscanf does not like %1d%4d%4d" with Oxxxxyyyy */
! 883: /* sscanf(buffer, "P%1d%4d%4d", &point, &x, &y); */
! 884: point = buffer[1] - '0';
! 885: sscanf(buffer + 2, "%4d%4d", &x, &y);
! 886: if (point == 7) {
! 887: /* set point size */
! 888: px = (int) (x * xscale * pointsize);
! 889: py = (int) (y * yscale * pointsize);
! 890: } else {
! 891: if (type != LineSolid || width != 0) { /* select solid line */
! 892: XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
! 893: }
! 894: switch (point) {
! 895: case 0: /* dot */
! 896: XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
! 897: break;
! 898: case 1: /* do diamond */
! 899: Diamond[0].x = (short) X(x) - px;
! 900: Diamond[0].y = (short) Y(y);
! 901: Diamond[1].x = (short) px;
! 902: Diamond[1].y = (short) -py;
! 903: Diamond[2].x = (short) px;
! 904: Diamond[2].y = (short) py;
! 905: Diamond[3].x = (short) -px;
! 906: Diamond[3].y = (short) py;
! 907: Diamond[4].x = (short) -px;
! 908: Diamond[4].y = (short) -py;
! 909:
! 910: /*
! 911: * Should really do a check with XMaxRequestSize()
! 912: */
! 913: XDrawLines(dpy, plot->pixmap, gc, Diamond, 5, CoordModePrevious);
! 914: XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
! 915: break;
! 916: case 2: /* do plus */
! 917: Plus[0].x1 = (short) X(x) - px;
! 918: Plus[0].y1 = (short) Y(y);
! 919: Plus[0].x2 = (short) X(x) + px;
! 920: Plus[0].y2 = (short) Y(y);
! 921: Plus[1].x1 = (short) X(x);
! 922: Plus[1].y1 = (short) Y(y) - py;
! 923: Plus[1].x2 = (short) X(x);
! 924: Plus[1].y2 = (short) Y(y) + py;
! 925:
! 926: XDrawSegments(dpy, plot->pixmap, gc, Plus, 2);
! 927: break;
! 928: case 3: /* do box */
! 929: XDrawRectangle(dpy, plot->pixmap, gc, X(x) - px, Y(y) - py, (px + px), (py + py));
! 930: XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
! 931: break;
! 932: case 4: /* do X */
! 933: Cross[0].x1 = (short) X(x) - px;
! 934: Cross[0].y1 = (short) Y(y) - py;
! 935: Cross[0].x2 = (short) X(x) + px;
! 936: Cross[0].y2 = (short) Y(y) + py;
! 937: Cross[1].x1 = (short) X(x) - px;
! 938: Cross[1].y1 = (short) Y(y) + py;
! 939: Cross[1].x2 = (short) X(x) + px;
! 940: Cross[1].y2 = (short) Y(y) - py;
! 941:
! 942: XDrawSegments(dpy, plot->pixmap, gc, Cross, 2);
! 943: break;
! 944: case 5: /* do triangle */
! 945: {
! 946: short temp_x, temp_y;
! 947:
! 948: temp_x = (short) (1.33 * (double) px + 0.5);
! 949: temp_y = (short) (1.33 * (double) py + 0.5);
! 950:
! 951: Triangle[0].x = (short) X(x);
! 952: Triangle[0].y = (short) Y(y) - temp_y;
! 953: Triangle[1].x = (short) temp_x;
! 954: Triangle[1].y = (short) 2 *py;
! 955: Triangle[2].x = (short) -(2 * temp_x);
! 956: Triangle[2].y = (short) 0;
! 957: Triangle[3].x = (short) temp_x;
! 958: Triangle[3].y = (short) -(2 * py);
! 959:
! 960: XDrawLines(dpy, plot->pixmap, gc, Triangle, 4, CoordModePrevious);
! 961: XDrawPoint(dpy, plot->pixmap, gc, X(x), Y(y));
! 962: }
! 963: break;
! 964: case 6: /* do star */
! 965: Star[0].x1 = (short) X(x) - px;
! 966: Star[0].y1 = (short) Y(y);
! 967: Star[0].x2 = (short) X(x) + px;
! 968: Star[0].y2 = (short) Y(y);
! 969: Star[1].x1 = (short) X(x);
! 970: Star[1].y1 = (short) Y(y) - py;
! 971: Star[1].x2 = (short) X(x);
! 972: Star[1].y2 = (short) Y(y) + py;
! 973: Star[2].x1 = (short) X(x) - px;
! 974: Star[2].y1 = (short) Y(y) - py;
! 975: Star[2].x2 = (short) X(x) + px;
! 976: Star[2].y2 = (short) Y(y) + py;
! 977: Star[3].x1 = (short) X(x) - px;
! 978: Star[3].y1 = (short) Y(y) + py;
! 979: Star[3].x2 = (short) X(x) + px;
! 980: Star[3].y2 = (short) Y(y) - py;
! 981:
! 982: XDrawSegments(dpy, plot->pixmap, gc, Star, 4);
! 983: break;
! 984: }
! 985: if (type != LineSolid || width != 0) { /* select solid line */
! 986: XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
! 987: }
! 988: }
! 989: }
! 990: }
! 991:
! 992: /* set new pixmap as window background */
! 993: XSetWindowBackgroundPixmap(dpy, plot->window, plot->pixmap);
! 994:
! 995: /* trigger exposure of background pixmap */
! 996: XClearWindow(dpy, plot->window);
! 997:
! 998: #ifdef EXPORT_SELECTION
! 999: export_graph(plot);
! 1000: #endif
! 1001:
! 1002: XFlush(dpy);
! 1003: }
! 1004:
! 1005: /*---------------------------------------------------------------------------
! 1006: * reset all cursors (since we dont have a record of the previous terminal #)
! 1007: *---------------------------------------------------------------------------*/
! 1008:
! 1009: void reset_cursor()
! 1010: {
! 1011: int plot_number;
! 1012: plot_struct *plot = plot_array;
! 1013:
! 1014: for (plot_number = 0, plot = plot_array;
! 1015: plot_number < MAX_WINDOWS;
! 1016: ++plot_number, ++plot) {
! 1017: if (plot->window) {
! 1018: FPRINTF((stderr, "Window for plot %d exists\n", plot_number));
! 1019: XUndefineCursor(dpy, plot->window);;
! 1020: }
! 1021: }
! 1022:
! 1023: FPRINTF((stderr, "Cursors reset\n"));
! 1024: return;
! 1025: }
! 1026:
! 1027: /*-----------------------------------------------------------------------------
! 1028: * resize - rescale last plot if window resized
! 1029: *---------------------------------------------------------------------------*/
! 1030:
! 1031: plot_struct *find_plot(window)
! 1032: Window window;
! 1033: {
! 1034: int plot_number;
! 1035: plot_struct *plot = plot_array;
! 1036:
! 1037: for (plot_number = 0, plot = plot_array;
! 1038: plot_number < MAX_WINDOWS;
! 1039: ++plot_number, ++plot) {
! 1040: if (plot->window == window) {
! 1041: FPRINTF((stderr, "Event for plot %d\n", plot_number));
! 1042: return plot;
! 1043: }
! 1044: }
! 1045:
! 1046: FPRINTF((stderr, "Bogus window 0x%x in event !\n", window));
! 1047: return NULL;
! 1048: }
! 1049:
! 1050: void process_event(event)
! 1051: XEvent *event;
! 1052: {
! 1053: FPRINTF((stderr, "Event 0x%x\n", event->type));
! 1054:
! 1055: switch (event->type) {
! 1056: case ConfigureNotify:
! 1057: {
! 1058: plot_struct *plot = find_plot(event->xconfigure.window);
! 1059: if (plot) {
! 1060: int w = event->xconfigure.width, h = event->xconfigure.height;
! 1061:
! 1062: /* store settings in case window is closed then recreated */
! 1063: plot->x = event->xconfigure.x;
! 1064: plot->y = event->xconfigure.y;
! 1065: plot->posn_flags = (plot->posn_flags & ~PPosition) | USPosition;
! 1066:
! 1067: if (w > 1 && h > 1 && (w != plot->width || h != plot->height)) {
! 1068: plot->width = w;
! 1069: plot->height = h;
! 1070: plot->posn_flags = (plot->posn_flags & ~PSize) | USSize;
! 1071: if (plot->pixmap) {
! 1072: /* it is the wrong size now */
! 1073: FPRINTF((stderr, "Free pixmap %d\n", 0));
! 1074: XFreePixmap(dpy, plot->pixmap);
! 1075: plot->pixmap = None;
! 1076: }
! 1077: display(plot);
! 1078: }
! 1079: }
! 1080: break;
! 1081: }
! 1082: case KeyPress:
! 1083: if (event->xkey.keycode == q_keycode) {
! 1084: plot_struct *plot = find_plot(event->xkey.window);
! 1085: if (plot)
! 1086: delete_plot(plot);
! 1087: }
! 1088: break;
! 1089: case ClientMessage:
! 1090: if (event->xclient.message_type == WM_PROTOCOLS &&
! 1091: event->xclient.format == 32 &&
! 1092: event->xclient.data.l[0] == WM_DELETE_WINDOW) {
! 1093: plot_struct *plot = find_plot(event->xclient.window);
! 1094: if (plot)
! 1095: delete_plot(plot);
! 1096: }
! 1097: break;
! 1098: #ifdef EXPORT_SELECTION
! 1099: case SelectionNotify:
! 1100: case SelectionRequest:
! 1101: handle_selection_event(event);
! 1102: break;
! 1103: #endif
! 1104: }
! 1105: }
! 1106:
! 1107: /*-----------------------------------------------------------------------------
! 1108: * preset - determine options, open display, create window
! 1109: *---------------------------------------------------------------------------*/
! 1110:
! 1111: #define On(v) ( !strcmp(v,"on") || !strcmp(v,"true") || \
! 1112: !strcmp(v,"On") || !strcmp(v,"True") || \
! 1113: !strcmp(v,"ON") || !strcmp(v,"TRUE") )
! 1114:
! 1115: #define AppDefDir "/usr/lib/X11/app-defaults"
! 1116: #ifndef MAXHOSTNAMELEN
! 1117: #define MAXHOSTNAMELEN 64
! 1118: #endif
! 1119:
! 1120: static XrmDatabase dbCmd, dbApp, dbDef, dbEnv, db = (XrmDatabase) 0;
! 1121:
! 1122: char *pr_GetR(), *getenv(), *type[20];
! 1123: XrmValue value;
! 1124:
! 1125: static XrmOptionDescRec options[] = {
! 1126: {"-mono", ".mono", XrmoptionNoArg, (caddr_t) "on"},
! 1127: {"-gray", ".gray", XrmoptionNoArg, (caddr_t) "on"},
! 1128: {"-clear", ".clear", XrmoptionNoArg, (caddr_t) "on"},
! 1129: {"-tvtwm", ".tvtwm", XrmoptionNoArg, (caddr_t) "on"},
! 1130: {"-pointsize", ".pointsize", XrmoptionSepArg, (caddr_t) NULL},
! 1131: {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
! 1132: {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL},
! 1133: {"-geometry", "*geometry", XrmoptionSepArg, (caddr_t) NULL},
! 1134: {"-background", "*background", XrmoptionSepArg, (caddr_t) NULL},
! 1135: {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL},
! 1136: {"-foreground", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
! 1137: {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
! 1138: {"-bordercolor", "*bordercolor", XrmoptionSepArg, (caddr_t) NULL},
! 1139: {"-bd", "*bordercolor", XrmoptionSepArg, (caddr_t) NULL},
! 1140: {"-borderwidth", ".borderwidth", XrmoptionSepArg, (caddr_t) NULL},
! 1141: {"-bw", ".borderwidth", XrmoptionSepArg, (caddr_t) NULL},
! 1142: {"-font", "*font", XrmoptionSepArg, (caddr_t) NULL},
! 1143: {"-fn", "*font", XrmoptionSepArg, (caddr_t) NULL},
! 1144: {"-reverse", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"},
! 1145: {"-rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"},
! 1146: {"+rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "off"},
! 1147: {"-iconic", "*iconic", XrmoptionNoArg, (caddr_t) "on"},
! 1148: {"-synchronous", "*synchronous", XrmoptionNoArg, (caddr_t) "on"},
! 1149: {"-xnllanguage", "*xnllanguage", XrmoptionSepArg, (caddr_t) NULL},
! 1150: {"-selectionTimeout", "*selectionTimeout", XrmoptionSepArg, (caddr_t) NULL},
! 1151: {"-title", ".title", XrmoptionSepArg, (caddr_t) NULL},
! 1152: {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL},
! 1153: {"-raise", "*raise", XrmoptionNoArg, (caddr_t) "on"},
! 1154: {"-noraise", "*raise", XrmoptionNoArg, (caddr_t) "off"},
! 1155: {"-persist", "*persist", XrmoptionNoArg, (caddr_t) "on"}
! 1156: };
! 1157:
! 1158: #define Nopt (sizeof(options) / sizeof(options[0]))
! 1159:
! 1160: void preset(argc, argv)
! 1161: int argc;
! 1162: char *argv[];
! 1163: {
! 1164: int Argc = argc;
! 1165: char **Argv = argv;
! 1166:
! 1167: #ifdef VMS
! 1168: char *ldisplay = (char *) 0;
! 1169: #else
! 1170: char *ldisplay = getenv("DISPLAY");
! 1171: #endif
! 1172: char *home = getenv("HOME");
! 1173: char *server_defaults, *env, buffer[256];
! 1174:
! 1175: /* avoid bus error when env vars are not set */
! 1176: if (ldisplay == NULL)
! 1177: ldisplay = "";
! 1178: if (home == NULL)
! 1179: home = "";
! 1180:
! 1181: /*---set to ignore ^C and ^Z----------------------------------------------*/
! 1182:
! 1183: signal(SIGINT, SIG_IGN);
! 1184: #ifdef SIGTSTP
! 1185: signal(SIGTSTP, SIG_IGN);
! 1186: #endif
! 1187:
! 1188: /*---prescan arguments for "-name"----------------------------------------*/
! 1189:
! 1190: while (++Argv, --Argc > 0) {
! 1191: if (!strcmp(*Argv, "-name") && Argc > 1) {
! 1192: safe_strncpy(Name, Argv[1], sizeof(Name));
! 1193: safe_strncpy(Class, Argv[1], sizeof(Class));
! 1194: if (Class[0] >= 'a' && Class[0] <= 'z')
! 1195: Class[0] -= 0x20;
! 1196: }
! 1197: }
! 1198: Argc = argc;
! 1199: Argv = argv;
! 1200:
! 1201: /*---parse command line---------------------------------------------------*/
! 1202:
! 1203: XrmInitialize();
! 1204: XrmParseCommand(&dbCmd, options, Nopt, Name, &Argc, Argv);
! 1205: if (Argc > 1) {
! 1206: fprintf(stderr, "\n\
! 1207: gnuplot: bad option: %s\n\
! 1208: gnuplot: X11 aborted.\n", Argv[1]);
! 1209: EXIT(1);
! 1210: }
! 1211: if (pr_GetR(dbCmd, ".display"))
! 1212: ldisplay = (char *) value.addr;
! 1213:
! 1214: /*---open display---------------------------------------------------------*/
! 1215:
! 1216: dpy = XOpenDisplay(ldisplay);
! 1217: if (!dpy) {
! 1218: fprintf(stderr, "\n\
! 1219: gnuplot: unable to open display '%s'\n\
! 1220: gnuplot: X11 aborted.\n", ldisplay);
! 1221: EXIT(1);
! 1222: }
! 1223: scr = DefaultScreen(dpy);
! 1224: vis = DefaultVisual(dpy, scr);
! 1225: D = DefaultDepth(dpy, scr);
! 1226: root = DefaultRootWindow(dpy);
! 1227: server_defaults = XResourceManagerString(dpy);
! 1228:
! 1229: /*---get symcode for key q ---*/
! 1230:
! 1231: q_keycode = XKeysymToKeycode(dpy, XK_q);
! 1232:
! 1233: /**** atoms we will need later ****/
! 1234:
! 1235: WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
! 1236: WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
! 1237:
! 1238:
! 1239: /*---get application defaults--(subset of Xt processing)------------------*/
! 1240:
! 1241: #ifdef VMS
! 1242: strcpy(buffer, "DECW$USER_DEFAULTS:GNUPLOT_X11.INI");
! 1243: #else
! 1244: # ifdef OS2
! 1245: /* for Xfree86 ... */
! 1246: {
! 1247: char *appdefdir = "XFree86/lib/X11/app-defaults";
! 1248: char *xroot = getenv("X11ROOT");
! 1249: sprintf(buffer, "%s/%s/%s", xroot, appdefdir, "Gnuplot");
! 1250: }
! 1251: # else
! 1252: sprintf(buffer, "%s/%s", AppDefDir, "Gnuplot");
! 1253: # endif /* !OS2 */
! 1254: #endif /* !VMS */
! 1255:
! 1256: dbApp = XrmGetFileDatabase(buffer);
! 1257: XrmMergeDatabases(dbApp, &db);
! 1258:
! 1259: /*---get server or ~/.Xdefaults-------------------------------------------*/
! 1260:
! 1261: if (server_defaults)
! 1262: dbDef = XrmGetStringDatabase(server_defaults);
! 1263: else {
! 1264: #ifdef VMS
! 1265: strcpy(buffer, "DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT");
! 1266: #else
! 1267: sprintf(buffer, "%s/.Xdefaults", home);
! 1268: #endif
! 1269: dbDef = XrmGetFileDatabase(buffer);
! 1270: }
! 1271: XrmMergeDatabases(dbDef, &db);
! 1272:
! 1273: /*---get XENVIRONMENT or ~/.Xdefaults-hostname---------------------------*/
! 1274:
! 1275: #ifndef VMS
! 1276: if ((env = getenv("XENVIRONMENT")) != NULL)
! 1277: dbEnv = XrmGetFileDatabase(env);
! 1278: else {
! 1279: char *p = NULL, host[MAXHOSTNAMELEN];
! 1280:
! 1281: if (GP_SYSTEMINFO(host) < 0) {
! 1282: fprintf(stderr, "gnuplot: %s failed. X11 aborted.\n", SYSINFO_METHOD);
! 1283: EXIT(1);
! 1284: }
! 1285: if ((p = strchr(host, '.')) != NULL)
! 1286: *p = '\0';
! 1287: sprintf(buffer, "%s/.Xdefaults-%s", home, host);
! 1288: dbEnv = XrmGetFileDatabase(buffer);
! 1289: }
! 1290: XrmMergeDatabases(dbEnv, &db);
! 1291: #endif /* not VMS */
! 1292:
! 1293: /*---merge command line options-------------------------------------------*/
! 1294:
! 1295: XrmMergeDatabases(dbCmd, &db);
! 1296:
! 1297: /*---set geometry, font, colors, line widths, dash styles, point size-----*/
! 1298:
! 1299: pr_geometry();
! 1300: pr_font();
! 1301: pr_color();
! 1302: pr_width();
! 1303: pr_dashes();
! 1304: pr_pointsize();
! 1305: pr_raise();
! 1306: pr_persist();
! 1307: }
! 1308:
! 1309: /*-----------------------------------------------------------------------------
! 1310: * pr_GetR - get resource from database using "-name" option (if any)
! 1311: *---------------------------------------------------------------------------*/
! 1312:
! 1313: char *
! 1314: pr_GetR(xrdb, resource)
! 1315: XrmDatabase xrdb;
! 1316: char *resource;
! 1317: {
! 1318: char name[128], class[128], *rc;
! 1319:
! 1320: strcpy(name, Name);
! 1321: strcat(name, resource);
! 1322: strcpy(class, Class);
! 1323: strcat(class, resource);
! 1324: rc = XrmGetResource(xrdb, name, class, type, &value)
! 1325: ? (char *) value.addr
! 1326: : (char *) 0;
! 1327: return (rc);
! 1328: }
! 1329:
! 1330: /*-----------------------------------------------------------------------------
! 1331: * pr_color - determine color values
! 1332: *---------------------------------------------------------------------------*/
! 1333:
! 1334: char color_keys[Ncolors][30] = {
! 1335: "background", "bordercolor", "text", "border", "axis",
! 1336: "line1", "line2", "line3", "line4",
! 1337: "line5", "line6", "line7", "line8"
! 1338: };
! 1339: char color_values[Ncolors][30] = {
! 1340: "white", "black", "black", "black", "black",
! 1341: "red", "green", "blue", "magenta",
! 1342: "cyan", "sienna", "orange", "coral"
! 1343: };
! 1344: char gray_values[Ncolors][30] = {
! 1345: "black", "white", "white", "gray50", "gray50",
! 1346: "gray100", "gray60", "gray80", "gray40",
! 1347: "gray90", "gray50", "gray70", "gray30"
! 1348: };
! 1349:
! 1350: void pr_color()
! 1351: {
! 1352: unsigned long black = BlackPixel(dpy, scr), white = WhitePixel(dpy, scr);
! 1353: char option[20], color[30], *v, *ctype;
! 1354: XColor xcolor;
! 1355: Colormap cmap;
! 1356: double intensity = -1;
! 1357: int n;
! 1358:
! 1359: pr_GetR(db, ".mono") && On(value.addr) && Mono++;
! 1360: pr_GetR(db, ".gray") && On(value.addr) && Gray++;
! 1361: pr_GetR(db, ".reverseVideo") && On(value.addr) && Rv++;
! 1362:
! 1363: if (!Gray && (vis->class == GrayScale || vis->class == StaticGray))
! 1364: Mono++;
! 1365:
! 1366: if (!Mono) {
! 1367: cmap = DefaultColormap(dpy, scr);
! 1368: ctype = (Gray) ? "Gray" : "Color";
! 1369:
! 1370: for (n = 0; n < Ncolors; n++) {
! 1371: strcpy(option, ".");
! 1372: strcat(option, color_keys[n]);
! 1373: (n > 1) && strcat(option, ctype);
! 1374: v = pr_GetR(db, option)
! 1375: ? (char *) value.addr
! 1376: : ((Gray) ? gray_values[n] : color_values[n]);
! 1377:
! 1378: if (sscanf(v, "%30[^,],%lf", color, &intensity) == 2) {
! 1379: if (intensity < 0 || intensity > 1) {
! 1380: fprintf(stderr, "\ngnuplot: invalid color intensity in '%s'\n",
! 1381: color);
! 1382: intensity = 1;
! 1383: }
! 1384: } else {
! 1385: strcpy(color, v);
! 1386: intensity = 1;
! 1387: }
! 1388:
! 1389: if (!XParseColor(dpy, cmap, color, &xcolor)) {
! 1390: fprintf(stderr, "\ngnuplot: unable to parse '%s'. Using black.\n",
! 1391: color);
! 1392: colors[n] = black;
! 1393: } else {
! 1394: xcolor.red *= intensity;
! 1395: xcolor.green *= intensity;
! 1396: xcolor.blue *= intensity;
! 1397: if (XAllocColor(dpy, cmap, &xcolor)) {
! 1398: colors[n] = xcolor.pixel;
! 1399: } else {
! 1400: fprintf(stderr, "\ngnuplot: can't allocate '%s'. Using black.\n",
! 1401: v);
! 1402: colors[n] = black;
! 1403: }
! 1404: }
! 1405: }
! 1406: } else {
! 1407: colors[0] = (Rv) ? black : white;
! 1408: for (n = 1; n < Ncolors; n++)
! 1409: colors[n] = (Rv) ? white : black;
! 1410: }
! 1411: }
! 1412:
! 1413: /*-----------------------------------------------------------------------------
! 1414: * pr_dashes - determine line dash styles
! 1415: *---------------------------------------------------------------------------*/
! 1416:
! 1417: char dash_keys[Ndashes][10] = {
! 1418: "border", "axis",
! 1419: "line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8"
! 1420: };
! 1421:
! 1422: char dash_mono[Ndashes][10] = {
! 1423: "0", "16",
! 1424: "0", "42", "13", "44", "15", "4441", "42", "13"
! 1425: };
! 1426:
! 1427: char dash_color[Ndashes][10] = {
! 1428: "0", "16",
! 1429: "0", "0", "0", "0", "0", "0", "0", "0"
! 1430: };
! 1431:
! 1432: void pr_dashes()
! 1433: {
! 1434: int n, j, l, ok;
! 1435: char option[20], *v;
! 1436:
! 1437: for (n = 0; n < Ndashes; n++) {
! 1438: strcpy(option, ".");
! 1439: strcat(option, dash_keys[n]);
! 1440: strcat(option, "Dashes");
! 1441: v = pr_GetR(db, option)
! 1442: ? (char *) value.addr
! 1443: : ((Mono) ? dash_mono[n] : dash_color[n]);
! 1444: l = strlen(v);
! 1445: if (l == 1 && *v == '0') {
! 1446: dashes[n][0] = (unsigned char) 0;
! 1447: continue;
! 1448: }
! 1449: for (ok = 0, j = 0; j < l; j++) {
! 1450: v[j] >= '1' && v[j] <= '9' && ok++;
! 1451: }
! 1452: if (ok != l || (ok != 2 && ok != 4)) {
! 1453: fprintf(stderr, "gnuplot: illegal dashes value %s:%s\n", option, v);
! 1454: dashes[n][0] = (unsigned char) 0;
! 1455: continue;
! 1456: }
! 1457: for (j = 0; j < l; j++) {
! 1458: dashes[n][j] = (unsigned char) (v[j] - '0');
! 1459: }
! 1460: dashes[n][l] = (unsigned char) 0;
! 1461: }
! 1462: }
! 1463:
! 1464: /*-----------------------------------------------------------------------------
! 1465: * pr_font - determine font
! 1466: *---------------------------------------------------------------------------*/
! 1467:
! 1468: void pr_font()
! 1469: {
! 1470: char *fontname = pr_GetR(db, ".font");
! 1471:
! 1472: if (!fontname)
! 1473: fontname = FallbackFont;
! 1474: font = XLoadQueryFont(dpy, fontname);
! 1475: if (!font) {
! 1476: fprintf(stderr, "\ngnuplot: can't load font '%s'\n", fontname);
! 1477: fprintf(stderr, "gnuplot: using font '%s' instead.\n", FallbackFont);
! 1478: font = XLoadQueryFont(dpy, FallbackFont);
! 1479: if (!font) {
! 1480: fprintf(stderr, "\
! 1481: gnuplot: can't load font '%s'\n\
! 1482: gnuplot: no useable font - X11 aborted.\n", FallbackFont);
! 1483: EXIT(1);
! 1484: }
! 1485: }
! 1486: vchar = font->ascent + font->descent;
! 1487: }
! 1488:
! 1489: /*-----------------------------------------------------------------------------
! 1490: * pr_geometry - determine window geometry
! 1491: *---------------------------------------------------------------------------*/
! 1492:
! 1493: void pr_geometry()
! 1494: {
! 1495: char *geometry = pr_GetR(db, ".geometry");
! 1496: int x, y, flags;
! 1497: unsigned int w, h;
! 1498:
! 1499: if (geometry) {
! 1500: flags = XParseGeometry(geometry, &x, &y, &w, &h);
! 1501: if (flags & WidthValue)
! 1502: gW = w;
! 1503: if (flags & HeightValue)
! 1504: gH = h;
! 1505: if (flags & (WidthValue | HeightValue))
! 1506: gFlags = (gFlags & ~PSize) | USSize;
! 1507:
! 1508: if (flags & XValue)
! 1509: gX = (flags & XNegative) ? x + DisplayWidth(dpy, scr) - gW - BorderWidth * 2 : x;
! 1510:
! 1511: if (flags & YValue)
! 1512: gY = (flags & YNegative) ? y + DisplayHeight(dpy, scr) - gH - BorderWidth * 2 : y;
! 1513:
! 1514: if (flags & (XValue | YValue))
! 1515: gFlags = (gFlags & ~PPosition) | USPosition;
! 1516: }
! 1517: }
! 1518:
! 1519: /*-----------------------------------------------------------------------------
! 1520: * pr_pointsize - determine size of points for 'points' plotting style
! 1521: *---------------------------------------------------------------------------*/
! 1522:
! 1523: void pr_pointsize()
! 1524: {
! 1525: if (pr_GetR(db, ".pointsize")) {
! 1526: if (sscanf((char *) value.addr, "%lf", &pointsize) == 1) {
! 1527: if (pointsize <= 0 || pointsize > 10) {
! 1528: fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
! 1529: pointsize = 1;
! 1530: }
! 1531: } else {
! 1532: fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
! 1533: pointsize = 1;
! 1534: }
! 1535: } else {
! 1536: pointsize = 1;
! 1537: }
! 1538: }
! 1539:
! 1540: /*-----------------------------------------------------------------------------
! 1541: * pr_width - determine line width values
! 1542: *---------------------------------------------------------------------------*/
! 1543:
! 1544: char width_keys[Nwidths][30] = {
! 1545: "border", "axis",
! 1546: "line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8"
! 1547: };
! 1548:
! 1549: void pr_width()
! 1550: {
! 1551: int n;
! 1552: char option[20], *v;
! 1553:
! 1554: for (n = 0; n < Nwidths; n++) {
! 1555: strcpy(option, ".");
! 1556: strcat(option, width_keys[n]);
! 1557: strcat(option, "Width");
! 1558: if ((v = pr_GetR(db, option)) != NULL) {
! 1559: if (*v < '0' || *v > '4' || strlen(v) > 1)
! 1560: fprintf(stderr, "gnuplot: illegal width value %s:%s\n", option, v);
! 1561: else
! 1562: widths[n] = (unsigned int) atoi(v);
! 1563: }
! 1564: }
! 1565: }
! 1566:
! 1567: /*-----------------------------------------------------------------------------
! 1568: * pr_window - create window
! 1569: *---------------------------------------------------------------------------*/
! 1570:
! 1571: Window pr_window(flags, x, y, width, height)
! 1572: unsigned int flags;
! 1573: int x, y;
! 1574: unsigned int width, height;
! 1575: {
! 1576: char *title = pr_GetR(db, ".title");
! 1577: static XSizeHints hints;
! 1578: int Tvtwm = 0;
! 1579:
! 1580: Window win = XCreateSimpleWindow(dpy, root, x, y, width, height, BorderWidth,
! 1581: colors[1], colors[0]);
! 1582:
! 1583: /* ask ICCCM-compliant window manager to tell us when close window
! 1584: * has been chosen, rather than just killing us
! 1585: */
! 1586:
! 1587: XChangeProperty(dpy, win, WM_PROTOCOLS, XA_ATOM, 32, PropModeReplace,
! 1588: (unsigned char *) &WM_DELETE_WINDOW, 1);
! 1589:
! 1590: pr_GetR(db, ".clear") && On(value.addr) && Clear++;
! 1591: pr_GetR(db, ".tvtwm") && On(value.addr) && Tvtwm++;
! 1592:
! 1593: if (!Tvtwm) {
! 1594: hints.flags = flags;
! 1595: } else {
! 1596: hints.flags = (flags & ~USPosition) | PPosition; /* ? */
! 1597: }
! 1598: hints.x = gX;
! 1599: hints.y = gY;
! 1600: hints.width = width;
! 1601: hints.height = height;
! 1602:
! 1603: XSetNormalHints(dpy, win, &hints);
! 1604:
! 1605: if (pr_GetR(db, ".iconic") && On(value.addr)) {
! 1606: XWMHints wmh;
! 1607:
! 1608: wmh.flags = StateHint;
! 1609: wmh.initial_state = IconicState;
! 1610: XSetWMHints(dpy, win, &wmh);
! 1611: }
! 1612: XStoreName(dpy, win, ((title) ? title : Class));
! 1613:
! 1614: XSelectInput(dpy, win, KeyPressMask | StructureNotifyMask);
! 1615: XMapWindow(dpy, win);
! 1616:
! 1617: return win;
! 1618: }
! 1619:
! 1620:
! 1621: /***** pr_raise ***/
! 1622: void pr_raise()
! 1623: {
! 1624: if (pr_GetR(db, ".raise"))
! 1625: do_raise = (On(value.addr));
! 1626: }
! 1627:
! 1628:
! 1629: void pr_persist()
! 1630: {
! 1631: if (pr_GetR(db, ".persist"))
! 1632: persist = (On(value.addr));
! 1633: }
! 1634:
! 1635: /************ code to handle selection export *********************/
! 1636:
! 1637: #ifdef EXPORT_SELECTION
! 1638:
! 1639: /* bit of a bodge, but ... */
! 1640: static struct plot_struct *exported_plot;
! 1641:
! 1642: void export_graph(plot)
! 1643: struct plot_struct *plot;
! 1644: {
! 1645: FPRINTF((stderr, "export_graph(0x%x)\n", plot));
! 1646:
! 1647: XSetSelectionOwner(dpy, EXPORT_SELECTION, plot->window, CurrentTime);
! 1648: /* to check we have selection, we would have to do a
! 1649: * GetSelectionOwner(), but if it failed, it failed - no big deal
! 1650: */
! 1651: exported_plot = plot;
! 1652: }
! 1653:
! 1654: void handle_selection_event(event)
! 1655: XEvent *event;
! 1656: {
! 1657: switch (event->type) {
! 1658: case SelectionRequest:
! 1659: {
! 1660: XEvent reply;
! 1661:
! 1662: static Atom XA_TARGETS = (Atom) 0;
! 1663: if (XA_TARGETS == 0)
! 1664: XA_TARGETS = XInternAtom(dpy, "TARGETS", False);
! 1665:
! 1666: reply.type = SelectionNotify;
! 1667: reply.xselection.send_event = True;
! 1668: reply.xselection.display = event->xselectionrequest.display;
! 1669: reply.xselection.requestor = event->xselectionrequest.requestor;
! 1670: reply.xselection.selection = event->xselectionrequest.selection;
! 1671: reply.xselection.target = event->xselectionrequest.target;
! 1672: reply.xselection.property = event->xselectionrequest.property;
! 1673: reply.xselection.time = event->xselectionrequest.time;
! 1674:
! 1675: FPRINTF((stderr, "selection request\n"));
! 1676:
! 1677: if (reply.xselection.target == XA_TARGETS) {
! 1678: static Atom targets[] = {XA_PIXMAP, XA_COLORMAP};
! 1679:
! 1680: FPRINTF((stderr, "Targets request from %d\n", reply.xselection.requestor));
! 1681:
! 1682: XChangeProperty(dpy, reply.xselection.requestor,
! 1683: reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
! 1684: (unsigned char *) targets, 2);
! 1685: } else if (reply.xselection.target == XA_COLORMAP) {
! 1686: Colormap cmap = DefaultColormap(dpy, 0);
! 1687:
! 1688: FPRINTF((stderr, "colormap request from %d\n", reply.xselection.requestor));
! 1689:
! 1690: XChangeProperty(dpy, reply.xselection.requestor,
! 1691: reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
! 1692: (unsigned char *) &cmap, 1);
! 1693: } else if (reply.xselection.target == XA_PIXMAP) {
! 1694:
! 1695: FPRINTF((stderr, "pixmap request from %d\n", reply.xselection.requestor));
! 1696:
! 1697: XChangeProperty(dpy, reply.xselection.requestor,
! 1698: reply.xselection.property, reply.xselection.target, 32, PropModeReplace,
! 1699: (unsigned char *) &(exported_plot->pixmap), 1);
! 1700: } else {
! 1701: reply.xselection.property = None;
! 1702: }
! 1703:
! 1704: XSendEvent(dpy, reply.xselection.requestor, False, 0L, &reply);
! 1705: /* we never block on XNextEvent(), so must flush manually
! 1706: * (took me *ages* to find this out !)
! 1707: */
! 1708:
! 1709: XFlush(dpy);
! 1710: }
! 1711: break;
! 1712: }
! 1713: }
! 1714:
! 1715: #endif /* EXPORT_SELECTION */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>