PLplot: plplotter.c Source File

PLplot 5.15.0

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
100 typedef 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
190 } PlPlotter;
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
224 static Tk_ConfigSpec configSpecs[] = {
225 { TK_CONFIG_BOOLEAN, "-activeplot", (char *) NULL, (char *) NULL,
226 "1", Tk_Offset( PlPlotter, active_plot ), TK_CONFIG_DONT_SET_DEFAULT },
227 { TK_CONFIG_BORDER, "-background", "background", "Background",
228 DEF_PLFRAME_BG_COLOR, Tk_Offset( PlPlotter, border ),
229 TK_CONFIG_COLOR_ONLY },
230 { TK_CONFIG_BORDER, "-background", "background", "Background",
231 DEF_PLFRAME_BG_MONO, Tk_Offset( 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, Tk_Offset( PlPlotter, bopCmd ), TK_CONFIG_NULL_OK },
239 { TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
240 DEF_PLFRAME_BORDER_WIDTH, Tk_Offset( PlPlotter, borderWidth ), 0 },
241 { TK_CONFIG_BOOLEAN, "-doublebuffer", (char *) NULL, (char *) NULL,
242 "0", Tk_Offset( PlPlotter, double_buffer ), TK_CONFIG_DONT_SET_DEFAULT },
243 { TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
244 DEF_PLFRAME_CURSOR, Tk_Offset( PlPlotter, cursor ), TK_CONFIG_NULL_OK },
245 { TK_CONFIG_STRING, "-eopcmd", "eopcmd", "PgCommand",
246 (char *) NULL, Tk_Offset( PlPlotter, eopCmd ), TK_CONFIG_NULL_OK },
247 { TK_CONFIG_PIXELS, "-height", "height", "Height",
248 DEF_PLFRAME_HEIGHT, Tk_Offset( PlPlotter, height ), 0 },
249 { TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
250 DEF_PLFRAME_RELIEF, Tk_Offset( PlPlotter, relief ), 0 },
251 { TK_CONFIG_PIXELS, "-width", "width", "Width",
252 DEF_PLFRAME_WIDTH, Tk_Offset( PlPlotter, width ), 0 },
253 { TK_CONFIG_BOOLEAN, "-xhairs", (char *) NULL, (char *) NULL,
254 "0", Tk_Offset( PlPlotter, xhairs ), TK_CONFIG_DONT_SET_DEFAULT },
255 { TK_CONFIG_BOOLEAN, "-rubberband", (char *) NULL, (char *) NULL,
256 "0", Tk_Offset( PlPlotter, rband ), TK_CONFIG_DONT_SET_DEFAULT },
257 { TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
258 (char *) NULL, Tk_Offset( PlPlotter, xScrollCmd ), TK_CONFIG_NULL_OK },
259 { TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
260 (char *) NULL, Tk_Offset( 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
269 int plPlotterCmd( ClientData, Tcl_Interp *, int, const char ** );
270 void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
271 void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
272
273 // These are invoked by the TK dispatcher
274
275 static void DestroyPlPlotter( ClientData );
276 static void DisplayPlPlotter( ClientData );
277 static void PlPlotterInit( ClientData );
278 static void PlPlotterFirstInit( ClientData clientData );
279 static void PlPlotterConfigureEH( ClientData, XEvent * );
280 static void PlPlotterExposeEH( ClientData, XEvent * );
281 static void PlPlotterMotionEH( ClientData, register XEvent * );
282 static void PlPlotterEnterEH( ClientData, register XEvent * );
283 static void PlPlotterLeaveEH( ClientData, register XEvent * );
284 static void PlPlotterButtonPressEH( ClientData clientData, register XEvent * );
285 static int PlPlotterWidgetCmd( ClientData, Tcl_Interp *, int, CONST char ** );
286 static int ReadData( ClientData, int );
287 static void Install_cmap( PlPlotter *plPlotterPtr );
288
289 // These are invoked by PlPlotterWidgetCmd to process widget commands
290
291 static int Closelink( Tcl_Interp *, PlPlotter *, int, CONST char ** );
292 static int Cmd( Tcl_Interp *, PlPlotter *, int, CONST char ** );
293 static int ConfigurePlPlotter( Tcl_Interp *, PlPlotter *, int, CONST char **, int );
294 static int Draw( Tcl_Interp *, PlPlotter *, int, CONST char ** );
295 static int Info( Tcl_Interp *, PlPlotter *, int, CONST char ** );
296 static int Openlink( Tcl_Interp *, PlPlotter *, int, CONST char ** );
297 static int Orient( Tcl_Interp *, PlPlotter *, int, CONST char ** );
298 static int Page( Tcl_Interp *, PlPlotter *, int, CONST char ** );
299 static int NextPage( Tcl_Interp *, PlPlotter *, int, CONST char ** );
300 static int Print( Tcl_Interp *, PlPlotter *, int, CONST char ** );
301 static int Redraw( Tcl_Interp *, PlPlotter *, int, CONST char ** );
302 static int Save( Tcl_Interp *, PlPlotter *, int, CONST char ** );
303 static int View( Tcl_Interp *, PlPlotter *, int, CONST char ** );
304 static int Scroll( Tcl_Interp *, PlPlotter * );
305 static int report( Tcl_Interp *, PlPlotter *, int, CONST char ** );
306
307 // Routines for manipulating graphic crosshairs
308
309 static void ActiveState( register PlPlotter *plPlotterPtr, int on );
310 static void CreateXhairs( PlPlotter * );
311 static void DestroyXhairs( PlPlotter * );
312 static void DrawXhairs( PlPlotter *, int, int );
313 static void UpdateXhairs( PlPlotter * );
314
315 // Routines for manipulating the rubberband line
316
317 static void CreateRband( PlPlotter * );
318 static void DestroyRband( PlPlotter * );
319 static void DrawRband( PlPlotter *, int, int );
320 static void UpdateRband( PlPlotter * );
321
322 // Utility routines
323
324 static void gbox( PLFLT *, PLFLT *, PLFLT *, PLFLT *, CONST char ** );
325 static void UpdateVScrollbar( register PlPlotter * );
326 static 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
346 int
347 plPlotterCmd( 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
502 static int
503 PlPlotterWidgetCmd( 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 Tk_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
783 done:
784 Tk_Release( (ClientData) plPlotterPtr );
785 return result;
786 }
787
788 //
789 //--------------------------------------------------------------------------
790 //
791 // DestroyPlPlotter --
792 //
793 // This procedure is invoked by Tk_EventuallyFree or Tk_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
806 static 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
890 static void
891 PlPlotterConfigureEH( 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 Tk_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
972 static void
973 PlPlotterExposeEH( 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
1036 static void
1037 PlPlotterMotionEH( 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
1070 static void
1071 PlPlotterEnterEH( 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
1107 static void
1108 PlPlotterLeaveEH( 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
1126 static void
1127 PlPlotterButtonPressEH( 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
1152 static void
1153 CreateXhairs( 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
1190 static void
1191 DestroyXhairs( 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
1205 static void
1206 DrawXhairs( 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
1230 static void
1231 UpdateXhairs( 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
1250 static void
1251 CreateRband( 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
1302 static void
1303 DestroyRband( 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
1317 static void
1318 DrawRband( 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
1336 static void
1337 UpdateRband( 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
1347 static 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
1387 static void
1388 PlPlotterInit( 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
1425 static void
1426 Install_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
1475 static void
1476 DisplayPlPlotter( 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
1611 static int
1612 scol0( 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
1657 static int
1658 scol1( 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
1728 static int
1729 Cmd( 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 )
1863 plP_state( PLSTATE_CMAP0 );
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 )
1927 plP_state( PLSTATE_CMAP0 );
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
1985 static 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 // ConfigurePlPlotter --
2033 //
2034 // This procedure is called to process an argv/argc list, plus the Tk
2035 // option database, in order to configure (or reconfigure) a
2036 // plframe widget.
2037 //
2038 // Results:
2039 // The return value is a standard Tcl result. If TCL_ERROR is
2040 // returned, then interp->result contains an error message.
2041 //
2042 // Side effects:
2043 // Configuration information, such as text string, colors, font, etc.
2044 // get set for plPlotterPtr; old resources get freed, if there were
2045 // any.
2046 //
2047 //--------------------------------------------------------------------------
2048 //
2049
2050 static int
2051 ConfigurePlPlotter( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2052 int argc, CONST char **argv, int flags )
2053 {
2054 register Tk_Window tkwin = plPlotterPtr->tkwin;
2055 PLStream *pls = plPlotterPtr->pls;
2056 TkwDev *dev = (TkwDev *) pls->dev;
2057 TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
2058 XGCValues gcValues;
2059 unsigned long mask;
2060 int need_redisplay = 0;
2061
2062 #ifdef DEBUG
2063 if ( pls->debug )
2064 {
2065 int i;
2066 fprintf( stderr, "Arguments to configure are:" );
2067 for ( i = 0; i < argc; i++ )
2068 {
2069 fprintf( stderr, " %s", argv[i] );
2070 }
2071 fprintf( stderr, "\n" );
2072 }
2073 #endif
2074
2075 dbug_enter( "ConfigurePlPlotter" );
2076
2077 if ( Tk_ConfigureWidget( interp, tkwin, configSpecs,
2078 argc, argv, (char *) plPlotterPtr, flags ) != TCL_OK )
2079 {
2080 return TCL_ERROR;
2081 }
2082
2083 //
2084 // Set background color using tkwin driver's pixel value. Done this way so
2085 // that (a) we can use r/w color cells, and (b) the BG pixel values as set
2086 // here and in the tkwin driver are consistent.
2087 //
2088
2089 plsstrm( plPlotterPtr->ipls );
2090 if ( PLColor_from_TkColor_Changed( &pls->cmap0[0],
2091 Tk_3DBorderColor( plPlotterPtr->border ) ) )
2092 {
2093 need_redisplay = 1;
2094 // need to redraw as well as simply refresh the window
2095 plPlotterPtr->flags |= REDRAW_PENDING;
2096 }
2097 pltkwin_setBGFG( pls );
2098
2099 Tk_SetWindowBackground( tkwin, tkwd->cmap0[0].pixel );
2100 Tk_SetWindowBorder( tkwin, tkwd->cmap0[0].pixel );
2101
2102 // Set up GC for rubber-band draws
2103
2104 gcValues.background = tkwd->cmap0[0].pixel;
2105 gcValues.foreground = 0xFF;
2106 gcValues.function = GXxor;
2107 mask = GCForeground | GCBackground | GCFunction;
2108
2109 if ( plPlotterPtr->xorGC != NULL )
2110 Tk_FreeGC( plPlotterPtr->display, plPlotterPtr->xorGC );
2111
2112 plPlotterPtr->xorGC = Tk_GetGC( plPlotterPtr->tkwin, mask, &gcValues );
2113
2114 // Geometry settings
2115
2116 Tk_SetInternalBorder( tkwin, plPlotterPtr->borderWidth );
2117 if ( ( plPlotterPtr->width > 0 ) || ( plPlotterPtr->height > 0 ) )
2118 {
2119 Tk_GeometryRequest( tkwin, plPlotterPtr->width, plPlotterPtr->height );
2120 if ( ( plPlotterPtr->width != plPlotterPtr->prevWidth ) ||
2121 ( plPlotterPtr->height != plPlotterPtr->prevHeight ) )
2122 need_redisplay = 1;
2123 }
2124
2125 // Create or destroy graphic crosshairs as specified
2126
2127 if ( Tk_IsMapped( tkwin ) )
2128 {
2129 if ( plPlotterPtr->xhairs )
2130 {
2131 if ( !plPlotterPtr->drawing_xhairs )
2132 CreateXhairs( plPlotterPtr );
2133 }
2134 else
2135 {
2136 if ( plPlotterPtr->drawing_xhairs )
2137 DestroyXhairs( plPlotterPtr );
2138 }
2139 }
2140
2141 // Create or destroy rubber band as specified
2142
2143 if ( Tk_IsMapped( tkwin ) )
2144 {
2145 if ( plPlotterPtr->rband )
2146 {
2147 if ( !plPlotterPtr->drawing_rband )
2148 CreateRband( plPlotterPtr );
2149 }
2150 else
2151 {
2152 if ( plPlotterPtr->drawing_rband )
2153 DestroyRband( plPlotterPtr );
2154 }
2155 }
2156 // Sets or clears events for the plot
2157 ActiveState( plPlotterPtr, plPlotterPtr->active_plot );
2158
2159 if ( !pls->nopixmap )
2160 {
2161 // can only adjust if this flag not set
2162 if ( plPlotterPtr->double_buffer != pls->db )
2163 {
2164 pls->db = plPlotterPtr->double_buffer;
2165 // turn on/off dbl-buffering in the driver
2166 dev->write_to_window = !pls->db;
2167 }
2168 }
2169 else
2170 {
2171 plPlotterPtr->double_buffer = 0;
2172 }
2173
2174 // Arrange for window to be refreshed if necessary
2175 if ( need_redisplay && Tk_IsMapped( tkwin )
2176 && !( plPlotterPtr->flags & REFRESH_PENDING ) )
2177 {
2178 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
2179 plPlotterPtr->flags |= REFRESH_PENDING;
2180 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
2181 }
2182
2183 return TCL_OK;
2184 }
2185
2186 //--------------------------------------------------------------------------
2187 // Draw
2188 //
2189 // Processes "draw" widget command.
2190 // Handles rubber-band drawing.
2191 //--------------------------------------------------------------------------
2192
2193 static int
2194 Draw( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2195 int argc, CONST char **argv )
2196 {
2197 register Tk_Window tkwin = plPlotterPtr->tkwin;
2198 int result = TCL_OK;
2199 char c = argv[0][0];
2200 int length = (int) strlen( argv[0] );
2201
2202 // Make sure widget has been initialized before going any further
2203
2204 if ( !plPlotterPtr->tkwin_initted )
2205 {
2206 Tcl_VarEval( plPlotterPtr->interp, "update", (char *) NULL );
2207 }
2208
2209 // init -- sets up for rubber-band drawing
2210
2211 if ( ( c == 'i' ) && ( strncmp( argv[0], "init", (size_t) length ) == 0 ) )
2212 {
2213 Tk_DefineCursor( tkwin, plPlotterPtr->xhair_cursor );
2214 }
2215
2216 // end -- ends rubber-band drawing
2217
2218 else if ( ( c == 'e' ) && ( strncmp( argv[0], "end", (size_t) length ) == 0 ) )
2219 {
2220 Tk_DefineCursor( tkwin, plPlotterPtr->cursor );
2221 if ( plPlotterPtr->continue_draw )
2222 {
2223 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2224 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2225 CoordModeOrigin );
2226 XSync( Tk_Display( tkwin ), 0 );
2227 }
2228
2229 plPlotterPtr->continue_draw = 0;
2230 }
2231
2232 // rect -- draw a rectangle, used to select rectangular areas
2233 // first draw erases old outline
2234
2235 else if ( ( c == 'r' ) && ( strncmp( argv[0], "rect", (size_t) length ) == 0 ) )
2236 {
2237 if ( argc < 5 )
2238 {
2239 Tcl_AppendResult( interp, "wrong # args: should be \"",
2240 " draw rect x0 y0 x1 y1\"", (char *) NULL );
2241 result = TCL_ERROR;
2242 }
2243 else
2244 {
2245 int x0, y0, x1, y1;
2246 int xmin = 0, xmax = Tk_Width( tkwin ) - 1;
2247 int ymin = 0, ymax = Tk_Height( tkwin ) - 1;
2248
2249 x0 = atoi( argv[1] );
2250 y0 = atoi( argv[2] );
2251 x1 = atoi( argv[3] );
2252 y1 = atoi( argv[4] );
2253
2254 x0 = MAX( xmin, MIN( xmax, x0 ) );
2255 y0 = MAX( ymin, MIN( ymax, y0 ) );
2256 x1 = MAX( xmin, MIN( xmax, x1 ) );
2257 y1 = MAX( ymin, MIN( ymax, y1 ) );
2258
2259 if ( plPlotterPtr->continue_draw )
2260 {
2261 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2262 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2263 CoordModeOrigin );
2264 XSync( Tk_Display( tkwin ), 0 );
2265 }
2266
2267 plPlotterPtr->pts[0].x = (short) x0; plPlotterPtr->pts[0].y = (short) y0;
2268 plPlotterPtr->pts[1].x = (short) x1; plPlotterPtr->pts[1].y = (short) y0;
2269 plPlotterPtr->pts[2].x = (short) x1; plPlotterPtr->pts[2].y = (short) y1;
2270 plPlotterPtr->pts[3].x = (short) x0; plPlotterPtr->pts[3].y = (short) y1;
2271 plPlotterPtr->pts[4].x = (short) x0; plPlotterPtr->pts[4].y = (short) y0;
2272
2273 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
2274 plPlotterPtr->xorGC, plPlotterPtr->pts, 5,
2275 CoordModeOrigin );
2276 XSync( Tk_Display( tkwin ), 0 );
2277
2278 plPlotterPtr->continue_draw = 1;
2279 }
2280 }
2281
2282 return result;
2283 }
2284
2285 //--------------------------------------------------------------------------
2286 // Info
2287 //
2288 // Processes "info" widget command.
2289 // Returns requested info.
2290 //--------------------------------------------------------------------------
2291
2292 static int
2293 Info( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2294 int argc, CONST char **argv )
2295 {
2296 int length;
2297 char c;
2298 int result = TCL_OK;
2299
2300 // no option -- return list of available info commands
2301
2302 if ( argc == 0 )
2303 {
2304 Tcl_SetResult( interp, "devkeys devnames", TCL_STATIC );
2305 return TCL_OK;
2306 }
2307
2308 c = argv[0][0];
2309 length = (int) strlen( argv[0] );
2310
2311 // devkeys -- return list of supported device keywords
2312
2313 if ( ( c == 'd' ) && ( strncmp( argv[0], "devkeys", (size_t) length ) == 0 ) )
2314 {
2315 int i = 0;
2316 while ( plPlotterPtr->devName[i] != NULL )
2317 Tcl_AppendElement( interp, plPlotterPtr->devName[i++] );
2318
2319 result = TCL_OK;
2320 }
2321
2322 // devkeys -- return list of supported device types
2323
2324 else if ( ( c == 'd' ) && ( strncmp( argv[0], "devnames", (size_t) length ) == 0 ) )
2325 {
2326 int i = 0;
2327 while ( plPlotterPtr->devDesc[i] != NULL )
2328 Tcl_AppendElement( interp, plPlotterPtr->devDesc[i++] );
2329
2330 result = TCL_OK;
2331 }
2332
2333 // unrecognized
2334
2335 else
2336 {
2337 Tcl_AppendResult( interp, "bad option to \"info\": must be ",
2338 "devkeys, devnames", (char *) NULL );
2339
2340 result = TCL_ERROR;
2341 }
2342
2343 return result;
2344 }
2345
2346 //--------------------------------------------------------------------------
2347 // Openlink
2348 //
2349 // Processes "openlink" widget command.
2350 // Opens channel (FIFO or socket) for binary data transfer between client
2351 // and server.
2352 //--------------------------------------------------------------------------
2353
2354 static int
2355 Openlink( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2356 int argc, CONST char **argv )
2357 {
2358 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2359 register PLRDev *plr = plPlotterPtr->plr;
2360 register PLiodev *iodev = plr->iodev;
2361
2362 char c = argv[0][0];
2363 int length = (int) strlen( argv[0] );
2364
2365 dbug_enter( "Openlink" );
2366
2367 // Open fifo
2368
2369 if ( ( c == 'f' ) && ( strncmp( argv[0], "fifo", (size_t) length ) == 0 ) )
2370 {
2371 if ( argc < 1 )
2372 {
2373 Tcl_AppendResult( interp, "bad command -- must be: ",
2374 "openlink fifo <pathname>",
2375 (char *) NULL );
2376 return TCL_ERROR;
2377 }
2378 if ( ( iodev->fd = open( argv[1], O_RDONLY ) ) == -1 )
2379 {
2380 Tcl_AppendResult( interp, "cannot open fifo ", argv[1],
2381 " for read", (char *) NULL );
2382 return TCL_ERROR;
2383 }
2384 iodev->type = 0;
2385 iodev->typeName = "fifo";
2386 iodev->file = fdopen( iodev->fd, "rb" );
2387 }
2388
2389 // Open socket
2390
2391 else if ( ( c == 's' ) && ( strncmp( argv[0], "socket", (size_t) length ) == 0 ) )
2392 {
2393 if ( argc < 1 )
2394 {
2395 Tcl_AppendResult( interp, "bad command -- must be: ",
2396 "openlink socket <sock-id>",
2397 (char *) NULL );
2398 return TCL_ERROR;
2399 }
2400 iodev->type = 1;
2401 iodev->typeName = "socket";
2402 iodev->fileHandle = (char *) argv[1];
2403
2404 if ( Tcl_GetOpenFile( interp, iodev->fileHandle,
2405 0, 1, ( ClientData ) & iodev->file ) != TCL_OK )
2406 {
2407 return TCL_ERROR;
2408 }
2409 iodev->fd = fileno( iodev->file );
2410 }
2411
2412 // unrecognized
2413
2414 else
2415 {
2416 Tcl_AppendResult( interp, "bad option to \"openlink\": must be ",
2417 "fifo or socket", (char *) NULL );
2418
2419 return TCL_ERROR;
2420 }
2421
2422 plr->pdfs = pdf_bopen( NULL, 4200 );
2423 Tcl_CreateFileHandler( iodev->fd,
2424 TK_READABLE, (Tk_FileProc *) ReadData,
2425 (ClientData) plPlotterPtr );
2426
2427 #endif
2428
2429 return TCL_OK;
2430 }
2431
2432 //--------------------------------------------------------------------------
2433 // Closelink
2434 //
2435 // Processes "closelink" widget command.
2436 // CLoses channel previously opened with the "openlink" widget command.
2437 //--------------------------------------------------------------------------
2438
2439 static int
2440 Closelink( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2441 int PL_UNUSED( argc ), CONST char ** PL_UNUSED( argv ) )
2442 {
2443 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2444 register PLRDev *plr = plPlotterPtr->plr;
2445 register PLiodev *iodev = plr->iodev;
2446
2447 dbug_enter( "Closelink" );
2448
2449 if ( iodev->fd == 0 )
2450 {
2451 Tcl_AppendResult( interp, "no link currently open", (char *) NULL );
2452 return TCL_ERROR;
2453 }
2454
2455 Tcl_DeleteFileHandler( iodev->fd );
2456 pdf_close( plr->pdfs );
2457 iodev->fd = 0;
2458 #endif
2459 return TCL_OK;
2460 }
2461
2462 //--------------------------------------------------------------------------
2463 // process_data
2464 //
2465 // Utility function for processing data and other housekeeping.
2466 //--------------------------------------------------------------------------
2467
2468 static int
2469 process_data( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2470 {
2471 register PLRDev *plr = plPlotterPtr->plr;
2472 register PLiodev *iodev = plr->iodev;
2473 int result = TCL_OK;
2474
2475 // Process data
2476
2477 if ( plr_process( plr ) == -1 )
2478 {
2479 Tcl_AppendResult( interp, "unable to read from ", iodev->typeName,
2480 (char *) NULL );
2481 result = TCL_ERROR;
2482 }
2483
2484 // Signal bop if necessary
2485
2486 if ( plr->at_bop && plPlotterPtr->bopCmd != NULL )
2487 {
2488 plr->at_bop = 0;
2489 if ( Tcl_Eval( interp, plPlotterPtr->bopCmd ) != TCL_OK )
2490 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2491 plPlotterPtr->bopCmd, Tcl_GetStringResult( interp ) );
2492 }
2493
2494 // Signal eop if necessary
2495
2496 if ( plr->at_eop && plPlotterPtr->eopCmd != NULL )
2497 {
2498 plr->at_eop = 0;
2499 if ( Tcl_Eval( interp, plPlotterPtr->eopCmd ) != TCL_OK )
2500 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2501 plPlotterPtr->eopCmd, Tcl_GetStringResult( interp ) );
2502 }
2503
2504 return result;
2505 }
2506
2507 void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2508 {
2509 if ( plPlotterPtr->eopCmd != NULL )
2510 {
2511 if ( Tcl_Eval( interp, plPlotterPtr->eopCmd ) != TCL_OK )
2512 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2513 plPlotterPtr->eopCmd, Tcl_GetStringResult( interp ) );
2514 }
2515 }
2516
2517 void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
2518 {
2519 if ( plPlotterPtr->bopCmd != NULL )
2520 {
2521 if ( Tcl_Eval( interp, plPlotterPtr->bopCmd ) != TCL_OK )
2522 fprintf( stderr, "Command \"%s\" failed:\n\t %s\n",
2523 plPlotterPtr->bopCmd, Tcl_GetStringResult( interp ) );
2524 }
2525 }
2526
2527 //--------------------------------------------------------------------------
2528 // ReadData
2529 //
2530 // Reads & processes data.
2531 // Intended to be installed as a filehandler command.
2532 //--------------------------------------------------------------------------
2533
2534 static int
2535 ReadData( ClientData clientData, int mask )
2536 {
2537 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
2538 register Tcl_Interp *interp = plPlotterPtr->interp;
2539
2540 register PLRDev *plr = plPlotterPtr->plr;
2541 register PLiodev *iodev = plr->iodev;
2542 register PDFstrm *pdfs = plr->pdfs;
2543 int result = TCL_OK;
2544
2545 if ( mask & TK_READABLE )
2546 {
2547 // Read from FIFO or socket
2548
2549 plsstrm( plPlotterPtr->ipls );
2550 #ifndef MAC_TCL
2551 if ( pl_PacketReceive( interp, iodev, pdfs ) )
2552 {
2553 #else
2554 if ( 1 )
2555 {
2556 #endif
2557 Tcl_AppendResult( interp, "Packet receive failed:\n\t %s\n",
2558 Tcl_GetStringResult( interp ), (char *) NULL );
2559 return TCL_ERROR;
2560 }
2561
2562 // If the packet isn't complete it will be put back and we just return.
2563 // Otherwise, the buffer pointer is saved and then cleared so that reads
2564 // from the buffer start at the beginning.
2565 //
2566 if ( pdfs->bp == 0 )
2567 return TCL_OK;
2568
2569 plr->nbytes = (int) pdfs->bp;
2570 pdfs->bp = 0;
2571 result = process_data( interp, plPlotterPtr );
2572 }
2573
2574 return result;
2575 }
2576
2577 //--------------------------------------------------------------------------
2578 // Orient
2579 //
2580 // Processes "orient" widget command.
2581 // Handles orientation of plot.
2582 //--------------------------------------------------------------------------
2583
2584 static int
2585 Orient( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2586 int argc, CONST char **argv )
2587 {
2588 int result = TCL_OK;
2589
2590 // orient -- return orientation of current plot window
2591
2592 plsstrm( plPlotterPtr->ipls );
2593
2594 if ( argc == 0 )
2595 {
2596 PLFLT rot;
2597 char result_str[128];
2598 plgdiori( &rot );
2599 sprintf( result_str, "%f", rot );
2600 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2601 }
2602
2603 // orient <rot> -- Set orientation to <rot>
2604
2605 else
2606 {
2607 plsdiori( (PLFLT) atof( argv[0] ) );
2608 result = Redraw( interp, plPlotterPtr, argc - 1, argv + 1 );
2609 }
2610
2611 return result;
2612 }
2613
2614 //--------------------------------------------------------------------------
2615 // Print
2616 //
2617 // Processes "print" widget command.
2618 // Handles printing of plot, duh.
2619 //
2620 // Creates a temporary file, dumps the current plot to it in metafile
2621 // form, and then execs the "plpr" script to actually print it. Since we
2622 // output it in metafile form here, plpr must invoke plrender to drive the
2623 // output to the appropriate file type. The script is responsible for the
2624 // deletion of the plot metafile.
2625 //--------------------------------------------------------------------------
2626
2627 static int
2628 Print( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2629 int PL_UNUSED( argc ), CONST char ** PL_UNUSED( argv ) )
2630 {
2631 PLINT ipls;
2632 int result = TCL_OK;
2633 char *sfnam;
2634 FILE *sfile;
2635 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2636 pid_t pid;
2637 #endif
2638
2639 // Make sure widget has been initialized before going any further
2640
2641 if ( !plPlotterPtr->tkwin_initted )
2642 {
2643 Tcl_AppendResult( interp, "Error -- widget not plotted to yet",
2644 (char *) NULL );
2645 return TCL_ERROR;
2646 }
2647
2648 // Create stream for save
2649
2650 plmkstrm( &ipls );
2651 if ( ipls < 0 )
2652 {
2653 Tcl_AppendResult( interp, "Error -- cannot create stream",
2654 (char *) NULL );
2655 return TCL_ERROR;
2656 }
2657
2658 // Open file for writes
2659
2660 // Create and open temporary file
2661 // NB use fdopen to get a file stream from the existing file handle
2662 if ( ( sfile = pl_create_tempfile( &sfnam ) ) == NULL )
2663 {
2664 Tcl_AppendResult( interp,
2665 "Error -- cannot open plot file for writing",
2666 (char *) NULL );
2667 plend1();
2668 if ( sfnam != NULL )
2669 free( sfnam );
2670 return TCL_ERROR;
2671 }
2672
2673 // Initialize stream
2674
2675 plsdev( "plmeta" );
2676 plsfile( sfile );
2677 plcpstrm( plPlotterPtr->ipls, 0 );
2678 pladv( 0 );
2679
2680 // Remake current plot, close file, and switch back to original stream
2681
2682 plreplot();
2683 plend1();
2684 plsstrm( plPlotterPtr->ipls );
2685
2686 // So far so good. Time to exec the print script.
2687
2688 if ( plPlotterPtr->plpr_cmd == NULL )
2689 plPlotterPtr->plpr_cmd = plFindCommand( "plpr" );
2690
2691 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
2692 if ( ( plPlotterPtr->plpr_cmd == NULL ) || ( pid = fork() ) < 0 )
2693 {
2694 Tcl_AppendResult( interp,
2695 "Error -- cannot fork print process",
2696 (char *) NULL );
2697 result = TCL_ERROR;
2698 }
2699 else if ( pid == 0 )
2700 {
2701 if ( execl( plPlotterPtr->plpr_cmd, plPlotterPtr->plpr_cmd, sfnam,
2702 (char *) 0 ) )
2703 {
2704 fprintf( stderr, "Unable to exec print command.\n" );
2705 free( sfnam );
2706 _exit( 1 );
2707 }
2708 }
2709 #endif
2710 free( sfnam );
2711 return result;
2712 }
2713
2714 //--------------------------------------------------------------------------
2715 // NextPage
2716 //
2717 // Tells the tkwin driver to move along to the next page.
2718 //--------------------------------------------------------------------------
2719
2720 static int
2721 NextPage( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2722 int argc, CONST char ** PL_UNUSED( argv ) )
2723 {
2724 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
2725 if ( argc == 0 )
2726 {
2727 dev->flags |= 2;
2728 }
2729 else
2730 {
2731 Tcl_AppendResult( interp, "wrong # args: should be \"",
2732 " nextpage\"", (char *) NULL );
2733 return TCL_ERROR;
2734 }
2735 return TCL_OK;
2736 }
2737
2738 //--------------------------------------------------------------------------
2739 // Page
2740 //
2741 // Processes "page" widget command.
2742 // Handles parameters such as margin, aspect ratio, and justification
2743 // of final plot.
2744 //--------------------------------------------------------------------------
2745
2746 static int
2747 Page( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2748 int argc, CONST char **argv )
2749 {
2750 // page -- return current device window parameters
2751
2752 plsstrm( plPlotterPtr->ipls );
2753
2754 if ( argc == 0 )
2755 {
2756 PLFLT mar, aspect, jx, jy;
2757 char result_str[128];
2758
2759 plgdidev( &mar, &aspect, &jx, &jy );
2760 sprintf( result_str, "%g %g %g %g", mar, aspect, jx, jy );
2761 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2762 return TCL_OK;
2763 }
2764
2765 // page <mar> <aspect> <jx> <jy> -- set up page
2766
2767 if ( argc < 4 )
2768 {
2769 Tcl_AppendResult( interp, "wrong # args: should be \"",
2770 " page mar aspect jx jy\"", (char *) NULL );
2771 return TCL_ERROR;
2772 }
2773
2774 plsdidev( (PLFLT) atof( argv[0] ), (PLFLT) atof( argv[1] ),
2775 (PLFLT) atof( argv[2] ), (PLFLT) atof( argv[3] ) );
2776 return ( Redraw( interp, plPlotterPtr, argc - 1, argv + 1 ) );
2777 }
2778
2779 //--------------------------------------------------------------------------
2780 // Redraw
2781 //
2782 // Processes "redraw" widget command.
2783 // Turns loose a DoWhenIdle command to redraw plot by replaying contents
2784 // of plot buffer.
2785 //--------------------------------------------------------------------------
2786
2787 static int
2788 Redraw( Tcl_Interp * PL_UNUSED( interp ), register PlPlotter *plPlotterPtr,
2789 int PL_UNUSED( argc ), CONST char ** PL_UNUSED( argv ) )
2790 {
2791 dbug_enter( "Redraw" );
2792
2793 plPlotterPtr->flags |= REDRAW_PENDING;
2794 if ( ( plPlotterPtr->tkwin != NULL ) &&
2795 !( plPlotterPtr->flags & REFRESH_PENDING ) )
2796 {
2797 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
2798 plPlotterPtr->flags |= REFRESH_PENDING;
2799 }
2800
2801 return TCL_OK;
2802 }
2803
2804 //--------------------------------------------------------------------------
2805 // Save
2806 //
2807 // Processes "save" widget command.
2808 // Saves plot to a file.
2809 //--------------------------------------------------------------------------
2810
2811 static int
2812 Save( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2813 int argc, CONST char **argv )
2814 {
2815 int length;
2816 char c;
2817 FILE *sfile;
2818
2819 // Make sure widget has been initialized before going any further
2820
2821 if ( !plPlotterPtr->tkwin_initted )
2822 {
2823 Tcl_AppendResult( interp, "Error -- widget not plotted to yet",
2824 (char *) NULL );
2825 return TCL_ERROR;
2826 }
2827
2828 // save -- save to already open file
2829
2830 if ( argc == 0 )
2831 {
2832 if ( !plPlotterPtr->ipls_save )
2833 {
2834 Tcl_AppendResult( interp, "Error -- no current save file",
2835 (char *) NULL );
2836 return TCL_ERROR;
2837 }
2838 plsstrm( plPlotterPtr->ipls_save );
2839 plcpstrm( plPlotterPtr->ipls, 0 );
2840 pladv( 0 );
2841 plreplot();
2842 plflush();
2843 plsstrm( plPlotterPtr->ipls );
2844 return TCL_OK;
2845 }
2846
2847 c = argv[0][0];
2848 length = (int) strlen( argv[0] );
2849
2850 // save to specified device & file
2851
2852 if ( ( c == 'a' ) && ( strncmp( argv[0], "as", (size_t) length ) == 0 ) )
2853 {
2854 if ( argc < 3 )
2855 {
2856 Tcl_AppendResult( interp, "wrong # args: should be \"",
2857 " save as device file\"", (char *) NULL );
2858 return TCL_ERROR;
2859 }
2860
2861 // If save previously in effect, delete old stream
2862
2863 if ( plPlotterPtr->ipls_save )
2864 {
2865 plsstrm( plPlotterPtr->ipls_save );
2866 plend1();
2867 }
2868
2869 // Create stream for saves to selected device & file
2870
2871 plmkstrm( &plPlotterPtr->ipls_save );
2872 if ( plPlotterPtr->ipls_save < 0 )
2873 {
2874 Tcl_AppendResult( interp, "Error -- cannot create stream",
2875 (char *) NULL );
2876 plPlotterPtr->ipls_save = 0;
2877 return TCL_ERROR;
2878 }
2879
2880 // Open file for writes
2881
2882 if ( ( sfile = fopen( argv[2], "wb+" ) ) == NULL )
2883 {
2884 Tcl_AppendResult( interp, "Error -- cannot open file ", argv[2],
2885 " for writing", (char *) NULL );
2886 plPlotterPtr->ipls_save = 0;
2887 plend1();
2888 return TCL_ERROR;
2889 }
2890
2891 // Initialize stream
2892
2893 plsdev( argv[1] );
2894 plsfile( sfile );
2895 plcpstrm( plPlotterPtr->ipls, 0 );
2896 pladv( 0 );
2897
2898 // Remake current plot and then switch back to original stream
2899
2900 plreplot();
2901 plflush();
2902 plsstrm( plPlotterPtr->ipls );
2903 }
2904
2905 // close save file
2906
2907 else if ( ( c == 'c' ) && ( strncmp( argv[0], "close", (size_t) length ) == 0 ) )
2908 {
2909 if ( !plPlotterPtr->ipls_save )
2910 {
2911 Tcl_AppendResult( interp, "Error -- no current save file",
2912 (char *) NULL );
2913 return TCL_ERROR;
2914 }
2915 else
2916 {
2917 plsstrm( plPlotterPtr->ipls_save );
2918 plend1();
2919 plPlotterPtr->ipls_save = 0;
2920 }
2921 }
2922
2923 // unrecognized
2924
2925 else
2926 {
2927 Tcl_AppendResult( interp, "bad option to \"save\": must be ",
2928 "as or close", (char *) NULL );
2929
2930 return TCL_ERROR;
2931 }
2932
2933 return TCL_OK;
2934 }
2935
2936 //--------------------------------------------------------------------------
2937 // View
2938 //
2939 // Processes "view" widget command.
2940 // Handles translation & scaling of view into plot.
2941 //--------------------------------------------------------------------------
2942
2943 static int
2944 View( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
2945 int argc, CONST char **argv )
2946 {
2947 int length;
2948 int dontRedraw = 0;
2949 char c;
2950 PLFLT xl, xr, yl, yr;
2951
2952 // view -- return current relative plot window coordinates
2953
2954 plsstrm( plPlotterPtr->ipls );
2955
2956 if ( argc == 0 )
2957 {
2958 char result_str[128];
2959 plgdiplt( &xl, &yl, &xr, &yr );
2960 sprintf( result_str, "%g %g %g %g", xl, yl, xr, yr );
2961 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2962 return TCL_OK;
2963 }
2964
2965 c = argv[0][0];
2966 length = (int) strlen( argv[0] );
2967
2968 // view bounds -- return relative device coordinates of bounds on current
2969 // plot window
2970
2971 if ( ( c == 'b' ) && ( strncmp( argv[0], "bounds", (size_t) length ) == 0 ) )
2972 {
2973 char result_str[128];
2974 xl = 0.; yl = 0.;
2975 xr = 1.; yr = 1.;
2976 pldip2dc( &xl, &yl, &xr, &yr );
2977 sprintf( result_str, "%g %g %g %g", xl, yl, xr, yr );
2978 Tcl_SetResult( interp, result_str, TCL_VOLATILE );
2979 return TCL_OK;
2980 }
2981
2982 // view reset -- Resets plot
2983
2984 if ( ( c == 'r' ) && ( strncmp( argv[0], "reset", (size_t) length ) == 0 ) )
2985 {
2986 xl = 0.; yl = 0.;
2987 xr = 1.; yr = 1.;
2988 plsdiplt( xl, yl, xr, yr );
2989 if ( argc > 1 && ( strcmp( argv[1], "wait" ) == 0 ) )
2990 {
2991 // We're going to update in a while, so don't do it now
2992 dontRedraw = 1;
2993 }
2994 }
2995
2996 // view select -- set window into plot space
2997 // Specifies in terms of plot window coordinates, not device coordinates
2998
2999 else if ( ( c == 's' ) && ( strncmp( argv[0], "select", (size_t) length ) == 0 ) )
3000 {
3001 if ( argc < 5 )
3002 {
3003 Tcl_AppendResult( interp, "wrong # args: should be \"",
3004 " view select xmin ymin xmax ymax\"",
3005 (char *) NULL );
3006 return TCL_ERROR;
3007 }
3008 else
3009 {
3010 gbox( &xl, &yl, &xr, &yr, argv + 1 );
3011 plsdiplt( xl, yl, xr, yr );
3012 }
3013 }
3014
3015 // view zoom -- set window into plot space incrementally (zoom)
3016 // Here we need to take the page (device) offsets into account
3017
3018 else if ( ( c == 'z' ) && ( strncmp( argv[0], "zoom", (size_t) length ) == 0 ) )
3019 {
3020 if ( argc < 5 )
3021 {
3022 Tcl_AppendResult( interp, "wrong # args: should be \"",
3023 " view zoom xmin ymin xmax ymax\"",
3024 (char *) NULL );
3025 return TCL_ERROR;
3026 }
3027 else
3028 {
3029 gbox( &xl, &yl, &xr, &yr, argv + 1 );
3030 pldid2pc( &xl, &yl, &xr, &yr );
3031 plsdiplz( xl, yl, xr, yr );
3032 if ( argc > 5 && ( strcmp( argv[5], "wait" ) == 0 ) )
3033 {
3034 // We're going to update in a while, so don't do it now
3035 dontRedraw = 1;
3036 }
3037 }
3038 }
3039
3040 // unrecognized
3041
3042 else
3043 {
3044 Tcl_AppendResult( interp, "bad option \"", argv[1],
3045 "\": options to \"view\" are: bounds, reset, select, or zoom",
3046 (char *) NULL );
3047
3048 return TCL_ERROR;
3049 }
3050
3051 // Update plot window bounds and arrange for plot to be updated
3052
3053 plgdiplt( &xl, &yl, &xr, &yr );
3054 plPlotterPtr->xl = xl;
3055 plPlotterPtr->yl = yl;
3056 plPlotterPtr->xr = xr;
3057 plPlotterPtr->yr = yr;
3058 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
3059
3060 if ( dontRedraw )
3061 {
3062 return TCL_OK;
3063 }
3064 else
3065 {
3066 return Redraw( interp, plPlotterPtr, argc, argv );
3067 }
3068 }
3069
3070 //--------------------------------------------------------------------------
3071 // Scroll
3072 //
3073 // Processes "xview or yview" widget command.
3074 // Handles horizontal/vert scroll-bar invoked translation of view into plot.
3075 //--------------------------------------------------------------------------
3076
3077 static int
3078 Scroll( Tcl_Interp *interp, register PlPlotter *plPlotterPtr )
3079 {
3080 plsstrm( plPlotterPtr->ipls );
3081 plsdiplt( plPlotterPtr->xl, plPlotterPtr->yl, plPlotterPtr->xr, plPlotterPtr->yr );
3082
3083 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
3084 return ( Redraw( interp, plPlotterPtr, 0, NULL ) );
3085 }
3086
3087
3088 //--------------------------------------------------------------------------
3089 // report
3090 //
3091 // 4/17/95 GMF
3092 // Processes "report" widget command.
3093 //--------------------------------------------------------------------------
3094
3095 static int
3096 report( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
3097 int argc, CONST char **argv )
3098 {
3099 PLFLT x, y;
3100 char res[40];
3101 // fprintf( stdout, "Made it into report, argc=%d\n", argc );
3102
3103 if ( argc == 0 )
3104 {
3105 Tcl_SetResult( interp, "report what?", TCL_STATIC );
3106 return TCL_ERROR;
3107 }
3108
3109 if ( !strcmp( argv[0], "wc" ) )
3110 {
3111 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
3112 PLGraphicsIn *gin = &( dev->gin );
3113
3114 if ( argc != 3 )
3115 {
3116 Tcl_SetResult( interp, "Wrong # of args: report wc x y", TCL_STATIC );
3117 return TCL_ERROR;
3118 }
3119
3120 x = (PLFLT) atof( argv[1] );
3121 y = (PLFLT) atof( argv[2] );
3122
3123 gin->dX = (PLFLT) x / ( dev->width - 1 );
3124 gin->dY = (PLFLT) 1.0 - (PLFLT) y / ( dev->height - 1 );
3125
3126 // Try to locate cursor
3127
3128 if ( plTranslateCursor( gin ) )
3129 {
3130 snprintf( res, 40, "%f %f", gin->wX, gin->wY );
3131 Tcl_SetResult( interp, res, TCL_VOLATILE );
3132 return TCL_OK;
3133 }
3134
3135 Tcl_SetResult( interp, "Cannot locate", TCL_STATIC );
3136 return TCL_OK;
3137 }
3138
3139 Tcl_SetResult( interp, "nonsensical request.", TCL_STATIC );
3140 return TCL_ERROR;
3141 }
3142
3143 //--------------------------------------------------------------------------
3144 // Utility routines
3145 //--------------------------------------------------------------------------
3146
3147 //--------------------------------------------------------------------------
3148 // UpdateVScrollbar
3149 //
3150 // Updates vertical scrollbar if needed.
3151 //--------------------------------------------------------------------------
3152
3153 static void
3154 UpdateVScrollbar( register PlPlotter *plPlotterPtr )
3155 {
3156 char string[60];
3157 int result;
3158
3159 if ( plPlotterPtr->yScrollCmd == NULL )
3160 return;
3161
3162 sprintf( string, " %f %f", 1. - plPlotterPtr->yr, 1. - plPlotterPtr->yl );
3163
3164 result = Tcl_VarEval( plPlotterPtr->interp, plPlotterPtr->yScrollCmd, string,
3165 (char *) NULL );
3166
3167 if ( result != TCL_OK )
3168 {
3169 Tcl_BackgroundError( plPlotterPtr->interp );
3170 }
3171 }
3172
3173 //--------------------------------------------------------------------------
3174 // UpdateHScrollbar
3175 //
3176 // Updates horizontal scrollbar if needed.
3177 //--------------------------------------------------------------------------
3178
3179 static void
3180 UpdateHScrollbar( register PlPlotter *plPlotterPtr )
3181 {
3182 char string[60];
3183 int result;
3184
3185 if ( plPlotterPtr->xScrollCmd == NULL )
3186 return;
3187
3188 sprintf( string, " %f %f", plPlotterPtr->xl, plPlotterPtr->xr );
3189
3190 result = Tcl_VarEval( plPlotterPtr->interp, plPlotterPtr->xScrollCmd, string,
3191 (char *) NULL );
3192
3193 if ( result != TCL_OK )
3194 {
3195 Tcl_BackgroundError( plPlotterPtr->interp );
3196 }
3197 }
3198
3199 //--------------------------------------------------------------------------
3200 // gbox
3201 //
3202 // Returns selection box coordinates. It's best if the TCL script does
3203 // bounds checking on the input but I do it here as well just to be safe.
3204 //--------------------------------------------------------------------------
3205
3206 static void
3207 gbox( PLFLT *xl, PLFLT *yl, PLFLT *xr, PLFLT *yr, CONST char **argv )
3208 {
3209 PLFLT x0, y0, x1, y1;
3210
3211 x0 = (PLFLT) atof( argv[0] );
3212 y0 = (PLFLT) atof( argv[1] );
3213 x1 = (PLFLT) atof( argv[2] );
3214 y1 = (PLFLT) atof( argv[3] );
3215
3216 x0 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., x0 ) );
3217 y0 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., y0 ) );
3218 x1 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., x1 ) );
3219 y1 = MAX( (PLFLT) 0., MIN( (PLFLT) 1., y1 ) );
3220
3221 // Only need two vertices, pick the lower left and upper right
3222
3223 *xl = MIN( x0, x1 );
3224 *yl = MIN( y0, y1 );
3225 *xr = MAX( x0, x1 );
3226 *yr = MAX( y0, y1 );
3227 }
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
PLControlPt::alt_hue_path
int alt_hue_path
Definition: plplot.h:564
plTclCmd
PLDLLIMPEXP_TCLTK int plTclCmd(char *cmdlist, Tcl_Interp *interp, int argc, const char **argv)
Definition: tclAPI.c:289
PLESC_REDRAW
#define PLESC_REDRAW
Definition: plplot.h:276
PlPlotterWidgetCmd
static int PlPlotterWidgetCmd(ClientData, Tcl_Interp *, int, CONST char **)
Definition: plplotter.c:503
PLiodev
Definition: pdf.h:61
PlPlotter::pts
XPoint pts[5]
Definition: plplotter.c:161
REFRESH_PENDING
#define REFRESH_PENDING
Definition: plplotter.c:206
PLSTATE_CMAP0
#define PLSTATE_CMAP0
Definition: plplotP.h:366
PLStream::cmap1cp
PLControlPt cmap1cp[PL_MAX_CMAP1CP]
Definition: plstrm.h:547
Redraw
static int Redraw(Tcl_Interp *, PlPlotter *, int, CONST char **)
argv
static char ** argv
Definition: qt.cpp:49
Page
static int Page(Tcl_Interp *, PlPlotter *, int, CONST char **)
NDEV
#define NDEV
Definition: plplotter.c:93
plr_process
int plr_process(PLRDev *plr)
Definition: plr.c:115
plsstrm
#define plsstrm
Definition: plplot.h:835
tcpip.h
PlPlotter::width
int width
Definition: plplotter.c:119
PLiodev::typeName
const char * typeName
Definition: pdf.h:68
scol0
static int scol0(Tcl_Interp *interp, register PlPlotter *plPlotterPtr, int i, CONST char *col, int *p_changed)
Definition: plplotter.c:1612
PlPlotter::tkwin
Tk_Window tkwin
Definition: plplotter.c:104
plplot_tkwin_ccmap
static int plplot_tkwin_ccmap
Definition: pltkwd.h:41
pdf_bopen
PDFstrm * pdf_bopen(U_CHAR *buffer, size_t bufmax)
Definition: pdfutils.c:152
PLColor::b
unsigned char b
Definition: plplot.h:550
PLiodev::fileHandle
const char * fileHandle
Definition: pdf.h:66
PlPlotter::height
int height
Definition: plplotter.c:121
PlPlotter::ipls_save
PLINT ipls_save
Definition: plplotter.c:134
plsdev
#define plsdev
Definition: plplot.h:806
PlPlotter::plr
PLRDev * plr
Definition: plplotter.c:136
PLStream::ncp1
PLINT ncp1
Definition: plstrm.h:539
PlPlotter::xorGC
GC xorGC
Definition: plplotter.c:160
PlPlotterConfigureEH
static void PlPlotterConfigureEH(ClientData, XEvent *)
DrawRband
static void DrawRband(PlPlotter *, int, int)
Definition: plplotter.c:1318
PlPlotterLeaveEH
static void PlPlotterLeaveEH(ClientData, register XEvent *)
pldid2pc
void pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1691
PDFstrm
Definition: pdf.h:49
PLDisplay::height
unsigned int height
Definition: plplot.h:462
Tk_Cursor
#define Tk_Cursor
Definition: plframe.c:80
PLiodev::fd
int fd
Definition: pdf.h:63
argc
static int argc
Definition: qt.cpp:48
PlPlotter::ipls
PLINT ipls
Definition: plplotter.c:133
report
static int report(Tcl_Interp *, PlPlotter *, int, CONST char **)
pl_create_tempfile
FILE * pl_create_tempfile(char **fname)
Definition: plstdio.c:240
DestroyXhairs
static void DestroyXhairs(PlPlotter *)
Definition: plplotter.c:1191
DrawXhairs
static void DrawXhairs(PlPlotter *, int, int)
Definition: plplotter.c:1206
TkwDev::flags
int flags
Definition: pltkwd.h:78
DestroyPlPlotter
static void DestroyPlPlotter(ClientData)
Definition: plplotter.c:806
DEF_PLFRAME_BORDER_WIDTH
#define DEF_PLFRAME_BORDER_WIDTH
Definition: plplotter.c:216
plcmap1_calc
void plcmap1_calc(void)
Bin up cmap 1 space and assign colors to make inverse mapping easy.
Definition: plctrl.c:764
Cmd
static int Cmd(Tcl_Interp *, PlPlotter *, int, CONST char **)
PLDisplay
Definition: plplot.h:459
plr_start
void plr_start(PLRDev *plr)
Definition: plr.c:95
b1
#define b1
Definition: defines.h:18
MAX
#define MAX(a, b)
Definition: dsplint.c:28
plTranslateCursor
PLINT plTranslateCursor(PLGraphicsIn *plg)
Definition: plpage.c:259
plsdiori
#define plsdiori
Definition: plplot.h:809
scol1
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
PlPlotter::xhair_x
XPoint xhair_x[2]
Definition: plplotter.c:181
PlPlotter::SaveFnam
char * SaveFnam
Definition: plplotter.c:151
PlplotterAtBop
void PlplotterAtBop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2517
PLRDev::at_eop
int at_eop
Definition: plserver.h:22
plinit
#define plinit
Definition: plplot.h:755
plsfile
void plsfile(FILE *file)
Definition: plcore.c:3802
plPlotterCmd
int plPlotterCmd(ClientData, Tcl_Interp *, int, const char **)
pldip2dc
void pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1737
plbop
#define plbop
Definition: plplot.h:696
plsdiplt
#define plsdiplt
Definition: plplot.h:810
PLiodev::file
FILE * file
Definition: pdf.h:64
PlPlotter::widgetCmd
Tcl_Command widgetCmd
Definition: plplotter.c:114
DEF_PLFRAME_WIDTH
#define DEF_PLFRAME_WIDTH
Definition: plplotter.c:220
plgdiplt
#define plgdiplt
Definition: plplot.h:732
PlPlotter::rband_pt
XPoint rband_pt[2]
Definition: plplotter.c:188
PlPlotter::xl
PLFLT xl
Definition: plplotter.c:164
UPDATE_V_SCROLLBAR
#define UPDATE_V_SCROLLBAR
Definition: plplotter.c:209
PlPlotter::xhair_y
XPoint xhair_y[2]
Definition: plplotter.c:182
plend1
#define plend1
Definition: plplot.h:710
NextPage
static int NextPage(Tcl_Interp *, PlPlotter *, int, CONST char **)
PLINT
int PLINT
Definition: plplot.h:181
plgdiori
#define plgdiori
Definition: plplot.h:731
MIN
#define MIN(a, b)
Definition: dsplint.c:29
process_data
static int process_data(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2469
plD_open_tkwin
void plD_open_tkwin(PLStream *pls)
DisplayPlPlotter
static void DisplayPlPlotter(ClientData)
Definition: plplotter.c:1476
PlPlotter::devName
const char ** devName
Definition: plplotter.c:155
DEF_PLFRAME_BG_MONO
#define DEF_PLFRAME_BG_MONO
Definition: plplotter.c:215
PLControlPt::c3
PLFLT c3
Definition: plplot.h:561
Closelink
static int Closelink(Tcl_Interp *, PlPlotter *, int, CONST char **)
PlPlotter::cursor
Tk_Cursor cursor
Definition: plplotter.c:123
PLRDev::iodev
PLiodev * iodev
Definition: plserver.h:20
plgdidev
#define plgdidev
Definition: plplot.h:730
PLControlPt::p
PLFLT p
Definition: plplot.h:562
DEF_PLFRAME_CURSOR
#define DEF_PLFRAME_CURSOR
Definition: plplotter.c:217
PLColor_from_TkColor_Changed
int PLColor_from_TkColor_Changed(PLColor *plcolor, XColor *xcolor)
PLStream::ncol0
PLINT ncol0
Definition: plstrm.h:539
plcpstrm
#define plcpstrm
Definition: plplot.h:707
PlPlotterMotionEH
static void PlPlotterMotionEH(ClientData, register XEvent *)
Definition: plplotter.c:1037
PLColor::g
unsigned char g
Definition: plplot.h:549
PlPlotter::xr
PLFLT xr
Definition: plplotter.c:164
PLStream::db
int db
Definition: plstrm.h:635
pltkwd.h
Draw
static int Draw(Tcl_Interp *, PlPlotter *, int, CONST char **)
configSpecs
static Tk_ConfigSpec configSpecs[]
Definition: plplotter.c:224
snprintf
#define snprintf
Definition: plplotP.h:235
plsdidev
#define plsdidev
Definition: plplot.h:807
dbug_enter
#define dbug_enter(a)
Definition: tclMatrix.c:59
PLDisplay::x
unsigned int x
Definition: plplot.h:461
PLESC_RESIZE
#define PLESC_RESIZE
Definition: plplot.h:275
PlPlotter::bopCmd
char * bopCmd
Definition: plplotter.c:174
UPDATE_H_SCROLLBAR
#define UPDATE_H_SCROLLBAR
Definition: plplotter.c:210
TkwDisplay
Definition: pltkwd.h:46
PLControlPt::c1
PLFLT c1
Definition: plplot.h:559
plFindCommand
char * plFindCommand(PLCHAR_VECTOR fn)
Definition: plctrl.c:2146
Info
static int Info(Tcl_Interp *, PlPlotter *, int, CONST char **)
PlPlotter::yScrollCmd
char * yScrollCmd
Definition: plplotter.c:168
plhlsrgb
#define plhlsrgb
Definition: plplot.h:752
PlPlotter::yr
PLFLT yr
Definition: plplotter.c:164
PlPlotter
struct PlPlotter PlPlotter
Orient
static int Orient(Tcl_Interp *, PlPlotter *, int, CONST char **)
DEF_PLFRAME_HEIGHT
#define DEF_PLFRAME_HEIGHT
Definition: plplotter.c:218
UpdateHScrollbar
static void UpdateHScrollbar(register PlPlotter *)
Definition: plplotter.c:3180
child
static int child
Definition: plserver.c:45
PlplotterAtEop
void PlplotterAtEop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2507
PlPlotter::double_buffer
int double_buffer
Definition: plplotter.c:189
pl_cmd
void pl_cmd(PLINT op, void *ptr)
Definition: plctrl.c:2118
plgFileDevs
void plgFileDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition: plcore.c:3530
View
static int View(Tcl_Interp *, PlPlotter *, int, CONST char **)
PLStream::cmap0
PLColor * cmap0
Definition: plstrm.h:544
CreateXhairs
static void CreateXhairs(PlPlotter *)
Definition: plplotter.c:1153
PlPlotter::continue_draw
int continue_draw
Definition: plplotter.c:162
plsdiplz
#define plsdiplz
Definition: plplot.h:811
PlPlotter::active_plot
int active_plot
Definition: plplotter.c:140
plspause
#define plspause
Definition: plplot.h:834
plplotc.plsxwin
def plsxwin
Definition: plplotc.py:364
ConfigurePlPlotter
static int ConfigurePlPlotter(Tcl_Interp *, PlPlotter *, int, CONST char **, int)
PlPlotter::devDesc
const char ** devDesc
Definition: plplotter.c:153
ReadData
static int ReadData(ClientData, int)
Definition: plplotter.c:2535
PLStream::nopixmap
int nopixmap
Definition: plstrm.h:635
DEF_PLFRAME_RELIEF
#define DEF_PLFRAME_RELIEF
Definition: plplotter.c:219
PlPlotter::pls
PLStream * pls
Definition: plplotter.c:132
PlPlotter::tkwin_initted
int tkwin_initted
Definition: plplotter.c:131
pl_PacketReceive
PLDLLIMPEXP_TCLTK int pl_PacketReceive(Tcl_Interp *interp, PLiodev *iodev, PDFstrm *pdfs)
PLStream
Definition: plstrm.h:523
PlPlotterFirstInit
static void PlPlotterFirstInit(ClientData clientData)
Definition: plplotter.c:1347
plstrdup
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition: plctrl.c:2985
PlPlotter::plpr_cmd
char * plpr_cmd
Definition: plplotter.c:137
PLRDev::nbytes
int nbytes
Definition: plserver.h:21
TkwDev::width
unsigned width
Definition: pltkwd.h:82
PLRDev
Definition: plserver.h:16
TkwDev::gin
PLGraphicsIn gin
Definition: pltkwd.h:97
UpdateVScrollbar
static void UpdateVScrollbar(register PlPlotter *)
Definition: plplotter.c:3154
PlPlotter::flags
int flags
Definition: plplotter.c:124
plP_state
void plP_state(PLINT op)
Definition: plcore.c:256
UpdateXhairs
static void UpdateXhairs(PlPlotter *)
Definition: plplotter.c:1231
PlPlotter::drawing_xhairs
int drawing_xhairs
Definition: plplotter.c:180
gbox
static void gbox(PLFLT *, PLFLT *, PLFLT *, PLFLT *, CONST char **)
Definition: plplotter.c:3207
plmkstrm
#define plmkstrm
Definition: plplot.h:772
PL_UNUSED
#define PL_UNUSED(x)
Definition: plplot.h:138
PLFLT
float PLFLT
Definition: plplot.h:163
PlPlotter::isActive
int isActive
Definition: plplotter.c:141
Scroll
static int Scroll(Tcl_Interp *, PlPlotter *)
pdf_close
int pdf_close(PDFstrm *pdfs)
Definition: pdfutils.c:238
Save
static int Save(Tcl_Interp *, PlPlotter *, int, CONST char **)
TkwDisplay::map
Colormap map
Definition: pltkwd.h:55
plflush
#define plflush
Definition: plplot.h:719
TkwDev::write_to_window
int write_to_window
Definition: pltkwd.h:91
free_mem
#define free_mem(a)
Definition: plplotP.h:182
PlPlotter::rband
int rband
Definition: plplotter.c:186
TkwDev::tkwd
TkwDisplay * tkwd
Definition: pltkwd.h:70
plserver.h
PlPlotter::eopCmd
char * eopCmd
Definition: plplotter.c:175
PlPlotter::pldis
PLDisplay pldis
Definition: plplotter.c:145
PlPlotter::border
Tk_3DBorder border
Definition: plplotter.c:115
PlPlotter::prevWidth
int prevWidth
Definition: plplotter.c:146
UpdateRband
static void UpdateRband(PlPlotter *)
Definition: plplotter.c:1337
PlPlotter::yl
PLFLT yl
Definition: plplotter.c:164
DEF_PLFRAME_BG_COLOR
#define DEF_PLFRAME_BG_COLOR
Definition: plplotter.c:214
PLColor::r
unsigned char r
Definition: plplot.h:548
DestroyRband
static void DestroyRband(PlPlotter *)
Definition: plplotter.c:1303
PlPlotter::prevHeight
int prevHeight
Definition: plplotter.c:147
PLiodev::type
int type
Definition: pdf.h:67
REDRAW_PENDING
#define REDRAW_PENDING
Definition: plplotter.c:208
pltkwin_setBGFG
void pltkwin_setBGFG(PLStream *pls)
PlPlotter::xhair_cursor
Tk_Cursor xhair_cursor
Definition: plplotter.c:163
plreplot
#define plreplot
Definition: plplot.h:788
PlPlotter::display
Display * display
Definition: plplotter.c:108
PlPlotter::xScrollCmd
char * xScrollCmd
Definition: plplotter.c:165
TkwDev::height
unsigned height
Definition: pltkwd.h:82
PLRDev::at_bop
int at_bop
Definition: plserver.h:22
PlPlotterEnterEH
static void PlPlotterEnterEH(ClientData, register XEvent *)
Definition: plplotter.c:1071
PLRDev::pdfs
PDFstrm * pdfs
Definition: plserver.h:19
TkwDev
Definition: pltkwd.h:68
PLControlPt::c2
PLFLT c2
Definition: plplot.h:560
CreateRband
static void CreateRband(PlPlotter *)
Definition: plplotter.c:1251
PlPlotter::drawing_rband
int drawing_rband
Definition: plplotter.c:187
PDFstrm::bp
size_t bp
Definition: pdf.h:56
PlPlotterButtonPressEH
static void PlPlotterButtonPressEH(ClientData clientData, register XEvent *)
Definition: plplotter.c:1127
PLStream::debug
PLINT debug
Definition: plstrm.h:527
pladv
#define pladv
Definition: plplot.h:692
PlPlotterInit
static void PlPlotterInit(ClientData)
Definition: plplotter.c:1388
ActiveState
static void ActiveState(register PlPlotter *plPlotterPtr, int on)
Definition: plplotter.c:1985
PLDisplay::width
unsigned int width
Definition: plplot.h:462
PlPlotterExposeEH
static void PlPlotterExposeEH(ClientData, XEvent *)
PlPlotter::borderWidth
int borderWidth
Definition: plplotter.c:117
PLDisplay::y
unsigned int y
Definition: plplot.h:461
PLStream::dev
void * dev
Definition: plstrm.h:594
plgpls
void plgpls(PLStream **p_pls)
Definition: plcore.c:3693
PlPlotter::interp
Tcl_Interp * interp
Definition: plplotter.c:111
PLESC_EXPOSE
#define PLESC_EXPOSE
Definition: plplot.h:274
Openlink
static int Openlink(Tcl_Interp *, PlPlotter *, int, CONST char **)
plrgbhls
#define plrgbhls
Definition: plplot.h:789
RESIZE_PENDING
#define RESIZE_PENDING
Definition: plplotter.c:207
Install_cmap
static void Install_cmap(PlPlotter *plPlotterPtr)
Definition: plplotter.c:1426
PlPlotter::relief
int relief
Definition: plplotter.c:118
Print
static int Print(Tcl_Interp *, PlPlotter *, int, CONST char **)
PlPlotter
Definition: plplotter.c:100
PlPlotter::xhairs
int xhairs
Definition: plplotter.c:179
PLGraphicsIn
Definition: plplot.h:433