PLplot 5.15.0
Loading...
Searching...
No Matches
plplotter.c
Go to the documentation of this file.
1// Copyright (C) 2004 Joao Cardoso
2//
3// This file is part of PLplot.
4//
5// PLplot is free software; you can redistribute it and/or modify
6// it under the terms of the GNU Library General Public License as published
7// by the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// PLplot is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Library General Public License for more details.
14//
15// You should have received a copy of the GNU Library General Public License
16// along with PLplot; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18//
19//
20
21//
22// plplotter.c
23//
24// Copyright 1993, 1994, 1995
25// Maurice LeBrun mjl@dino.ph.utexas.edu
26// Institute for Fusion Studies University of Texas at Austin
27//
28// This library is free software; you can redistribute it and/or
29// modify it under the terms of the GNU Library General Public
30// License as published by the Free Software Foundation; either
31// version 2 of the License, or (at your option) any later version.
32//
33// This library is distributed in the hope that it will be useful,
34// but WITHOUT ANY WARRANTY; without even the implied warranty of
35// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36// Library General Public License for more details.
37//
38// You should have received a copy of the GNU Library General Public
39// License along with this library; if not, write to the Free Software
40// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41//
42// Based upon tkFrame.c from the TK 3.2 distribution:
43//
44// Copyright 1990 Regents of the University of California.
45// Permission to use, copy, modify, and distribute this
46// software and its documentation for any purpose and without
47// fee is hereby granted, provided that the above copyright
48// notice appear in all copies. The University of California
49// makes no representations about the suitability of this
50// software for any purpose. It is provided "as is" without
51// express or implied warranty.
52//
53//--------------------------------------------------------------------------
54//
55// This module implements "plframe" widgets for the Tk toolkit. These are
56// frames that have extra logic to allow them to be interfaced with the
57// PLplot X driver. These are then drawn into and respond to keyboard and
58// mouse events.
59//
60//
61// #define DEBUG_ENTER
62// #define DEBUG
63//
64
65#define NEED_PLDEBUG
66#include "plserver.h"
67#include "pltkwd.h"
68#include "tcpip.h"
69
70#ifdef _WIN32
71#define XSynchronize( display, bool ) { display->request++; }
72#define XSync( display, bool ) { display->request++; }
73#define XFlush( display )
74#endif
75
76#ifdef DEBUG_ENTER
77// This version of dbug_enter works cross-platform
78#undef dbug_enter
79#define dbug_enter( a ) if ( plsc->debug ) { \
80 Tcl_Write( Tcl_GetStdChannel( TCL_STDERR ), a, -1 ); }
81#endif
82
83#ifndef _WIN32
84#ifdef PL_HAVE_UNISTD_H
85#include <unistd.h>
86#include <fcntl.h>
87#endif
88#endif
89
90// plplot_tkwin_ccmap is statically defined in pltkwd.h. Note that
91// tkwin.c also includes that header and uses that variable.
92
93#define NDEV 100 // Max number of output device types
94
95//
96// A data structure of the following type is kept for each
97// plframe that currently exists for this process:
98//
99
100typedef struct PlPlotter
101{
102// This is stuff taken from tkFrame.c
103
104 Tk_Window tkwin; // Window that embodies the frame. NULL
105 // means that the window has been destroyed
106 // but the data structures haven't yet been
107 // cleaned up.
108 Display *display; // Display containing widget. Used, among
109 // other things, so that resources can be
110 // freed even after tkwin has gone away.
111 Tcl_Interp *interp; // Interpreter associated with
112 // widget. Used to delete widget
113 // command.
114 Tcl_Command widgetCmd; // Token for frame's widget command.
115 Tk_3DBorder border; // Structure used to draw 3-D border and
116 // background.
117 int borderWidth; // Width of 3-D border (if any).
118 int relief; // 3-d effect: TK_RELIEF_RAISED etc.
119 int width; // Width to request for window. <= 0 means
120 // don't request any size.
121 int height; // Height to request for window. <= 0 means
122 // don't request any size.
123 Tk_Cursor cursor; // Current cursor for window, or None.
124 int flags; // Various flags; see below for
125 // definitions.
126
127// These are new to plframe widgets
128
129// control stuff
130
131 int tkwin_initted; // Set first time widget is mapped
132 PLStream *pls; // PLplot stream pointer
133 PLINT ipls; // PLplot stream number
134 PLINT ipls_save; // PLplot stream number, save files
135
136 PLRDev *plr; // Renderer state information. Malloc'ed
137 char *plpr_cmd; // Holds print command name. Malloc'ed
138
139// Used to allow active stuff on the plot
140 int active_plot; // The plot responds to mouse movement etc.
141 int isActive; // Used to turn event handling on and off.
142
143// Used to handle resize and expose events
144
145 PLDisplay pldis; // Info about the display window
146 int prevWidth; // Previous window width
147 int prevHeight; // Previous window height
148
149// Support for save operations
150
151 char *SaveFnam; // File name we are currently saving to.
152 // Malloc'ed.
153 const char **devDesc; // Descriptive names for file-oriented
154 // devices. Malloc'ed.
155 const char **devName; // Keyword names of file-oriented devices.
156 // Malloc'ed.
157
158// Used in selecting & modifying plot or device area
159
160 GC xorGC; // GC used for rubber-band drawing
161 XPoint pts[5]; // Points for rubber-band drawing
162 int continue_draw; // Set when doing rubber-band draws
163 Tk_Cursor xhair_cursor; // cursor used for drawing
164 PLFLT xl, xr, yl, yr; // Bounds on plot viewing area
165 char *xScrollCmd; // Command prefix for communicating with
166 // horizontal scrollbar. NULL means no
167 // command to issue. Malloc'ed.
168 char *yScrollCmd; // Command prefix for communicating with
169 // vertical scrollbar. NULL means no
170 // command to issue. Malloc'ed.
171
172// Used for flashing bop or eop condition
173
174 char *bopCmd; // Proc to call at bop
175 char *eopCmd; // Proc to call at eop
176
177// Used for drawing graphic crosshairs
178
179 int xhairs; // Configuration option to turn on xhairs
180 int drawing_xhairs; // Set if we are currently drawing xhairs
181 XPoint xhair_x[2]; // Points for horizontal xhair line
182 XPoint xhair_y[2]; // Points for vertical xhair line
183
184// Used for drawing a rubber band lilne segment
185
186 int rband; // Configuration option to turn on rband
187 int drawing_rband; // See if we are currently drawing rband
188 XPoint rband_pt[2]; // Ends of rubber band line
189 int double_buffer; // Double buffering configuration option
191
192//
193// Flag bits for plframes:
194//
195// REFRESH_PENDING: Non-zero means a DoWhenIdle handler
196// has already been queued to refresh
197// this window.
198// RESIZE_PENDING; Used to reschedule resize events
199// REDRAW_PENDING; Used to redraw contents of plot buffer
200// UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs
201// to be updated.
202// UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs
203// to be updated.
204//
205
206#define REFRESH_PENDING 1
207#define RESIZE_PENDING 2
208#define REDRAW_PENDING 4
209#define UPDATE_V_SCROLLBAR 8
210#define UPDATE_H_SCROLLBAR 16
211
212// Defaults for plframes:
213
214#define DEF_PLFRAME_BG_COLOR "Black"
215#define DEF_PLFRAME_BG_MONO "White"
216#define DEF_PLFRAME_BORDER_WIDTH "0"
217#define DEF_PLFRAME_CURSOR ( (char *) NULL )
218#define DEF_PLFRAME_HEIGHT "250"
219#define DEF_PLFRAME_RELIEF "flat"
220#define DEF_PLFRAME_WIDTH "250"
221
222// Configuration info
223
224static Tk_ConfigSpec configSpecs[] = {
225 { TK_CONFIG_BOOLEAN, "-activeplot", (char *) NULL, (char *) NULL,
226 "1", 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
269int plPlotterCmd( ClientData, Tcl_Interp *, int, const char ** );
270void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
271void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
272
273// These are invoked by the TK dispatcher
274
275static void DestroyPlPlotter( ClientData );
276static void DisplayPlPlotter( ClientData );
277static void PlPlotterInit( ClientData );
278static void PlPlotterFirstInit( ClientData clientData );
279static void PlPlotterConfigureEH( ClientData, XEvent * );
280static void PlPlotterExposeEH( ClientData, XEvent * );
281static void PlPlotterMotionEH( ClientData, register XEvent * );
282static void PlPlotterEnterEH( ClientData, register XEvent * );
283static void PlPlotterLeaveEH( ClientData, register XEvent * );
284static void PlPlotterButtonPressEH( ClientData clientData, register XEvent * );
285static int PlPlotterWidgetCmd( ClientData, Tcl_Interp *, int, CONST char ** );
286static int ReadData( ClientData, int );
287static void Install_cmap( PlPlotter *plPlotterPtr );
288
289// These are invoked by PlPlotterWidgetCmd to process widget commands
290
291static int Closelink( Tcl_Interp *, PlPlotter *, int, CONST char ** );
292static int Cmd( Tcl_Interp *, PlPlotter *, int, CONST char ** );
293static int ConfigurePlPlotter( Tcl_Interp *, PlPlotter *, int, CONST char **, int );
294static int Draw( Tcl_Interp *, PlPlotter *, int, CONST char ** );
295static int Info( Tcl_Interp *, PlPlotter *, int, CONST char ** );
296static int Openlink( Tcl_Interp *, PlPlotter *, int, CONST char ** );
297static int Orient( Tcl_Interp *, PlPlotter *, int, CONST char ** );
298static int Page( Tcl_Interp *, PlPlotter *, int, CONST char ** );
299static int NextPage( Tcl_Interp *, PlPlotter *, int, CONST char ** );
300static int Print( Tcl_Interp *, PlPlotter *, int, CONST char ** );
301static int Redraw( Tcl_Interp *, PlPlotter *, int, CONST char ** );
302static int Save( Tcl_Interp *, PlPlotter *, int, CONST char ** );
303static int View( Tcl_Interp *, PlPlotter *, int, CONST char ** );
304static int Scroll( Tcl_Interp *, PlPlotter * );
305static int report( Tcl_Interp *, PlPlotter *, int, CONST char ** );
306
307// Routines for manipulating graphic crosshairs
308
309static void ActiveState( register PlPlotter *plPlotterPtr, int on );
310static void CreateXhairs( PlPlotter * );
311static void DestroyXhairs( PlPlotter * );
312static void DrawXhairs( PlPlotter *, int, int );
313static void UpdateXhairs( PlPlotter * );
314
315// Routines for manipulating the rubberband line
316
317static void CreateRband( PlPlotter * );
318static void DestroyRband( PlPlotter * );
319static void DrawRband( PlPlotter *, int, int );
320static void UpdateRband( PlPlotter * );
321
322// Utility routines
323
324static void gbox( PLFLT *, PLFLT *, PLFLT *, PLFLT *, CONST char ** );
325static void UpdateVScrollbar( register PlPlotter * );
326static void UpdateHScrollbar( register PlPlotter * );
327
328//
329//--------------------------------------------------------------------------
330//
331// plPlotterCmd --
332//
333// This procedure is invoked to process the "plframe" Tcl
334// command. See the user documentation for details on what it
335// does.
336//
337// Results:
338// A standard Tcl result.
339//
340// Side effects:
341// See the user documentation.
342//
343//--------------------------------------------------------------------------
344//
345
346int
347plPlotterCmd( ClientData PL_UNUSED( clientData ), Tcl_Interp *interp,
348 int argc, const char **argv )
349{
350 Tk_Window tkwin;
351 register PlPlotter *plPlotterPtr;
352 register PLRDev *plr;
353 int i, ndev;
354
355 dbug_enter( "plPlotterCmd" );
356
357 if ( argc < 2 )
358 {
359 Tcl_AppendResult( interp, "wrong # args: should be \"",
360 argv[0], " pathName ?options?\"", (char *) NULL );
361 return TCL_ERROR;
362 }
363
364// Create the window.
365
366 tkwin = Tk_CreateWindowFromPath( interp, Tk_MainWindow( interp ), argv[1], (char *) NULL );
367 if ( tkwin == NULL )
368 {
369 return TCL_ERROR;
370 }
371 Tk_SetClass( tkwin, "Plframe" );
372
373 plPlotterPtr = (PlPlotter *) malloc( sizeof ( PlPlotter ) );
374
375 // Initialize in the same order as the members of the struct just
376 // to keep track of what is initialized and what not.
377 plPlotterPtr->tkwin = tkwin;
378 plPlotterPtr->display = Tk_Display( tkwin );
379 plPlotterPtr->interp = interp;
380 plPlotterPtr->widgetCmd =
381 Tcl_CreateCommand( interp, Tk_PathName( plPlotterPtr->tkwin ),
382 (Tcl_CmdProc *) PlPlotterWidgetCmd, (ClientData) plPlotterPtr,
383 (Tcl_CmdDeleteProc *) NULL );
384 plPlotterPtr->border = NULL;
385 //plPlotterPtr->borderWidth = <uninitialized>;
386 //plPlotterPtr->relief = <uninitialized>;
387 plPlotterPtr->width = Tk_Width( plPlotterPtr->tkwin );
388 plPlotterPtr->height = Tk_Height( plPlotterPtr->tkwin );
389 plPlotterPtr->cursor = None;
390 plPlotterPtr->flags = 0;
391 plPlotterPtr->tkwin_initted = 0;
392 // Associate new PLplot stream with this widget
393 plmkstrm( &plPlotterPtr->ipls );
394 plgpls( &plPlotterPtr->pls );
395 plPlotterPtr->ipls_save = 0;
396 plPlotterPtr->plr = (PLRDev *) malloc( sizeof ( PLRDev ) );
397 plPlotterPtr->plpr_cmd = NULL;
398 plPlotterPtr->active_plot = 1;
399 plPlotterPtr->isActive = 0;
400 plPlotterPtr->pldis.x = 0;
401 plPlotterPtr->pldis.y = 0;
402 plPlotterPtr->pldis.width = 0;
403 plPlotterPtr->pldis.height = 0;
404 plPlotterPtr->prevWidth = 0;
405 plPlotterPtr->prevHeight = 0;
406 plPlotterPtr->SaveFnam = NULL;
407 // plPlotterPtr->devDesc = <uninitialized, to be malloced?>;
408 // plPlotterPtr->devName = <uninitialized, to be malloced?>;
409 plPlotterPtr->xorGC = NULL;
410 // plPlotterPtr->pts = <uninitialized array>;
411 plPlotterPtr->continue_draw = 0;
412 plPlotterPtr->xhair_cursor = None;
413 plPlotterPtr->xl = 0.;
414 plPlotterPtr->yl = 0.;
415 plPlotterPtr->xr = 1.;
416 plPlotterPtr->yr = 1.;
417 plPlotterPtr->xScrollCmd = NULL;
418 plPlotterPtr->yScrollCmd = NULL;
419 plPlotterPtr->bopCmd = NULL;
420 plPlotterPtr->eopCmd = NULL;
421 plPlotterPtr->xhairs = 0;
422 plPlotterPtr->drawing_xhairs = 0;
423 // plPlotterPtr->xhair_x = <uninitialized array>;
424 // plPlotterPtr->xhair_y = <uninitialized array>;
425 plPlotterPtr->rband = 0;
426 plPlotterPtr->drawing_rband = 0;
427 // plPlotterPtr->rband_pt = <uninitialized array>;
428 plPlotterPtr->double_buffer = 1;
429
430 plr = plPlotterPtr->plr;
431 plr->pdfs = NULL;
432 plr->iodev = (PLiodev *) malloc( sizeof ( PLiodev ) );
433 plr_start( plr );
434
435 // Tell the stream about myself
436 plPlotterPtr->pls->plPlotterPtr = plPlotterPtr;
437
438// Set up stuff for rubber-band drawing
439
440 plPlotterPtr->xhair_cursor =
441 Tk_GetCursor( plPlotterPtr->interp, plPlotterPtr->tkwin, "crosshair" );
442
443// Partially initialize Tk driver.
444
445 plD_open_tkwin( plPlotterPtr->pls );
446
447// Create list of valid device names and keywords for page dumps
448
449 plPlotterPtr->devDesc = (const char **) malloc( (size_t) NDEV * sizeof ( char ** ) );
450 plPlotterPtr->devName = (const char **) malloc( (size_t) NDEV * sizeof ( char ** ) );
451 for ( i = 0; i < NDEV; i++ )
452 {
453 plPlotterPtr->devDesc[i] = NULL;
454 plPlotterPtr->devName[i] = NULL;
455 }
456 ndev = NDEV;
457 plgFileDevs( &plPlotterPtr->devDesc, &plPlotterPtr->devName, &ndev );
458
459// Start up event handlers and other good stuff
460
461 Tk_CreateEventHandler( plPlotterPtr->tkwin, StructureNotifyMask,
462 PlPlotterConfigureEH, (ClientData) plPlotterPtr );
463
464 Tk_CreateEventHandler( plPlotterPtr->tkwin, ExposureMask,
465 PlPlotterExposeEH, (ClientData) plPlotterPtr );
466
467// for active plot
468 ActiveState( plPlotterPtr, 1 );
469
470 if ( ConfigurePlPlotter( interp, plPlotterPtr, argc - 2, (CONST char **) argv + 2, 0 ) != TCL_OK )
471 {
472 Tk_DestroyWindow( plPlotterPtr->tkwin );
473 return TCL_ERROR;
474 }
475 Tk_MakeWindowExist( plPlotterPtr->tkwin );
476 PlPlotterFirstInit( (ClientData) plPlotterPtr );
477 Tk_GeometryRequest( plPlotterPtr->tkwin, 200, 200 );
478
479 Tcl_SetResult( interp, Tk_PathName( plPlotterPtr->tkwin ), TCL_VOLATILE );
480
481 return TCL_OK;
482}
483
484//
485//--------------------------------------------------------------------------
486//
487// PlPlotterWidgetCmd --
488//
489// This procedure is invoked to process the Tcl command that
490// corresponds to a plframe widget. See the user
491// documentation for details on what it does.
492//
493// Results:
494// A standard Tcl result.
495//
496// Side effects:
497// See the user documentation.
498//
499//--------------------------------------------------------------------------
500//
501
502static int
503PlPlotterWidgetCmd( ClientData clientData, Tcl_Interp *interp,
504 int argc, CONST char **argv )
505{
506 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
507 int result = TCL_OK;
508 int length;
509 char c;
510
511 dbug_enter( "PlPlotterWidgetCmd" );
512
513 if ( argc < 2 )
514 {
515 Tcl_AppendResult( interp, "wrong # args: should be \"",
516 argv[0], " option ?arg arg ...?\"", (char *) NULL );
517 return TCL_ERROR;
518 }
519 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
783done:
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
806static void DestroyPlPlotter( ClientData clientData )
807{
808 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
809 register PLRDev *plr = plPlotterPtr->plr;
810 TkwDev *dev = (TkwDev *) plPlotterPtr->pls->dev;
811
812 dbug_enter( "DestroyPlPlotter" );
813
814 dev->flags |= 0x3;
815
816 if ( plPlotterPtr->border != NULL )
817 {
818 Tk_Free3DBorder( plPlotterPtr->border );
819 }
820 if ( plPlotterPtr->plpr_cmd != NULL )
821 {
822 free( (char *) plPlotterPtr->plpr_cmd );
823 }
824 if ( plPlotterPtr->cursor != None )
825 {
826 Tk_FreeCursor( plPlotterPtr->display, plPlotterPtr->cursor );
827 }
828 if ( plPlotterPtr->xhair_cursor != None )
829 {
830 Tk_FreeCursor( plPlotterPtr->display, plPlotterPtr->xhair_cursor );
831 }
832 if ( plPlotterPtr->xorGC != NULL )
833 {
834 Tk_FreeGC( plPlotterPtr->display, plPlotterPtr->xorGC );
835 }
836 if ( plPlotterPtr->yScrollCmd != NULL )
837 {
838 free( (char *) plPlotterPtr->yScrollCmd );
839 }
840 if ( plPlotterPtr->xScrollCmd != NULL )
841 {
842 free( (char *) plPlotterPtr->xScrollCmd );
843 }
844 if ( plPlotterPtr->SaveFnam != NULL )
845 {
846 free( (char *) plPlotterPtr->SaveFnam );
847 }
848 if ( plPlotterPtr->devDesc != NULL )
849 {
850 free( (char *) plPlotterPtr->devDesc );
851 }
852 if ( plPlotterPtr->devName != NULL )
853 {
854 free( (char *) plPlotterPtr->devName );
855 }
856
857// Clean up data connection
858
859 pdf_close( plr->pdfs );
860 free( (char *) plPlotterPtr->plr->iodev );
861
862// Tell PLplot to clean up
863
864 plsstrm( plPlotterPtr->ipls );
865 plend1();
866
867// Delete main data structures
868
869 free( (char *) plPlotterPtr->plr );
870 free( (char *) plPlotterPtr );
871}
872
873//
874//--------------------------------------------------------------------------
875//
876// PlPlotterConfigureEH --
877//
878// Invoked by the Tk dispatcher on structure changes to a plframe.
879//
880// Results:
881// None.
882//
883// Side effects:
884// When the window gets deleted, internal structures get cleaned up.
885// When it gets resized, it is redrawn.
886//
887//--------------------------------------------------------------------------
888//
889
890static void
891PlPlotterConfigureEH( ClientData clientData, register XEvent *eventPtr )
892{
893 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
894 register Tk_Window tkwin = plPlotterPtr->tkwin;
895
896 dbug_enter( "PlPlotterConfigureEH" );
897
898 switch ( eventPtr->type )
899 {
900 case ConfigureNotify:
901 pldebug( "PLFrameConfigureEH", "ConfigureNotify\n" );
902 plPlotterPtr->flags |= RESIZE_PENDING;
903 plPlotterPtr->width = Tk_Width( tkwin );
904 plPlotterPtr->height = Tk_Height( tkwin );
905 if ( ( tkwin != NULL ) && !( plPlotterPtr->flags & REFRESH_PENDING ) )
906 {
907 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
908 plPlotterPtr->flags |= REFRESH_PENDING;
909 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
910 }
911 break;
912
913 case DestroyNotify:
914 pldebug( "PLFrameConfigureEH", "DestroyNotify\n" );
915 Tcl_DeleteCommand( plPlotterPtr->interp, Tk_PathName( tkwin ) );
916 plPlotterPtr->tkwin = NULL;
917 if ( plPlotterPtr->flags & REFRESH_PENDING )
918 {
919 Tcl_CancelIdleCall( DisplayPlPlotter, (ClientData) plPlotterPtr );
920 }
921 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
972static void
973PlPlotterExposeEH( ClientData clientData, register XEvent *eventPtr )
974{
975 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
976 XExposeEvent *event = (XExposeEvent *) eventPtr;
977 register Tk_Window tkwin = plPlotterPtr->tkwin;
978
979 dbug_enter( "PlPlotterExposeEH" );
980
981 pldebug( "PLFrameExposeEH", "Expose\n" );
982
983// Set up the area to refresh
984
985 if ( !( plPlotterPtr->drawing_xhairs || plPlotterPtr->drawing_rband ) )
986 {
987 int x0_old, x1_old, y0_old, y1_old, x0_new, x1_new, y0_new, y1_new;
988
989 x0_old = (int) plPlotterPtr->pldis.x;
990 y0_old = (int) plPlotterPtr->pldis.y;
991 x1_old = x0_old + (int) plPlotterPtr->pldis.width;
992 y1_old = y0_old + (int) plPlotterPtr->pldis.height;
993
994 x0_new = event->x;
995 y0_new = event->y;
996 x1_new = x0_new + event->width;
997 y1_new = y0_new + event->height;
998
999 plPlotterPtr->pldis.x = (unsigned int) MIN( x0_old, x0_new );
1000 plPlotterPtr->pldis.y = (unsigned int) MIN( y0_old, y0_new );
1001 plPlotterPtr->pldis.width = (unsigned int) MAX( x1_old, x1_new ) - plPlotterPtr->pldis.x;
1002 plPlotterPtr->pldis.height = (unsigned int) MAX( y1_old, y1_new ) - plPlotterPtr->pldis.y;
1003 }
1004
1005// Invoke DoWhenIdle handler to redisplay widget.
1006
1007 if ( event->count == 0 )
1008 {
1009 if ( ( tkwin != NULL ) && !( plPlotterPtr->flags & REFRESH_PENDING ) )
1010 {
1011 Tcl_DoWhenIdle( DisplayPlPlotter, (ClientData) plPlotterPtr );
1012 plPlotterPtr->width = Tk_Width( tkwin );
1013 plPlotterPtr->height = Tk_Height( tkwin );
1014 plPlotterPtr->flags |= REFRESH_PENDING;
1015 }
1016 }
1017}
1018
1019//
1020//--------------------------------------------------------------------------
1021//
1022// PlPlotterMotionEH --
1023//
1024// Invoked by the Tk dispatcher on MotionNotify events in a plframe.
1025// Not invoked unless we are drawing graphic crosshairs.
1026//
1027// Results:
1028// None.
1029//
1030// Side effects:
1031// Graphic crosshairs are drawn.
1032//
1033//--------------------------------------------------------------------------
1034//
1035
1036static void
1037PlPlotterMotionEH( ClientData clientData, register XEvent *eventPtr )
1038{
1039 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1040 XMotionEvent *event = (XMotionEvent *) eventPtr;
1041
1042 dbug_enter( "PlPlotterMotionEH" );
1043
1044 if ( plPlotterPtr->drawing_xhairs )
1045 {
1046 DrawXhairs( plPlotterPtr, event->x, event->y );
1047 }
1048 if ( plPlotterPtr->drawing_rband )
1049 {
1050 DrawRband( plPlotterPtr, event->x, event->y );
1051 }
1052}
1053
1054//
1055//--------------------------------------------------------------------------
1056//
1057// PlPlotterEnterEH --
1058//
1059// Invoked by the Tk dispatcher on EnterNotify events in a plframe.
1060// Not invoked unless we are drawing graphic crosshairs.
1061//
1062// Results:
1063// None.
1064//
1065// Side effects:
1066// Graphic crosshairs are updated.
1067//
1068//--------------------------------------------------------------------------
1069
1070static void
1071PlPlotterEnterEH( ClientData clientData, register XEvent *eventPtr )
1072{
1073 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1074 XCrossingEvent *crossingEvent = (XCrossingEvent *) eventPtr;
1075
1076 dbug_enter( "PlPlotterEnterEH" );
1077
1078 if ( plPlotterPtr->xhairs )
1079 {
1080 DrawXhairs( plPlotterPtr, crossingEvent->x, crossingEvent->y );
1081 plPlotterPtr->drawing_xhairs = 1;
1082 }
1083 if ( plPlotterPtr->rband )
1084 {
1085 plPlotterPtr->drawing_rband = 1;
1086 UpdateRband( plPlotterPtr );
1087 DrawRband( plPlotterPtr, crossingEvent->x, crossingEvent->y );
1088 }
1089}
1090
1091//
1092//--------------------------------------------------------------------------
1093//
1094// PlPlotterLeaveEH --
1095//
1096// Invoked by the Tk dispatcher on LeaveNotify events in a plframe.
1097// Not invoked unless we are drawing graphic crosshairs.
1098//
1099// Results:
1100// None.
1101//
1102// Side effects:
1103// Graphic crosshairs are updated.
1104//
1105//--------------------------------------------------------------------------
1106
1107static void
1108PlPlotterLeaveEH( ClientData clientData, register XEvent * PL_UNUSED( eventPtr ) )
1109{
1110 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1111
1112 dbug_enter( "PlPlotterLeaveEH" );
1113
1114 if ( plPlotterPtr->drawing_xhairs )
1115 {
1116 UpdateXhairs( plPlotterPtr );
1117 plPlotterPtr->drawing_xhairs = 0;
1118 }
1119 if ( plPlotterPtr->drawing_rband )
1120 {
1121 UpdateRband( plPlotterPtr );
1122 plPlotterPtr->drawing_rband = 0;
1123 }
1124}
1125
1126static void
1127PlPlotterButtonPressEH( ClientData clientData, register XEvent *eventPtr )
1128{
1129 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1130 XButtonEvent *event = (XButtonEvent *) eventPtr;
1131
1132 // Get modifier keys
1133 switch ( event->state )
1134 {
1135 case 256: // plain
1136 if ( plPlotterPtr->drawing_rband )
1137 {
1138 UpdateRband( plPlotterPtr );
1139 }
1140 if ( plPlotterPtr->rband )
1141 CreateRband( plPlotterPtr );
1142 break;
1143 }
1144}
1145
1146//--------------------------------------------------------------------------
1147// CreateXhairs()
1148//
1149// Creates graphic crosshairs at current pointer location.
1150//--------------------------------------------------------------------------
1151
1152static void
1153CreateXhairs( PlPlotter *plPlotterPtr )
1154{
1155 register Tk_Window tkwin = plPlotterPtr->tkwin;
1156 Window root, child;
1157 int root_x, root_y, win_x, win_y;
1158 unsigned int mask;
1159
1160
1161// Find current pointer location and draw graphic crosshairs if pointer is
1162// inside our window.
1163
1164 if ( XQueryPointer( plPlotterPtr->display, Tk_WindowId( tkwin ),
1165 &root, &child, &root_x, &root_y, &win_x, &win_y,
1166 &mask ) )
1167 {
1168 #ifdef MAC_TCL
1169 // Mac Tk only has a partial implementation of the above function
1170 // so we must fix it
1171 Tk_GetRootCoords( tkwin, &win_x, &win_y );
1172 win_x = root_x - win_x;
1173 win_y = root_y - win_y;
1174 #endif
1175 if ( win_x >= 0 && win_x < Tk_Width( tkwin ) &&
1176 win_y >= 0 && win_y < Tk_Height( tkwin ) )
1177 {
1178 DrawXhairs( plPlotterPtr, win_x, win_y );
1179 plPlotterPtr->drawing_xhairs = 1;
1180 }
1181 }
1182}
1183
1184//--------------------------------------------------------------------------
1185// DestroyXhairs()
1186//
1187// Destroys graphic crosshairs.
1188//--------------------------------------------------------------------------
1189
1190static void
1191DestroyXhairs( PlPlotter *plPlotterPtr )
1192{
1193// This draw removes the last set of graphic crosshairs
1194
1195 UpdateXhairs( plPlotterPtr );
1196 plPlotterPtr->drawing_xhairs = 0;
1197}
1198
1199//--------------------------------------------------------------------------
1200// DrawXhairs()
1201//
1202// Draws graphic crosshairs at (x0, y0). The first draw erases the old set.
1203//--------------------------------------------------------------------------
1204
1205static void
1206DrawXhairs( PlPlotter *plPlotterPtr, int x0, int y0 )
1207{
1208 register Tk_Window tkwin = plPlotterPtr->tkwin;
1209 int xmin = 0, xmax = Tk_Width( tkwin ) - 1;
1210 int ymin = 0, ymax = Tk_Height( tkwin ) - 1;
1211
1212 if ( plPlotterPtr->drawing_xhairs )
1213 UpdateXhairs( plPlotterPtr );
1214
1215 plPlotterPtr->xhair_x[0].x = (short) xmin; plPlotterPtr->xhair_x[0].y = (short) y0;
1216 plPlotterPtr->xhair_x[1].x = (short) xmax; plPlotterPtr->xhair_x[1].y = (short) y0;
1217
1218 plPlotterPtr->xhair_y[0].x = (short) x0; plPlotterPtr->xhair_y[0].y = (short) ymin;
1219 plPlotterPtr->xhair_y[1].x = (short) x0; plPlotterPtr->xhair_y[1].y = (short) ymax;
1220
1221 UpdateXhairs( plPlotterPtr );
1222}
1223
1224//--------------------------------------------------------------------------
1225// UpdateXhairs()
1226//
1227// Updates graphic crosshairs. If already there, they are erased.
1228//--------------------------------------------------------------------------
1229
1230static void
1231UpdateXhairs( PlPlotter *plPlotterPtr )
1232{
1233 register Tk_Window tkwin = plPlotterPtr->tkwin;
1234
1235 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1236 plPlotterPtr->xorGC, plPlotterPtr->xhair_x, 2,
1237 CoordModeOrigin );
1238
1239 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1240 plPlotterPtr->xorGC, plPlotterPtr->xhair_y, 2,
1241 CoordModeOrigin );
1242}
1243
1244//--------------------------------------------------------------------------
1245// CreateRband()
1246//
1247// Initiate rubber banding.
1248//--------------------------------------------------------------------------
1249
1250static void
1251CreateRband( PlPlotter *plPlotterPtr )
1252{
1253 register Tk_Window tkwin = plPlotterPtr->tkwin;
1254 Window root, child;
1255 int root_x, root_y, win_x, win_y;
1256 unsigned int mask;
1257
1258// Find current pointer location, and initiate rubber banding.
1259
1260 if ( XQueryPointer( plPlotterPtr->display, Tk_WindowId( tkwin ),
1261 &root, &child, &root_x, &root_y, &win_x, &win_y,
1262 &mask ) )
1263 {
1264 #ifdef MAC_TCL
1265 // Mac Tk only has a partial implementation of the above function
1266 // so we must fix it
1267 Tk_GetRootCoords( tkwin, &win_x, &win_y );
1268 win_x = root_x - win_x;
1269 win_y = root_y - win_y;
1270 #endif
1271 if ( win_x >= 0 && win_x < Tk_Width( tkwin ) &&
1272 win_y >= 0 && win_y < Tk_Height( tkwin ) )
1273 {
1274 // Okay, pointer is in our window.
1275 plPlotterPtr->rband_pt[0].x = (short) win_x;
1276 plPlotterPtr->rband_pt[0].y = (short) win_y;
1277
1278 DrawRband( plPlotterPtr, win_x, win_y );
1279 plPlotterPtr->drawing_rband = 1;
1280 }
1281 else
1282 {
1283 // Hmm, somehow they turned it on without even being in the window.
1284 // Just put the anchor in top left, they'll soon realize this is a
1285 // mistake...
1286
1287 plPlotterPtr->rband_pt[0].x = 0;
1288 plPlotterPtr->rband_pt[0].y = 0;
1289
1290 DrawRband( plPlotterPtr, win_x, win_y );
1291 plPlotterPtr->drawing_rband = 1;
1292 }
1293 }
1294}
1295
1296//--------------------------------------------------------------------------
1297// DestroyRband()
1298//
1299// Turn off rubber banding.
1300//--------------------------------------------------------------------------
1301
1302static void
1303DestroyRband( PlPlotter *plPlotterPtr )
1304{
1305// This draw removes the residual rubber band.
1306
1307 UpdateRband( plPlotterPtr );
1308 plPlotterPtr->drawing_rband = 0;
1309}
1310
1311//--------------------------------------------------------------------------
1312// DrawRband()
1313//
1314// Draws a rubber band from the anchor to the current cursor location.
1315//--------------------------------------------------------------------------
1316
1317static void
1318DrawRband( PlPlotter *plPlotterPtr, int x0, int y0 )
1319{
1320// If the line is already up, clear it.
1321
1322 if ( plPlotterPtr->drawing_rband )
1323 UpdateRband( plPlotterPtr );
1324
1325 plPlotterPtr->rband_pt[1].x = (short) x0; plPlotterPtr->rband_pt[1].y = (short) y0;
1326
1327 UpdateRband( plPlotterPtr );
1328}
1329
1330//--------------------------------------------------------------------------
1331// UpdateRband()
1332//
1333// Updates rubber band. If already there, it is erased.
1334//--------------------------------------------------------------------------
1335
1336static void
1337UpdateRband( PlPlotter *plPlotterPtr )
1338{
1339 register Tk_Window tkwin = plPlotterPtr->tkwin;
1340
1341 XDrawLines( Tk_Display( tkwin ), Tk_WindowId( tkwin ),
1342 plPlotterPtr->xorGC, plPlotterPtr->rband_pt, 2,
1343 CoordModeOrigin );
1344}
1345
1346// First-time initialization
1347static void PlPlotterFirstInit( ClientData clientData )
1348{
1349 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1350 register Tk_Window tkwin = plPlotterPtr->tkwin;
1351
1352 plsstrm( plPlotterPtr->ipls );
1353 plsdev( "tkwin" );
1354// We should probably rename plsxwin to plstkwin
1355 plsxwin( (PLINT) Tk_WindowId( tkwin ) );
1356 plspause( 0 );
1357 plinit();
1358 if ( plplot_tkwin_ccmap )
1359 {
1360 Install_cmap( plPlotterPtr );
1361 }
1362 plbop();
1363
1364 plPlotterPtr->tkwin_initted = 1;
1365 plPlotterPtr->width = Tk_Width( tkwin );
1366 plPlotterPtr->height = Tk_Height( tkwin );
1367 plPlotterPtr->prevWidth = plPlotterPtr->width;
1368 plPlotterPtr->prevHeight = plPlotterPtr->height;
1369}
1370
1371//
1372//--------------------------------------------------------------------------
1373//
1374// PlPlotterInit --
1375//
1376// Invoked to handle miscellaneous initialization after window gets
1377// mapped.
1378//
1379// Results:
1380// None.
1381//
1382// Side effects:
1383// PLplot internal parameters and device driver are initialized.
1384//
1385//--------------------------------------------------------------------------
1386
1387static void
1388PlPlotterInit( ClientData clientData )
1389{
1390 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1391
1392// Set up window parameters and arrange for window to be refreshed
1393
1394 plPlotterPtr->flags |= REFRESH_PENDING;
1395 plPlotterPtr->flags |= UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR;
1396
1397// Draw plframe
1398
1399 DisplayPlPlotter( clientData );
1400
1401 if ( plPlotterPtr->xhairs )
1402 CreateXhairs( plPlotterPtr );
1403
1404 if ( plPlotterPtr->rband )
1405 CreateRband( plPlotterPtr );
1406}
1407
1408//
1409//--------------------------------------------------------------------------
1410//
1411// Install_cmap --
1412//
1413// Installs X driver color map as necessary when custom color maps
1414// are used.
1415//
1416// Results:
1417// None.
1418//
1419// Side effects:
1420// Parent color maps may get changed.
1421//
1422//--------------------------------------------------------------------------
1423//
1424
1425static void
1426Install_cmap( PlPlotter *plPlotterPtr )
1427{
1428 TkwDev *dev;
1429
1430#define INSTALL_COLORMAP_IN_TK
1431#ifdef INSTALL_COLORMAP_IN_TK
1432 dev = (TkwDev *) plPlotterPtr->pls->dev;
1433 Tk_SetWindowColormap( Tk_MainWindow( plPlotterPtr->interp ), dev->tkwd->map );
1434
1435//
1436// If the colormap is local to this widget, the WM must be informed that
1437// it should be installed when the widget gets the focus. The top level
1438// window must be added to the end of its own list, because otherwise the
1439// window manager adds it to the front (as required by the ICCCM). Thanks
1440// to Paul Mackerras for providing this info in his TK photo widget.
1441//
1442
1443#else
1444 int count = 0;
1445 Window top, colormap_windows[5];
1446
1447 top = Tk_WindowId( Tk_MainWindow( plPlotterPtr->interp ) );
1448
1449 colormap_windows[count++] = Tk_WindowId( plPlotterPtr->tkwin );
1450 colormap_windows[count++] = top;
1451
1452 if ( !XSetWMColormapWindows( plPlotterPtr->display,
1453 top, colormap_windows, count ) )
1454 fprintf( stderr, "Unable to set color map property!\n" );
1455#endif
1456}
1457
1458//
1459//--------------------------------------------------------------------------
1460//
1461// DisplayPlPlotter --
1462//
1463// This procedure is invoked to display a plframe widget.
1464//
1465// Results:
1466// None.
1467//
1468// Side effects:
1469// Commands are output to X to display the plframe in its
1470// current mode.
1471//
1472//--------------------------------------------------------------------------
1473//
1474
1475static void
1476DisplayPlPlotter( ClientData clientData )
1477{
1478 register PlPlotter *plPlotterPtr = (PlPlotter *) clientData;
1479 register Tk_Window tkwin = plPlotterPtr->tkwin;
1480
1481 dbug_enter( "DisplayPlPlotter" );
1482
1483// Update scrollbars if needed
1484
1485 if ( plPlotterPtr->flags & UPDATE_V_SCROLLBAR )
1486 {
1487 UpdateVScrollbar( plPlotterPtr );
1488 }
1489 if ( plPlotterPtr->flags & UPDATE_H_SCROLLBAR )
1490 {
1491 UpdateHScrollbar( plPlotterPtr );
1492 }
1493 plPlotterPtr->flags &= ~( UPDATE_V_SCROLLBAR | UPDATE_H_SCROLLBAR );
1494
1495// If not mapped yet, just return and cancel pending refresh
1496
1497 if ( ( plPlotterPtr->tkwin == NULL ) || !Tk_IsMapped( tkwin ) )
1498 {
1499 plPlotterPtr->flags &= ~REFRESH_PENDING;
1500 return;
1501 }
1502
1503// All refresh events
1504
1505 if ( plPlotterPtr->flags & REFRESH_PENDING )
1506 {
1507 plPlotterPtr->flags &= ~REFRESH_PENDING;
1508
1509 // Reschedule resizes to avoid occasional ordering conflicts with
1510 // the packer's resize of the window (this call must come last).
1511
1512 if ( plPlotterPtr->flags & RESIZE_PENDING )
1513 {
1514 plPlotterPtr->flags |= REFRESH_PENDING;
1515 plPlotterPtr->flags &= ~RESIZE_PENDING;
1516 Tcl_DoWhenIdle( DisplayPlPlotter, clientData );
1517 return;
1518 }
1519
1520 // Redraw border if necessary
1521
1522 if ( ( plPlotterPtr->border != NULL ) &&
1523 ( plPlotterPtr->relief != TK_RELIEF_FLAT ) )
1524 {
1525 Tk_Draw3DRectangle( plPlotterPtr->tkwin, Tk_WindowId( tkwin ),
1526 plPlotterPtr->border, 0, 0, Tk_Width( tkwin ), Tk_Height( tkwin ),
1527 plPlotterPtr->borderWidth, plPlotterPtr->relief );
1528 }
1529
1530 // Redraw -- replay contents of plot buffer
1531
1532 if ( plPlotterPtr->flags & REDRAW_PENDING )
1533 {
1534 plPlotterPtr->flags &= ~REDRAW_PENDING;
1535 plsstrm( plPlotterPtr->ipls );
1536 pl_cmd( PLESC_REDRAW, (void *) NULL );
1537 }
1538
1539 // Resize -- if window bounds have changed
1540
1541 else if ( ( plPlotterPtr->width != plPlotterPtr->prevWidth ) ||
1542 ( plPlotterPtr->height != plPlotterPtr->prevHeight ) )
1543 {
1544 plPlotterPtr->pldis.width = (unsigned int) ( plPlotterPtr->width );
1545 plPlotterPtr->pldis.height = (unsigned int) ( plPlotterPtr->height );
1546
1547 plsstrm( plPlotterPtr->ipls );
1548 pl_cmd( PLESC_RESIZE, (void *) &( plPlotterPtr->pldis ) );
1549 plPlotterPtr->prevWidth = plPlotterPtr->width;
1550 plPlotterPtr->prevHeight = plPlotterPtr->height;
1551 }
1552
1553 // Expose -- if window bounds are unchanged
1554
1555 else
1556 {
1557 if ( plPlotterPtr->drawing_xhairs )
1558 {
1559 #ifdef MAC_TCL
1560 // For MacTk we just zap the whole window like this
1561 Tk_Draw3DRectangle( plPlotterPtr->tkwin, Tk_WindowId( tkwin ),
1562 plPlotterPtr->border, 0, 0, Tk_Width( tkwin ), Tk_Height( tkwin ),
1563 plPlotterPtr->borderWidth, plPlotterPtr->relief );
1564 #else
1565 XClearWindow( plPlotterPtr->display, Tk_WindowId( tkwin ) );
1566 #endif
1567 XFlush( plPlotterPtr->display );
1568 plsstrm( plPlotterPtr->ipls );
1569 pl_cmd( PLESC_EXPOSE, NULL );
1570 }
1571 else
1572 {
1573 plsstrm( plPlotterPtr->ipls );
1574 pl_cmd( PLESC_EXPOSE, (void *) &( plPlotterPtr->pldis ) );
1575 }
1576
1577 // Reset window bounds so that next time they are set fresh
1578
1579 plPlotterPtr->pldis.x = (unsigned int) ( Tk_X( tkwin ) + Tk_Width( tkwin ) );
1580 plPlotterPtr->pldis.y = (unsigned int) ( Tk_Y( tkwin ) + Tk_Height( tkwin ) );
1581 plPlotterPtr->pldis.width = (unsigned int) -Tk_Width( tkwin );
1582 plPlotterPtr->pldis.height = (unsigned int) -Tk_Height( tkwin );
1583 }
1584
1585 // Update graphic crosshairs if necessary
1586
1587 if ( plPlotterPtr->drawing_xhairs )
1588 {
1589 UpdateXhairs( plPlotterPtr );
1590 }
1591
1592 // Update rubber band if necessary.
1593
1594 if ( plPlotterPtr->drawing_rband )
1595 {
1596 UpdateRband( plPlotterPtr );
1597 }
1598 }
1599}
1600
1601//--------------------------------------------------------------------------
1602// Routines to process widget commands.
1603//--------------------------------------------------------------------------
1604
1605//--------------------------------------------------------------------------
1606// scol0
1607//
1608// Sets a color in cmap0.
1609//--------------------------------------------------------------------------
1610
1611static int
1612scol0( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1613 int i, CONST char *col, int *p_changed )
1614{
1615 PLStream *pls = plPlotterPtr->pls;
1616 XColor xcol;
1617 PLINT r, g, b;
1618
1619 if ( col == NULL )
1620 {
1621 Tcl_AppendResult( interp, "color value not specified",
1622 (char *) NULL );
1623 return TCL_ERROR;
1624 }
1625
1626 if ( !XParseColor( plPlotterPtr->display,
1627 Tk_Colormap( plPlotterPtr->tkwin ), col, &xcol ) )
1628 {
1629 Tcl_AppendResult( interp, "Couldn't parse color ", col,
1630 (char *) NULL );
1631 return TCL_ERROR;
1632 }
1633
1634 r = (unsigned) ( xcol.red & 0xFF00 ) >> 8;
1635 g = (unsigned) ( xcol.green & 0xFF00 ) >> 8;
1636 b = (unsigned) ( xcol.blue & 0xFF00 ) >> 8;
1637
1638 if ( ( pls->cmap0[i].r != r ) ||
1639 ( pls->cmap0[i].g != g ) ||
1640 ( pls->cmap0[i].b != b ) )
1641 {
1642 pls->cmap0[i].r = (unsigned char) r;
1643 pls->cmap0[i].g = (unsigned char) g;
1644 pls->cmap0[i].b = (unsigned char) b;
1645 *p_changed = 1;
1646 }
1647
1648 return TCL_OK;
1649}
1650
1651//--------------------------------------------------------------------------
1652// scol1
1653//
1654// Sets a color in cmap1.
1655//--------------------------------------------------------------------------
1656
1657static int
1658scol1( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1659 int i, CONST char *col, CONST char *pos, CONST char *rev, int *p_changed )
1660{
1661 PLStream *pls = plPlotterPtr->pls;
1662 XColor xcol;
1663 PLFLT h, l, s, r, g, b, p;
1664 int reverse;
1665
1666 if ( col == NULL )
1667 {
1668 Tcl_AppendResult( interp, "color value not specified",
1669 (char *) NULL );
1670 return TCL_ERROR;
1671 }
1672
1673 if ( pos == NULL )
1674 {
1675 Tcl_AppendResult( interp, "control point position not specified",
1676 (char *) NULL );
1677 return TCL_ERROR;
1678 }
1679
1680 if ( rev == NULL )
1681 {
1682 Tcl_AppendResult( interp, "interpolation sense not specified",
1683 (char *) NULL );
1684 return TCL_ERROR;
1685 }
1686
1687 if ( !XParseColor( plPlotterPtr->display,
1688 Tk_Colormap( plPlotterPtr->tkwin ), col, &xcol ) )
1689 {
1690 Tcl_AppendResult( interp, "Couldn't parse color ", col,
1691 (char *) NULL );
1692 return TCL_ERROR;
1693 }
1694
1695 r = (PLFLT) ( ( (unsigned) ( xcol.red & 0xFF00 ) >> 8 ) / 255.0 );
1696 g = (PLFLT) ( ( (unsigned) ( xcol.green & 0xFF00 ) >> 8 ) / 255.0 );
1697 b = (PLFLT) ( ( (unsigned) ( xcol.blue & 0xFF00 ) >> 8 ) / 255.0 );
1698
1699 plrgbhls( r, g, b, &h, &l, &s );
1700
1701 p = (PLFLT) ( atof( pos ) / 100.0 );
1702 reverse = atoi( rev );
1703
1704 if ( ( pls->cmap1cp[i].c1 != h ) ||
1705 ( pls->cmap1cp[i].c2 != l ) ||
1706 ( pls->cmap1cp[i].c3 != s ) ||
1707 ( pls->cmap1cp[i].p != p ) ||
1708 ( pls->cmap1cp[i].alt_hue_path != reverse ) )
1709 {
1710 pls->cmap1cp[i].c1 = h;
1711 pls->cmap1cp[i].c2 = l;
1712 pls->cmap1cp[i].c2 = s;
1713 pls->cmap1cp[i].p = p;
1714 pls->cmap1cp[i].alt_hue_path = reverse;
1715 *p_changed = 1;
1716 }
1717 return TCL_OK;
1718}
1719
1720//--------------------------------------------------------------------------
1721// Cmd
1722//
1723// Processes "cmd" widget command.
1724// Handles commands that go more or less directly to the PLplot library.
1725// Most of these come out of the PLplot Tcl API support file.
1726//--------------------------------------------------------------------------
1727
1728static int
1729Cmd( Tcl_Interp *interp, register PlPlotter *plPlotterPtr,
1730 int argc, CONST char **argv )
1731{
1732 PLStream *pls = plPlotterPtr->pls;
1733 int length;
1734 char c3;
1735 int result = TCL_OK;
1736 char cmdlist[] = "plgcmap0 plgcmap1 plscmap0 plscmap1 plscol0 plscol1";
1737 char * argv_cp;
1738
1739#ifdef DEBUG
1740 if ( pls->debug )
1741 {
1742 int i;
1743 fprintf( stderr, "There are %d arguments to Cmd:", argc );
1744 for ( i = 0; i < argc; i++ )
1745 {
1746 fprintf( stderr, " %s", argv[i] );
1747 }
1748 fprintf( stderr, "\n" );
1749 }
1750#endif
1751
1752// no option -- return list of available PLplot commands
1753
1754 if ( argc == 0 )
1755 return plTclCmd( cmdlist, interp, argc, argv );
1756
1757// Make sure widget has been initialized before going any further
1758
1759 if ( !plPlotterPtr->tkwin_initted )
1760 {
1761 Tcl_VarEval( plPlotterPtr->interp, "update", (char *) NULL );
1762 }
1763
1764// Set stream number and get ready to process the command
1765
1766 plsstrm( plPlotterPtr->ipls );
1767
1768 c3 = argv[0][2];
1769 length = (int) strlen( argv[0] );
1770
1771// plgcmap0 -- get color map 0
1772// first arg is number of colors, the rest are hex number specifications
1773
1774 if ( ( c3 == 'g' ) && ( strncmp( argv[0], "plgcmap0", (size_t) length ) == 0 ) )
1775 {
1776 int i;
1777 unsigned long plcolor;
1778 char str[10];
1779
1780 sprintf( str, "%d", (int) pls->ncol0 );
1781 Tcl_AppendElement( interp, str );
1782 for ( i = 0; i < pls->ncol0; i++ )
1783 {
1784 plcolor = (unsigned long) ( ( pls->cmap0[i].r << 16 ) |
1785 ( pls->cmap0[i].g << 8 ) |
1786 ( pls->cmap0[i].b ) );
1787
1788 sprintf( str, "#%06lx", ( plcolor & 0xFFFFFF ) );
1789 Tcl_AppendElement( interp, str );
1790 }
1791 result = TCL_OK;
1792 }
1793
1794// plgcmap1 -- get color map 1
1795// first arg is number of control points
1796// the rest are hex number specifications followed by positions (0-100)
1797
1798 else if ( ( c3 == 'g' ) && ( strncmp( argv[0], "plgcmap1", (size_t) length ) == 0 ) )
1799 {
1800 int i;
1801 unsigned long plcolor;
1802 char str[10];
1803 PLFLT h, l, s, r, g, b;
1804 int r1, g1, b1;
1805
1806 sprintf( str, "%d", (int) pls->ncp1 );
1807 Tcl_AppendElement( interp, str );
1808 for ( i = 0; i < pls->ncp1; i++ )
1809 {
1810 h = pls->cmap1cp[i].c1;
1811 l = pls->cmap1cp[i].c2;
1812 s = pls->cmap1cp[i].c3;
1813
1814 plhlsrgb( h, l, s, &r, &g, &b );
1815
1816 r1 = MAX( 0, MIN( 255, (int) ( 256. * r ) ) );
1817 g1 = MAX( 0, MIN( 255, (int) ( 256. * g ) ) );
1818 b1 = MAX( 0, MIN( 255, (int) ( 256. * b ) ) );
1819
1820 plcolor = (unsigned long) ( ( r1 << 16 ) | ( g1 << 8 ) | ( b1 ) );
1821
1822 sprintf( str, "#%06lx", ( plcolor & 0xFFFFFF ) );
1823 Tcl_AppendElement( interp, str );
1824
1825 sprintf( str, "%02d", (int) ( 100 * pls->cmap1cp[i].p ) );
1826 Tcl_AppendElement( interp, str );
1827
1828 sprintf( str, "%01d", (int) ( pls->cmap1cp[i].alt_hue_path ) );
1829 Tcl_AppendElement( interp, str );
1830 }
1831 result = TCL_OK;
1832 }
1833
1834// plscmap0 -- set color map 0
1835// first arg is number of colors, the rest are hex number specifications
1836
1837 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscmap0", (size_t) length ) == 0 ) )
1838 {
1839 int i, changed = 1, ncol0 = atoi( argv[1] );
1840 char *col;
1841
1842 if ( ncol0 > 16 || ncol0 < 1 )
1843 {
1844 Tcl_AppendResult( interp, "illegal number of colors in cmap0: ",
1845 argv[1], (char *) NULL );
1846 return TCL_ERROR;
1847 }
1848
1849 pls->ncol0 = ncol0;
1850 for ( i = 0; i < pls->ncol0; i++ )
1851 {
1852 argv_cp = plstrdup( argv[2 + i] );
1853 col = strtok( argv_cp, " " );
1854 if ( col == NULL )
1855 break;
1856
1857 if ( scol0( interp, plPlotterPtr, i, col, &changed ) != TCL_OK )
1858 return TCL_ERROR;
1859 free_mem( argv_cp );
1860 }
1861
1862 if ( changed )
1864 }
1865
1866// plscmap1 -- set color map 1
1867// first arg is number of colors, the rest are hex number specifications
1868
1869 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscmap1", (size_t) length ) == 0 ) )
1870 {
1871 int i, changed = 1, ncp1 = atoi( argv[1] );
1872 char *col, *pos, *rev;
1873
1874 if ( ncp1 > 32 || ncp1 < 1 )
1875 {
1876 Tcl_AppendResult( interp,
1877 "illegal number of control points in cmap1: ",
1878 argv[1], (char *) NULL );
1879 return TCL_ERROR;
1880 }
1881
1882 argv_cp = plstrdup( argv[2] );
1883 col = strtok( argv_cp, " " );
1884 pos = strtok( NULL, " " );
1885 rev = strtok( NULL, " " );
1886 for ( i = 0; i < ncp1; i++ )
1887 {
1888 if ( col == NULL )
1889 break;
1890
1891 if ( scol1( interp, plPlotterPtr,
1892 i, col, pos, rev, &changed ) != TCL_OK )
1893 return TCL_ERROR;
1894
1895 col = strtok( NULL, " " );
1896 pos = strtok( NULL, " " );
1897 rev = strtok( NULL, " " );
1898 }
1899
1900 free_mem( argv_cp );
1901
1902 if ( changed )
1903 {
1904 plsc->ncp1 = ncp1;
1905 plcmap1_calc();
1906 }
1907 }
1908
1909// plscol0 -- set single color in cmap0
1910// first arg is the color number, the next is the color in hex
1911
1912 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscol0", (size_t) length ) == 0 ) )
1913 {
1914 int i = atoi( argv[1] ), changed = 1;
1915
1916 if ( i > pls->ncol0 || i < 0 )
1917 {
1918 Tcl_AppendResult( interp, "illegal color number in cmap0: ",
1919 argv[1], (char *) NULL );
1920 return TCL_ERROR;
1921 }
1922
1923 if ( scol0( interp, plPlotterPtr, i, argv[2], &changed ) != TCL_OK )
1924 return TCL_ERROR;
1925
1926 if ( changed )
1928 }
1929
1930// plscol1 -- set color of control point in cmap1
1931// first arg is the control point, the next two are the color in hex and pos
1932
1933 else if ( ( c3 == 's' ) && ( strncmp( argv[0], "plscol1", (size_t) length ) == 0 ) )
1934 {
1935 int i = atoi( argv[1] ), changed = 1;
1936
1937 if ( i > pls->ncp1 || i < 0 )
1938 {
1939 Tcl_AppendResult( interp, "illegal control point number in cmap1: ",
1940 argv[1], (char *) NULL );
1941 return TCL_ERROR;
1942 }
1943
1944 if ( scol1( interp, plPlotterPtr,
1945 i, argv[2], argv[3], argv[4], &changed ) != TCL_OK )
1946 return TCL_ERROR;
1947
1948 if ( changed )
1949 plcmap1_calc();
1950 }
1951
1952// Added by Vince, disabled by default since we want a minimal patch
1953#ifdef USING_PLESC_COPY
1954// plcopy -- copy a region of the plot; useful for scrolling plots
1955// first 4 args are the source rectangle, next 2 args are the destination
1956
1957 else if ( ( c3 == 'c' ) && ( strncmp( argv[0], "plcopy", (size_t) length ) == 0 ) )
1958 {
1959 PLFLT xx[3], yy[3];
1960 if ( argc != 7 )
1961 {
1962 Tcl_AppendResult( interp, "Need exactly 6 arguments to copy.",
1963 (char *) NULL );
1964 return TCL_ERROR;
1965 }
1966 xx[0] = atof( argv[1] );
1967 yy[0] = atof( argv[2] );
1968 xx[1] = atof( argv[3] );
1969 yy[1] = atof( argv[4] );
1970 xx[2] = atof( argv[5] );
1971 yy[2] = atof( argv[6] );
1972 plcopy( xx, yy );
1973 }
1974#endif
1975
1976// unrecognized, so give it to plTclCmd to take care of
1977
1978 else
1979 result = plTclCmd( cmdlist, interp, argc, argv );
1980
1981 plflush();
1982 return result;
1983}
1984
1985static void ActiveState( register PlPlotter *plPlotterPtr, int on )
1986{
1987 if ( on )
1988 {
1989 if ( !plPlotterPtr->isActive )
1990 {
1991 Tk_CreateEventHandler( plPlotterPtr->tkwin, ButtonPressMask,
1992 PlPlotterButtonPressEH, (ClientData) plPlotterPtr );
1993
1994 Tk_CreateEventHandler( plPlotterPtr->tkwin, PointerMotionMask,
1995 PlPlotterMotionEH, (ClientData) plPlotterPtr );
1996
1997 Tk_CreateEventHandler( plPlotterPtr->tkwin, EnterWindowMask,
1998 PlPlotterEnterEH, (ClientData) plPlotterPtr );
1999
2000 Tk_CreateEventHandler( plPlotterPtr->tkwin, LeaveWindowMask,
2001 PlPlotterLeaveEH, (ClientData) plPlotterPtr );
2002 // Switch to crosshair cursor.
2003
2004 Tk_DefineCursor( plPlotterPtr->tkwin, plPlotterPtr->xhair_cursor );
2005 }
2006 }
2007 else
2008 {
2009 if ( plPlotterPtr->isActive )
2010 {
2011 Tk_DeleteEventHandler( plPlotterPtr->tkwin, ButtonPressMask,
2012 PlPlotterButtonPressEH, (ClientData) plPlotterPtr );
2013 Tk_DeleteEventHandler( plPlotterPtr->tkwin, PointerMotionMask,
2014 PlPlotterMotionEH, (ClientData) plPlotterPtr );
2015
2016 Tk_DeleteEventHandler( plPlotterPtr->tkwin, EnterWindowMask,
2017 PlPlotterEnterEH, (ClientData) plPlotterPtr );
2018
2019 Tk_DeleteEventHandler( plPlotterPtr->tkwin, LeaveWindowMask,
2020 PlPlotterLeaveEH, (ClientData) plPlotterPtr );
2021 // Switch back to boring old pointer
2022
2023 Tk_DefineCursor( plPlotterPtr->tkwin, plPlotterPtr->cursor );
2024 }
2025 }
2026}
2027
2028
2029//
2030//--------------------------------------------------------------------------
2031//
2032// 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
2050static int
2051ConfigurePlPlotter( 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 );
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 }
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
2193static int
2194Draw( 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
2292static int
2293Info( 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
2354static int
2355Openlink( 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
2439static int
2440Closelink( 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
2468static int
2469process_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
2507void 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
2517void 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
2534static int
2535ReadData( 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
2584static int
2585Orient( 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
2627static int
2628Print( 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
2720static int
2721NextPage( 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
2746static int
2747Page( 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
2787static int
2788Redraw( 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
2811static int
2812Save( 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
2943static int
2944View( 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
3077static int
3078Scroll( 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
3095static int
3096report( 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
3153static void
3154UpdateVScrollbar( 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
3179static void
3180UpdateHScrollbar( 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
3206static void
3207gbox( 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
#define b1
Definition: defines.h:18
#define MIN(a, b)
Definition: dsplint.c:29
#define MAX(a, b)
Definition: dsplint.c:28
int pdf_close(PDFstrm *pdfs)
Definition: pdfutils.c:238
PDFstrm * pdf_bopen(U_CHAR *buffer, size_t bufmax)
Definition: pdfutils.c:152
void plP_state(PLINT op)
Definition: plcore.c:256
void pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1737
void plgpls(PLStream **p_pls)
Definition: plcore.c:3693
void plsxwin(PLINT window_id)
Definition: plcore.c:3978
void plsfile(FILE *file)
Definition: plcore.c:3802
void pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1691
void plgFileDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition: plcore.c:3530
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
static PLINT ipls
Definition: plcore.h:86
void plcmap1_calc(void)
Bin up cmap 1 space and assign colors to make inverse mapping easy.
Definition: plctrl.c:764
char * plFindCommand(PLCHAR_VECTOR fn)
Definition: plctrl.c:2146
void pl_cmd(PLINT op, void *ptr)
Definition: plctrl.c:2118
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition: plctrl.c:2985
#define Tk_Cursor
Definition: plframe.c:80
PLINT plTranslateCursor(PLGraphicsIn *plg)
Definition: plpage.c:259
#define PLSTATE_CMAP0
Definition: plplotP.h:366
#define snprintf
Definition: plplotP.h:235
#define free_mem(a)
Definition: plplotP.h:182
#define PLESC_EXPOSE
Definition: plplot.h:274
#define plgdiplt
Definition: plplot.h:732
#define plinit
Definition: plplot.h:755
float PLFLT
Definition: plplot.h:163
#define plrgbhls
Definition: plplot.h:789
#define plbop
Definition: plplot.h:696
#define plgdidev
Definition: plplot.h:730
#define plgdiori
Definition: plplot.h:731
#define plspause
Definition: plplot.h:834
#define plhlsrgb
Definition: plplot.h:752
#define plsdev
Definition: plplot.h:806
#define PL_UNUSED(x)
Definition: plplot.h:138
#define plsdiplz
Definition: plplot.h:811
#define plsdiori
Definition: plplot.h:809
#define PLESC_RESIZE
Definition: plplot.h:275
#define plsstrm
Definition: plplot.h:835
#define plsdiplt
Definition: plplot.h:810
#define plcpstrm
Definition: plplot.h:707
#define plmkstrm
Definition: plplot.h:772
#define pladv
Definition: plplot.h:692
int PLINT
Definition: plplot.h:181
#define plend1
Definition: plplot.h:710
#define plsdidev
Definition: plplot.h:807
#define plflush
Definition: plplot.h:719
#define plreplot
Definition: plplot.h:788
#define PLESC_REDRAW
Definition: plplot.h:276
static void UpdateXhairs(PlPlotter *)
Definition: plplotter.c:1231
static int Closelink(Tcl_Interp *, PlPlotter *, int, CONST char **)
static int Page(Tcl_Interp *, PlPlotter *, int, CONST char **)
static int Save(Tcl_Interp *, PlPlotter *, int, CONST char **)
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
static int Info(Tcl_Interp *, PlPlotter *, int, CONST char **)
static int Cmd(Tcl_Interp *, PlPlotter *, int, CONST char **)
static void PlPlotterInit(ClientData)
Definition: plplotter.c:1388
static int Scroll(Tcl_Interp *, PlPlotter *)
static void DrawRband(PlPlotter *, int, int)
Definition: plplotter.c:1318
static int ConfigurePlPlotter(Tcl_Interp *, PlPlotter *, int, CONST char **, int)
#define DEF_PLFRAME_CURSOR
Definition: plplotter.c:217
#define REDRAW_PENDING
Definition: plplotter.c:208
static void Install_cmap(PlPlotter *plPlotterPtr)
Definition: plplotter.c:1426
#define UPDATE_H_SCROLLBAR
Definition: plplotter.c:210
static void PlPlotterFirstInit(ClientData clientData)
Definition: plplotter.c:1347
static void PlPlotterExposeEH(ClientData, XEvent *)
static Tk_ConfigSpec configSpecs[]
Definition: plplotter.c:224
#define DEF_PLFRAME_HEIGHT
Definition: plplotter.c:218
void PlplotterAtEop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2507
static void DestroyPlPlotter(ClientData)
Definition: plplotter.c:806
#define UPDATE_V_SCROLLBAR
Definition: plplotter.c:209
#define REFRESH_PENDING
Definition: plplotter.c:206
static void gbox(PLFLT *, PLFLT *, PLFLT *, PLFLT *, CONST char **)
Definition: plplotter.c:3207
static void DestroyXhairs(PlPlotter *)
Definition: plplotter.c:1191
static int Orient(Tcl_Interp *, PlPlotter *, int, CONST char **)
static void UpdateHScrollbar(register PlPlotter *)
Definition: plplotter.c:3180
static int Openlink(Tcl_Interp *, PlPlotter *, int, CONST char **)
static int scol0(Tcl_Interp *interp, register PlPlotter *plPlotterPtr, int i, CONST char *col, int *p_changed)
Definition: plplotter.c:1612
void PlplotterAtBop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2517
static void PlPlotterConfigureEH(ClientData, XEvent *)
static int Draw(Tcl_Interp *, PlPlotter *, int, CONST char **)
static void PlPlotterEnterEH(ClientData, register XEvent *)
Definition: plplotter.c:1071
#define DEF_PLFRAME_BORDER_WIDTH
Definition: plplotter.c:216
static void DrawXhairs(PlPlotter *, int, int)
Definition: plplotter.c:1206
#define DEF_PLFRAME_RELIEF
Definition: plplotter.c:219
int plPlotterCmd(ClientData, Tcl_Interp *, int, const char **)
#define DEF_PLFRAME_BG_COLOR
Definition: plplotter.c:214
static void CreateRband(PlPlotter *)
Definition: plplotter.c:1251
static int Redraw(Tcl_Interp *, PlPlotter *, int, CONST char **)
static void ActiveState(register PlPlotter *plPlotterPtr, int on)
Definition: plplotter.c:1985
#define NDEV
Definition: plplotter.c:93
static void UpdateRband(PlPlotter *)
Definition: plplotter.c:1337
static int ReadData(ClientData, int)
Definition: plplotter.c:2535
static int Print(Tcl_Interp *, PlPlotter *, int, CONST char **)
#define RESIZE_PENDING
Definition: plplotter.c:207
static void CreateXhairs(PlPlotter *)
Definition: plplotter.c:1153
#define DEF_PLFRAME_BG_MONO
Definition: plplotter.c:215
static void DestroyRband(PlPlotter *)
Definition: plplotter.c:1303
static int View(Tcl_Interp *, PlPlotter *, int, CONST char **)
static void UpdateVScrollbar(register PlPlotter *)
Definition: plplotter.c:3154
static void PlPlotterLeaveEH(ClientData, register XEvent *)
static void DisplayPlPlotter(ClientData)
Definition: plplotter.c:1476
static int report(Tcl_Interp *, PlPlotter *, int, CONST char **)
#define DEF_PLFRAME_WIDTH
Definition: plplotter.c:220
static int NextPage(Tcl_Interp *, PlPlotter *, int, CONST char **)
static int process_data(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2469
static int PlPlotterWidgetCmd(ClientData, Tcl_Interp *, int, CONST char **)
Definition: plplotter.c:503
static void PlPlotterMotionEH(ClientData, register XEvent *)
Definition: plplotter.c:1037
static void PlPlotterButtonPressEH(ClientData clientData, register XEvent *)
Definition: plplotter.c:1127
int plr_process(PLRDev *plr)
Definition: plr.c:115
void plr_start(PLRDev *plr)
Definition: plr.c:95
static int child
Definition: plserver.c:45
FILE * pl_create_tempfile(char **fname)
Definition: plstdio.c:240
PLDLLIMPEXP_TCLTK int plTclCmd(char *cmdlist, Tcl_Interp *interp, int argc, const char **argv)
Definition: tclAPI.c:289
void pltkwin_setBGFG(PLStream *pls)
static int plplot_tkwin_ccmap
Definition: pltkwd.h:41
int PLColor_from_TkColor_Changed(PLColor *plcolor, XColor *xcolor)
void plD_open_tkwin(PLStream *pls)
static int argc
Definition: qt.cpp:48
static char ** argv
Definition: qt.cpp:49
Definition: pdf.h:50
size_t bp
Definition: pdf.h:56
unsigned char r
Definition: plplot.h:548
unsigned char g
Definition: plplot.h:549
unsigned char b
Definition: plplot.h:550
PLFLT c1
Definition: plplot.h:559
PLFLT c2
Definition: plplot.h:560
PLFLT c3
Definition: plplot.h:561
PLFLT p
Definition: plplot.h:562
int alt_hue_path
Definition: plplot.h:564
unsigned int y
Definition: plplot.h:461
unsigned int x
Definition: plplot.h:461
unsigned int height
Definition: plplot.h:462
unsigned int width
Definition: plplot.h:462
int at_eop
Definition: plserver.h:22
int at_bop
Definition: plserver.h:22
int nbytes
Definition: plserver.h:21
PLiodev * iodev
Definition: plserver.h:20
PDFstrm * pdfs
Definition: plserver.h:19
PLINT ncp1
Definition: plstrm.h:539
PLINT ncol0
Definition: plstrm.h:539
PLColor * cmap0
Definition: plstrm.h:544
PLINT debug
Definition: plstrm.h:527
int nopixmap
Definition: plstrm.h:635
int db
Definition: plstrm.h:635
struct PlPlotter * plPlotterPtr
Definition: plstrm.h:742
void * dev
Definition: plstrm.h:594
PLControlPt cmap1cp[PL_MAX_CMAP1CP]
Definition: plstrm.h:547
Definition: pdf.h:62
int fd
Definition: pdf.h:63
int type
Definition: pdf.h:67
FILE * file
Definition: pdf.h:64
const char * fileHandle
Definition: pdf.h:66
const char * typeName
Definition: pdf.h:68
int width
Definition: plplotter.c:119
int xhairs
Definition: plplotter.c:179
PLDisplay pldis
Definition: plplotter.c:145
int drawing_rband
Definition: plplotter.c:187
char * yScrollCmd
Definition: plplotter.c:168
int double_buffer
Definition: plplotter.c:189
PLStream * pls
Definition: plplotter.c:132
char * plpr_cmd
Definition: plplotter.c:137
int prevHeight
Definition: plplotter.c:147
PLRDev * plr
Definition: plplotter.c:136
int tkwin_initted
Definition: plplotter.c:131
int borderWidth
Definition: plplotter.c:117
XPoint rband_pt[2]
Definition: plplotter.c:188
PLFLT xl
Definition: plplotter.c:164
XPoint xhair_x[2]
Definition: plplotter.c:181
int continue_draw
Definition: plplotter.c:162
int active_plot
Definition: plplotter.c:140
char * bopCmd
Definition: plplotter.c:174
char * SaveFnam
Definition: plplotter.c:151
int relief
Definition: plplotter.c:118
Tk_3DBorder border
Definition: plplotter.c:115
Tk_Cursor xhair_cursor
Definition: plplotter.c:163
PLFLT yr
Definition: plplotter.c:164
Tcl_Interp * interp
Definition: plplotter.c:111
int height
Definition: plplotter.c:121
const char ** devName
Definition: plplotter.c:155
char * eopCmd
Definition: plplotter.c:175
const char ** devDesc
Definition: plplotter.c:153
PLFLT xr
Definition: plplotter.c:164
Display * display
Definition: plplotter.c:108
XPoint pts[5]
Definition: plplotter.c:161
Tcl_Command widgetCmd
Definition: plplotter.c:114
int prevWidth
Definition: plplotter.c:146
PLFLT yl
Definition: plplotter.c:164
PLINT ipls
Definition: plplotter.c:133
int flags
Definition: plplotter.c:124
XPoint xhair_y[2]
Definition: plplotter.c:182
char * xScrollCmd
Definition: plplotter.c:165
Tk_Window tkwin
Definition: plplotter.c:104
int drawing_xhairs
Definition: plplotter.c:180
PLINT ipls_save
Definition: plplotter.c:134
int isActive
Definition: plplotter.c:141
int rband
Definition: plplotter.c:186
Tk_Cursor cursor
Definition: plplotter.c:123
Definition: pltkwd.h:69
unsigned width
Definition: pltkwd.h:82
int flags
Definition: pltkwd.h:78
int write_to_window
Definition: pltkwd.h:91
unsigned height
Definition: pltkwd.h:82
TkwDisplay * tkwd
Definition: pltkwd.h:70
PLGraphicsIn gin
Definition: pltkwd.h:97
Colormap map
Definition: pltkwd.h:55
#define dbug_enter(a)
Definition: tclMatrix.c:59
PLDLLIMPEXP_TCLTK int pl_PacketReceive(Tcl_Interp *interp, PLiodev *iodev, PDFstrm *pdfs)
static Tcl_Interp * interp
Definition: tkMain.c:120