PLplot 5.15.0
Loading...
Searching...
No Matches
plplotter.c
Go to the documentation of this file.
1// Copyright (C) 2004 Joao Cardoso
2//
3// This file is part of PLplot.
4//
5// PLplot is free software; you can redistribute it and/or modify
6// it under the terms of the GNU Library General Public License as published
7// by the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// PLplot is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Library General Public License for more details.
14//
15// You should have received a copy of the GNU Library General Public License
16// along with PLplot; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18//
19//
20
21//
22// plplotter.c
23//
24// Copyright 1993, 1994, 1995
25// Maurice LeBrun mjl@dino.ph.utexas.edu
26// Institute for Fusion Studies University of Texas at Austin
27//
28// This library is free software; you can redistribute it and/or
29// modify it under the terms of the GNU Library General Public
30// License as published by the Free Software Foundation; either
31// version 2 of the License, or (at your option) any later version.
32//
33// This library is distributed in the hope that it will be useful,
34// but WITHOUT ANY WARRANTY; without even the implied warranty of
35// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36// Library General Public License for more details.
37//
38// You should have received a copy of the GNU Library General Public
39// License along with this library; if not, write to the Free Software
40// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41//
42// Based upon tkFrame.c from the TK 3.2 distribution:
43//
44// Copyright 1990 Regents of the University of California.
45// Permission to use, copy, modify, and distribute this
46// software and its documentation for any purpose and without
47// fee is hereby granted, provided that the above copyright
48// notice appear in all copies. The University of California
49// makes no representations about the suitability of this
50// software for any purpose. It is provided "as is" without
51// express or implied warranty.
52//
53//--------------------------------------------------------------------------
54//
55// This module implements "plframe" widgets for the Tk toolkit. These are
56// frames that have extra logic to allow them to be interfaced with the
57// PLplot X driver. These are then drawn into and respond to keyboard and
58// mouse events.
59//
60//
61// #define DEBUG_ENTER
62// #define DEBUG
63//
64
65#define NEED_PLDEBUG
66#include "plserver.h"
67#include "pltkwd.h"
68#include "tcpip.h"
69
70#ifdef _WIN32
71#define XSynchronize( display, bool ) { display->request++; }
72#define XSync( display, bool ) { display->request++; }
73#define XFlush( display )
74#endif
75
76#ifdef DEBUG_ENTER
77// This version of dbug_enter works cross-platform
78#undef dbug_enter
79#define dbug_enter( a ) if ( plsc->debug ) { \
80 Tcl_Write( Tcl_GetStdChannel( TCL_STDERR ), a, -1 ); }
81#endif
82
83#ifndef _WIN32
84#ifdef PL_HAVE_UNISTD_H
85#include <unistd.h>
86#include <fcntl.h>
87#endif
88#endif
89
90// plplot_tkwin_ccmap is statically defined in pltkwd.h. Note that
91// tkwin.c also includes that header and uses that variable.
92
93#define NDEV 100 // Max number of output device types
94
95//
96// A data structure of the following type is kept for each
97// plframe that currently exists for this process:
98//
99
100typedef struct PlPlotter
101{
102// This is stuff taken from tkFrame.c
103
104 Tk_Window tkwin; // Window that embodies the frame. NULL
105 // means that the window has been destroyed
106 // but the data structures haven't yet been
107 // cleaned up.
108 Display *display; // Display containing widget. Used, among
109 // other things, so that resources can be
110 // freed even after tkwin has gone away.
111 Tcl_Interp *interp; // Interpreter associated with
112 // widget. Used to delete widget
113 // command.
114 Tcl_Command widgetCmd; // Token for frame's widget command.
115 Tk_3DBorder border; // Structure used to draw 3-D border and
116 // background.
117 int borderWidth; // Width of 3-D border (if any).
118 int relief; // 3-d effect: TK_RELIEF_RAISED etc.
119 int width; // Width to request for window. <= 0 means
120 // don't request any size.
121 int height; // Height to request for window. <= 0 means
122 // don't request any size.
123 Tk_Cursor cursor; // Current cursor for window, or None.
124 int flags; // Various flags; see below for
125 // definitions.
126
127// These are new to plframe widgets
128
129// control stuff
130
131 int tkwin_initted; // Set first time widget is mapped
132 PLStream *pls; // PLplot stream pointer
133 PLINT ipls; // PLplot stream number
134 PLINT ipls_save; // PLplot stream number, save files
135
136 PLRDev *plr; // Renderer state information. Malloc'ed
137 char *plpr_cmd; // Holds print command name. Malloc'ed
138
139// Used to allow active stuff on the plot
140 int active_plot; // The plot responds to mouse movement etc.
141 int isActive; // Used to turn event handling on and off.
142
143// Used to handle resize and expose events
144
145 PLDisplay pldis; // Info about the display window
146 int prevWidth; // Previous window width
147 int prevHeight; // Previous window height
148
149// Support for save operations
150
151 char *SaveFnam; // File name we are currently saving to.
152 // Malloc'ed.
153 const char **devDesc; // Descriptive names for file-oriented
154 // devices. Malloc'ed.
155 const char **devName; // Keyword names of file-oriented devices.
156 // Malloc'ed.
157
158// Used in selecting & modifying plot or device area
159
160 GC xorGC; // GC used for rubber-band drawing
161 XPoint pts[5]; // Points for rubber-band drawing
162 int continue_draw; // Set when doing rubber-band draws
163 Tk_Cursor xhair_cursor; // cursor used for drawing
164 PLFLT xl, xr, yl, yr; // Bounds on plot viewing area
165 char *xScrollCmd; // Command prefix for communicating with
166 // horizontal scrollbar. NULL means no
167 // command to issue. Malloc'ed.
168 char *yScrollCmd; // Command prefix for communicating with
169 // vertical scrollbar. NULL means no
170 // command to issue. Malloc'ed.
171
172// Used for flashing bop or eop condition
173
174 char *bopCmd; // Proc to call at bop
175 char *eopCmd; // Proc to call at eop
176
177// Used for drawing graphic crosshairs
178
179 int xhairs; // Configuration option to turn on xhairs
180 int drawing_xhairs; // Set if we are currently drawing xhairs
181 XPoint xhair_x[2]; // Points for horizontal xhair line
182 XPoint xhair_y[2]; // Points for vertical xhair line
183
184// Used for drawing a rubber band lilne segment
185
186 int rband; // Configuration option to turn on rband
187 int drawing_rband; // See if we are currently drawing rband
188 XPoint rband_pt[2]; // Ends of rubber band line
189 int double_buffer; // Double buffering configuration option
191
192//
193// Flag bits for plframes:
194//
195// REFRESH_PENDING: Non-zero means a DoWhenIdle handler
196// has already been queued to refresh
197// this window.
198// RESIZE_PENDING; Used to reschedule resize events
199// REDRAW_PENDING; Used to redraw contents of plot buffer
200// UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs
201// to be updated.
202// UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs
203// to be updated.
204//
205
206#define REFRESH_PENDING 1
207#define RESIZE_PENDING 2
208#define REDRAW_PENDING 4
209#define UPDATE_V_SCROLLBAR 8
210#define UPDATE_H_SCROLLBAR 16
211
212// Defaults for plframes:
213
214#define DEF_PLFRAME_BG_COLOR "Black"
215#define DEF_PLFRAME_BG_MONO "White"
216#define DEF_PLFRAME_BORDER_WIDTH "0"
217#define DEF_PLFRAME_CURSOR ( (char *) NULL )
218#define DEF_PLFRAME_HEIGHT "250"
219#define DEF_PLFRAME_RELIEF "flat"
220#define DEF_PLFRAME_WIDTH "250"
221
222// Configuration info
223
224static Tk_ConfigSpec configSpecs[] = {
225 { TK_CONFIG_BOOLEAN, "-activeplot", (char *) NULL, (char *) NULL,
226 "1", offsetof( PlPlotter, active_plot ), TK_CONFIG_DONT_SET_DEFAULT },
227 { TK_CONFIG_BORDER, "-background", "background", "Background",
228 DEF_PLFRAME_BG_COLOR, offsetof( PlPlotter, border ),
229 TK_CONFIG_COLOR_ONLY },
230 { TK_CONFIG_BORDER, "-background", "background", "Background",
231 DEF_PLFRAME_BG_MONO, offsetof( PlPlotter, border ),
232 TK_CONFIG_MONO_ONLY },
233 { TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
234 (char *) NULL, 0, 0 },
235 { TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
236 (char *) NULL, 0, 0 },
237 { TK_CONFIG_STRING, "-bopcmd", "bopcmd", "PgCommand",
238 (char *) NULL, offsetof( PlPlotter, bopCmd ), TK_CONFIG_NULL_OK },
239 { TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
240 DEF_PLFRAME_BORDER_WIDTH, offsetof( PlPlotter, borderWidth ), 0 },
241 { TK_CONFIG_BOOLEAN, "-doublebuffer", (char *) NULL, (char *) NULL,
242 "0", offsetof( PlPlotter, double_buffer ), TK_CONFIG_DONT_SET_DEFAULT },
243 { TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
244 DEF_PLFRAME_CURSOR, offsetof( PlPlotter, cursor ), TK_CONFIG_NULL_OK },
245 { TK_CONFIG_STRING, "-eopcmd", "eopcmd", "PgCommand",
246 (char *) NULL, offsetof( PlPlotter, eopCmd ), TK_CONFIG_NULL_OK },
247 { TK_CONFIG_PIXELS, "-height", "height", "Height",
248 DEF_PLFRAME_HEIGHT, offsetof( PlPlotter, height ), 0 },
249 { TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
250 DEF_PLFRAME_RELIEF, offsetof( PlPlotter, relief ), 0 },
251 { TK_CONFIG_PIXELS, "-width", "width", "Width",
252 DEF_PLFRAME_WIDTH, offsetof( PlPlotter, width ), 0 },
253 { TK_CONFIG_BOOLEAN, "-xhairs", (char *) NULL, (char *) NULL,
254 "0", offsetof( PlPlotter, xhairs ), TK_CONFIG_DONT_SET_DEFAULT },
255 { TK_CONFIG_BOOLEAN, "-rubberband", (char *) NULL, (char *) NULL,
256 "0", offsetof( PlPlotter, rband ), TK_CONFIG_DONT_SET_DEFAULT },
257 { TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
258 (char *) NULL, offsetof( PlPlotter, xScrollCmd ), TK_CONFIG_NULL_OK },
259 { TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
260 (char *) NULL, offsetof( PlPlotter, yScrollCmd ), TK_CONFIG_NULL_OK },
261 { TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
262 (char *) NULL, 0, 0 }
263};
264
265// Forward declarations for procedures defined later in this file:
266
267// Externals
268
269int plPlotterCmd( ClientData, Tcl_Interp *, int, const char ** );
270void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
271void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
272
273// These are invoked by the TK dispatcher
274
275static void DestroyPlPlotter( ClientData );
276static void DisplayPlPlotter( ClientData );
277static void PlPlotterInit( ClientData );
278static void PlPlotterFirstInit( ClientData clientData );
279static void PlPlotterConfigureEH( ClientData, XEvent * );
280static void PlPlotterExposeEH( ClientData, XEvent * );
281static void PlPlotterMotionEH( ClientData, register XEvent * );
282static void PlPlotterEnterEH( ClientData, register XEvent * );
283static void PlPlotterLeaveEH( ClientData, register XEvent * );
284static void PlPlotterButtonPressEH( ClientData clientData, register XEvent * );
285static int PlPlotterWidgetCmd( ClientData, Tcl_Interp *, int, const char ** );
286static int ReadData( ClientData, int );
287static void Install_cmap( PlPlotter *plPlotterPtr );
288
289// These are invoked by PlPlotterWidgetCmd to process widget commands
290
291static int Closelink( Tcl_Interp *, PlPlotter *, int, const char ** );
292static int Cmd( Tcl_Interp *, PlPlotter *, int, const char ** );
293static int ConfigurePlPlotter( Tcl_Interp *, PlPlotter *, int, const char **, int );
294static int Draw( Tcl_Interp *, PlPlotter *, int, const char ** );
295static int Info( Tcl_Interp *, PlPlotter *, int, const char ** );
296static int Openlink( Tcl_Interp *, PlPlotter *, int, const char ** );
297static int Orient( Tcl_Interp *, PlPlotter *, int, const char ** );
298static int Page( Tcl_Interp *, PlPlotter *, int, const char ** );
299static int NextPage( Tcl_Interp *, PlPlotter *, int, const char ** );
300static int Print( Tcl_Interp *, PlPlotter *, int, const char ** );
301static int Redraw( Tcl_Interp *, PlPlotter *, int, const char ** );
302static int Save( Tcl_Interp *, PlPlotter *, int, const char ** );
303static int View( Tcl_Interp *, PlPlotter *, int, const char ** );
304static int Scroll( Tcl_Interp *, PlPlotter * );
305static int report( Tcl_Interp *, PlPlotter *, int, const char ** );
306
307// Routines for manipulating graphic crosshairs
308
309static void ActiveState( register PlPlotter *plPlotterPtr, int on );
310static void CreateXhairs( PlPlotter * );
311static void DestroyXhairs( PlPlotter * );
312static void DrawXhairs( PlPlotter *, int, int );
313static void UpdateXhairs( PlPlotter * );
314
315// Routines for manipulating the rubberband line
316
317static void CreateRband( PlPlotter * );
318static void DestroyRband( PlPlotter * );
319static void DrawRband( PlPlotter *, int, int );
320static void UpdateRband( PlPlotter * );
321
322// Utility routines
323
324static void gbox( PLFLT *, PLFLT *, PLFLT *, PLFLT *, const char ** );
325static void UpdateVScrollbar( register PlPlotter * );
326static void UpdateHScrollbar( register PlPlotter * );
327
328//
329//--------------------------------------------------------------------------
330//
331// plPlotterCmd --
332//
333// This procedure is invoked to process the "plframe" Tcl
334// command. See the user documentation for details on what it
335// does.
336//
337// Results:
338// A standard Tcl result.
339//
340// Side effects:
341// See the user documentation.
342//
343//--------------------------------------------------------------------------
344//
345
346int
347plPlotterCmd( ClientData PL_UNUSED( clientData ), Tcl_Interp *interp,
348 int argc, const char **argv )
349{
350 Tk_Window tkwin;
351 register PlPlotter *plPlotterPtr;
352 register PLRDev *plr;
353 int i, ndev;
354
355 dbug_enter( "plPlotterCmd" );
356
357 if ( argc < 2 )
358 {
359 Tcl_AppendResult( interp, "wrong # args: should be \"",
360 argv[0], " pathName ?options?\"", (char *) NULL );
361 return TCL_ERROR;
362 }
363
364// Create the window.
365
366 tkwin = Tk_CreateWindowFromPath( interp, Tk_MainWindow( interp ), argv[1], (char *) NULL );
367 if ( tkwin == NULL )
368 {
369 return TCL_ERROR;
370 }
371 Tk_SetClass( tkwin, "Plframe" );
372
373 plPlotterPtr = (PlPlotter *) malloc( sizeof ( PlPlotter ) );
374
375 // Initialize in the same order as the members of the struct just
376 // to keep track of what is initialized and what not.
377 plPlotterPtr->tkwin = tkwin;
378 plPlotterPtr->display = Tk_Display( tkwin );
379 plPlotterPtr->interp = interp;
380 plPlotterPtr->widgetCmd =
381 Tcl_CreateCommand( interp, Tk_PathName( plPlotterPtr->tkwin ),
382 (Tcl_CmdProc *) PlPlotterWidgetCmd, (ClientData) plPlotterPtr,
383 (Tcl_CmdDeleteProc *) NULL );
384 plPlotterPtr->border = NULL;
385 //plPlotterPtr->borderWidth = <uninitialized>;
386 //plPlotterPtr->relief = <uninitialized>;
387 plPlotterPtr->width = Tk_Width( plPlotterPtr->tkwin );
388 plPlotterPtr->height = Tk_Height( plPlotterPtr->tkwin );
389 plPlotterPtr->cursor = None;
390 plPlotterPtr->flags = 0;
391 plPlotterPtr->tkwin_initted = 0;
392 // Associate new PLplot stream with this widget
393 plmkstrm( &plPlotterPtr->ipls );
394 plgpls( &plPlotterPtr->pls );
395 plPlotterPtr->ipls_save = 0;
396 plPlotterPtr->plr = (PLRDev *) malloc( sizeof ( PLRDev ) );
397 plPlotterPtr->plpr_cmd = NULL;
398 plPlotterPtr->active_plot = 1;
399 plPlotterPtr->isActive = 0;
400 plPlotterPtr->pldis.x = 0;
401 plPlotterPtr->pldis.y = 0;
402 plPlotterPtr->pldis.width = 0;
403 plPlotterPtr->pldis.height = 0;
404 plPlotterPtr->prevWidth = 0;
405 plPlotterPtr->prevHeight = 0;
406 plPlotterPtr->SaveFnam = NULL;
407 // plPlotterPtr->devDesc = <uninitialized, to be malloced?>;
408 // plPlotterPtr->devName = <uninitialized, to be malloced?>;
409 plPlotterPtr->xorGC = NULL;
410 // plPlotterPtr->pts = <uninitialized array>;
411 plPlotterPtr->continue_draw = 0;
412 plPlotterPtr->xhair_cursor = None;
413 plPlotterPtr->xl = 0.;
414 plPlotterPtr->yl = 0.;
415 plPlotterPtr->xr = 1.;
416 plPlotterPtr->yr = 1.;
417 plPlotterPtr->xScrollCmd = NULL;
418 plPlotterPtr->yScrollCmd = NULL;
419 plPlotterPtr->bopCmd = NULL;
420 plPlotterPtr->eopCmd = NULL;
421 plPlotterPtr->xhairs = 0;
422 plPlotterPtr->drawing_xhairs = 0;
423 // plPlotterPtr->xhair_x = <uninitialized array>;
424 // plPlotterPtr->xhair_y = <uninitialized array>;
425 plPlotterPtr->rband = 0;
426 plPlotterPtr->drawing_rband = 0;
427 // plPlotterPtr->rband_pt = <uninitialized array>;
428 plPlotterPtr->double_buffer = 1;
429
430 plr = plPlotterPtr->plr;
431 plr->pdfs = NULL;
432 plr->iodev = (PLiodev *) malloc( sizeof ( PLiodev ) );
433 plr_start( plr );
434
435 // Tell the stream about myself
436 plPlotterPtr->pls->plPlotterPtr = plPlotterPtr;
437
438// Set up stuff for rubber-band drawing
439
440 plPlotterPtr->xhair_cursor =
441 Tk_GetCursor( plPlotterPtr->interp, plPlotterPtr->tkwin, "crosshair" );
442
443// Partially initialize Tk driver.
444
445 plD_open_tkwin( plPlotterPtr->pls );
446
447// Create list of valid device names and keywords for page dumps
448
449 plPlotterPtr->devDesc = (const char **) malloc( (size_t) NDEV * sizeof ( char ** ) );
450 plPlotterPtr->devName = (const char **) malloc( (size_t) NDEV * sizeof ( char ** ) );
451 for ( i = 0; i < NDEV; i++ )
452 {
453 plPlotterPtr->devDesc[i] = NULL;
454 plPlotterPtr->devName[i] = NULL;
455 }
456 ndev = NDEV;
457 plgFileDevs( &plPlotterPtr->devDesc, &plPlotterPtr->devName, &ndev );
458
459// Start up event handlers and other good stuff
460
461 Tk_CreateEventHandler( plPlotterPtr->tkwin, StructureNotifyMask,
462 PlPlotterConfigureEH, (ClientData) plPlotterPtr );
463
464 Tk_CreateEventHandler( plPlotterPtr->tkwin, ExposureMask,
465 PlPlotterExposeEH, (ClientData) plPlotterPtr );
466
467// for active plot
468 ActiveState( plPlotterPtr, 1 );
469
470 if ( ConfigurePlPlotter( interp, plPlotterPtr, argc - 2, (const char **) argv + 2, 0 ) != TCL_OK )
471 {
472 Tk_DestroyWindow( plPlotterPtr->tkwin );
473 return TCL_ERROR;
474 }
475 Tk_MakeWindowExist( plPlotterPtr->tkwin );
476 PlPlotterFirstInit( (ClientData) plPlotterPtr );
477 Tk_GeometryRequest( plPlotterPtr->tkwin, 200, 200 );
478
479 Tcl_SetResult( interp, Tk_PathName( plPlotterPtr->tkwin ), TCL_VOLATILE );
480
481 return TCL_OK;
482}
483
484//
485//--------------------------------------------------------------------------
486//
487// PlPlotterWidgetCmd --
488//
489// This procedure is invoked to process the Tcl command that
490// corresponds to a plframe widget. See the user
491// documentation for details on what it does.
492//
493// Results:
494// A standard Tcl result.
495//
496// Side effects:
497// See the user documentation.
498//
499//--------------------------------------------------------------------------
500//
501
502static int
503PlPlotterWidgetCmd( ClientData clientData, Tcl_Interp *interp,
504 int argc, const char **argv )
505{
506 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
507 int result = TCL_OK;
508 int length;
509 char c;
510
511 dbug_enter( "PlPlotterWidgetCmd" );
512
513 if ( argc < 2 )
514 {
515 Tcl_AppendResult( interp, "wrong # args: should be \"",
516 argv[0], " option ?arg arg ...?\"", (char *) NULL );
517 return TCL_ERROR;
518 }
519 Tcl_Preserve( (ClientData) plPlotterPtr );
520 c = argv[1][0];
521 length = (int) strlen( argv[1] );
522
523// cmd -- issue a command to the PLplot library
524
525 if ( ( c == 'c' ) && ( strncmp( argv[1], "cmd", (size_t) length ) == 0 ) )
526 {
527 result = Cmd( interp, plPlotterPtr, argc - 2, argv + 2 );
528 }
529
530// configure
531
532 else if ( ( c == 'c' ) && ( strncmp( argv[1], "cget", (size_t) length ) == 0 )
533 && ( length >= 2 ) )
534 {
535 if ( argc != 3 )
536 {
537 Tcl_AppendResult( interp, "wrong # args: should be \"",
538 argv[0], " cget option\"",
539 (char *) NULL );
540 result = TCL_ERROR;
541 goto done;
542 }
543 result = Tk_ConfigureValue( interp, plPlotterPtr->tkwin, configSpecs,
544 (char *) plPlotterPtr, argv[2], 0 );
545 }
546 else if ( ( c == 'c' ) && ( strncmp( argv[1], "configure", (size_t) length ) == 0 ) )
547 {
548 if ( argc == 2 )
549 {
550 result = Tk_ConfigureInfo( interp, plPlotterPtr->tkwin, configSpecs,
551 (char *) plPlotterPtr, (char *) NULL, 0 );
552 }
553 else if ( argc == 3 )
554 {
555 result = Tk_ConfigureInfo( interp, plPlotterPtr->tkwin, configSpecs,
556 (char *) plPlotterPtr, argv[2], 0 );
557 }
558 else
559 {
560 result = ConfigurePlPlotter( interp, plPlotterPtr, argc - 2, argv + 2,
561 TK_CONFIG_ARGV_ONLY );
562 }
563 }
564
565// closelink -- Close a binary data link previously opened with openlink
566
567 else if ( ( c == 'c' ) && ( strncmp( argv[1], "closelink", (size_t) length ) == 0 ) )
568 {
569 if ( argc > 2 )
570 {
571 Tcl_AppendResult( interp, "wrong # args: should be \"",
572 argv[0], (char *) NULL );
573 result = TCL_ERROR;
574 goto done;
575 }
576 else
577 {
578 result = Closelink( interp, plPlotterPtr, argc - 2, argv + 2 );
579 }
580 }
581
582// draw -- rubber-band draw used in region selection
583
584 else if ( ( c == 'd' ) && ( strncmp( argv[1], "draw", (size_t) length ) == 0 ) )
585 {
586 if ( argc == 2 )
587 {
588 Tcl_AppendResult( interp, "wrong # args: should be \"",
589 argv[0], " draw op ?options?\"", (char *) NULL );
590 result = TCL_ERROR;
591 goto done;
592 }
593 else
594 {
595 result = Draw( interp, plPlotterPtr, argc - 2, argv + 2 );
596 }
597 }
598
599// info -- returns requested info
600
601 else if ( ( c == 'i' ) && ( strncmp( argv[1], "info", (size_t) length ) == 0 ) )
602 {
603 result = Info( interp, plPlotterPtr, argc - 2, argv + 2 );
604 }
605
606// next page. called to cancel wait for page in tkwin driver
607
608 else if ( ( c == 'n' ) && ( strncmp( argv[1], "nextpage", (size_t) length ) == 0 ) )
609 {
610 result = NextPage( interp, plPlotterPtr, argc - 2, argv + 2 );
611 }
612
613// orient -- Set plot orientation
614
615 else if ( ( c == 'o' ) && ( strncmp( argv[1], "orient", (size_t) length ) == 0 ) )
616 {
617 result = Orient( interp, plPlotterPtr, argc - 2, argv + 2 );
618 }
619
620// openlink -- Open a binary data link (FIFO or socket)
621
622 else if ( ( c == 'o' ) && ( strncmp( argv[1], "openlink", (size_t) length ) == 0 ) )
623 {
624 if ( argc < 3 )
625 {
626 Tcl_AppendResult( interp, "wrong # args: should be \"",
627 argv[0], " option ?arg arg ...?\"", (char *) NULL );
628 result = TCL_ERROR;
629 goto done;
630 }
631 else
632 {
633 result = Openlink( interp, plPlotterPtr, argc - 2, argv + 2 );
634 }
635 }
636
637// page -- change or return output page setup
638
639 else if ( ( c == 'p' ) && ( strncmp( argv[1], "page", (size_t) length ) == 0 ) )
640 {
641 result = Page( interp, plPlotterPtr, argc - 2, argv + 2 );
642 }
643
644// print -- prints plot
645
646 else if ( ( c == 'p' ) && ( strncmp( argv[1], "print", (size_t) length ) == 0 ) )
647 {
648 result = Print( interp, plPlotterPtr, argc - 2, argv + 2 );
649 }
650
651// redraw -- redraw plot
652
653 else if ( ( c == 'r' ) && ( strncmp( argv[1], "redraw", (size_t) length ) == 0 ) )
654 {
655 if ( argc > 2 )
656 {
657 Tcl_AppendResult( interp, "wrong # args: should be \"",
658 argv[0], " redraw\"", (char *) NULL );
659 result = TCL_ERROR;
660 goto done;
661 }
662 else
663 {
664 result = Redraw( interp, plPlotterPtr, argc - 2, argv + 2 );
665 }
666 }
667
668// report -- find out useful info about the plframe (GMF)
669
670 else if ( ( c == 'r' ) && ( strncmp( argv[1], "report", (size_t) length ) == 0 ) )
671 {
672 result = report( interp, plPlotterPtr, argc - 2, argv + 2 );
673 }
674
675// save -- saves plot to the specified plot file type
676
677 else if ( ( c == 's' ) && ( strncmp( argv[1], "save", (size_t) length ) == 0 ) )
678 {
679 result = Save( interp, plPlotterPtr, argc - 2, argv + 2 );
680 }
681
682// view -- change or return window into plot
683
684 else if ( ( c == 'v' ) && ( strncmp( argv[1], "view", (size_t) length ) == 0 ) )
685 {
686 result = View( interp, plPlotterPtr, argc - 2, argv + 2 );
687 }
688
689// xscroll -- horizontally scroll window into plot
690
691 else if ( ( c == 'x' ) && ( strncmp( argv[1], "xview", (size_t) length ) == 0 ) )
692 {
693 int count, type;
694 double width = (double) ( plPlotterPtr->xr - plPlotterPtr->xl );
695
696 double fraction;
697
698 type = Tk_GetScrollInfo( interp, argc, argv, &fraction, &count );
699 switch ( type )
700 {
701 case TK_SCROLL_ERROR:
702 result = TCL_ERROR;
703 goto done;
704 case TK_SCROLL_MOVETO:
705 plPlotterPtr->xl = (PLFLT) fraction;
706 plPlotterPtr->xr = (PLFLT) ( fraction + width );
707 break;
708 case TK_SCROLL_PAGES:
709 plPlotterPtr->xl += (PLFLT) ( count * width * .9 );
710 plPlotterPtr->xr += (PLFLT) ( count * width * .9 );
711 break;
712 case TK_SCROLL_UNITS:
713 plPlotterPtr->xl += (PLFLT) ( count * width / 50 );
714 plPlotterPtr->xr += (PLFLT) ( count * width / 50 );
715 break;
716 }
717 if ( plPlotterPtr->xr > 1.0 )
718 {
719 plPlotterPtr->xr = 1.0;
720 plPlotterPtr->xl = (PLFLT) ( 1.0 - width );
721 }
722 else if ( plPlotterPtr->xl < 0.0 )
723 {
724 plPlotterPtr->xl = 0.0;
725 plPlotterPtr->xr = (PLFLT) width;
726 }
727 Scroll( interp, plPlotterPtr );
728 }
729
730// yscroll -- vertically scroll window into plot
731
732 else if ( ( c == 'y' ) && ( strncmp( argv[1], "yview", (size_t) length ) == 0 ) )
733 {
734 int count, type;
735 double height = plPlotterPtr->yr - plPlotterPtr->yl;
736
737 double fraction;
738
739 type = Tk_GetScrollInfo( interp, argc, argv, &fraction, &count );
740 switch ( type )
741 {
742 case TK_SCROLL_ERROR:
743 result = TCL_ERROR;
744 goto done;
745 case TK_SCROLL_MOVETO:
746 plPlotterPtr->yl = (PLFLT) ( 1.0 - fraction - height );
747 plPlotterPtr->yr = (PLFLT) ( 1.0 - fraction );
748 break;
749 case TK_SCROLL_PAGES:
750 plPlotterPtr->yl -= (PLFLT) ( count * height * .9 );
751 plPlotterPtr->yr -= (PLFLT) ( count * height * .9 );
752 break;
753 case TK_SCROLL_UNITS:
754 plPlotterPtr->yl -= (PLFLT) ( count * height / 50 );
755 plPlotterPtr->yr -= (PLFLT) ( count * height / 50 );
756 break;
757 }
758 if ( plPlotterPtr->yr > 1.0 )
759 {
760 plPlotterPtr->yr = 1.0;
761 plPlotterPtr->yl = (PLFLT) ( 1.0 - height );
762 }
763 else if ( plPlotterPtr->yl < 0.0 )
764 {
765 plPlotterPtr->yl = 0.0;
766 plPlotterPtr->yr = (PLFLT) height;
767 }
768 Scroll( interp, plPlotterPtr );
769 }
770
771// unrecognized widget command
772
773 else
774 {
775 Tcl_AppendResult( interp, "bad option \"", argv[1],
776 "\": must be closelink, cmd, configure, draw, info, nextpage ",
777 "openlink, orient, page, print, redraw, save, view, ",
778 "xview, or yview", (char *) NULL );
779
780 result = TCL_ERROR;
781 }
782
783done:
784 Tcl_Release( (ClientData) plPlotterPtr );
785 return result;
786}
787
788//
789//--------------------------------------------------------------------------
790//
791// DestroyPlPlotter --
792//
793// This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
794// clean up the internal structure of a plframe at a safe time
795// (when no-one is using it anymore).
796//
797// Results:
798// None.
799//
800// Side effects:
801// Everything associated with the plframe is freed up.
802//
803//--------------------------------------------------------------------------
804//
805
806static void DestroyPlPlotter( ClientData clientData )
807{
808 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
809 register PLRDev *plr = plPlotterPtr->plr;
810 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
811
812 dbug_enter( "DestroyPlPlotter" );
813
814 dev->flags |= 0x3;
815
816 if ( plPlotterPtr->border != NULL )
817 {
818 Tk_Free3DBorder( plPlotterPtr->border );
819 }
820 if ( plPlotterPtr->plpr_cmd != NULL )
821 {
822 free( (char *) plPlotterPtr->plpr_cmd );
823 }
824 if ( plPlotterPtr->cursor != None )
825 {
826 Tk_FreeCursor( plPlotterPtr->display, plPlotterPtr->cursor );
827 }
828 if ( plPlotterPtr->xhair_cursor != None )
829 {
830 Tk_FreeCursor( plPlotterPtr->display, plPlotterPtr->xhair_cursor );
831 }
832 if ( plPlotterPtr->xorGC != NULL )
833 {
834 Tk_FreeGC( plPlotterPtr->display, plPlotterPtr->xorGC );
835 }
836 if ( plPlotterPtr->yScrollCmd != NULL )
837 {
838 free( (char *) plPlotterPtr->yScrollCmd );
839 }
840 if ( plPlotterPtr->xScrollCmd != NULL )
841 {
842 free( (char *) plPlotterPtr->xScrollCmd );
843 }
844 if ( plPlotterPtr->SaveFnam != NULL )
845 {
846 free( (char *) plPlotterPtr->SaveFnam );
847 }
848 if ( plPlotterPtr->devDesc != NULL )
849 {
850 free( (char *) plPlotterPtr->devDesc );
851 }
852 if ( plPlotterPtr->devName != NULL )
853 {
854 free( (char *) plPlotterPtr->devName );
855 }
856
857// Clean up data connection
858
859 pdf_close( plr->pdfs );
860 free( (char *) plPlotterPtr->plr->iodev );
861
862// Tell PLplot to clean up
863
864 plsstrm( plPlotterPtr->ipls );
865 plend1();
866
867// Delete main data structures
868
869 free( (char *) plPlotterPtr->plr );
870 free( (char *) plPlotterPtr );
871}
872
873//
874//--------------------------------------------------------------------------
875//
876// PlPlotterConfigureEH --
877//
878// Invoked by the Tk dispatcher on structure changes to a plframe.
879//
880// Results:
881// None.
882//
883// Side effects:
884// When the window gets deleted, internal structures get cleaned up.
885// When it gets resized, it is redrawn.
886//
887//--------------------------------------------------------------------------
888//
889
890static void
891PlPlotterConfigureEH( ClientData clientData, register XEvent *eventPtr )
892{
893 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
894 register Tk_Window tkwin = plPlotterPtr->tkwin;
895
896 dbug_enter( "PlPlotterConfigureEH" );
897
898 switch ( eventPtr->type )
899 {
900 case ConfigureNotify:
901 pldebug( "PLFrameConfigureEH", "ConfigureNotify\n" );
902 plPlotterPtr->flags |= RESIZE_PENDING;
903 plPlotterPtr->width = Tk_Width( tkwin );
904 plPlotterPtr->height = Tk_Height( tkwin );
905 if ( ( tkwin != NULL ) && !( plPlotterPtr->flags & REFRESH_PENDING ) )
906 {
907 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
908 plPlotterPtr->flags |= REFRESH_PENDING;
909 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
910 }
911 break;
912
913 case DestroyNotify:
914 pldebug( "PLFrameConfigureEH", "DestroyNotify\n" );
915 Tcl_DeleteCommand( plPlotterPtr->interp, Tk_PathName( tkwin ) );
916 plPlotterPtr->tkwin = NULL;
917 if ( plPlotterPtr->flags & REFRESH_PENDING )
918 {
919 Tcl_CancelIdleCall( DisplayPlPlotter, (ClientData) plPlotterPtr );
920 }
921 Tcl_EventuallyFree( (ClientData) plPlotterPtr, (Tcl_FreeProc *) DestroyPlPlotter );
922 break;
923
924 case MapNotify:
925 pldebug( "PLFrameConfigureEH", "MapNotify\n" );
926 if ( plPlotterPtr->flags & REFRESH_PENDING )
927 {
928 Tcl_CancelIdleCall( DisplayPlPlotter, (ClientData) plPlotterPtr );
929 }
930
931// Vince thinks we don't want these lines any more
932// We forced the window into existence when we created it.
933#if 0
934 // For some reason, "." must be mapped or PlPlotterInit will die (Note:
935 // mapped & withdrawn or mapped in the withdrawn state is OK). Issuing
936 // an update fixes this. I'd love to know why this occurs.
937 //
938
939 if ( !plPlotterPtr->tkwin_initted )
940 {
941 Tcl_VarEval( plPlotterPtr->interp, "update", (char *) NULL );
942 }
943#endif
944 // Set up window parameters and arrange for window to be refreshed
945
946 Tcl_DoWhenIdle( PlPlotterInit, (ClientData) plPlotterPtr );
947 break;
948 }
949}
950
951//
952//--------------------------------------------------------------------------
953//
954// PlPlotterExposeEH --
955//
956// Invoked by the Tk dispatcher on exposes of a plframe.
957//
958// Results:
959// None.
960//
961// Side effects:
962// Widget is redisplayed.
963//
964// Note: it's customary in Tk to collapse multiple exposes, so for best
965// performance without losing the window contents, I keep track of the
966// smallest single rectangle that can satisfy all expose events. If there
967// are any overlaid graphics (like crosshairs), however, we need to refresh
968// the entire plot in order to have a predictable outcome.
969//
970//--------------------------------------------------------------------------
971
972static void
973PlPlotterExposeEH( ClientData clientData, register XEvent *eventPtr )
974{
975 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
976 XExposeEvent *event = (XExposeEvent *) eventPtr;
977 register Tk_Window tkwin = plPlotterPtr->tkwin;
978
979 dbug_enter( "PlPlotterExposeEH" );
980
981 pldebug( "PLFrameExposeEH", "Expose\n" );
982
983// Set up the area to refresh
984
985 if ( !( plPlotterPtr->drawing_xhairs || plPlotterPtr->drawing_rband ) )
986 {
987 int x0_old, x1_old, y0_old, y1_old, x0_new, x1_new, y0_new, y1_new;
988
989 x0_old = (int) plPlotterPtr->pldis.x;
990 y0_old = (int) plPlotterPtr->pldis.y;
991 x1_old = x0_old + (int) plPlotterPtr->pldis.width;
992 y1_old = y0_old + (int) plPlotterPtr->pldis.height;
993
994 x0_new = event->x;
995 y0_new = event->y;
996 x1_new = x0_new + event->width;
997 y1_new = y0_new + event->height;
998
999 plPlotterPtr->pldis.x = (unsigned int) MIN( x0_old, x0_new );
1000 plPlotterPtr->pldis.y = (unsigned int) MIN( y0_old, y0_new );
1001 plPlotterPtr->pldis.width = (unsigned int) MAX( x1_old, x1_new ) - plPlotterPtr->pldis.x;
1002 plPlotterPtr->pldis.height = (unsigned int) MAX( y1_old, y1_new ) - plPlotterPtr->pldis.y;
1003 }
1004
1005// Invoke DoWhenIdle handler to redisplay widget.
1006
1007 if ( event->count == 0 )
1008 {
1009 if ( ( tkwin != NULL ) && !( plPlotterPtr->flags & REFRESH_PENDING ) )
1010 {
1011 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
1012 plPlotterPtr->width = Tk_Width( tkwin );
1013 plPlotterPtr->height = Tk_Height( tkwin );
1014 plPlotterPtr->flags |= REFRESH_PENDING;
1015 }
1016 }
1017}
1018
1019//
1020//--------------------------------------------------------------------------
1021//
1022// PlPlotterMotionEH --
1023//
1024// Invoked by the Tk dispatcher on MotionNotify events in a plframe.
1025// Not invoked unless we are drawing graphic crosshairs.
1026//
1027// Results:
1028// None.
1029//
1030// Side effects:
1031// Graphic crosshairs are drawn.
1032//
1033//--------------------------------------------------------------------------
1034//
1035
1036static void
1037PlPlotterMotionEH( ClientData clientData, register XEvent *eventPtr )
1038{
1039 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1040 XMotionEvent *event = (XMotionEvent *) eventPtr;
1041
1042 dbug_enter( "PlPlotterMotionEH" );
1043
1044 if ( plPlotterPtr->drawing_xhairs )
1045 {
1046 DrawXhairs( plPlotterPtr, event->x, event->y );
1047 }
1048 if ( plPlotterPtr->drawing_rband )
1049 {
1050 DrawRband( plPlotterPtr, event->x, event->y );
1051 }
1052}
1053
1054//
1055//--------------------------------------------------------------------------
1056//
1057// PlPlotterEnterEH --
1058//
1059// Invoked by the Tk dispatcher on EnterNotify events in a plframe.
1060// Not invoked unless we are drawing graphic crosshairs.
1061//
1062// Results:
1063// None.
1064//
1065// Side effects:
1066// Graphic crosshairs are updated.
1067//
1068//--------------------------------------------------------------------------
1069
1070static void
1071PlPlotterEnterEH( ClientData clientData, register XEvent *eventPtr )
1072{
1073 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1074 XCrossingEvent *crossingEvent = (XCrossingEvent *) eventPtr;
1075
1076 dbug_enter( "PlPlotterEnterEH" );
1077
1078 if ( plPlotterPtr->xhairs )
1079 {
1080 DrawXhairs( plPlotterPtr, crossingEvent->x, crossingEvent->y );
1081 plPlotterPtr->drawing_xhairs = 1;
1082 }
1083 if ( plPlotterPtr->rband )
1084 {
1085 plPlotterPtr->drawing_rband = 1;
1086 UpdateRband( plPlotterPtr );
1087 DrawRband( plPlotterPtr, crossingEvent->x, crossingEvent->y );
1088 }
1089}
1090
1091//
1092//--------------------------------------------------------------------------
1093//
1094// PlPlotterLeaveEH --
1095//
1096// Invoked by the Tk dispatcher on LeaveNotify events in a plframe.
1097// Not invoked unless we are drawing graphic crosshairs.
1098//
1099// Results:
1100// None.
1101//
1102// Side effects:
1103// Graphic crosshairs are updated.
1104//
1105//--------------------------------------------------------------------------
1106
1107static void
1108PlPlotterLeaveEH( ClientData clientData, register XEvent * PL_UNUSED( eventPtr ) )
1109{
1110 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1111
1112 dbug_enter( "PlPlotterLeaveEH" );
1113
1114 if ( plPlotterPtr->drawing_xhairs )
1115 {
1116 UpdateXhairs( plPlotterPtr );
1117 plPlotterPtr->drawing_xhairs = 0;
1118 }
1119 if ( plPlotterPtr->drawing_rband )
1120 {
1121 UpdateRband( plPlotterPtr );
1122 plPlotterPtr->drawing_rband = 0;
1123 }
1124}
1125
1126static void
1127PlPlotterButtonPressEH( ClientData clientData, register XEvent *eventPtr )
1128{
1129 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1130 XButtonEvent *event = (XButtonEvent *) eventPtr;
1131
1132 // Get modifier keys
1133 switch ( event->state )
1134 {
1135 case 256: // plain
1136 if ( plPlotterPtr->drawing_rband )
1137 {
1138 UpdateRband( plPlotterPtr );
1139 }
1140 if ( plPlotterPtr->rband )
1141 CreateRband( plPlotterPtr );
1142 break;
1143 }
1144}
1145
1146//--------------------------------------------------------------------------
1147// CreateXhairs()
1148//
1149// Creates graphic crosshairs at current pointer location.
1150//--------------------------------------------------------------------------
1151
1152static void
1153CreateXhairs( PlPlotter *plPlotterPtr )
1154{
1155 register Tk_Window tkwin = plPlotterPtr->tkwin;
1156 Window root, child;
1157 int root_x, root_y, win_x, win_y;
1158 unsigned int mask;
1159
1160
1161// Find current pointer location and draw graphic crosshairs if pointer is
1162// inside our window.
1163
1164 if ( XQueryPointer( plPlotterPtr->display, Tk_WindowId( tkwin ),
1165 &root, &child, &root_x, &root_y, &win_x, &win_y,
1166 &mask ) )
1167 {
1168 #ifdef MAC_TCL
1169 // Mac Tk only has a partial implementation of the above function
1170 // so we must fix it
1171 Tk_GetRootCoords( tkwin, &win_x, &win_y );
1172 win_x = root_x - win_x;
1173 win_y = root_y - win_y;
1174 #endif
1175 if ( win_x >= 0 && win_x < Tk_Width( tkwin ) &&
1176 win_y >= 0 && win_y < Tk_Height( tkwin ) )
1177 {
1178 DrawXhairs( plPlotterPtr, win_x, win_y );
1179 plPlotterPtr->drawing_xhairs = 1;
1180 }
1181 }
1182}
1183
1184//--------------------------------------------------------------------------
1185// DestroyXhairs()
1186//
1187// Destroys graphic crosshairs.
1188//--------------------------------------------------------------------------
1189
1190static void
1191DestroyXhairs( PlPlotter *plPlotterPtr )
1192{
1193// This draw removes the last set of graphic crosshairs
1194
1195 UpdateXhairs( plPlotterPtr );
1196 plPlotterPtr->drawing_xhairs = 0;
1197}
1198
1199//--------------------------------------------------------------------------
1200// DrawXhairs()
1201//
1202// Draws graphic crosshairs at (x0, y0). The first draw erases the old set.
1203//--------------------------------------------------------------------------
1204
1205static void
1206DrawXhairs( PlPlotter *plPlotterPtr, int x0, int y0 )
1207{
1208 register Tk_Window tkwin = plPlotterPtr->tkwin;
1209 int xmin = 0, xmax = Tk_Width( tkwin ) - 1;
1210 int ymin = 0, ymax = Tk_Height( tkwin ) - 1;
1211
1212 if ( plPlotterPtr->drawing_xhairs )
1213 UpdateXhairs( plPlotterPtr );
1214
1215 plPlotterPtr->xhair_x[0].x = (short) xmin; plPlotterPtr->xhair_x[0].y = (short) y0;
1216 plPlotterPtr->xhair_x[1].x = (short) xmax; plPlotterPtr->xhair_x[1].y = (short) y0;
1217
1218 plPlotterPtr->xhair_y[0].x = (short) x0; plPlotterPtr->xhair_y[0].y = (short) ymin;
1219 plPlotterPtr->xhair_y[1].x = (short) x0; plPlotterPtr->xhair_y[1].y = (short) ymax;
1220
1221 UpdateXhairs( plPlotterPtr );
1222}
1223
1224//--------------------------------------------------------------------------
1225// UpdateXhairs()
1226//
1227// Updates graphic crosshairs. If already there, they are erased.
1228//--------------------------------------------------------------------------
1229
1230static void
1231UpdateXhairs( PlPlotter *plPlotterPtr )
1232{
1233 register Tk_Window tkwin = plPlotterPtr->tkwin;
1234
1235 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1236 plPlotterPtr->xorGC, plPlotterPtr->xhair_x, 2,
1237 CoordModeOrigin );
1238
1239 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1240 plPlotterPtr->xorGC, plPlotterPtr->xhair_y, 2,
1241 CoordModeOrigin );
1242}
1243
1244//--------------------------------------------------------------------------
1245// CreateRband()
1246//
1247// Initiate rubber banding.
1248//--------------------------------------------------------------------------
1249
1250static void
1251CreateRband( PlPlotter *plPlotterPtr )
1252{
1253 register Tk_Window tkwin = plPlotterPtr->tkwin;
1254 Window root, child;
1255 int root_x, root_y, win_x, win_y;
1256 unsigned int mask;
1257
1258// Find current pointer location, and initiate rubber banding.
1259
1260 if ( XQueryPointer( plPlotterPtr->display, Tk_WindowId( tkwin ),
1261 &root, &child, &root_x, &root_y, &win_x, &win_y,
1262 &mask ) )
1263 {
1264 #ifdef MAC_TCL
1265 // Mac Tk only has a partial implementation of the above function
1266 // so we must fix it
1267 Tk_GetRootCoords( tkwin, &win_x, &win_y );
1268 win_x = root_x - win_x;
1269 win_y = root_y - win_y;
1270 #endif
1271 if ( win_x >= 0 && win_x < Tk_Width( tkwin ) &&
1272 win_y >= 0 && win_y < Tk_Height( tkwin ) )
1273 {
1274 // Okay, pointer is in our window.
1275 plPlotterPtr->rband_pt[0].x = (short) win_x;
1276 plPlotterPtr->rband_pt[0].y = (short) win_y;
1277
1278 DrawRband( plPlotterPtr, win_x, win_y );
1279 plPlotterPtr->drawing_rband = 1;
1280 }
1281 else
1282 {
1283 // Hmm, somehow they turned it on without even being in the window.
1284 // Just put the anchor in top left, they'll soon realize this is a
1285 // mistake...
1286
1287 plPlotterPtr->rband_pt[0].x = 0;
1288 plPlotterPtr->rband_pt[0].y = 0;
1289
1290 DrawRband( plPlotterPtr, win_x, win_y );
1291 plPlotterPtr->drawing_rband = 1;
1292 }
1293 }
1294}
1295
1296//--------------------------------------------------------------------------
1297// DestroyRband()
1298//
1299// Turn off rubber banding.
1300//--------------------------------------------------------------------------
1301
1302static void
1303DestroyRband( PlPlotter *plPlotterPtr )
1304{
1305// This draw removes the residual rubber band.
1306
1307 UpdateRband( plPlotterPtr );
1308 plPlotterPtr->drawing_rband = 0;
1309}
1310
1311//--------------------------------------------------------------------------
1312// DrawRband()
1313//
1314// Draws a rubber band from the anchor to the current cursor location.
1315//--------------------------------------------------------------------------
1316
1317static void
1318DrawRband( PlPlotter *plPlotterPtr, int x0, int y0 )
1319{
1320// If the line is already up, clear it.
1321
1322 if ( plPlotterPtr->drawing_rband )
1323 UpdateRband( plPlotterPtr );
1324
1325 plPlotterPtr->rband_pt[1].x = (short) x0; plPlotterPtr->rband_pt[1].y = (short) y0;
1326
1327 UpdateRband( plPlotterPtr );
1328}
1329
1330//--------------------------------------------------------------------------
1331// UpdateRband()
1332//
1333// Updates rubber band. If already there, it is erased.
1334//--------------------------------------------------------------------------
1335
1336static void
1337UpdateRband( PlPlotter *plPlotterPtr )
1338{
1339 register Tk_Window tkwin = plPlotterPtr->tkwin;
1340
1341 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1342 plPlotterPtr->xorGC, plPlotterPtr->rband_pt, 2,
1343 CoordModeOrigin );
1344}
1345
1346// First-time initialization
1347static void PlPlotterFirstInit( ClientData clientData )
1348{
1349 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1350 register Tk_Window tkwin = plPlotterPtr->tkwin;
1351
1352 plsstrm( plPlotterPtr->ipls );
1353 plsdev( "tkwin" );
1354// We should probably rename plsxwin to plstkwin
1355 plsxwin( (PLINT) Tk_WindowId( tkwin ) );
1356 plspause( 0 );
1357 plinit();
1358 if ( plplot_tkwin_ccmap )
1359 {
1360 Install_cmap( plPlotterPtr );
1361 }
1362 plbop();
1363
1364 plPlotterPtr->tkwin_initted = 1;
1365 plPlotterPtr->width = Tk_Width( tkwin );
1366 plPlotterPtr->height = Tk_Height( tkwin );
1367 plPlotterPtr->prevWidth = plPlotterPtr->width;
1368 plPlotterPtr->prevHeight = plPlotterPtr->height;
1369}
1370
1371//
1372//--------------------------------------------------------------------------
1373//
1374// PlPlotterInit --
1375//
1376// Invoked to handle miscellaneous initialization after window gets
1377// mapped.
1378//
1379// Results:
1380// None.
1381//
1382// Side effects:
1383// PLplot internal parameters and device driver are initialized.
1384//
1385//--------------------------------------------------------------------------
1386
1387static void
1388PlPlotterInit( ClientData clientData )
1389{
1390 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1391
1392// Set up window parameters and arrange for window to be refreshed
1393
1394 plPlotterPtr->flags |= REFRESH_PENDING;
1395 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
1396
1397// Draw plframe
1398
1399 DisplayPlPlotter( clientData );
1400
1401 if ( plPlotterPtr->xhairs )
1402 CreateXhairs( plPlotterPtr );
1403
1404 if ( plPlotterPtr->rband )
1405 CreateRband( plPlotterPtr );
1406}
1407
1408//
1409//--------------------------------------------------------------------------
1410//
1411// Install_cmap --
1412//
1413// Installs X driver color map as necessary when custom color maps
1414// are used.
1415//
1416// Results:
1417// None.
1418//
1419// Side effects:
1420// Parent color maps may get changed.
1421//
1422//--------------------------------------------------------------------------
1423//
1424
1425static void
1426Install_cmap( PlPlotter *plPlotterPtr )
1427{
1428 TkwDev *dev;
1429
1430#define INSTALL_COLORMAP_IN_TK
1431#ifdef INSTALL_COLORMAP_IN_TK
1432 dev = (TkwDev *) plPlotterPtr->pls->dev;
1433 Tk_SetWindowColormap( Tk_MainWindow( plPlotterPtr->interp ), dev->tkwd->map );
1434
1435//
1436// If the colormap is local to this widget, the WM must be informed that
1437// it should be installed when the widget gets the focus. The top level
1438// window must be added to the end of its own list, because otherwise the
1439// window manager adds it to the front (as required by the ICCCM). Thanks
1440// to Paul Mackerras for providing this info in his TK photo widget.
1441//
1442
1443#else
1444 int count = 0;
1445 Window top, colormap_windows[5];
1446
1447 top = Tk_WindowId( Tk_MainWindow( plPlotterPtr->interp ) );
1448
1449 colormap_windows[count++] = Tk_WindowId( plPlotterPtr->tkwin );
1450 colormap_windows[count++] = top;
1451
1452 if ( !XSetWMColormapWindows( plPlotterPtr->display,
1453 top, colormap_windows, count ) )
1454 fprintf( stderr, "Unable to set color map property!\n" );
1455#endif
1456}
1457
1458//
1459//--------------------------------------------------------------------------
1460//
1461// DisplayPlPlotter --
1462//
1463// This procedure is invoked to display a plframe widget.
1464//
1465// Results:
1466// None.
1467//
1468// Side effects:
1469// Commands are output to X to display the plframe in its
1470// current mode.
1471//
1472//--------------------------------------------------------------------------
1473//
1474
1475static void
1476DisplayPlPlotter( ClientData clientData )
1477{
1478 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1479 register Tk_Window tkwin = plPlotterPtr->tkwin;
1480
1481 dbug_enter( "DisplayPlPlotter" );
1482
1483// Update scrollbars if needed
1484
1485 if ( plPlotterPtr->flags & UPDATE_V_SCROLLBAR )
1486 {
1487 UpdateVScrollbar( plPlotterPtr );
1488 }
1489 if ( plPlotterPtr->flags & UPDATE_H_SCROLLBAR )
1490 {
1491 UpdateHScrollbar( plPlotterPtr );
1492 }
1493 plPlotterPtr->flags &= ~( UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR );
1494
1495// If not mapped yet, just return and cancel pending refresh
1496
1497 if ( ( plPlotterPtr->tkwin == NULL ) || !Tk_IsMapped( tkwin ) )
1498 {
1499 plPlotterPtr->flags &= ~REFRESH_PENDING;
1500 return;
1501 }
1502
1503// All refresh events
1504
1505 if ( plPlotterPtr->flags & REFRESH_PENDING )
1506 {
1507 plPlotterPtr->flags &= ~REFRESH_PENDING;
1508
1509 // Reschedule resizes to avoid occasional ordering conflicts with
1510 // the packer's resize of the window (this call must come last).
1511
1512 if ( plPlotterPtr->flags & RESIZE_PENDING )
1513 {
1514 plPlotterPtr->flags |= REFRESH_PENDING;
1515 plPlotterPtr->flags &= ~RESIZE_PENDING;
1516 Tcl_DoWhenIdle( DisplayPlPlotter, clientData );
1517 return;
1518 }
1519
1520 // Redraw border if necessary
1521
1522 if ( ( plPlotterPtr->border != NULL ) &&
1523 ( plPlotterPtr->relief != TK_RELIEF_FLAT ) )
1524 {
1525 Tk_Draw3DRectangle( plPlotterPtr->tkwin, Tk_WindowId( tkwin ),
1526 plPlotterPtr->border, 0, 0, Tk_Width( tkwin ), Tk_Height( tkwin ),
1527 plPlotterPtr->borderWidth, plPlotterPtr->relief );
1528 }
1529
1530 // Redraw -- replay contents of plot buffer
1531
1532 if ( plPlotterPtr->flags & REDRAW_PENDING )
1533 {
1534 plPlotterPtr->flags &= ~REDRAW_PENDING;
1535 plsstrm( plPlotterPtr->ipls );
1536 pl_cmd( PLESC_REDRAW, (void *) NULL );
1537 }
1538
1539 // Resize -- if window bounds have changed
1540
1541 else if ( ( plPlotterPtr->width != plPlotterPtr->prevWidth ) ||
1542 ( plPlotterPtr->height != plPlotterPtr->prevHeight ) )
1543 {
1544 plPlotterPtr->pldis.width = (unsigned int) ( plPlotterPtr->width );
1545 plPlotterPtr->pldis.height = (unsigned int) ( plPlotterPtr->height );
1546
1547 plsstrm( plPlotterPtr->ipls );
1548 pl_cmd( PLESC_RESIZE, (void *) &( plPlotterPtr->pldis ) );
1549 plPlotterPtr->prevWidth = plPlotterPtr->width;
1550 plPlotterPtr->prevHeight = plPlotterPtr->height;
1551 }
1552
1553 // Expose -- if window bounds are unchanged
1554
1555 else
1556 {
1557 if ( plPlotterPtr->drawing_xhairs )
1558 {
1559 #ifdef MAC_TCL
1560 // For MacTk we just zap the whole window like this
1561 Tk_Draw3DRectangle( plPlotterPtr->tkwin, Tk_WindowId( tkwin ),
1562 plPlotterPtr->border, 0, 0, Tk_Width( tkwin ), Tk_Height( tkwin ),
1563 plPlotterPtr->borderWidth, plPlotterPtr->relief );
1564 #else
1565 XClearWindow( plPlotterPtr->display, Tk_WindowId( tkwin ) );
1566 #endif
1567 XFlush( plPlotterPtr->display );
1568 plsstrm( plPlotterPtr->ipls );
1569 pl_cmd( PLESC_EXPOSE, NULL );
1570 }
1571 else
1572 {
1573 plsstrm( plPlotterPtr->ipls );
1574 pl_cmd( PLESC_EXPOSE, (void *) &( plPlotterPtr->pldis ) );
1575 }
1576
1577 // Reset window bounds so that next time they are set fresh
1578
1579 plPlotterPtr->pldis.x = (unsigned int) ( Tk_X( tkwin ) + Tk_Width( tkwin ) );
1580 plPlotterPtr->pldis.y = (unsigned int) ( Tk_Y( tkwin ) + Tk_Height( tkwin ) );
1581 plPlotterPtr->pldis.width = (unsigned int) -Tk_Width( tkwin );
1582 plPlotterPtr->pldis.height = (unsigned int) -Tk_Height( tkwin );
1583 }
1584
1585 // Update graphic crosshairs if necessary
1586
1587 if ( plPlotterPtr->drawing_xhairs )
1588 {
1589 UpdateXhairs( plPlotterPtr );
1590 }
1591
1592 // Update rubber band if necessary.
1593
1594 if ( plPlotterPtr->drawing_rband )
1595 {
1596 UpdateRband( plPlotterPtr );
1597 }
1598 }
1599}
1600
1601//--------------------------------------------------------------------------
1602// Routines to process widget commands.
1603//--------------------------------------------------------------------------
1604
1605//--------------------------------------------------------------------------
1606// scol0
1607//
1608// Sets a color in cmap0.
1609//--------------------------------------------------------------------------
1610
1611static int
1612scol0( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1613 int i, const char *col, int *p_changed )
1614{
1615 PLStream *pls = plPlotterPtr->pls;
1616 XColor xcol;
1617 PLINT r, g, b;
1618
1619 if ( col == NULL )
1620 {
1621 Tcl_AppendResult( interp, "color value not specified",
1622 (char *) NULL );
1623 return TCL_ERROR;
1624 }
1625
1626 if ( !XParseColor( plPlotterPtr->display,
1627 Tk_Colormap( plPlotterPtr->tkwin ), col, &xcol ) )
1628 {
1629 Tcl_AppendResult( interp, "Couldn't parse color ", col,
1630 (char *) NULL );
1631 return TCL_ERROR;
1632 }
1633
1634 r = (unsigned) ( xcol.red & 0xFF00 ) >> 8;
1635 g = (unsigned) ( xcol.green & 0xFF00 ) >> 8;
1636 b = (unsigned) ( xcol.blue & 0xFF00 ) >> 8;
1637
1638 if ( ( pls->cmap0[i].r != r ) ||
1639 ( pls->cmap0[i].g != g ) ||
1640 ( pls->cmap0[i].b != b ) )
1641 {
1642 pls->cmap0[i].r = (unsigned char) r;
1643 pls->cmap0[i].g = (unsigned char) g;
1644 pls->cmap0[i].b = (unsigned char) b;
1645 *p_changed = 1;
1646 }
1647
1648 return TCL_OK;
1649}
1650
1651//--------------------------------------------------------------------------
1652// scol1
1653//
1654// Sets a color in cmap1.
1655//--------------------------------------------------------------------------
1656
1657static int
1658scol1( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1659 int i, const char *col, const char *pos, const char *rev, int *p_changed )
1660{
1661 PLStream *pls = plPlotterPtr->pls;
1662 XColor xcol;
1663 PLFLT h, l, s, r, g, b, p;
1664 int reverse;
1665
1666 if ( col == NULL )
1667 {
1668 Tcl_AppendResult( interp, "color value not specified",
1669 (char *) NULL );
1670 return TCL_ERROR;
1671 }
1672
1673 if ( pos == NULL )
1674 {
1675 Tcl_AppendResult( interp, "control point position not specified",
1676 (char *) NULL );
1677 return TCL_ERROR;
1678 }
1679
1680 if ( rev == NULL )
1681 {
1682 Tcl_AppendResult( interp, "interpolation sense not specified",
1683 (char *) NULL );
1684 return TCL_ERROR;
1685 }
1686
1687 if ( !XParseColor( plPlotterPtr->display,
1688 Tk_Colormap( plPlotterPtr->tkwin ), col, &xcol ) )
1689 {
1690 Tcl_AppendResult( interp, "Couldn't parse color ", col,
1691 (char *) NULL );
1692 return TCL_ERROR;
1693 }
1694
1695 r = (PLFLT) ( ( (unsigned) ( xcol.red & 0xFF00 ) >> 8 ) / 255.0 );
1696 g = (PLFLT) ( ( (unsigned) ( xcol.green & 0xFF00 ) >> 8 ) / 255.0 );
1697 b = (PLFLT) ( ( (unsigned) ( xcol.blue & 0xFF00 ) >> 8 ) / 255.0 );
1698
1699 plrgbhls( r, g, b, &h, &l, &s );
1700
1701 p = (PLFLT) ( atof( pos ) / 100.0 );
1702 reverse = atoi( rev );
1703
1704 if ( ( pls->cmap1cp[i].c1 != h ) ||
1705 ( pls->cmap1cp[i].c2 != l ) ||
1706 ( pls->cmap1cp[i].c3 != s ) ||
1707 ( pls->cmap1cp[i].p != p ) ||
1708 ( pls->cmap1cp[i].alt_hue_path != reverse ) )
1709 {
1710 pls->cmap1cp[i].c1 = h;
1711 pls->cmap1cp[i].c2 = l;
1712 pls->cmap1cp[i].c2 = s;
1713 pls->cmap1cp[i].p = p;
1714 pls->cmap1cp[i].alt_hue_path = reverse;
1715 *p_changed = 1;
1716 }
1717 return TCL_OK;
1718}
1719
1720//--------------------------------------------------------------------------
1721// Cmd
1722//
1723// Processes "cmd" widget command.
1724// Handles commands that go more or less directly to the PLplot library.
1725// Most of these come out of the PLplot Tcl API support file.
1726//--------------------------------------------------------------------------
1727
1728static int
1729Cmd( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1730 int argc, const char **argv )
1731{
1732 PLStream *pls = plPlotterPtr->pls;
1733 int length;
1734 char c3;
1735 int result = TCL_OK;
1736 char cmdlist[] = "plgcmap0 plgcmap1 plscmap0 plscmap1 plscol0 plscol1";
1737 char * argv_cp;
1738
1739#ifdef DEBUG
1740 if ( pls->debug )
1741 {
1742 int i;
1743 fprintf( stderr, "There are %d arguments to Cmd:", argc );
1744 for ( i = 0; i < argc; i++ )
1745 {
1746 fprintf( stderr, " %s", argv[i] );
1747 }
1748 fprintf( stderr, "\n" );
1749 }
1750#endif
1751
1752// no option -- return list of available PLplot commands
1753
1754 if ( argc == 0 )
1755 return plTclCmd( cmdlist, interp, argc, argv );
1756
1757// Make sure widget has been initialized before going any further
1758
1759 if ( !plPlotterPtr->tkwin_initted )
1760 {
1761 Tcl_VarEval( plPlotterPtr->interp, "update", (char *) NULL );
1762 }
1763
1764// Set stream number and get ready to process the command
1765
1766 plsstrm( plPlotterPtr->ipls );
1767
1768 c3 = argv[0][2];
1769 length = (int) strlen( argv[0] );
1770
1771// plgcmap0 -- get color map 0
1772// first arg is number of colors, the rest are hex number specifications
1773
1774 if ( ( c3 == 'g' ) && ( strncmp( argv[0], "plgcmap0", (size_t) length ) == 0 ) )
1775 {
1776 int i;
1777 unsigned long plcolor;
1778 char str[10];
1779
1780 sprintf( str, "%d", (int) pls->ncol0 );
1781 Tcl_AppendElement( interp, str );
1782 for ( i = 0; i < pls->ncol0; i++ )
1783 {
1784 plcolor = (unsigned long) ( ( pls->cmap0[i].r << 16 ) |
1785 ( pls->cmap0[i].g << 8 ) |
1786 ( pls->cmap0[i].b ) );
1787
1788 sprintf( str, "#%06lx", ( plcolor & 0xFFFFFF ) );
1789 Tcl_AppendElement( interp, str );
1790 }
1791 result = TCL_OK;
1792 }
1793
1794// plgcmap1 -- get color map 1
1795// first arg is number of control points
1796// the rest are hex number specifications followed by positions (0-100)
1797
1798 else if ( ( c3 == 'g' ) && ( strncmp( argv[0], "plgcmap1", (size_t) length ) == 0 ) )
1799 {
1800 int i;
1801 unsigned long plcolor;
1802 char str[10];
1803 PLFLT h, l, s, r, g, b;
1804 int r1, g1, b1;
1805
1806 sprintf( str, "%d", (int) pls->ncp1 );
1807 Tcl_AppendElement( interp, str );
1808 for ( i = 0; i < pls->ncp1; i++ )
1809 {
1810 h = pls->cmap1cp[i].c1;
1811 l = pls->cmap1cp[i].c2;
1812 s = pls->cmap1cp[i].c3;
1813
1814 plhlsrgb( h, l, s, &r, &g, &b );
1815
1816 r1 = MAX( 0, MIN( 255, (int) ( 256. * r ) ) );
1817 g1 = MAX( 0, MIN( 255, (int) ( 256. * g ) ) );
1818 b1 = MAX( 0, MIN( 255, (int) ( 256. * b ) ) );
1819
1820 plcolor = (unsigned long) ( ( r1 << 16 ) | ( g1 << 8 ) | ( b1 ) );
1821
1822 sprintf( str, "#%06lx", ( plcolor & 0xFFFFFF ) );
1823 Tcl_AppendElement( interp, str );
1824
1825 sprintf( str, "%02d", (int) ( 100 * pls->cmap1cp[i].p ) );
1826 Tcl_AppendElement( interp, str );
1827
1828 sprintf( str, "%01d", (int) ( pls->cmap1cp[i].alt_hue_path ) );
1829 Tcl_AppendElement( interp, str );
1830 }
1831 result = TCL_OK;
1832 }
1833
1834// plscmap0 -- set color map 0
1835// first arg is number of colors, the rest are hex number specifications
1836
1837 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscmap0", (size_t) length ) == 0 ) )
1838 {
1839 int i, changed = 1, ncol0 = atoi( argv[1] );
1840 char *col;
1841
1842 if ( ncol0 > 16 || ncol0 < 1 )
1843 {
1844 Tcl_AppendResult( interp, "illegal number of colors in cmap0: ",
1845 argv[1], (char *) NULL );
1846 return TCL_ERROR;
1847 }
1848
1849 pls->ncol0 = ncol0;
1850 for ( i = 0; i < pls->ncol0; i++ )
1851 {
1852 argv_cp = plstrdup( argv[2 + i] );
1853 col = strtok( argv_cp, " " );
1854 if ( col == NULL )
1855 break;
1856
1857 if ( scol0( interp, plPlotterPtr, i, col, &changed ) != TCL_OK )
1858 return TCL_ERROR;
1859 free_mem( argv_cp );
1860 }
1861
1862 if ( changed )
1864 }
1865
1866// plscmap1 -- set color map 1
1867// first arg is number of colors, the rest are hex number specifications
1868
1869 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscmap1", (size_t) length ) == 0 ) )
1870 {
1871 int i, changed = 1, ncp1 = atoi( argv[1] );
1872 char *col, *pos, *rev;
1873
1874 if ( ncp1 > 32 || ncp1 < 1 )
1875 {
1876 Tcl_AppendResult( interp,
1877 "illegal number of control points in cmap1: ",
1878 argv[1], (char *) NULL );
1879 return TCL_ERROR;
1880 }
1881
1882 argv_cp = plstrdup( argv[2] );
1883 col = strtok( argv_cp, " " );
1884 pos = strtok( NULL, " " );
1885 rev = strtok( NULL, " " );
1886 for ( i = 0; i < ncp1; i++ )
1887 {
1888 if ( col == NULL )
1889 break;
1890
1891 if ( scol1( interp, plPlotterPtr,
1892 i, col, pos, rev, &changed ) != TCL_OK )
1893 return TCL_ERROR;
1894
1895 col = strtok( NULL, " " );
1896 pos = strtok( NULL, " " );
1897 rev = strtok( NULL, " " );
1898 }
1899
1900 free_mem( argv_cp );
1901
1902 if ( changed )
1903 {
1904 plsc->ncp1 = ncp1;
1905 plcmap1_calc();
1906 }
1907 }
1908
1909// plscol0 -- set single color in cmap0
1910// first arg is the color number, the next is the color in hex
1911
1912 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscol0", (size_t) length ) == 0 ) )
1913 {
1914 int i = atoi( argv[1] ), changed = 1;
1915
1916 if ( i > pls->ncol0 || i < 0 )
1917 {
1918 Tcl_AppendResult( interp, "illegal color number in cmap0: ",
1919 argv[1], (char *) NULL );
1920 return TCL_ERROR;
1921 }
1922
1923 if ( scol0( interp, plPlotterPtr, i, argv[2], &changed ) != TCL_OK )
1924 return TCL_ERROR;
1925
1926 if ( changed )
1928 }
1929
1930// plscol1 -- set color of control point in cmap1
1931// first arg is the control point, the next two are the color in hex and pos
1932
1933 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscol1", (size_t) length ) == 0 ) )
1934 {
1935 int i = atoi( argv[1] ), changed = 1;
1936
1937 if ( i > pls->ncp1 || i < 0 )
1938 {
1939 Tcl_AppendResult( interp, "illegal control point number in cmap1: ",
1940 argv[1], (char *) NULL );
1941 return TCL_ERROR;
1942 }
1943
1944 if ( scol1( interp, plPlotterPtr,
1945 i, argv[2], argv[3], argv[4], &changed ) != TCL_OK )
1946 return TCL_ERROR;
1947
1948 if ( changed )
1949 plcmap1_calc();
1950 }
1951
1952// Added by Vince, disabled by default since we want a minimal patch
1953#ifdef USING_PLESC_COPY
1954// plcopy -- copy a region of the plot; useful for scrolling plots
1955// first 4 args are the source rectangle, next 2 args are the destination
1956
1957 else if ( ( c3 == 'c' ) && ( strncmp( argv[0], "plcopy", (size_t) length ) == 0 ) )
1958 {
1959 PLFLT xx[3], yy[3];
1960 if ( argc != 7 )
1961 {
1962 Tcl_AppendResult( interp, "Need exactly 6 arguments to copy.",
1963 (char *) NULL );
1964 return TCL_ERROR;
1965 }
1966 xx[0] = atof( argv[1] );
1967 yy[0] = atof( argv[2] );
1968 xx[1] = atof( argv[3] );
1969 yy[1] = atof( argv[4] );
1970 xx[2] = atof( argv[5] );
1971 yy[2] = atof( argv[6] );
1972 plcopy( xx, yy );
1973 }
1974#endif
1975
1976// unrecognized, so give it to plTclCmd to take care of
1977
1978 else
1979 result = plTclCmd( cmdlist, interp, argc, argv );
1980
1981 plflush();
1982 return result;
1983}
1984
1985static void ActiveState( register PlPlotter *plPlotterPtr, int on )
1986{
1987 if ( on )
1988 {
1989 if ( !plPlotterPtr->isActive )
1990 {
1991 Tk_CreateEventHandler( plPlotterPtr->tkwin, ButtonPressMask,
1992 PlPlotterButtonPressEH, (ClientData) plPlotterPtr );
1993
1994 Tk_CreateEventHandler( plPlotterPtr->tkwin, PointerMotionMask,
1995 PlPlotterMotionEH, (ClientData) plPlotterPtr );
1996
1997 Tk_CreateEventHandler( plPlotterPtr->tkwin, EnterWindowMask,
1998 PlPlotterEnterEH, (ClientData) plPlotterPtr );
1999
2000 Tk_CreateEventHandler( plPlotterPtr->tkwin, LeaveWindowMask,
2001 PlPlotterLeaveEH, (ClientData) plPlotterPtr );
2002 // Switch to crosshair cursor.
2003
2004 Tk_DefineCursor( plPlotterPtr->tkwin, plPlotterPtr->xhair_cursor );
2005 }
2006 }
2007 else
2008 {
2009 if ( plPlotterPtr->isActive )
2010 {
2011 Tk_DeleteEventHandler( plPlotterPtr->tkwin, ButtonPressMask,
2012 PlPlotterButtonPressEH, (ClientData) plPlotterPtr );
2013 Tk_DeleteEventHandler( plPlotterPtr->tkwin, PointerMotionMask,
2014 PlPlotterMotionEH, (ClientData) plPlotterPtr );
2015
2016 Tk_DeleteEventHandler( plPlotterPtr->tkwin, EnterWindowMask,
2017 PlPlotterEnterEH, (ClientData) plPlotterPtr );
2018
2019 Tk_DeleteEventHandler( plPlotterPtr->tkwin, LeaveWindowMask,
2020 PlPlotterLeaveEH, (ClientData) plPlotterPtr );
2021 // Switch back to boring old pointer
2022
2023 Tk_DefineCursor( plPlotterPtr->tkwin, plPlotterPtr->cursor );
2024 }
2025 }
2026}
2027
2028
2029//
2030//--------------------------------------------------------------------------
2031//
2032// ConfigureWidgetCompat --
2033//
2034// Compatibility wrapper for Tk_ConfigureWidget. Tk 9 expects the
2035// argument vector as Tcl_Obj pointers rather than string pointers.
2036//
2037//--------------------------------------------------------------------------
2038//
2039
2040static int
2041ConfigureWidgetCompat( Tcl_Interp *interp, Tk_Window tkwin,
2042 const Tk_ConfigSpec *configSpecs,
2043 int argc, const char **argv, char *widgRec, int flags )
2044{
2045#if TK_MAJOR_VERSION >= 9
2046 Tcl_Obj **objv = NULL;
2047 int i;
2048 int result;
2049
2050 if ( argc > 0 )
2051 {
2052 objv = (Tcl_Obj **) Tcl_Alloc( (size_t) argc * sizeof( Tcl_Obj * ) );
2053 if ( objv == NULL )
2054 {
2055 Tcl_SetResult( interp, "out of memory", TCL_STATIC );
2056 return TCL_ERROR;
2057 }
2058
2059 for ( i = 0; i < argc; i++ )
2060 {
2061 objv[i] = Tcl_NewStringObj( argv[i], -1 );
2062 }
2063 }
2064
2065 result = Tk_ConfigureWidget( interp, tkwin, configSpecs, argc,
2066 (Tcl_Obj *const *) objv, widgRec, flags );
2067
2068 if ( objv != NULL )
2069 {
2070 for ( i = 0; i < argc; i++ )
2071 {
2072 Tcl_DecrRefCount( objv[i] );
2073 }
2074 Tcl_Free( (char *) objv );
2075 }
2076
2077 return result;
2078#else
2079 return Tk_ConfigureWidget( interp, tkwin, configSpecs, argc, argv,
2080 widgRec, flags );
2081#endif
2082}
2083
2084static int
2085ConfigurePlPlotter( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2086 int argc, const char **argv, int flags )
2087{
2088 register Tk_Window tkwin = plPlotterPtr->tkwin;
2089 PLStream *pls = plPlotterPtr->pls;
2090 TkwDev *dev = (TkwDev *) pls->dev;
2091 TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
2092 XGCValues gcValues;
2093 unsigned long mask;
2094 int need_redisplay = 0;
2095
2096#ifdef DEBUG
2097 if ( pls->debug )
2098 {
2099 int i;
2100 fprintf( stderr, "Arguments to configure are:" );
2101 for ( i = 0; i < argc; i++ )
2102 {
2103 fprintf( stderr, " %s", argv[i] );
2104 }
2105 fprintf( stderr, "\n" );
2106 }
2107#endif
2108
2109 dbug_enter( "ConfigurePlPlotter" );
2110
2112 argc, argv, (char *) plPlotterPtr, flags ) != TCL_OK )
2113 {
2114 return TCL_ERROR;
2115 }
2116
2117//
2118// Set background color using tkwin driver's pixel value. Done this way so
2119// that (a) we can use r/w color cells, and (b) the BG pixel values as set
2120// here and in the tkwin driver are consistent.
2121//
2122
2123 plsstrm( plPlotterPtr->ipls );
2124 if ( PLColor_from_TkColor_Changed( &pls->cmap0[0],
2125 Tk_3DBorderColor( plPlotterPtr->border ) ) )
2126 {
2127 need_redisplay = 1;
2128 // need to redraw as well as simply refresh the window
2129 plPlotterPtr->flags |= REDRAW_PENDING;
2130 }
2132
2133 Tk_SetWindowBackground( tkwin, tkwd->cmap0[0].pixel );
2134 Tk_SetWindowBorder( tkwin, tkwd->cmap0[0].pixel );
2135
2136 // Set up GC for rubber-band draws
2137
2138 gcValues.background = tkwd->cmap0[0].pixel;
2139 gcValues.foreground = 0xFF;
2140 gcValues.function = GXxor;
2141 mask = GCForeground | GCBackground | GCFunction;
2142
2143 if ( plPlotterPtr->xorGC != NULL )
2144 Tk_FreeGC( plPlotterPtr->display, plPlotterPtr->xorGC );
2145
2146 plPlotterPtr->xorGC = Tk_GetGC( plPlotterPtr->tkwin, mask, &gcValues );
2147
2148// Geometry settings
2149
2150 Tk_SetInternalBorder( tkwin, plPlotterPtr->borderWidth );
2151 if ( ( plPlotterPtr->width > 0 ) || ( plPlotterPtr->height > 0 ) )
2152 {
2153 Tk_GeometryRequest( tkwin, plPlotterPtr->width, plPlotterPtr->height );
2154 if ( ( plPlotterPtr->width != plPlotterPtr->prevWidth ) ||
2155 ( plPlotterPtr->height != plPlotterPtr->prevHeight ) )
2156 need_redisplay = 1;
2157 }
2158
2159// Create or destroy graphic crosshairs as specified
2160
2161 if ( Tk_IsMapped( tkwin ) )
2162 {
2163 if ( plPlotterPtr->xhairs )
2164 {
2165 if ( !plPlotterPtr->drawing_xhairs )
2166 CreateXhairs( plPlotterPtr );
2167 }
2168 else
2169 {
2170 if ( plPlotterPtr->drawing_xhairs )
2171 DestroyXhairs( plPlotterPtr );
2172 }
2173 }
2174
2175// Create or destroy rubber band as specified
2176
2177 if ( Tk_IsMapped( tkwin ) )
2178 {
2179 if ( plPlotterPtr->rband )
2180 {
2181 if ( !plPlotterPtr->drawing_rband )
2182 CreateRband( plPlotterPtr );
2183 }
2184 else
2185 {
2186 if ( plPlotterPtr->drawing_rband )
2187 DestroyRband( plPlotterPtr );
2188 }
2189 }
2190// Sets or clears events for the plot
2191 ActiveState( plPlotterPtr, plPlotterPtr->active_plot );
2192
2193 if ( !pls->nopixmap )
2194 {
2195 // can only adjust if this flag not set
2196 if ( plPlotterPtr->double_buffer != pls->db )
2197 {
2198 pls->db = plPlotterPtr->double_buffer;
2199 // turn on/off dbl-buffering in the driver
2200 dev->write_to_window = !pls->db;
2201 }
2202 }
2203 else
2204 {
2205 plPlotterPtr->double_buffer = 0;
2206 }
2207
2208// Arrange for window to be refreshed if necessary
2209 if ( need_redisplay && Tk_IsMapped( tkwin )
2210 && !( plPlotterPtr->flags & REFRESH_PENDING ) )
2211 {
2212 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
2213 plPlotterPtr->flags |= REFRESH_PENDING;
2214 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
2215 }
2216
2217 return TCL_OK;
2218}
2219
2220//--------------------------------------------------------------------------
2221// Draw
2222//
2223// Processes "draw" widget command.
2224// Handles rubber-band drawing.
2225//--------------------------------------------------------------------------
2226
2227static int
2228Draw( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2229 int argc, const char **argv )
2230{
2231 register Tk_Window tkwin = plPlotterPtr->tkwin;
2232 int result = TCL_OK;
2233 char c = argv[0][0];
2234 int length = (int) strlen( argv[0] );
2235
2236// Make sure widget has been initialized before going any further
2237
2238 if ( !plPlotterPtr->tkwin_initted )
2239 {
2240 Tcl_VarEval( plPlotterPtr->interp, "update", (char *) NULL );
2241 }
2242
2243// init -- sets up for rubber-band drawing
2244
2245 if ( ( c == 'i' ) && ( strncmp( argv[0], "init", (size_t) length ) == 0 ) )
2246 {
2247 Tk_DefineCursor( tkwin, plPlotterPtr->xhair_cursor );
2248 }
2249
2250// end -- ends rubber-band drawing
2251
2252 else if ( ( c == 'e' ) && ( strncmp( argv[0], "end", (size_t) length ) == 0 ) )
2253 {
2254 Tk_DefineCursor( tkwin, plPlotterPtr->cursor );
2255 if ( plPlotterPtr->continue_draw )
2256 {
2257 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2258 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2259 CoordModeOrigin );
2260 XSync( Tk_Display( tkwin ), 0 );
2261 }
2262
2263 plPlotterPtr->continue_draw = 0;
2264 }
2265
2266// rect -- draw a rectangle, used to select rectangular areas
2267// first draw erases old outline
2268
2269 else if ( ( c == 'r' ) && ( strncmp( argv[0], "rect", (size_t) length ) == 0 ) )
2270 {
2271 if ( argc < 5 )
2272 {
2273 Tcl_AppendResult( interp, "wrong # args: should be \"",
2274 " draw rect x0 y0 x1 y1\"", (char *) NULL );
2275 result = TCL_ERROR;
2276 }
2277 else
2278 {
2279 int x0, y0, x1, y1;
2280 int xmin = 0, xmax = Tk_Width( tkwin ) - 1;
2281 int ymin = 0, ymax = Tk_Height( tkwin ) - 1;
2282
2283 x0 = atoi( argv[1] );
2284 y0 = atoi( argv[2] );
2285 x1 = atoi( argv[3] );
2286 y1 = atoi( argv[4] );
2287
2288 x0 = MAX( xmin, MIN( xmax, x0 ) );
2289 y0 = MAX( ymin, MIN( ymax, y0 ) );
2290 x1 = MAX( xmin, MIN( xmax, x1 ) );
2291 y1 = MAX( ymin, MIN( ymax, y1 ) );
2292
2293 if ( plPlotterPtr->continue_draw )
2294 {
2295 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2296 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2297 CoordModeOrigin );
2298 XSync( Tk_Display( tkwin ), 0 );
2299 }
2300
2301 plPlotterPtr->pts[0].x = (short) x0; plPlotterPtr->pts[0].y = (short) y0;
2302 plPlotterPtr->pts[1].x = (short) x1; plPlotterPtr->pts[1].y = (short) y0;
2303 plPlotterPtr->pts[2].x = (short) x1; plPlotterPtr->pts[2].y = (short) y1;
2304 plPlotterPtr->pts[3].x = (short) x0; plPlotterPtr->pts[3].y = (short) y1;
2305 plPlotterPtr->pts[4].x = (short) x0; plPlotterPtr->pts[4].y = (short) y0;
2306
2307 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2308 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2309 CoordModeOrigin );
2310 XSync( Tk_Display( tkwin ), 0 );
2311
2312 plPlotterPtr->continue_draw = 1;
2313 }
2314 }
2315
2316 return result;
2317}
2318
2319//--------------------------------------------------------------------------
2320// Info
2321//
2322// Processes "info" widget command.
2323// Returns requested info.
2324//--------------------------------------------------------------------------
2325
2326static int
2327Info( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2328 int argc, const char **argv )
2329{
2330 int length;
2331 char c;
2332 int result = TCL_OK;
2333
2334// no option -- return list of available info commands
2335
2336 if ( argc == 0 )
2337 {
2338 Tcl_SetResult( interp, "devkeys devnames", TCL_STATIC );
2339 return TCL_OK;
2340 }
2341
2342 c = argv[0][0];
2343 length = (int) strlen( argv[0] );
2344
2345// devkeys -- return list of supported device keywords
2346
2347 if ( ( c == 'd' ) && ( strncmp( argv[0], "devkeys", (size_t) length ) == 0 ) )
2348 {
2349 int i = 0;
2350 while ( plPlotterPtr->devName[i] != NULL )
2351 Tcl_AppendElement( interp, plPlotterPtr->devName[i++] );
2352
2353 result = TCL_OK;
2354 }
2355
2356// devkeys -- return list of supported device types
2357
2358 else if ( ( c == 'd' ) && ( strncmp( argv[0], "devnames", (size_t) length ) == 0 ) )
2359 {
2360 int i = 0;
2361 while ( plPlotterPtr->devDesc[i] != NULL )
2362 Tcl_AppendElement( interp, plPlotterPtr->devDesc[i++] );
2363
2364 result = TCL_OK;
2365 }
2366
2367// unrecognized
2368
2369 else
2370 {
2371 Tcl_AppendResult( interp, "bad option to \"info\": must be ",
2372 "devkeys, devnames", (char *) NULL );
2373
2374 result = TCL_ERROR;
2375 }
2376
2377 return result;
2378}
2379
2380//--------------------------------------------------------------------------
2381// Openlink
2382//
2383// Processes "openlink" widget command.
2384// Opens channel (FIFO or socket) for binary data transfer between client
2385// and server.
2386//--------------------------------------------------------------------------
2387
2388static int
2389Openlink( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2390 int argc, const char **argv )
2391{
2392#if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2393 register PLRDev *plr = plPlotterPtr->plr;
2394 register PLiodev *iodev = plr->iodev;
2395
2396 char c = argv[0][0];
2397 int length = (int) strlen( argv[0] );
2398
2399 dbug_enter( "Openlink" );
2400
2401// Open fifo
2402
2403 if ( ( c == 'f' ) && ( strncmp( argv[0], "fifo", (size_t) length ) == 0 ) )
2404 {
2405 if ( argc < 1 )
2406 {
2407 Tcl_AppendResult( interp, "bad command -- must be: ",
2408 "openlink fifo <pathname>",
2409 (char *) NULL );
2410 return TCL_ERROR;
2411 }
2412 if ( ( iodev->fd = open( argv[1], O_RDONLY ) ) == -1 )
2413 {
2414 Tcl_AppendResult( interp, "cannot open fifo ", argv[1],
2415 " for read", (char *) NULL );
2416 return TCL_ERROR;
2417 }
2418 iodev->type = 0;
2419 iodev->typeName = "fifo";
2420 iodev->file = fdopen( iodev->fd, "rb" );
2421 }
2422
2423// Open socket
2424
2425 else if ( ( c == 's' ) && ( strncmp( argv[0], "socket", (size_t) length ) == 0 ) )
2426 {
2427 if ( argc < 1 )
2428 {
2429 Tcl_AppendResult( interp, "bad command -- must be: ",
2430 "openlink socket <sock-id>",
2431 (char *) NULL );
2432 return TCL_ERROR;
2433 }
2434 iodev->type = 1;
2435 iodev->typeName = "socket";
2436 iodev->fileHandle = (char *) argv[1];
2437
2438 if ( Tcl_GetOpenFile( interp, iodev->fileHandle,
2439 0, 1, ( ClientData ) & iodev->file ) != TCL_OK )
2440 {
2441 return TCL_ERROR;
2442 }
2443 iodev->fd = fileno( iodev->file );
2444 }
2445
2446// unrecognized
2447
2448 else
2449 {
2450 Tcl_AppendResult( interp, "bad option to \"openlink\": must be ",
2451 "fifo or socket", (char *) NULL );
2452
2453 return TCL_ERROR;
2454 }
2455
2456 plr->pdfs = pdf_bopen( NULL, 4200 );
2457#if defined( TCL_MAJOR_VERSION ) && TCL_MAJOR_VERSION >= 9
2458 Tcl_CreateFileHandler( iodev->fd, TCL_READABLE, (Tcl_FileProc *) ReadData,
2459 (void *) plPlotterPtr );
2460#else
2461 Tcl_CreateFileHandler( iodev->fd,
2462 TCL_READABLE, (Tcl_FileProc *) ReadData,
2463 (ClientData) plPlotterPtr );
2464#endif
2465
2466#endif
2467
2468 return TCL_OK;
2469}
2470
2471//--------------------------------------------------------------------------
2472// Closelink
2473//
2474// Processes "closelink" widget command.
2475// CLoses channel previously opened with the "openlink" widget command.
2476//--------------------------------------------------------------------------
2477
2478static int
2479Closelink( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2480 int PL_UNUSED( argc ), const char ** PL_UNUSED( argv ) )
2481{
2482#if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2483 register PLRDev *plr = plPlotterPtr->plr;
2484 register PLiodev *iodev = plr->iodev;
2485
2486 dbug_enter( "Closelink" );
2487
2488 if ( iodev->fd == 0 )
2489 {
2490 Tcl_AppendResult( interp, "no link currently open", (char *) NULL );
2491 return TCL_ERROR;
2492 }
2493
2494 Tcl_DeleteFileHandler( iodev->fd );
2495 pdf_close( plr->pdfs );
2496 iodev->fd = 0;
2497#endif
2498 return TCL_OK;
2499}
2500
2501//--------------------------------------------------------------------------
2502// process_data
2503//
2504// Utility function for processing data and other housekeeping.
2505//--------------------------------------------------------------------------
2506
2507static int
2508process_data( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2509{
2510 register PLRDev *plr = plPlotterPtr->plr;
2511 register PLiodev *iodev = plr->iodev;
2512 int result = TCL_OK;
2513
2514// Process data
2515
2516 if ( plr_process( plr ) == -1 )
2517 {
2518 Tcl_AppendResult( interp, "unable to read from ", iodev->typeName,
2519 (char *) NULL );
2520 result = TCL_ERROR;
2521 }
2522
2523// Signal bop if necessary
2524
2525 if ( plr->at_bop && plPlotterPtr->bopCmd != NULL )
2526 {
2527 plr->at_bop = 0;
2528 if ( Tcl_Eval( interp, plPlotterPtr->bopCmd ) != TCL_OK )
2529 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2530 plPlotterPtr->bopCmd, Tcl_GetStringResult( interp ) );
2531 }
2532
2533// Signal eop if necessary
2534
2535 if ( plr->at_eop && plPlotterPtr->eopCmd != NULL )
2536 {
2537 plr->at_eop = 0;
2538 if ( Tcl_Eval( interp, plPlotterPtr->eopCmd ) != TCL_OK )
2539 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2540 plPlotterPtr->eopCmd, Tcl_GetStringResult( interp ) );
2541 }
2542
2543 return result;
2544}
2545
2546void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2547{
2548 if ( plPlotterPtr->eopCmd != NULL )
2549 {
2550 if ( Tcl_Eval( interp, plPlotterPtr->eopCmd ) != TCL_OK )
2551 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2552 plPlotterPtr->eopCmd, Tcl_GetStringResult( interp ) );
2553 }
2554}
2555
2556void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2557{
2558 if ( plPlotterPtr->bopCmd != NULL )
2559 {
2560 if ( Tcl_Eval( interp, plPlotterPtr->bopCmd ) != TCL_OK )
2561 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2562 plPlotterPtr->bopCmd, Tcl_GetStringResult( interp ) );
2563 }
2564}
2565
2566//--------------------------------------------------------------------------
2567// ReadData
2568//
2569// Reads & processes data.
2570// Intended to be installed as a filehandler command.
2571//--------------------------------------------------------------------------
2572
2573static int
2574ReadData( ClientData clientData, int mask )
2575{
2576 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
2577 register Tcl_Interp *interp = plPlotterPtr->interp;
2578
2579 register PLRDev *plr = plPlotterPtr->plr;
2580 register PLiodev *iodev = plr->iodev;
2581 register PDFstrm *pdfs = plr->pdfs;
2582 int result = TCL_OK;
2583
2584 if ( mask & TCL_READABLE )
2585 {
2586 // Read from FIFO or socket
2587
2588 plsstrm( plPlotterPtr->ipls );
2589 #ifndef MAC_TCL
2590 if ( pl_PacketReceive( interp, iodev, pdfs ) )
2591 {
2592 #else
2593 if ( 1 )
2594 {
2595 #endif
2596 Tcl_AppendResult( interp, "Packet receive failed:\n\t %s\n",
2597 Tcl_GetStringResult( interp ), (char *) NULL );
2598 return TCL_ERROR;
2599 }
2600
2601 // If the packet isn't complete it will be put back and we just return.
2602 // Otherwise, the buffer pointer is saved and then cleared so that reads
2603 // from the buffer start at the beginning.
2604 //
2605 if ( pdfs->bp == 0 )
2606 return TCL_OK;
2607
2608 plr->nbytes = (int) pdfs->bp;
2609 pdfs->bp = 0;
2610 result = process_data( interp, plPlotterPtr );
2611 }
2612
2613 return result;
2614}
2615
2616//--------------------------------------------------------------------------
2617// Orient
2618//
2619// Processes "orient" widget command.
2620// Handles orientation of plot.
2621//--------------------------------------------------------------------------
2622
2623static int
2624Orient( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2625 int argc, const char **argv )
2626{
2627 int result = TCL_OK;
2628
2629// orient -- return orientation of current plot window
2630
2631 plsstrm( plPlotterPtr->ipls );
2632
2633 if ( argc == 0 )
2634 {
2635 PLFLT rot;
2636 char result_str[128];
2637 plgdiori( &rot );
2638 sprintf( result_str, "%f", rot );
2639 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2640 }
2641
2642// orient <rot> -- Set orientation to <rot>
2643
2644 else
2645 {
2646 plsdiori( (PLFLT) atof( argv[0] ) );
2647 result = Redraw( interp, plPlotterPtr, argc - 1, argv + 1 );
2648 }
2649
2650 return result;
2651}
2652
2653//--------------------------------------------------------------------------
2654// Print
2655//
2656// Processes "print" widget command.
2657// Handles printing of plot, duh.
2658//
2659// Creates a temporary file, dumps the current plot to it in metafile
2660// form, and then execs the "plpr" script to actually print it. Since we
2661// output it in metafile form here, plpr must invoke plrender to drive the
2662// output to the appropriate file type. The script is responsible for the
2663// deletion of the plot metafile.
2664//--------------------------------------------------------------------------
2665
2666static int
2667Print( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2668 int PL_UNUSED( argc ), const char ** PL_UNUSED( argv ) )
2669{
2670 PLINT ipls;
2671 int result = TCL_OK;
2672 char *sfnam;
2673 FILE *sfile;
2674#if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2675 pid_t pid;
2676#endif
2677
2678// Make sure widget has been initialized before going any further
2679
2680 if ( !plPlotterPtr->tkwin_initted )
2681 {
2682 Tcl_AppendResult( interp, "Error -- widget not plotted to yet",
2683 (char *) NULL );
2684 return TCL_ERROR;
2685 }
2686
2687// Create stream for save
2688
2689 plmkstrm( &ipls );
2690 if ( ipls < 0 )
2691 {
2692 Tcl_AppendResult( interp, "Error -- cannot create stream",
2693 (char *) NULL );
2694 return TCL_ERROR;
2695 }
2696
2697// Open file for writes
2698
2699 // Create and open temporary file
2700 // NB use fdopen to get a file stream from the existing file handle
2701 if ( ( sfile = pl_create_tempfile( &sfnam ) ) == NULL )
2702 {
2703 Tcl_AppendResult( interp,
2704 "Error -- cannot open plot file for writing",
2705 (char *) NULL );
2706 plend1();
2707 if ( sfnam != NULL )
2708 free( sfnam );
2709 return TCL_ERROR;
2710 }
2711
2712// Initialize stream
2713
2714 plsdev( "plmeta" );
2715 plsfile( sfile );
2716 plcpstrm( plPlotterPtr->ipls, 0 );
2717 pladv( 0 );
2718
2719// Remake current plot, close file, and switch back to original stream
2720
2721 plreplot();
2722 plend1();
2723 plsstrm( plPlotterPtr->ipls );
2724
2725// So far so good. Time to exec the print script.
2726
2727 if ( plPlotterPtr->plpr_cmd == NULL )
2728 plPlotterPtr->plpr_cmd = plFindCommand( "plpr" );
2729
2730#if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2731 if ( ( plPlotterPtr->plpr_cmd == NULL ) || ( pid = fork() ) < 0 )
2732 {
2733 Tcl_AppendResult( interp,
2734 "Error -- cannot fork print process",
2735 (char *) NULL );
2736 result = TCL_ERROR;
2737 }
2738 else if ( pid == 0 )
2739 {
2740 if ( execl( plPlotterPtr->plpr_cmd, plPlotterPtr->plpr_cmd, sfnam,
2741 (char *) 0 ) )
2742 {
2743 fprintf( stderr, "Unable to exec print command.\n" );
2744 free( sfnam );
2745 _exit( 1 );
2746 }
2747 }
2748#endif
2749 free( sfnam );
2750 return result;
2751}
2752
2753//--------------------------------------------------------------------------
2754// NextPage
2755//
2756// Tells the tkwin driver to move along to the next page.
2757//--------------------------------------------------------------------------
2758
2759static int
2760NextPage( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2761 int argc, const char ** PL_UNUSED( argv ) )
2762{
2763 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
2764 if ( argc == 0 )
2765 {
2766 dev->flags |= 2;
2767 }
2768 else
2769 {
2770 Tcl_AppendResult( interp, "wrong # args: should be \"",
2771 " nextpage\"", (char *) NULL );
2772 return TCL_ERROR;
2773 }
2774 return TCL_OK;
2775}
2776
2777//--------------------------------------------------------------------------
2778// Page
2779//
2780// Processes "page" widget command.
2781// Handles parameters such as margin, aspect ratio, and justification
2782// of final plot.
2783//--------------------------------------------------------------------------
2784
2785static int
2786Page( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2787 int argc, const char **argv )
2788{
2789// page -- return current device window parameters
2790
2791 plsstrm( plPlotterPtr->ipls );
2792
2793 if ( argc == 0 )
2794 {
2795 PLFLT mar, aspect, jx, jy;
2796 char result_str[128];
2797
2798 plgdidev( &mar, &aspect, &jx, &jy );
2799 sprintf( result_str, "%g %g %g %g", mar, aspect, jx, jy );
2800 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2801 return TCL_OK;
2802 }
2803
2804// page <mar> <aspect> <jx> <jy> -- set up page
2805
2806 if ( argc < 4 )
2807 {
2808 Tcl_AppendResult( interp, "wrong # args: should be \"",
2809 " page mar aspect jx jy\"", (char *) NULL );
2810 return TCL_ERROR;
2811 }
2812
2813 plsdidev( (PLFLT) atof( argv[0] ), (PLFLT) atof( argv[1] ),
2814 (PLFLT) atof( argv[2] ), (PLFLT) atof( argv[3] ) );
2815 return ( Redraw( interp, plPlotterPtr, argc - 1, argv + 1 ) );
2816}
2817
2818//--------------------------------------------------------------------------
2819// Redraw
2820//
2821// Processes "redraw" widget command.
2822// Turns loose a DoWhenIdle command to redraw plot by replaying contents
2823// of plot buffer.
2824//--------------------------------------------------------------------------
2825
2826static int
2827Redraw( Tcl_Interp * PL_UNUSED( interp ), register PlPlotter *plPlotterPtr,
2828 int PL_UNUSED( argc ), const char ** PL_UNUSED( argv ) )
2829{
2830 dbug_enter( "Redraw" );
2831
2832 plPlotterPtr->flags |= REDRAW_PENDING;
2833 if ( ( plPlotterPtr->tkwin != NULL ) &&
2834 !( plPlotterPtr->flags & REFRESH_PENDING ) )
2835 {
2836 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
2837 plPlotterPtr->flags |= REFRESH_PENDING;
2838 }
2839
2840 return TCL_OK;
2841}
2842
2843//--------------------------------------------------------------------------
2844// Save
2845//
2846// Processes "save" widget command.
2847// Saves plot to a file.
2848//--------------------------------------------------------------------------
2849
2850static int
2851Save( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2852 int argc, const char **argv )
2853{
2854 int length;
2855 char c;
2856 FILE *sfile;
2857
2858// Make sure widget has been initialized before going any further
2859
2860 if ( !plPlotterPtr->tkwin_initted )
2861 {
2862 Tcl_AppendResult( interp, "Error -- widget not plotted to yet",
2863 (char *) NULL );
2864 return TCL_ERROR;
2865 }
2866
2867// save -- save to already open file
2868
2869 if ( argc == 0 )
2870 {
2871 if ( !plPlotterPtr->ipls_save )
2872 {
2873 Tcl_AppendResult( interp, "Error -- no current save file",
2874 (char *) NULL );
2875 return TCL_ERROR;
2876 }
2877 plsstrm( plPlotterPtr->ipls_save );
2878 plcpstrm( plPlotterPtr->ipls, 0 );
2879 pladv( 0 );
2880 plreplot();
2881 plflush();
2882 plsstrm( plPlotterPtr->ipls );
2883 return TCL_OK;
2884 }
2885
2886 c = argv[0][0];
2887 length = (int) strlen( argv[0] );
2888
2889// save to specified device & file
2890
2891 if ( ( c == 'a' ) && ( strncmp( argv[0], "as", (size_t) length ) == 0 ) )
2892 {
2893 if ( argc < 3 )
2894 {
2895 Tcl_AppendResult( interp, "wrong # args: should be \"",
2896 " save as device file\"", (char *) NULL );
2897 return TCL_ERROR;
2898 }
2899
2900 // If save previously in effect, delete old stream
2901
2902 if ( plPlotterPtr->ipls_save )
2903 {
2904 plsstrm( plPlotterPtr->ipls_save );
2905 plend1();
2906 }
2907
2908 // Create stream for saves to selected device & file
2909
2910 plmkstrm( &plPlotterPtr->ipls_save );
2911 if ( plPlotterPtr->ipls_save < 0 )
2912 {
2913 Tcl_AppendResult( interp, "Error -- cannot create stream",
2914 (char *) NULL );
2915 plPlotterPtr->ipls_save = 0;
2916 return TCL_ERROR;
2917 }
2918
2919 // Open file for writes
2920
2921 if ( ( sfile = fopen( argv[2], "wb+" ) ) == NULL )
2922 {
2923 Tcl_AppendResult( interp, "Error -- cannot open file ", argv[2],
2924 " for writing", (char *) NULL );
2925 plPlotterPtr->ipls_save = 0;
2926 plend1();
2927 return TCL_ERROR;
2928 }
2929
2930 // Initialize stream
2931
2932 plsdev( argv[1] );
2933 plsfile( sfile );
2934 plcpstrm( plPlotterPtr->ipls, 0 );
2935 pladv( 0 );
2936
2937 // Remake current plot and then switch back to original stream
2938
2939 plreplot();
2940 plflush();
2941 plsstrm( plPlotterPtr->ipls );
2942 }
2943
2944// close save file
2945
2946 else if ( ( c == 'c' ) && ( strncmp( argv[0], "close", (size_t) length ) == 0 ) )
2947 {
2948 if ( !plPlotterPtr->ipls_save )
2949 {
2950 Tcl_AppendResult( interp, "Error -- no current save file",
2951 (char *) NULL );
2952 return TCL_ERROR;
2953 }
2954 else
2955 {
2956 plsstrm( plPlotterPtr->ipls_save );
2957 plend1();
2958 plPlotterPtr->ipls_save = 0;
2959 }
2960 }
2961
2962// unrecognized
2963
2964 else
2965 {
2966 Tcl_AppendResult( interp, "bad option to \"save\": must be ",
2967 "as or close", (char *) NULL );
2968
2969 return TCL_ERROR;
2970 }
2971
2972 return TCL_OK;
2973}
2974
2975//--------------------------------------------------------------------------
2976// View
2977//
2978// Processes "view" widget command.
2979// Handles translation & scaling of view into plot.
2980//--------------------------------------------------------------------------
2981
2982static int
2983View( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2984 int argc, const char **argv )
2985{
2986 int length;
2987 int dontRedraw = 0;
2988 char c;
2989 PLFLT xl, xr, yl, yr;
2990
2991// view -- return current relative plot window coordinates
2992
2993 plsstrm( plPlotterPtr->ipls );
2994
2995 if ( argc == 0 )
2996 {
2997 char result_str[128];
2998 plgdiplt( &xl, &yl, &xr, &yr );
2999 sprintf( result_str, "%g %g %g %g", xl, yl, xr, yr );
3000 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
3001 return TCL_OK;
3002 }
3003
3004 c = argv[0][0];
3005 length = (int) strlen( argv[0] );
3006
3007// view bounds -- return relative device coordinates of bounds on current
3008// plot window
3009
3010 if ( ( c == 'b' ) && ( strncmp( argv[0], "bounds", (size_t) length ) == 0 ) )
3011 {
3012 char result_str[128];
3013 xl = 0.; yl = 0.;
3014 xr = 1.; yr = 1.;
3015 pldip2dc( &xl, &yl, &xr, &yr );
3016 sprintf( result_str, "%g %g %g %g", xl, yl, xr, yr );
3017 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
3018 return TCL_OK;
3019 }
3020
3021// view reset -- Resets plot
3022
3023 if ( ( c == 'r' ) && ( strncmp( argv[0], "reset", (size_t) length ) == 0 ) )
3024 {
3025 xl = 0.; yl = 0.;
3026 xr = 1.; yr = 1.;
3027 plsdiplt( xl, yl, xr, yr );
3028 if ( argc > 1 && ( strcmp( argv[1], "wait" ) == 0 ) )
3029 {
3030 // We're going to update in a while, so don't do it now
3031 dontRedraw = 1;
3032 }
3033 }
3034
3035// view select -- set window into plot space
3036// Specifies in terms of plot window coordinates, not device coordinates
3037
3038 else if ( ( c == 's' ) && ( strncmp( argv[0], "select", (size_t) length ) == 0 ) )
3039 {
3040 if ( argc < 5 )
3041 {
3042 Tcl_AppendResult( interp, "wrong # args: should be \"",
3043 " view select xmin ymin xmax ymax\"",
3044 (char *) NULL );
3045 return TCL_ERROR;
3046 }
3047 else
3048 {
3049 gbox( &xl, &yl, &xr, &yr, argv + 1 );
3050 plsdiplt( xl, yl, xr, yr );
3051 }
3052 }
3053
3054// view zoom -- set window into plot space incrementally (zoom)
3055// Here we need to take the page (device) offsets into account
3056
3057 else if ( ( c == 'z' ) && ( strncmp( argv[0], "zoom", (size_t) length ) == 0 ) )
3058 {
3059 if ( argc < 5 )
3060 {
3061 Tcl_AppendResult( interp, "wrong # args: should be \"",
3062 " view zoom xmin ymin xmax ymax\"",
3063 (char *) NULL );
3064 return TCL_ERROR;
3065 }
3066 else
3067 {
3068 gbox( &xl, &yl, &xr, &yr, argv + 1 );
3069 pldid2pc( &xl, &yl, &xr, &yr );
3070 plsdiplz( xl, yl, xr, yr );
3071 if ( argc > 5 && ( strcmp( argv[5], "wait" ) == 0 ) )
3072 {
3073 // We're going to update in a while, so don't do it now
3074 dontRedraw = 1;
3075 }
3076 }
3077 }
3078
3079// unrecognized
3080
3081 else
3082 {
3083 Tcl_AppendResult( interp, "bad option \"", argv[1],
3084 "\": options to \"view\" are: bounds, reset, select, or zoom",
3085 (char *) NULL );
3086
3087 return TCL_ERROR;
3088 }
3089
3090// Update plot window bounds and arrange for plot to be updated
3091
3092 plgdiplt( &xl, &yl, &xr, &yr );
3093 plPlotterPtr->xl = xl;
3094 plPlotterPtr->yl = yl;
3095 plPlotterPtr->xr = xr;
3096 plPlotterPtr->yr = yr;
3097 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
3098
3099 if ( dontRedraw )
3100 {
3101 return TCL_OK;
3102 }
3103 else
3104 {
3105 return Redraw( interp, plPlotterPtr, argc, argv );
3106 }
3107}
3108
3109//--------------------------------------------------------------------------
3110// Scroll
3111//
3112// Processes "xview or yview" widget command.
3113// Handles horizontal/vert scroll-bar invoked translation of view into plot.
3114//--------------------------------------------------------------------------
3115
3116static int
3117Scroll( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
3118{
3119 plsstrm( plPlotterPtr->ipls );
3120 plsdiplt( plPlotterPtr->xl, plPlotterPtr->yl, plPlotterPtr->xr, plPlotterPtr->yr );
3121
3122 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
3123 return ( Redraw( interp, plPlotterPtr, 0, NULL ) );
3124}
3125
3126
3127//--------------------------------------------------------------------------
3128// report
3129//
3130// 4/17/95 GMF
3131// Processes "report" widget command.
3132//--------------------------------------------------------------------------
3133
3134static int
3135report( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
3136 int argc, const char **argv )
3137{
3138 PLFLT x, y;
3139 char res[40];
3140// fprintf( stdout, "Made it into report, argc=%d\n", argc );
3141
3142 if ( argc == 0 )
3143 {
3144 Tcl_SetResult( interp, "report what?", TCL_STATIC );
3145 return TCL_ERROR;
3146 }
3147
3148 if ( !strcmp( argv[0], "wc" ) )
3149 {
3150 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
3151 PLGraphicsIn *gin = &( dev->gin );
3152
3153 if ( argc != 3 )
3154 {
3155 Tcl_SetResult( interp, "Wrong # of args: report wc x y", TCL_STATIC );
3156 return TCL_ERROR;
3157 }
3158
3159 x = (PLFLT) atof( argv[1] );
3160 y = (PLFLT) atof( argv[2] );
3161
3162 gin->dX = (PLFLT) x / ( dev->width - 1 );
3163 gin->dY = (PLFLT) 1.0 - (PLFLT) y / ( dev->height - 1 );
3164
3165 // Try to locate cursor
3166
3167 if ( plTranslateCursor( gin ) )
3168 {
3169 snprintf( res, 40, "%f %f", gin->wX, gin->wY );
3170 Tcl_SetResult( interp, res, TCL_VOLATILE );
3171 return TCL_OK;
3172 }
3173
3174 Tcl_SetResult( interp, "Cannot locate", TCL_STATIC );
3175 return TCL_OK;
3176 }
3177
3178 Tcl_SetResult( interp, "nonsensical request.", TCL_STATIC );
3179 return TCL_ERROR;
3180}
3181
3182//--------------------------------------------------------------------------
3183// Utility routines
3184//--------------------------------------------------------------------------
3185
3186//--------------------------------------------------------------------------
3187// UpdateVScrollbar
3188//
3189// Updates vertical scrollbar if needed.
3190//--------------------------------------------------------------------------
3191
3192static void
3193UpdateVScrollbar( register PlPlotter *plPlotterPtr )
3194{
3195 char string[60];
3196 int result;
3197
3198 if ( plPlotterPtr->yScrollCmd == NULL )
3199 return;
3200
3201 sprintf( string, " %f %f", 1. - plPlotterPtr->yr, 1. - plPlotterPtr->yl );
3202
3203 result = Tcl_VarEval( plPlotterPtr->interp, plPlotterPtr->yScrollCmd, string,
3204 (char *) NULL );
3205
3206 if ( result != TCL_OK )
3207 {
3208 Tcl_BackgroundError( plPlotterPtr->interp );
3209 }
3210}
3211
3212//--------------------------------------------------------------------------
3213// UpdateHScrollbar
3214//
3215// Updates horizontal scrollbar if needed.
3216//--------------------------------------------------------------------------
3217
3218static void
3219UpdateHScrollbar( register PlPlotter *plPlotterPtr )
3220{
3221 char string[60];
3222 int result;
3223
3224 if ( plPlotterPtr->xScrollCmd == NULL )
3225 return;
3226
3227 sprintf( string, " %f %f", plPlotterPtr->xl, plPlotterPtr->xr );
3228
3229 result = Tcl_VarEval( plPlotterPtr->interp, plPlotterPtr->xScrollCmd, string,
3230 (char *) NULL );
3231
3232 if ( result != TCL_OK )
3233 {
3234 Tcl_BackgroundError( plPlotterPtr->interp );
3235 }
3236}
3237
3238//--------------------------------------------------------------------------
3239// gbox
3240//
3241// Returns selection box coordinates. It's best if the TCL script does
3242// bounds checking on the input but I do it here as well just to be safe.
3243//--------------------------------------------------------------------------
3244
3245static void
3246gbox( PLFLT *xl, PLFLT *yl, PLFLT *xr, PLFLT *yr, const char **argv )
3247{
3248 PLFLT x0, y0, x1, y1;
3249
3250 x0 = (PLFLT) atof( argv[0] );
3251 y0 = (PLFLT) atof( argv[1] );
3252 x1 = (PLFLT) atof( argv[2] );
3253 y1 = (PLFLT) atof( argv[3] );
3254
3255 x0 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., x0 ) );
3256 y0 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., y0 ) );
3257 x1 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., x1 ) );
3258 y1 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., y1 ) );
3259
3260// Only need two vertices, pick the lower left and upper right
3261
3262 *xl = MIN( x0, x1 );
3263 *yl = MIN( y0, y1 );
3264 *xr = MAX( x0, x1 );
3265 *yr = MAX( y0, y1 );
3266}
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
#define b1
Definition defines.h:18
#define MIN(a, b)
Definition dsplint.c:29
#define MAX(a, b)
Definition dsplint.c:28
int pdf_close(PDFstrm *pdfs)
Definition pdfutils.c:238
PDFstrm * pdf_bopen(U_CHAR *buffer, size_t bufmax)
Definition pdfutils.c:152
void plP_state(PLINT op)
Definition plcore.c:256
void pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition plcore.c:1737
void plgpls(PLStream **p_pls)
Definition plcore.c:3693
void plsxwin(PLINT window_id)
Definition plcore.c:3978
void plsfile(FILE *file)
Definition plcore.c:3802
void pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition plcore.c:1691
void plgFileDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition plcore.c:3530
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
static PLINT ipls
Definition plcore.h:86
void plcmap1_calc(void)
Bin up cmap 1 space and assign colors to make inverse mapping easy.
Definition plctrl.c:764
char * plFindCommand(PLCHAR_VECTOR fn)
Definition plctrl.c:2146
void pl_cmd(PLINT op, void *ptr)
Definition plctrl.c:2118
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition plctrl.c:2985
#define Tk_Cursor
Definition plframe.c:80
PLINT plTranslateCursor(PLGraphicsIn *plg)
Definition plpage.c:259
#define PLSTATE_CMAP0
Definition plplotP.h:366
#define free_mem(a)
Definition plplotP.h:182
#define PLESC_EXPOSE
Definition plplot.h:274
#define plgdiplt
Definition plplot.h:732
#define plinit
Definition plplot.h:755
float PLFLT
Definition plplot.h:163
#define plrgbhls
Definition plplot.h:789
#define plbop
Definition plplot.h:696
#define plgdidev
Definition plplot.h:730
#define plgdiori
Definition plplot.h:731
#define plspause
Definition plplot.h:834
#define plhlsrgb
Definition plplot.h:752
#define plsdev
Definition plplot.h:806
#define PL_UNUSED(x)
Definition plplot.h:138
#define plsdiplz
Definition plplot.h:811
#define plsdiori
Definition plplot.h:809
#define PLESC_RESIZE
Definition plplot.h:275
#define plsstrm
Definition plplot.h:835
#define plsdiplt
Definition plplot.h:810
#define plcpstrm
Definition plplot.h:707
#define plmkstrm
Definition plplot.h:772
#define pladv
Definition plplot.h:692
int PLINT
Definition plplot.h:181
#define plend1
Definition plplot.h:710
#define plsdidev
Definition plplot.h:807
#define plflush
Definition plplot.h:719
#define plreplot
Definition plplot.h:788
#define PLESC_REDRAW
Definition plplot.h:276
static void UpdateXhairs(PlPlotter *)
Definition plplotter.c:1231
static int ConfigureWidgetCompat(Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *configSpecs, int argc, const char **argv, char *widgRec, int flags)
Definition plplotter.c:2041
static int Orient(Tcl_Interp *, PlPlotter *, int, const char **)
static void PlPlotterInit(ClientData)
Definition plplotter.c:1388
static int Scroll(Tcl_Interp *, PlPlotter *)
static void DrawRband(PlPlotter *, int, int)
Definition plplotter.c:1318
#define DEF_PLFRAME_CURSOR
Definition plplotter.c:217
static int scol1(Tcl_Interp *interp, register PlPlotter *plPlotterPtr, int i, const char *col, const char *pos, const char *rev, int *p_changed)
Definition plplotter.c:1658
#define REDRAW_PENDING
Definition plplotter.c:208
static int Info(Tcl_Interp *, PlPlotter *, int, const char **)
static void Install_cmap(PlPlotter *plPlotterPtr)
Definition plplotter.c:1426
#define UPDATE_H_SCROLLBAR
Definition plplotter.c:210
static void PlPlotterFirstInit(ClientData clientData)
Definition plplotter.c:1347
static int report(Tcl_Interp *, PlPlotter *, int, const char **)
static void PlPlotterExposeEH(ClientData, XEvent *)
static Tk_ConfigSpec configSpecs[]
Definition plplotter.c:224
#define DEF_PLFRAME_HEIGHT
Definition plplotter.c:218
void PlplotterAtEop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition plplotter.c:2546
static void DestroyPlPlotter(ClientData)
Definition plplotter.c:806
#define UPDATE_V_SCROLLBAR
Definition plplotter.c:209
#define REFRESH_PENDING
Definition plplotter.c:206
static void DestroyXhairs(PlPlotter *)
Definition plplotter.c:1191
static void UpdateHScrollbar(register PlPlotter *)
Definition plplotter.c:3219
static int Save(Tcl_Interp *, PlPlotter *, int, const char **)
void PlplotterAtBop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition plplotter.c:2556
static void PlPlotterConfigureEH(ClientData, XEvent *)
static int Draw(Tcl_Interp *, PlPlotter *, int, const char **)
static void PlPlotterEnterEH(ClientData, register XEvent *)
Definition plplotter.c:1071
#define DEF_PLFRAME_BORDER_WIDTH
Definition plplotter.c:216
static int NextPage(Tcl_Interp *, PlPlotter *, int, const char **)
static void DrawXhairs(PlPlotter *, int, int)
Definition plplotter.c:1206
#define DEF_PLFRAME_RELIEF
Definition plplotter.c:219
int plPlotterCmd(ClientData, Tcl_Interp *, int, const char **)
#define DEF_PLFRAME_BG_COLOR
Definition plplotter.c:214
static void gbox(PLFLT *, PLFLT *, PLFLT *, PLFLT *, const char **)
Definition plplotter.c:3246
static void CreateRband(PlPlotter *)
Definition plplotter.c:1251
static void ActiveState(register PlPlotter *plPlotterPtr, int on)
Definition plplotter.c:1985
#define NDEV
Definition plplotter.c:93
static void UpdateRband(PlPlotter *)
Definition plplotter.c:1337
static int ReadData(ClientData, int)
Definition plplotter.c:2574
#define RESIZE_PENDING
Definition plplotter.c:207
static int Openlink(Tcl_Interp *, PlPlotter *, int, const char **)
static int ConfigurePlPlotter(Tcl_Interp *, PlPlotter *, int, const char **, int)
static void CreateXhairs(PlPlotter *)
Definition plplotter.c:1153
static int Redraw(Tcl_Interp *, PlPlotter *, int, const char **)
static int PlPlotterWidgetCmd(ClientData, Tcl_Interp *, int, const char **)
Definition plplotter.c:503
#define DEF_PLFRAME_BG_MONO
Definition plplotter.c:215
static void DestroyRband(PlPlotter *)
Definition plplotter.c:1303
static void UpdateVScrollbar(register PlPlotter *)
Definition plplotter.c:3193
static void PlPlotterLeaveEH(ClientData, register XEvent *)
static void DisplayPlPlotter(ClientData)
Definition plplotter.c:1476
static int scol0(Tcl_Interp *interp, register PlPlotter *plPlotterPtr, int i, const char *col, int *p_changed)
Definition plplotter.c:1612
#define DEF_PLFRAME_WIDTH
Definition plplotter.c:220
static int View(Tcl_Interp *, PlPlotter *, int, const char **)
static int Print(Tcl_Interp *, PlPlotter *, int, const char **)
static int process_data(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition plplotter.c:2508
static int Page(Tcl_Interp *, PlPlotter *, int, const char **)
static int Closelink(Tcl_Interp *, PlPlotter *, int, const char **)
static void PlPlotterMotionEH(ClientData, register XEvent *)
Definition plplotter.c:1037
static void PlPlotterButtonPressEH(ClientData clientData, register XEvent *)
Definition plplotter.c:1127
static int Cmd(Tcl_Interp *, PlPlotter *, int, const char **)
int plr_process(PLRDev *plr)
Definition plr.c:115
void plr_start(PLRDev *plr)
Definition plr.c:95
static int child
Definition plserver.c:45
FILE * pl_create_tempfile(char **fname)
Definition plstdio.c:240
PLDLLIMPEXP_TCLTK int plTclCmd(char *cmdlist, Tcl_Interp *interp, int argc, const char **argv)
Definition tclAPI.c:295
void pltkwin_setBGFG(PLStream *pls)
static int plplot_tkwin_ccmap
Definition pltkwd.h:41
int PLColor_from_TkColor_Changed(PLColor *plcolor, XColor *xcolor)
void plD_open_tkwin(PLStream *pls)
static int argc
Definition qt.cpp:48
static char ** argv
Definition qt.cpp:49
Definition pdf.h:50
size_t bp
Definition pdf.h:56
unsigned int y
Definition plplot.h:461
unsigned int x
Definition plplot.h:461
unsigned int height
Definition plplot.h:462
unsigned int width
Definition plplot.h:462
PLFLT wX
Definition plplot.h:443
PLFLT wY
Definition plplot.h:443
PLFLT dY
Definition plplot.h:442
PLFLT dX
Definition plplot.h:442
int at_eop
Definition plserver.h:22
int at_bop
Definition plserver.h:22
int nbytes
Definition plserver.h:21
PLiodev * iodev
Definition plserver.h:20
PDFstrm * pdfs
Definition plserver.h:19
struct PlPlotter * plPlotterPtr
Definition plstrm.h:742
void * dev
Definition plstrm.h:594
Definition pdf.h:62
int fd
Definition pdf.h:63
int type
Definition pdf.h:67
FILE * file
Definition pdf.h:64
const char * fileHandle
Definition pdf.h:66
const char * typeName
Definition pdf.h:68
PLDisplay pldis
Definition plplotter.c:145
int drawing_rband
Definition plplotter.c:187
char * yScrollCmd
Definition plplotter.c:168
int double_buffer
Definition plplotter.c:189
PLStream * pls
Definition plplotter.c:132
char * plpr_cmd
Definition plplotter.c:137
int prevHeight
Definition plplotter.c:147
PLRDev * plr
Definition plplotter.c:136
int tkwin_initted
Definition plplotter.c:131
int borderWidth
Definition plplotter.c:117
XPoint rband_pt[2]
Definition plplotter.c:188
PLFLT xl
Definition plplotter.c:164
XPoint xhair_x[2]
Definition plplotter.c:181
int continue_draw
Definition plplotter.c:162
int active_plot
Definition plplotter.c:140
char * bopCmd
Definition plplotter.c:174
char * SaveFnam
Definition plplotter.c:151
Tk_3DBorder border
Definition plplotter.c:115
Tk_Cursor xhair_cursor
Definition plplotter.c:163
PLFLT yr
Definition plplotter.c:164
Tcl_Interp * interp
Definition plplotter.c:111
const char ** devName
Definition plplotter.c:155
char * eopCmd
Definition plplotter.c:175
const char ** devDesc
Definition plplotter.c:153
PLFLT xr
Definition plplotter.c:164
Display * display
Definition plplotter.c:108
XPoint pts[5]
Definition plplotter.c:161
Tcl_Command widgetCmd
Definition plplotter.c:114
int prevWidth
Definition plplotter.c:146
PLFLT yl
Definition plplotter.c:164
PLINT ipls
Definition plplotter.c:133
XPoint xhair_y[2]
Definition plplotter.c:182
char * xScrollCmd
Definition plplotter.c:165
Tk_Window tkwin
Definition plplotter.c:104
int drawing_xhairs
Definition plplotter.c:180
PLINT ipls_save
Definition plplotter.c:134
int isActive
Definition plplotter.c:141
Tk_Cursor cursor
Definition plplotter.c:123
unsigned width
Definition pltkwd.h:82
int flags
Definition pltkwd.h:78
int write_to_window
Definition pltkwd.h:91
unsigned height
Definition pltkwd.h:82
TkwDisplay * tkwd
Definition pltkwd.h:70
PLGraphicsIn gin
Definition pltkwd.h:97
Colormap map
Definition pltkwd.h:55
XColor cmap0[16]
Definition pltkwd.h:60
#define dbug_enter(a)
Definition tclMatrix.c:65
PLDLLIMPEXP_TCLTK int pl_PacketReceive(Tcl_Interp *interp, PLiodev *iodev, PDFstrm *pdfs)
static Tcl_Interp * interp
Definition tkMain.c:117