PLplot  5.15.0
tkwin.c
Go to the documentation of this file.
1 // PLplot Tk device driver.
2 //
3 // Copyright (C) 2004 Maurice LeBrun
4 // Copyright (C) 2004 Joao Cardoso
5 //
6 // This file is part of PLplot.
7 //
8 // PLplot is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU Library General Public License as published
10 // by the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // PLplot is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public License
19 // along with PLplot; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 // This device driver is designed to be used by a PlPlotter, and in fact requires
23 // the existence of an enclosing PlPlotter.
24 //
25 // The idea is that this should develop into a completely cross-platform driver
26 // for use by the cross platform Tk system.
27 //
28 //
29 
30 #include "plDevs.h"
31 
32 #define DEBUG
33 
34 #ifdef PLD_tkwin
35 
36 
37 #define NEED_PLDEBUG
38 #include "plplotP.h"
39 #include "pltkwd.h"
40 #include "drivers.h"
41 #include "plevent.h"
42 
43 #define _TCLINT
44 #ifdef USE_TCL_STUBS
45 // Unfortunately, tkInt.h ends up loading Malloc.h under Windows
46 // So we have to deal with this mess
47  #undef malloc
48  #undef free
49  #undef realloc
50  #undef calloc
51 #if defined ( _WIN32 ) || defined ( MAC_TCL )
52 #include <tkInt.h>
53 #else
54 #include <tk.h>
55 #endif
56  #define malloc ckalloc
57  #define free( m ) ckfree( (char *) m )
58  #define realloc ckrealloc
59  #define calloc ckcalloc
60 #else
61 #if defined ( _WIN32 ) || defined ( MAC_TCL )
62 #include <tkInt.h>
63 #else
64 #include <tk.h>
65 #endif
66 #endif
67 
68 #ifdef ckalloc
69 #undef ckalloc
70 #define ckalloc malloc
71 #endif
72 #ifdef ckfree
73 #undef ckfree
74 #define ckfree free
75 #endif
76 #ifdef free
77 #undef free
78 #endif
79 
80 // Device info
81 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_tkwin = "tkwin:New tk driver:1:tkwin:45:tkwin\n";
82 
83 
84 void * ckcalloc( size_t nmemb, size_t size );
85 
86 //
87 // We want to use the 'pure Tk' interface. On Unix we can use
88 // some direct calls to X instead of Tk, if we want, although
89 // that code hasn't been tested for some time. So this define
90 // is required on Windows/MacOS and perhaps optional on Unix.
91 //
92 #define USE_TK
93 
94 #ifdef _WIN32
95 #define XSynchronize( display, bool ) { display->request++; }
96 #define XSync( display, bool ) { display->request++; }
97 #define XFlush( display )
98 #endif
99 
100 // Dummy definition of PlPlotter containing first few fields
101 typedef struct PlPlotter
102 {
103  Tk_Window tkwin; // Window that embodies the frame. NULL
104  // means that the window has been destroyed
105  // but the data structures haven't yet been
106  // cleaned up.
107  //
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  //
112  Tcl_Interp *interp; // Interpreter associated with
113  // widget. Used to delete widget
114  // command.
115  //
116 } PlPlotter;
117 
118 void CopyColour( XColor* from, XColor* to );
119 void Tkw_StoreColor( PLStream* pls, TkwDisplay* tkwd, XColor* col );
120 static int pltk_AreWeGrayscale( PlPlotter *plf );
121 void PlplotterAtEop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
122 void PlplotterAtBop( Tcl_Interp *interp, register PlPlotter *plPlotterPtr );
123 
124 static int synchronize = 0; // change to 1 for synchronized operation
125 // for debugging only
126 
127 // Number of instructions to skip between querying the X server for events
128 
129 #define MAX_INSTR 20
130 
131 // Pixels/mm
132 
133 #define PHYSICAL 0 // Enables physical scaling..
134 
135 // Set constants for dealing with colormap. In brief:
136 //
137 // ccmap When set, turns on custom color map
138 //
139 // XWM_COLORS Number of low "pixel" values to copy.
140 // CMAP0_COLORS Color map 0 entries.
141 // CMAP1_COLORS Color map 1 entries.
142 // MAX_COLORS Maximum colors period.
143 //
144 // See Init_CustomCmap() and Init_DefaultCmap() for more info.
145 // Set ccmap at your own risk -- still under development.
146 //
147 
148 // plplot_tkwin_ccmap is statically defined in pltkwd.h. Note that
149 // plplotter.c also includes that header and uses that variable.
150 
151 #define XWM_COLORS 70
152 #define CMAP0_COLORS 16
153 #define CMAP1_COLORS 50
154 #define MAX_COLORS 256
155 
156 #ifndef USE_TK
157 // Variables to hold RGB components of given colormap.
158 // Used in an ugly hack to get past some X11R5 and TK limitations.
159 
160 static int sxwm_colors_set;
161 static XColor sxwm_colors[MAX_COLORS];
162 #endif
163 
164 // Keep pointers to all the displays in use
165 
166 static TkwDisplay *tkwDisplay[PLTKDISPLAYS];
167 
168 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
169 static unsigned char CreatePixmapStatus;
170 static int CreatePixmapErrorHandler( Display *display, XErrorEvent *error );
171 #endif
172 
173 // Function prototypes
174 // Initialization
175 
176 static void Init( PLStream *pls );
177 static void InitColors( PLStream *pls );
178 static void AllocCustomMap( PLStream *pls );
179 static void AllocCmap0( PLStream *pls );
180 static void AllocCmap1( PLStream *pls );
181 static void CreatePixmap( PLStream *pls );
182 static void GetVisual( PLStream *pls );
183 static void AllocBGFG( PLStream *pls );
184 
185 // Escape function commands
186 
187 static void ExposeCmd( PLStream *pls, PLDisplay *ptr );
188 static void RedrawCmd( PLStream *pls );
189 static void ResizeCmd( PLStream *pls, PLDisplay *ptr );
190 #ifndef USE_TK
191 static void GetCursorCmd( PLStream *pls, PLGraphicsIn *ptr );
192 #endif
193 static void FillPolygonCmd( PLStream *pls );
194 #ifdef USING_PLESC_COPY
195 static void CopyCommand( PLStream *pls );
196 #endif
197 
198 // Miscellaneous
199 
200 static void StoreCmap0( PLStream *pls );
201 static void StoreCmap1( PLStream *pls );
202 static void WaitForPage( PLStream *pls );
203 
205 
206 void plD_init_tkwin( PLStream * );
207 void plD_line_tkwin( PLStream *, short, short, short, short );
208 void plD_polyline_tkwin( PLStream *, short *, short *, PLINT );
209 void plD_eop_tkwin( PLStream * );
210 void plD_bop_tkwin( PLStream * );
211 void plD_tidy_tkwin( PLStream * );
212 void plD_state_tkwin( PLStream *, PLINT );
213 void plD_esc_tkwin( PLStream *, PLINT, void * );
214 void plD_wait_tkwin( PLStream * );
215 void plD_open_tkwin( PLStream *pls );
216 
218 {
219 #ifndef ENABLE_DYNDRIVERS
220  pdt->pl_MenuStr = "PLplot Tk plotter";
221  pdt->pl_DevName = "tkwin";
222 #endif
224  pdt->pl_seq = 45;
225  pdt->pl_init = (plD_init_fp) plD_init_tkwin;
226  pdt->pl_line = (plD_line_fp) plD_line_tkwin;
227  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_tkwin;
228  pdt->pl_eop = (plD_eop_fp) plD_eop_tkwin;
229  pdt->pl_bop = (plD_bop_fp) plD_bop_tkwin;
230  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_tkwin;
231  pdt->pl_state = (plD_state_fp) plD_state_tkwin;
232  pdt->pl_esc = (plD_esc_fp) plD_esc_tkwin;
233  pdt->pl_wait = (plD_wait_fp) plD_wait_tkwin;
234 }
235 
236 //--------------------------------------------------------------------------
237 // plD_init_tkwin()
238 //
239 // Initialize device.
240 // Tk-dependent stuff done in plD_open_tkwin() and Init().
241 //--------------------------------------------------------------------------
242 
243 void
244 plD_init_tkwin( PLStream *pls )
245 {
246  TkwDev *dev;
247  float pxlx, pxly;
248  int xmin = 0;
249  int xmax = PIXELS_X - 1;
250  int ymin = 0;
251  int ymax = PIXELS_Y - 1;
252 
253  dbug_enter( "plD_init_tkw" );
254 
255  pls->termin = 1; // Is an interactive terminal
256  pls->dev_flush = 1; // Handle our own flushes
257  pls->dev_fill0 = 1; // Handle solid fills
258  pls->plbuf_write = 1; // Activate plot buffer
259 
260  // The real meat of the initialization done here
261 
262  if ( pls->dev == NULL )
263  plD_open_tkwin( pls );
264 
265  dev = (TkwDev *) pls->dev;
266 
267  Init( pls );
268 
269  // Get ready for plotting
270 
271  dev->xlen = (short) ( xmax - xmin );
272  dev->ylen = (short) ( ymax - ymin );
273 
274  dev->xscale_init = (double) dev->init_width / (double) dev->xlen;
275  dev->yscale_init = (double) dev->init_height / (double) dev->ylen;
276 
277  dev->xscale = dev->xscale_init;
278  dev->yscale = dev->yscale_init;
279 
280 #if PHYSICAL
281  pxlx = (PLFLT) ( (double) PIXELS_X / dev->width * DPMM );
282  pxly = (PLFLT) ( (double) PIXELS_Y / dev->height * DPMM );
283 #else
284  pxlx = (PLFLT) ( (double) PIXELS_X / LPAGE_X );
285  pxly = (PLFLT) ( (double) PIXELS_Y / LPAGE_Y );
286 #endif
287 
288  plP_setpxl( pxlx, pxly );
289  plP_setphy( xmin, xmax, ymin, ymax );
290 }
291 
292 //--------------------------------------------------------------------------
293 // plD_open_tkwin()
294 //
295 // Performs basic driver initialization, without actually opening or
296 // modifying a window. May be called by the outside world before plinit
297 // in case the caller needs early access to the driver internals (not
298 // very common -- currently only used externally by plplotter).
299 //--------------------------------------------------------------------------
300 
301 void
302 plD_open_tkwin( PLStream *pls )
303 {
304  TkwDev *dev;
305  TkwDisplay *tkwd;
306  int i;
307 
308  dbug_enter( "plD_open_tkw" );
309 
310  // Allocate and initialize device-specific data
311 
312  if ( pls->dev != NULL )
313  plwarn( "plD_open_tkw: device pointer is already set" );
314 
315  pls->dev = (TkwDev *) calloc( 1, (size_t) sizeof ( TkwDev ) );
316  if ( pls->dev == NULL )
317  plexit( "plD_init_tkw: Out of memory." );
318 
319  dev = (TkwDev *) pls->dev;
320 
321  // Variables used in querying the X server for events
322 
323  dev->instr = 0;
324  dev->max_instr = MAX_INSTR;
325 
326  // See if display matches any already in use, and if so use that
327 
328  dev->tkwd = NULL;
329  for ( i = 0; i < PLTKDISPLAYS; i++ )
330  {
331  if ( tkwDisplay[i] == NULL )
332  {
333  continue;
334  }
335  else if ( pls->FileName == NULL && tkwDisplay[i]->displayName == NULL )
336  {
337  dev->tkwd = tkwDisplay[i];
338  break;
339  }
340  else if ( pls->FileName == NULL || tkwDisplay[i]->displayName == NULL )
341  {
342  continue;
343  }
344  else if ( strcmp( tkwDisplay[i]->displayName, pls->FileName ) == 0 )
345  {
346  dev->tkwd = tkwDisplay[i];
347  break;
348  }
349  }
350 
351  // If no display matched, create a new one
352 
353  if ( dev->tkwd == NULL )
354  {
355  dev->tkwd = (TkwDisplay *) calloc( 1, (size_t) sizeof ( TkwDisplay ) );
356  if ( dev->tkwd == NULL )
357  plexit( "Init: Out of memory." );
358 
359  for ( i = 0; i < PLTKDISPLAYS; i++ )
360  {
361  if ( tkwDisplay[i] == NULL )
362  break;
363  }
364  if ( i == PLTKDISPLAYS )
365  plexit( "Init: Out of tkwDisplay's." );
366 
367  tkwDisplay[i] = tkwd = (TkwDisplay *) dev->tkwd;
368  tkwd->nstreams = 1;
369 
370  //
371  // If we don't have a tk widget we're being called on, then
372  // abort operations now
373  //
374  if ( pls->plPlotterPtr == NULL )
375  {
376  plexit( "No tk plframe widget to connect to" );
377  }
378  // Old version for MacOS Tk8.0
379  //
380  // char deflt[] = "Macintosh:0";
381  // pls->FileName = deflt;
382  // tkwd->display = (Display*) TkpOpenDisplay(pls->FileName);
383  //
384 
385  // Open display
386 #if defined ( MAC_TCL ) || defined ( _WIN32 )
387  if ( !pls->FileName )
388  {
389  //
390  // Need to strdup because Tk has allocated the screen name,
391  // but we will actually 'free' it later ourselves, and therefore
392  // need to own the memory.
393  //
394  pls->FileName = plstrdup( TkGetDefaultScreenName( NULL, NULL ) );
395  }
396  tkwd->display = pls->plPlotterPtr->display;
397 #else
398  tkwd->display = XOpenDisplay( pls->FileName );
399 #endif
400  if ( tkwd->display == NULL )
401  {
402  plexit( "Can't open display" );
403  }
404  tkwd->displayName = pls->FileName;
405  tkwd->screen = DefaultScreen( tkwd->display );
406  if ( synchronize )
407  {
408  XSynchronize( tkwd->display, 1 );
409  }
410  // Get colormap and visual
411 
412  tkwd->map = Tk_Colormap( pls->plPlotterPtr->tkwin );
413  GetVisual( pls );
414 
415  //
416  // Figure out if we have a color display or not.
417  // Default is color IF the user hasn't specified and IF the output device is
418  // not grayscale.
419  //
420 
421  if ( pls->colorset )
422  tkwd->color = pls->color;
423  else
424  {
425  pls->color = 1;
426  tkwd->color = !pltk_AreWeGrayscale( pls->plPlotterPtr );
427  }
428 
429  // Allocate & set background and foreground colors
430 
431  AllocBGFG( pls );
432  pltkwin_setBGFG( pls );
433  }
434 
435  // Display matched, so use existing display data
436 
437  else
438  {
439  tkwd = (TkwDisplay *) dev->tkwd;
440  tkwd->nstreams++;
441  }
442  tkwd->ixwd = i;
443 }
444 
445 //--------------------------------------------------------------------------
446 // plD_line_tkwin()
447 //
448 // Draw a line in the current color from (x1,y1) to (x2,y2).
449 //--------------------------------------------------------------------------
450 
451 void
452 plD_line_tkwin( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
453 {
454  TkwDev *dev = (TkwDev *) pls->dev;
455  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
456 
457  int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
458 
459  if ( dev->flags & 1 )
460  return;
461 
462  y1 = dev->ylen - y1;
463  y2 = dev->ylen - y2;
464 
465  x1 = (int) ( x1 * dev->xscale );
466  x2 = (int) ( x2 * dev->xscale );
467  y1 = (int) ( y1 * dev->yscale );
468  y2 = (int) ( y2 * dev->yscale );
469 
470  if ( dev->write_to_window )
471  XDrawLine( tkwd->display, dev->window, dev->gc, x1, y1, x2, y2 );
472 
473  if ( dev->write_to_pixmap )
474  XDrawLine( tkwd->display, dev->pixmap, dev->gc, x1, y1, x2, y2 );
475 }
476 
477 //--------------------------------------------------------------------------
478 // plD_polyline_tkwin()
479 //
480 // Draw a polyline in the current color from (x1,y1) to (x2,y2).
481 //--------------------------------------------------------------------------
482 
483 void
484 plD_polyline_tkwin( PLStream *pls, short *xa, short *ya, PLINT npts )
485 {
486  TkwDev *dev = (TkwDev *) pls->dev;
487  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
488 
489  PLINT i;
490  XPoint _pts[PL_MAXPOLY];
491  XPoint *pts;
492 
493  if ( dev->flags & 1 )
494  return;
495 
496  if ( npts > PL_MAXPOLY )
497  {
498  pts = (XPoint *) malloc( sizeof ( XPoint ) * (size_t) npts );
499  }
500  else
501  {
502  pts = _pts;
503  }
504 
505  for ( i = 0; i < npts; i++ )
506  {
507  pts[i].x = (short) ( dev->xscale * xa[i] );
508  pts[i].y = (short) ( dev->yscale * ( dev->ylen - ya[i] ) );
509  }
510 
511  if ( dev->write_to_window )
512  XDrawLines( tkwd->display, dev->window, dev->gc, pts, npts,
513  CoordModeOrigin );
514 
515  if ( dev->write_to_pixmap )
516  XDrawLines( tkwd->display, dev->pixmap, dev->gc, pts, npts,
517  CoordModeOrigin );
518 
519  if ( npts > PL_MAXPOLY )
520  {
521  free( pts );
522  }
523 }
524 
525 //--------------------------------------------------------------------------
526 // plD_eop_tkwin()
527 //
528 // End of page.
529 //--------------------------------------------------------------------------
530 
531 void
532 plD_eop_tkwin( PLStream *pls )
533 {
534  TkwDev *dev = (TkwDev *) pls->dev;
535  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
536 
537  dbug_enter( "plD_eop_tkw" );
538  if ( dev->flags & 1 )
539  return;
540 
541  XFlush( tkwd->display );
542  if ( pls->db )
543  ExposeCmd( pls, NULL );
544 }
545 
546 //--------------------------------------------------------------------------
547 // plD_wait_tkwin()
548 //
549 // User must hit return (or third mouse button) to continue.
550 //--------------------------------------------------------------------------
551 
552 void
553 plD_wait_tkwin( PLStream *pls )
554 {
555  TkwDev *dev = (TkwDev *) pls->dev;
556  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
557 
558  dbug_enter( "plD_wait_tkw" );
559  if ( dev->flags & 1 )
560  return;
561 
562  WaitForPage( pls );
563 }
564 
565 //--------------------------------------------------------------------------
566 // WaitForPage()
567 //
568 // This routine waits for the user to advance the plot, while handling
569 // all other events.
570 //--------------------------------------------------------------------------
571 
572 static void
573 WaitForPage( PLStream *pls )
574 {
575  PlPlotter *plf = pls->plPlotterPtr;
576  TkwDev *dev = (TkwDev *) pls->dev;
577 
578  dbug_enter( "WaitForPage" );
579 
580  dev->flags &= 1;
581  if ( plf == NULL )
582  {
583  plwarn( "WaitForPage: Illegal call --- driver can't find enclosing PlPlotter" );
584  return;
585  }
586  PlplotterAtEop( plf->interp, plf );
587 
588  while ( !( dev->flags ) && !Tcl_InterpDeleted( plf->interp ) && ( Tk_GetNumMainWindows() > 0 ) )
589  {
590  Tcl_DoOneEvent( 0 );
591  }
592 
593  if ( Tcl_InterpDeleted( plf->interp ) || ( Tk_GetNumMainWindows() <= 0 ) )
594  {
595  dev->flags |= 1;
596  }
597 
598  dev->flags &= 1;
599 }
600 
601 //--------------------------------------------------------------------------
602 // plD_bop_tkwin()
603 //
604 // Set up for the next page.
605 //--------------------------------------------------------------------------
606 
607 void
608 plD_bop_tkwin( PLStream *pls )
609 {
610  PlPlotter *plf = pls->plPlotterPtr;
611  TkwDev *dev = (TkwDev *) pls->dev;
612  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
613 
614  XRectangle xrect;
615  xrect.x = 0; xrect.y = 0;
616  xrect.width = (short unsigned) dev->width;
617  xrect.height = (short unsigned) dev->height;
618 
619  dbug_enter( "plD_bop_tkw" );
620  if ( dev->flags & 1 )
621  return;
622 
623  if ( dev->write_to_window )
624  {
625 #ifdef MAC_TCL
626  // MacTk only has these X calls
627  XSetForeground( tkwd->display, dev->gc, tkwd->cmap0[0].pixel );
628  XFillRectangles( tkwd->display, dev->window, dev->gc, &xrect, 1 );
629  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
630 #else
631  XClearWindow( tkwd->display, dev->window );
632 #endif
633  }
634  if ( dev->write_to_pixmap )
635  {
636  XSetForeground( tkwd->display, dev->gc, tkwd->cmap0[0].pixel );
637  XFillRectangles( tkwd->display, dev->pixmap, dev->gc, &xrect, 1 );
638  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
639  }
640  XSync( tkwd->display, 0 );
641  pls->page++;
642  PlplotterAtBop( plf->interp, plf );
643 }
644 
645 //--------------------------------------------------------------------------
646 // plD_tidy_tkwin()
647 //
648 // Close graphics file
649 //--------------------------------------------------------------------------
650 
651 void
652 plD_tidy_tkwin( PLStream *pls )
653 {
654  TkwDev *dev = (TkwDev *) pls->dev;
655  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
656 
657  dbug_enter( "plD_tidy_tkw" );
658 
659  tkwd->nstreams--;
660  if ( tkwd->nstreams == 0 )
661  {
662  int ixwd = tkwd->ixwd;
663  XFreeGC( tkwd->display, dev->gc );
664 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
665  XCloseDisplay( tkwd->display );
666 #endif
667  free_mem( tkwDisplay[ixwd] );
668  }
669  //
670  // Vince removed this November 1999. It seems as if a simple
671  // 'plframe .p ; destroy .p' leaves a temporary buf file open
672  // if we clear this flag here. It should be checked and then
673  // cleared by whoever called us. An alternative fix would
674  // be to carry out the check/tidy here. The plframe widget
675  // handles this stuff for us.
676  //
677  // pls->plbuf_write = 0;
678 }
679 
680 //--------------------------------------------------------------------------
681 // plD_state_tkwin()
682 //
683 // Handle change in PLStream state (color, pen width, fill attribute, etc).
684 //--------------------------------------------------------------------------
685 
686 void
687 plD_state_tkwin( PLStream *pls, PLINT op )
688 {
689  TkwDev *dev = (TkwDev *) pls->dev;
690  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
691  dbug_enter( "plD_state_tkw" );
692  if ( dev->flags & 1 )
693  return;
694 
695  switch ( op )
696  {
697  case PLSTATE_WIDTH:
698  break;
699 
700  case PLSTATE_COLOR0: {
701  int icol0 = pls->icol0;
702  if ( tkwd->color )
703  {
704  if ( icol0 == PL_RGB_COLOR )
705  {
706  PLColor_to_TkColor( &pls->curcolor, &dev->curcolor );
707  Tkw_StoreColor( pls, tkwd, &dev->curcolor );
708  }
709  else
710  {
711  dev->curcolor = tkwd->cmap0[icol0];
712  }
713  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
714  }
715  else
716  {
717  dev->curcolor = tkwd->fgcolor;
718  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
719  }
720  break;
721  }
722 
723  case PLSTATE_COLOR1: {
724  int icol1;
725 
726  if ( tkwd->ncol1 == 0 )
727  AllocCmap1( pls );
728 
729  if ( tkwd->ncol1 < 2 )
730  break;
731 
732  icol1 = ( pls->icol1 * ( tkwd->ncol1 - 1 ) ) / ( pls->ncol1 - 1 );
733  if ( tkwd->color )
734  dev->curcolor = tkwd->cmap1[icol1];
735  else
736  dev->curcolor = tkwd->fgcolor;
737 
738  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
739  break;
740  }
741 
742  case PLSTATE_CMAP0:
743  pltkwin_setBGFG( pls );
744  StoreCmap0( pls );
745  break;
746 
747  case PLSTATE_CMAP1:
748  StoreCmap1( pls );
749  break;
750  }
751 }
752 
753 //--------------------------------------------------------------------------
754 // plD_esc_tkwin()
755 //
756 // Escape function.
757 //
758 // Functions:
759 //
760 // PLESC_EH Handle pending events
761 // PLESC_EXPOSE Force an expose
762 // PLESC_FILL Fill polygon
763 // PLESC_FLUSH Flush X event buffer
764 // PLESC_GETC Get coordinates upon mouse click
765 // PLESC_REDRAW Force a redraw
766 // PLESC_RESIZE Force a resize
767 //--------------------------------------------------------------------------
768 
769 void
770 plD_esc_tkwin( PLStream *pls, PLINT op, void *ptr )
771 {
772  TkwDev *dev = (TkwDev *) pls->dev;
773 #ifndef USE_TK
774  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
775 #endif
776  dbug_enter( "plD_esc_tkw" );
777  if ( dev->flags & 1 )
778  return;
779 
780  switch ( op )
781  {
782  case PLESC_EH:
783 #ifndef USE_TK
784  HandleEvents( pls );
785 #endif
786  break;
787 
788  case PLESC_EXPOSE:
789  ExposeCmd( pls, (PLDisplay *) ptr );
790  break;
791 
792  case PLESC_FILL:
793  FillPolygonCmd( pls );
794  break;
795 
796  case PLESC_FLUSH:
797 #ifndef USE_TK
798  HandleEvents( pls );
799  XFlush( tkwd->display );
800 #endif
801  break;
802 
803  case PLESC_GETC:
804 #ifndef USE_TK
805  GetCursorCmd( pls, (PLGraphicsIn *) ptr );
806 #endif
807  break;
808 
809  case PLESC_REDRAW:
810  RedrawCmd( pls );
811  break;
812 
813  case PLESC_RESIZE:
814  ResizeCmd( pls, (PLDisplay *) ptr );
815  break;
816 
817 // Added by Vince, disabled by default since we want a minimal patch
818 #ifdef USING_PLESC_COPY
819  case PLESC_COPY:
820  CopyCommand( pls );
821  break;
822 #endif
823  }
824 }
825 
826 #ifdef USING_PLESC_COPY
827 //--------------------------------------------------------------------------
828 // CopyCommand()
829 //
830 // Copy a rectangle to a new part of the image.
831 // Points described in first 3 elements of pls->dev_x[] and pls->dev_y[].
832 //--------------------------------------------------------------------------
833 
834 static void
835 CopyCommand( PLStream *pls )
836 {
837  int x0, w, x1, y0, h, y1;
838  TkwDev *dev = (TkwDev *) pls->dev;
839  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
840 
841  x0 = (int) ( dev->xscale * pls->dev_x[0] );
842  x1 = (int) ( dev->xscale * pls->dev_x[2] );
843  y0 = (int) ( dev->yscale * ( dev->ylen - pls->dev_y[0] ) );
844  y1 = (int) ( dev->yscale * ( dev->ylen - pls->dev_y[2] ) );
845  w = (int) ( dev->xscale * ( pls->dev_x[1] - pls->dev_x[0] ) );
846  h = (int) ( -dev->yscale * ( pls->dev_y[1] - pls->dev_y[0] ) );
847 
848  if ( dev->write_to_window )
849  XCopyArea( tkwd->display, dev->window, dev->window, dev->gc,
850  x0, y0, w, h, x1, y1 );
851 
852  if ( dev->write_to_pixmap )
853  XCopyArea( tkwd->display, dev->pixmap, dev->pixmap, dev->gc,
854  x0, y0, w, h, x1, y1 );
855 }
856 #endif
857 
858 //--------------------------------------------------------------------------
859 // FillPolygonCmd()
860 //
861 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
862 // Only solid color fill supported.
863 //--------------------------------------------------------------------------
864 
865 static void
866 FillPolygonCmd( PLStream *pls )
867 {
868  TkwDev *dev = (TkwDev *) pls->dev;
869  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
870  XPoint _pts[PL_MAXPOLY];
871  XPoint *pts;
872  int i;
873 
874  if ( pls->dev_npts > PL_MAXPOLY )
875  {
876  pts = (XPoint *) malloc( sizeof ( XPoint ) * (size_t) ( pls->dev_npts ) );
877  }
878  else
879  {
880  pts = _pts;
881  }
882 
883  for ( i = 0; i < pls->dev_npts; i++ )
884  {
885  pts[i].x = (short) ( dev->xscale * pls->dev_x[i] );
886  pts[i].y = (short) ( dev->yscale * ( dev->ylen - pls->dev_y[i] ) );
887  }
888 
889 // Fill polygons
890 
891  if ( dev->write_to_window )
892  XFillPolygon( tkwd->display, dev->window, dev->gc,
893  pts, pls->dev_npts, Nonconvex, CoordModeOrigin );
894 
895  if ( dev->write_to_pixmap )
896  XFillPolygon( tkwd->display, dev->pixmap, dev->gc,
897  pts, pls->dev_npts, Nonconvex, CoordModeOrigin );
898 
899 // If in debug mode, draw outline of boxes being filled
900 
901 #ifdef DEBUG
902  if ( pls->debug )
903  {
904  XSetForeground( tkwd->display, dev->gc, tkwd->fgcolor.pixel );
905  if ( dev->write_to_window )
906  XDrawLines( tkwd->display, dev->window, dev->gc, pts, pls->dev_npts,
907  CoordModeOrigin );
908 
909  if ( dev->write_to_pixmap )
910  XDrawLines( tkwd->display, dev->pixmap, dev->gc, pts, pls->dev_npts,
911  CoordModeOrigin );
912 
913  XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel );
914  }
915 #endif
916 
917  if ( pls->dev_npts > PL_MAXPOLY )
918  {
919  free( pts );
920  }
921 }
922 
923 //--------------------------------------------------------------------------
924 // Init()
925 //
926 // Xlib initialization routine.
927 //
928 // Controlling routine for X window creation and/or initialization.
929 // The user may customize the window in the following ways:
930 //
931 // display: pls->OutFile (use plsfnam() or -display option)
932 // size: pls->xlength, pls->ylength (use plspage() or -geo option)
933 // bg color: pls->cmap0[0] (use plscolbg() or -bg option)
934 //--------------------------------------------------------------------------
935 
936 static void
937 Init( PLStream *pls )
938 {
939  PlPlotter *plf;
940  TkwDev *dev = (TkwDev *) pls->dev;
941  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
942 
943  dbug_enter( "Init" );
944 
945  dev->window = (Window) pls->window_id;
946 
947  plf = pls->plPlotterPtr;
948  if ( plf == NULL )
949  {
950  plwarn( "Init: Illegal call --- driver can't find enclosing PlPlotter" );
951  return;
952  }
953 
954 // Initialize colors
955  InitColors( pls );
956 #ifndef MAC_TCL
957  XSetWindowColormap( tkwd->display, dev->window, tkwd->map );
958 #else
959 #endif
960 
961 // Set up GC for ordinary draws
962  if ( !dev->gc )
963  dev->gc = XCreateGC( tkwd->display, dev->window, 0, 0 );
964 
965 // Set up GC for rubber-band draws
966  if ( !tkwd->gcXor )
967  {
968  XGCValues gcValues;
969  unsigned long mask;
970 
971  gcValues.background = tkwd->cmap0[0].pixel;
972  gcValues.foreground = 0xFF;
973  gcValues.function = GXxor;
974  mask = GCForeground | GCBackground | GCFunction;
975 
976  tkwd->gcXor = XCreateGC( tkwd->display, dev->window, mask, &gcValues );
977  }
978 
979 // Get initial drawing area dimensions
980  dev->width = (unsigned int) Tk_Width( plf->tkwin );
981  dev->height = (unsigned int) Tk_Height( plf->tkwin );
982  dev->border = (unsigned int) Tk_InternalBorderWidth( plf->tkwin );
983  tkwd->depth = (unsigned int) Tk_Depth( plf->tkwin );
984 
985  dev->init_width = dev->width;
986  dev->init_height = dev->height;
987 
988  // Set up flags that determine what we are writing to
989  // If nopixmap is set, ignore db
990 
991  if ( pls->nopixmap )
992  {
993  dev->write_to_pixmap = 0;
994  pls->db = 0;
995  }
996  else
997  {
998  dev->write_to_pixmap = 1;
999  }
1000  dev->write_to_window = !pls->db;
1001 
1002  // Create pixmap for holding plot image (for expose events).
1003 
1004  if ( dev->write_to_pixmap )
1005  CreatePixmap( pls );
1006 
1007  // Set drawing color
1008 
1009  plD_state_tkwin( pls, PLSTATE_COLOR0 );
1010 
1011  XSetWindowBackground( tkwd->display, dev->window, tkwd->cmap0[0].pixel );
1012  XSetBackground( tkwd->display, dev->gc, tkwd->cmap0[0].pixel );
1013 }
1014 
1015 //--------------------------------------------------------------------------
1016 // ExposeCmd()
1017 //
1018 // Event handler routine for expose events.
1019 // These are "pure" exposures (no resize), so don't need to clear window.
1020 //--------------------------------------------------------------------------
1021 
1022 static void
1023 ExposeCmd( PLStream *pls, PLDisplay *pldis )
1024 {
1025  TkwDev *dev = (TkwDev *) pls->dev;
1026  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1027  int x, y, width, height;
1028 
1029  dbug_enter( "ExposeCmd" );
1030 
1031  // Return if plD_init_tkw hasn't been called yet
1032 
1033  if ( dev == NULL )
1034  {
1035  plwarn( "ExposeCmd: Illegal call -- driver uninitialized" );
1036  return;
1037  }
1038 
1039  // Exposed area. If unspecified, the entire window is used.
1040 
1041  if ( pldis == NULL )
1042  {
1043  x = 0;
1044  y = 0;
1045  width = (int) dev->width;
1046  height = (int) dev->height;
1047  }
1048  else
1049  {
1050  x = (int) pldis->x;
1051  y = (int) pldis->y;
1052  width = (int) pldis->width;
1053  height = (int) pldis->height;
1054  }
1055 
1056  // Usual case: refresh window from pixmap
1057  // DEBUG option: draws rectangle around refreshed region
1058 
1059  XSync( tkwd->display, 0 );
1060  if ( dev->write_to_pixmap )
1061  {
1062  XCopyArea( tkwd->display, dev->pixmap, dev->window, dev->gc,
1063  x, y, (unsigned int) width, (unsigned int) height, x, y );
1064  XSync( tkwd->display, 0 );
1065 #ifdef DEBUG
1066  if ( pls->debug )
1067  {
1068  XPoint pts[5];
1069  int x0 = x, x1 = x + width, y0 = y, y1 = y + height;
1070  pts[0].x = (short) x0; pts[0].y = (short) y0;
1071  pts[1].x = (short) x1; pts[1].y = (short) y0;
1072  pts[2].x = (short) x1; pts[2].y = (short) y1;
1073  pts[3].x = (short) x0; pts[3].y = (short) y1;
1074  pts[4].x = (short) x0; pts[4].y = (short) y0;
1075 
1076  XDrawLines( tkwd->display, dev->window, dev->gc, pts, 5,
1077  CoordModeOrigin );
1078  }
1079 #endif
1080  }
1081  else
1082  {
1083  plRemakePlot( pls );
1084  XFlush( tkwd->display );
1085  }
1086 }
1087 
1088 //--------------------------------------------------------------------------
1089 // ResizeCmd()
1090 //
1091 // Event handler routine for resize events.
1092 //--------------------------------------------------------------------------
1093 
1094 static void
1095 ResizeCmd( PLStream *pls, PLDisplay *pldis )
1096 {
1097  TkwDev *dev = (TkwDev *) pls->dev;
1098  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1099  int write_to_window = dev->write_to_window;
1100 
1101  dbug_enter( "ResizeCmd" );
1102 
1103  // Return if plD_init_tkw hasn't been called yet
1104 
1105  if ( dev == NULL )
1106  {
1107  plwarn( "ResizeCmd: Illegal call -- driver uninitialized" );
1108  return;
1109  }
1110 
1111  // Return if pointer to window not specified.
1112 
1113  if ( pldis == NULL )
1114  {
1115  plwarn( "ResizeCmd: Illegal call -- window pointer uninitialized" );
1116  return;
1117  }
1118 
1119  // Reset current window bounds
1120 
1121  dev->width = pldis->width;
1122  dev->height = pldis->height;
1123 
1124  dev->xscale = dev->width / (double) dev->init_width;
1125  dev->yscale = dev->height / (double) dev->init_height;
1126 
1127  dev->xscale = dev->xscale * dev->xscale_init;
1128  dev->yscale = dev->yscale * dev->yscale_init;
1129 
1130 #if PHYSICAL
1131  {
1132  float pxlx = (double) PIXELS_X / dev->width * DPMM;
1133  float pxly = (double) PIXELS_Y / dev->height * DPMM;
1134  plP_setpxl( pxlx, pxly );
1135  }
1136 #endif
1137 
1138  // Note: the following order MUST be obeyed -- if you instead redraw into
1139  // the window and then copy it to the pixmap, off-screen parts of the window
1140  // may contain garbage which is then transferred to the pixmap (and thus
1141  // will not go away after an expose).
1142  //
1143 
1144  // Resize pixmap using new dimensions
1145 
1146  if ( dev->write_to_pixmap )
1147  {
1148  dev->write_to_window = 0;
1149 #if defined ( _WIN32 ) || defined ( MAC_TCL )
1150  Tk_FreePixmap( tkwd->display, dev->pixmap );
1151 #else
1152  // Vince's original driver code used
1153  // Tk_FreePixmap(tkwd->display, dev->pixmap);
1154  //which is defined in tk-8.3 (and 8.2?) source as
1155  //void
1156  // Tk_FreePixmap(display, pixmap)
1157  // Display *display;
1158  // Pixmap pixmap;
1159  // {
1160  // XFreePixmap(display, pixmap);
1161  // Tk_FreeXId(display, (XID) pixmap);
1162  // }
1163  // But that bombed under Linux and tcl/tk8.2 so now just call
1164  // XFreePixmap directly. (Not recommended as permanent solution
1165  // because you eventually run out of resources according to man
1166  // page if you don't call Tk_FreeXId.) Vince is still looking into
1167  // how to resolve this problem.
1168  //
1169  XFreePixmap( tkwd->display, dev->pixmap );
1170 #endif
1171  CreatePixmap( pls );
1172  }
1173 
1174  // Initialize & redraw (to pixmap, if available).
1175 
1176  plD_bop_tkwin( pls );
1177  plRemakePlot( pls );
1178  XSync( tkwd->display, 0 );
1179 
1180  // If pixmap available, fake an expose
1181 
1182  if ( dev->write_to_pixmap )
1183  {
1184  dev->write_to_window = write_to_window;
1185  XCopyArea( tkwd->display, dev->pixmap, dev->window, dev->gc, 0, 0,
1186  dev->width, dev->height, 0, 0 );
1187  XSync( tkwd->display, 0 );
1188  }
1189 }
1190 
1191 //--------------------------------------------------------------------------
1192 // RedrawCmd()
1193 //
1194 // Handles page redraw without resize (pixmap does not get reallocated).
1195 // Calling this makes sure all necessary housekeeping gets done.
1196 //--------------------------------------------------------------------------
1197 
1198 static void
1199 RedrawCmd( PLStream *pls )
1200 {
1201  TkwDev *dev = (TkwDev *) pls->dev;
1202  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1203  int write_to_window = dev->write_to_window;
1204 
1205  dbug_enter( "RedrawCmd" );
1206 
1207  // Return if plD_init_tkw hasn't been called yet
1208 
1209  if ( dev == NULL )
1210  {
1211  plwarn( "RedrawCmd: Illegal call -- driver uninitialized" );
1212  return;
1213  }
1214 
1215  // Initialize & redraw (to pixmap, if available).
1216 
1217  if ( dev->write_to_pixmap )
1218  dev->write_to_window = 0;
1219 
1220  plD_bop_tkwin( pls );
1221  plRemakePlot( pls );
1222  XSync( tkwd->display, 0 );
1223 
1224  dev->write_to_window = write_to_window;
1225 
1226  // If pixmap available, fake an expose
1227 
1228  if ( dev->write_to_pixmap )
1229  {
1230  XCopyArea( tkwd->display, dev->pixmap, dev->window, dev->gc, 0, 0,
1231  dev->width, dev->height, 0, 0 );
1232  XSync( tkwd->display, 0 );
1233  }
1234 }
1235 
1236 //--------------------------------------------------------------------------
1237 // CreatePixmap()
1238 //
1239 // This routine creates a pixmap, doing error trapping in case there
1240 // isn't enough memory on the server.
1241 //--------------------------------------------------------------------------
1242 
1243 static void
1244 CreatePixmap( PLStream *pls )
1245 {
1246  TkwDev *dev = (TkwDev *) pls->dev;
1247  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1248  Tk_Window tkwin = pls->plPlotterPtr->tkwin;
1249 
1250 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
1251  int ( *oldErrorHandler )( Display *, XErrorEvent * );
1252  oldErrorHandler = XSetErrorHandler( CreatePixmapErrorHandler );
1253  CreatePixmapStatus = Success;
1254 #endif
1255 
1256 #ifdef MAC_TCL
1257  // MAC_TCL's version of XCreatePixmap doesn't like 0 by 0 maps
1258  if ( dev->width == 0 )
1259  {
1260  dev->width = 10;
1261  }
1262  if ( dev->height == 0 )
1263  {
1264  dev->height = 10;
1265  }
1266 #endif
1267  pldebug( "CreatePixmap",
1268  "creating pixmap: width = %d, height = %d, depth = %d\n",
1269  dev->width, dev->height, tkwd->depth );
1270 //
1271 // dev->pixmap = Tk_GetPixmap(tkwd->display, dev->window,
1272 // dev->width, dev->height, tkwd->depth);
1273 //
1274 //
1275 // Vince's original driver code used Tk_Display(tkwin) for first argument,
1276 // but that bombed on an Linux tcl/tk 8.2 machine. Something was wrong
1277 // with that value. Thus, we now use tkwd->display, and that works well.
1278 // Vince is looking into why Tk_Display(tkwin) is badly defined under 8.2.
1279 // old code:
1280 //
1281 // dev->pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
1282 // Tk_Width(tkwin), Tk_Height(tkwin),
1283 // DefaultDepthOfScreen(Tk_Screen(tkwin)));
1284 //
1285  dev->pixmap = Tk_GetPixmap( tkwd->display, Tk_WindowId( tkwin ),
1286  Tk_Width( tkwin ), Tk_Height( tkwin ),
1287  DefaultDepthOfScreen( Tk_Screen( tkwin ) ) );
1288  XSync( tkwd->display, 0 );
1289 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
1290  if ( CreatePixmapStatus != Success )
1291  {
1292  dev->write_to_pixmap = 0;
1293  dev->write_to_window = 1;
1294  pls->db = 0;
1295  fprintf( stderr, "\n\
1296  Warning: pixmap could not be allocated (insufficient memory on server).\n\
1297  Driver will redraw the entire plot to handle expose events.\n" );
1298  }
1299 
1300  XSetErrorHandler( oldErrorHandler );
1301 #endif
1302 }
1303 
1304 //--------------------------------------------------------------------------
1305 // GetVisual()
1306 //
1307 // Get visual info. In order to safely use a visual other than that of
1308 // the parent (which hopefully is that returned by DefaultVisual), you
1309 // must first find (using XGetRGBColormaps) or create a colormap matching
1310 // this visual and then set the colormap window attribute in the
1311 // XCreateWindow attributes and valuemask arguments. I don't do this
1312 // right now, so this is turned off by default.
1313 //--------------------------------------------------------------------------
1314 
1315 static void
1316 GetVisual( PLStream *pls )
1317 {
1318  int depth;
1319  TkwDev *dev = (TkwDev *) pls->dev;
1320  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1321 
1322  dbug_enter( "GetVisual" );
1323 
1324  tkwd->visual = Tk_GetVisual( pls->plPlotterPtr->interp,
1325  pls->plPlotterPtr->tkwin,
1326  "best",
1327  &depth, NULL );
1328  tkwd->depth = (unsigned int) depth;
1329 }
1330 
1331 //--------------------------------------------------------------------------
1332 // AllocBGFG()
1333 //
1334 // Allocate background & foreground colors. If possible, I choose pixel
1335 // values such that the fg pixel is the xor of the bg pixel, to make
1336 // rubber-banding easy to see.
1337 //--------------------------------------------------------------------------
1338 
1339 static void
1340 AllocBGFG( PLStream *pls )
1341 {
1342  TkwDev *dev = (TkwDev *) pls->dev;
1343  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1344 
1345 #ifndef USE_TK
1346  int i, j, npixels;
1347  unsigned long plane_masks[1], pixels[MAX_COLORS];
1348 #endif
1349 
1350  dbug_enter( "AllocBGFG" );
1351 
1352  // If not on a color system, just return
1353 
1354  if ( !tkwd->color )
1355  return;
1356 #ifndef USE_TK
1357  // Allocate r/w color cell for background
1358 
1359  if ( XAllocColorCells( tkwd->display, tkwd->map, False,
1360  plane_masks, 0, pixels, 1 ) )
1361  {
1362  tkwd->cmap0[0].pixel = pixels[0];
1363  }
1364  else
1365  {
1366  plexit( "couldn't allocate background color cell" );
1367  }
1368 
1369  // Allocate as many colors as we can
1370 
1371  npixels = MAX_COLORS;
1372  for (;; )
1373  {
1374  if ( XAllocColorCells( tkwd->display, tkwd->map, False,
1375  plane_masks, 0, pixels, npixels ) )
1376  break;
1377  npixels--;
1378  if ( npixels == 0 )
1379  break;
1380  }
1381 
1382  // Find the color with pixel = xor of the bg color pixel.
1383  // If a match isn't found, the last pixel allocated is used.
1384 
1385  for ( i = 0; i < npixels - 1; i++ )
1386  {
1387  if ( pixels[i] == ( ~tkwd->cmap0[0].pixel & 0xFF ) )
1388  break;
1389  }
1390 
1391  // Use this color cell for our foreground color. Then free the rest.
1392 
1393  tkwd->fgcolor.pixel = pixels[i];
1394  for ( j = 0; j < npixels; j++ )
1395  {
1396  if ( j != i )
1397  XFreeColors( tkwd->display, tkwd->map, &pixels[j], 1, 0 );
1398  }
1399 #endif
1400 }
1401 
1402 //--------------------------------------------------------------------------
1403 // pltkwin_setBGFG()
1404 //
1405 // Set background & foreground colors. Foreground over background should
1406 // have high contrast.
1407 //--------------------------------------------------------------------------
1408 
1409 void
1410 pltkwin_setBGFG( PLStream *pls )
1411 {
1412  TkwDev *dev = (TkwDev *) pls->dev;
1413  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1414  PLColor fgcolor;
1415  int gslevbg, gslevfg;
1416 
1417  dbug_enter( "pltkwin_setBGFG" );
1418 
1419  //
1420  // Set background color.
1421  //
1422  // Background defaults to black on color screens, white on grayscale (many
1423  // grayscale monitors have poor contrast, and black-on-white looks better).
1424  //
1425 
1426  if ( !tkwd->color )
1427  {
1428  pls->cmap0[0].r = pls->cmap0[0].g = pls->cmap0[0].b = 0xFF;
1429  }
1430  gslevbg = (int) ( ( (long) pls->cmap0[0].r +
1431  (long) pls->cmap0[0].g +
1432  (long) pls->cmap0[0].b ) / 3 );
1433 
1434  PLColor_to_TkColor( &pls->cmap0[0], &tkwd->cmap0[0] );
1435 
1436  //
1437  // Set foreground color.
1438  //
1439  // Used for grayscale output, since otherwise the plots can become nearly
1440  // unreadable (i.e. if colors get mapped onto grayscale values). In this
1441  // case it becomes the grayscale level for all draws, and is taken to be
1442  // black if the background is light, and white if the background is dark.
1443  // Note that white/black allocations never fail.
1444  //
1445 
1446  if ( gslevbg > 0x7F )
1447  gslevfg = 0;
1448  else
1449  gslevfg = 0xFF;
1450 
1451  fgcolor.r = fgcolor.g = fgcolor.b = (unsigned char) gslevfg;
1452 
1453  PLColor_to_TkColor( &fgcolor, &tkwd->fgcolor );
1454 
1455  // Now store
1456 #ifndef USE_TK
1457  if ( tkwd->color )
1458  {
1459  XStoreColor( tkwd->display, tkwd->map, &tkwd->fgcolor );
1460  XStoreColor( tkwd->display, tkwd->map, &tkwd->cmap0[0] );
1461  }
1462  else
1463  {
1464  XAllocColor( tkwd->display, tkwd->map, &tkwd->cmap0[0] );
1465  XAllocColor( tkwd->display, tkwd->map, &tkwd->fgcolor );
1466  }
1467 #else
1468  Tkw_StoreColor( pls, tkwd, &tkwd->cmap0[0] );
1469  Tkw_StoreColor( pls, tkwd, &tkwd->fgcolor );
1470 #endif
1471 }
1472 
1473 //--------------------------------------------------------------------------
1474 // InitColors()
1475 //
1476 // Does all color initialization.
1477 //--------------------------------------------------------------------------
1478 
1479 static void
1480 InitColors( PLStream *pls )
1481 {
1482  TkwDev *dev = (TkwDev *) pls->dev;
1483  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1484 
1485  dbug_enter( "InitColors" );
1486 
1487  // Allocate and initialize color maps.
1488  // Defer cmap1 allocation until it's actually used
1489 
1490  if ( tkwd->color )
1491  {
1492  if ( plplot_tkwin_ccmap )
1493  {
1494  AllocCustomMap( pls );
1495  }
1496  else
1497  {
1498  AllocCmap0( pls );
1499  }
1500  }
1501 }
1502 
1503 //--------------------------------------------------------------------------
1504 // AllocCustomMap()
1505 //
1506 // Initializes custom color map and all the cruft that goes with it.
1507 //
1508 // Assuming all color X displays do 256 colors, the breakdown is as follows:
1509 //
1510 // XWM_COLORS Number of low "pixel" values to copy. These are typically
1511 // allocated first, thus are in use by the window manager. I
1512 // copy them to reduce flicker.
1513 //
1514 // CMAP0_COLORS Color map 0 entries. I allocate these both in the default
1515 // colormap and the custom colormap to reduce flicker.
1516 //
1517 // CMAP1_COLORS Color map 1 entries. There should be as many as practical
1518 // available for smooth shading. On the order of 50-100 is
1519 // pretty reasonable. You don't really need all 256,
1520 // especially if all you're going to do is to print it to
1521 // postscript (which doesn't have any intrinsic limitation on
1522 // the number of colors).
1523 //
1524 // It's important to leave some extra colors unallocated for Tk. In
1525 // particular the palette tools require a fair amount. I recommend leaving
1526 // at least 40 or so free.
1527 //--------------------------------------------------------------------------
1528 
1529 static void
1530 AllocCustomMap( PLStream *pls )
1531 {
1532  TkwDev *dev = (TkwDev *) pls->dev;
1533  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1534 
1535  XColor xwm_colors[MAX_COLORS];
1536  int i;
1537 #ifndef USE_TK
1538  int npixels;
1539  unsigned long plane_masks[1], pixels[MAX_COLORS];
1540 #endif
1541 
1542  dbug_enter( "AllocCustomMap" );
1543 
1544  // Determine current default colors
1545 
1546  for ( i = 0; i < MAX_COLORS; i++ )
1547  {
1548  xwm_colors[i].pixel = (long unsigned) i;
1549  }
1550 #ifndef MAC_TCL
1551  XQueryColors( tkwd->display, tkwd->map, xwm_colors, MAX_COLORS );
1552 #endif
1553 
1554  // Allocate cmap0 colors in the default colormap.
1555  // The custom cmap0 colors are later stored at the same pixel values.
1556  // This is a really cool trick to reduce the flicker when changing colormaps.
1557  //
1558 
1559  AllocCmap0( pls );
1560  XAllocColor( tkwd->display, tkwd->map, &tkwd->fgcolor );
1561 
1562  // Create new color map
1563 
1564  tkwd->map = XCreateColormap( tkwd->display, DefaultRootWindow( tkwd->display ),
1565  tkwd->visual, AllocNone );
1566 
1567  // Now allocate all colors so we can fill the ones we want to copy
1568 
1569 #ifndef USE_TK
1570  npixels = MAX_COLORS;
1571  for (;; )
1572  {
1573  if ( XAllocColorCells( tkwd->display, tkwd->map, False,
1574  plane_masks, 0, pixels, npixels ) )
1575  break;
1576  npixels--;
1577  if ( npixels == 0 )
1578  plexit( "couldn't allocate any colors" );
1579  }
1580 
1581  // Fill the low colors since those are in use by the window manager
1582 
1583  for ( i = 0; i < XWM_COLORS; i++ )
1584  {
1585  XStoreColor( tkwd->display, tkwd->map, &xwm_colors[i] );
1586  pixels[xwm_colors[i].pixel] = 0;
1587  }
1588 
1589  // Fill the ones we will use in cmap0
1590 
1591  for ( i = 0; i < tkwd->ncol0; i++ )
1592  {
1593  XStoreColor( tkwd->display, tkwd->map, &tkwd->cmap0[i] );
1594  pixels[tkwd->cmap0[i].pixel] = 0;
1595  }
1596 
1597  // Finally, if the colormap was saved by an external agent, see if there are
1598  // any differences from the current default map and save those! A very cool
1599  // (or sick, depending on how you look at it) trick to get over some X and
1600  // Tk limitations.
1601  //
1602 
1603  if ( sxwm_colors_set )
1604  {
1605  for ( i = 0; i < MAX_COLORS; i++ )
1606  {
1607  if ( ( xwm_colors[i].red != sxwm_colors[i].red ) ||
1608  ( xwm_colors[i].green != sxwm_colors[i].green ) ||
1609  ( xwm_colors[i].blue != sxwm_colors[i].blue ) )
1610  {
1611  if ( pixels[i] != 0 )
1612  {
1613  XStoreColor( tkwd->display, tkwd->map, &xwm_colors[i] );
1614  pixels[i] = 0;
1615  }
1616  }
1617  }
1618  }
1619 
1620  // Now free the ones we're not interested in
1621 
1622  for ( i = 0; i < npixels; i++ )
1623  {
1624  if ( pixels[i] != 0 )
1625  XFreeColors( tkwd->display, tkwd->map, &pixels[i], 1, 0 );
1626  }
1627 #endif
1628  // Allocate colors in cmap 1
1629 
1630  AllocCmap1( pls );
1631 }
1632 
1633 //--------------------------------------------------------------------------
1634 // AllocCmap0()
1635 //
1636 // Allocate & initialize cmap0 entries.
1637 //--------------------------------------------------------------------------
1638 
1639 static void
1640 AllocCmap0( PLStream *pls )
1641 {
1642  TkwDev *dev = (TkwDev *) pls->dev;
1643  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1644 
1645 #ifndef USE_TK
1646  int npixels;
1647  int i;
1648  unsigned long plane_masks[1], pixels[MAX_COLORS];
1649 #endif
1650 
1651  dbug_enter( "AllocCmap0" );
1652 
1653  // Allocate and assign colors in cmap 0
1654 
1655 #ifndef USE_TK
1656  npixels = pls->ncol0 - 1;
1657  for (;; )
1658  {
1659  if ( XAllocColorCells( tkwd->display, tkwd->map, False,
1660  plane_masks, 0, &pixels[1], npixels ) )
1661  break;
1662  npixels--;
1663  if ( npixels == 0 )
1664  plexit( "couldn't allocate any colors" );
1665  }
1666 
1667  tkwd->ncol0 = npixels + 1;
1668  for ( i = 1; i < tkwd->ncol0; i++ )
1669  {
1670  tkwd->cmap0[i].pixel = pixels[i];
1671  }
1672 #else
1673  // We use the Tk color scheme
1674  tkwd->ncol0 = pls->ncol0;
1675 #endif
1676  StoreCmap0( pls );
1677 }
1678 
1679 //--------------------------------------------------------------------------
1680 // AllocCmap1()
1681 //
1682 // Allocate & initialize cmap1 entries. If using the default color map,
1683 // must severely limit number of colors otherwise TK won't have enough.
1684 //--------------------------------------------------------------------------
1685 
1686 static void
1687 AllocCmap1( PLStream *pls )
1688 {
1689  TkwDev *dev = (TkwDev *) pls->dev;
1690  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1691 
1692  int npixels;
1693 #ifndef USE_TK
1694  int i, j;
1695  unsigned long plane_masks[1], pixels[MAX_COLORS];
1696 #endif
1697 
1698  dbug_enter( "AllocCmap1" );
1699 
1700  // Allocate colors in cmap 1
1701 
1702  npixels = MAX( 2, MIN( CMAP1_COLORS, pls->ncol1 ) );
1703 #ifndef USE_TK
1704  for (;; )
1705  {
1706  if ( XAllocColorCells( tkwd->display, tkwd->map, False,
1707  plane_masks, 0, pixels, npixels ) )
1708  break;
1709  npixels--;
1710  if ( npixels == 0 )
1711  break;
1712  }
1713 
1714  if ( npixels < 2 )
1715  {
1716  tkwd->ncol1 = -1;
1717  fprintf( stderr,
1718  "Warning: unable to allocate sufficient colors in cmap1\n" );
1719  return;
1720  }
1721  else
1722  {
1723  tkwd->ncol1 = npixels;
1724  if ( pls->verbose )
1725  fprintf( stderr, "AllocCmap1 (xwin.c): Allocated %d colors in cmap1\n", npixels );
1726  }
1727 
1728  // Don't assign pixels sequentially, to avoid strange problems with xor GC's
1729  // Skipping by 2 seems to do the job best
1730 
1731  for ( j = i = 0; i < tkwd->ncol1; i++ )
1732  {
1733  while ( pixels[j] == 0 )
1734  j++;
1735 
1736  tkwd->cmap1[i].pixel = pixels[j];
1737  pixels[j] = 0;
1738 
1739  j += 2;
1740  if ( j >= tkwd->ncol1 )
1741  j = 0;
1742  }
1743 #else
1744  tkwd->ncol1 = npixels;
1745 #endif
1746  StoreCmap1( pls );
1747 }
1748 
1749 //--------------------------------------------------------------------------
1750 // StoreCmap0()
1751 //
1752 // Stores cmap 0 entries in X-server colormap.
1753 //--------------------------------------------------------------------------
1754 
1755 static void
1756 StoreCmap0( PLStream *pls )
1757 {
1758  TkwDev *dev = (TkwDev *) pls->dev;
1759  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1760  int i;
1761 
1762  if ( !tkwd->color )
1763  return;
1764 
1765  for ( i = 1; i < tkwd->ncol0; i++ )
1766  {
1767  PLColor_to_TkColor( &pls->cmap0[i], &tkwd->cmap0[i] );
1768 #ifndef USE_TK
1769  XStoreColor( tkwd->display, tkwd->map, &tkwd->cmap0[i] );
1770 #else
1771  Tkw_StoreColor( pls, tkwd, &tkwd->cmap0[i] );
1772 #endif
1773  }
1774 }
1775 
1776 void CopyColour( XColor* from, XColor* to )
1777 {
1778  to->pixel = from->pixel;
1779  to->red = from->red;
1780  to->blue = from->blue;
1781  to->green = from->green;
1782  to->flags = from->flags;
1783 }
1784 
1785 //--------------------------------------------------------------------------
1786 // StoreCmap1()
1787 //
1788 // Stores cmap 1 entries in X-server colormap.
1789 //--------------------------------------------------------------------------
1790 
1791 static void
1792 StoreCmap1( PLStream *pls )
1793 {
1794  TkwDev *dev = (TkwDev *) pls->dev;
1795  TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd;
1796 
1797  PLColor cmap1color;
1798  int i;
1799 
1800  if ( !tkwd->color )
1801  return;
1802 
1803  for ( i = 0; i < tkwd->ncol1; i++ )
1804  {
1805  plcol_interp( pls, &cmap1color, i, tkwd->ncol1 );
1806  PLColor_to_TkColor( &cmap1color, &tkwd->cmap1[i] );
1807 #ifndef USE_TK
1808  XStoreColor( tkwd->display, tkwd->map, &tkwd->cmap1[i] );
1809 #else
1810  Tkw_StoreColor( pls, tkwd, &tkwd->cmap1[i] );
1811 #endif
1812  }
1813 }
1814 
1815 void Tkw_StoreColor( PLStream* pls, TkwDisplay* tkwd, XColor* col )
1816 {
1817  XColor *xc;
1818 #ifndef USE_TK
1819  XStoreColor( tkwd->display, tkwd->map, col );
1820 #else
1821  (void) tkwd; // tkwd unused in this case
1822  // We're probably losing memory here
1823  xc = Tk_GetColorByValue( pls->plPlotterPtr->tkwin, col );
1824  CopyColour( xc, col );
1825 #endif
1826 }
1827 
1828 //--------------------------------------------------------------------------
1829 // void PLColor_to_TkColor()
1830 //
1831 // Copies the supplied PLColor to an XColor, padding with bits as necessary
1832 // (a PLColor uses 8 bits for color storage, while an XColor uses 16 bits).
1833 // The argument types follow the same order as in the function name.
1834 //--------------------------------------------------------------------------
1835 
1836 #define ToXColor( a ) ( ( ( 0xFF & ( a ) ) << 8 ) | ( a ) )
1837 #define ToPLColor( a ) ( ( (U_LONG) a ) >> 8 )
1838 
1839 void
1840 PLColor_to_TkColor( PLColor *plcolor, XColor *xcolor )
1841 {
1842  xcolor->red = (short unsigned) ToXColor( plcolor->r );
1843  xcolor->green = (short unsigned) ToXColor( plcolor->g );
1844  xcolor->blue = (short unsigned) ToXColor( plcolor->b );
1845  xcolor->flags = DoRed | DoGreen | DoBlue;
1846 }
1847 
1848 //--------------------------------------------------------------------------
1849 // void PLColor_from_TkColor()
1850 //
1851 // Copies the supplied XColor to a PLColor, stripping off bits as
1852 // necessary. See the previous routine for more info.
1853 //--------------------------------------------------------------------------
1854 
1855 void
1856 PLColor_from_TkColor( PLColor *plcolor, XColor *xcolor )
1857 {
1858  plcolor->r = (unsigned char) ToPLColor( xcolor->red );
1859  plcolor->g = (unsigned char) ToPLColor( xcolor->green );
1860  plcolor->b = (unsigned char) ToPLColor( xcolor->blue );
1861 }
1862 
1863 //--------------------------------------------------------------------------
1864 // void PLColor_from_TkColor_Changed()
1865 //
1866 // Copies the supplied XColor to a PLColor, stripping off bits as
1867 // necessary. See the previous routine for more info.
1868 //
1869 // Returns 1 if the color was different from the old one.
1870 //--------------------------------------------------------------------------
1871 
1872 int
1873 PLColor_from_TkColor_Changed( PLColor *plcolor, XColor *xcolor )
1874 {
1875  int changed = 0;
1876  int color;
1877  color = ToPLColor( xcolor->red );
1878 
1879  if ( plcolor->r != color )
1880  {
1881  changed = 1;
1882  plcolor->r = (unsigned char) color;
1883  }
1884  color = ToPLColor( xcolor->green );
1885  if ( plcolor->g != color )
1886  {
1887  changed = 1;
1888  plcolor->g = (unsigned char) color;
1889  }
1890  color = ToPLColor( xcolor->blue );
1891  if ( plcolor->b != color )
1892  {
1893  changed = 1;
1894  plcolor->b = (unsigned char) color;
1895  }
1896  return changed;
1897 }
1898 
1899 //--------------------------------------------------------------------------
1900 // int pltk_AreWeGrayscale(PlPlotter *plf)
1901 //
1902 // Determines if we're using a monochrome or grayscale device.
1903 // gmf 11-8-91; Courtesy of Paul Martz of Evans and Sutherland.
1904 // Changed July 1996 by Vince: now uses Tk to check the enclosing PlPlotter
1905 //--------------------------------------------------------------------------
1906 
1907 static int
1908 pltk_AreWeGrayscale( PlPlotter *plf )
1909 {
1910 #if defined ( __cplusplus ) || defined ( c_plusplus )
1911 #define THING c_class
1912 #else
1913 #define THING class
1914 #endif
1915 
1916  Visual* visual;
1917  // get the window's Visual
1918  visual = Tk_Visual( plf->tkwin );
1919  if ( ( visual->THING != GrayScale ) && ( visual->THING != StaticGray ) )
1920  return ( 0 );
1921  // if we got this far, only StaticGray and GrayScale classes available
1922  return ( 1 );
1923 }
1924 
1925 #if !defined ( MAC_TCL ) && !defined ( _WIN32 )
1926 //--------------------------------------------------------------------------
1927 // CreatePixmapErrorHandler()
1928 //
1929 // Error handler used in CreatePixmap() to catch errors in allocating
1930 // storage for pixmap. This way we can nicely substitute redraws for
1931 // pixmap copies if the server has insufficient memory.
1932 //--------------------------------------------------------------------------
1933 
1934 static int
1935 CreatePixmapErrorHandler( Display *display, XErrorEvent *error )
1936 {
1937  if ( error->error_code == BadAlloc )
1938  {
1939  CreatePixmapStatus = error->error_code;
1940  }
1941  else
1942  {
1943  char buffer[256];
1944  XGetErrorText( display, error->error_code, buffer, 256 );
1945  fprintf( stderr, "Error in XCreatePixmap: %s.\n", buffer );
1946  }
1947  return 1;
1948 }
1949 #endif
1950 
1951 #else
1952 int
1954 {
1955  return 0;
1956 }
1957 
1958 #endif // PLD_tkwin
1959 
1960 void * ckcalloc( size_t nmemb, size_t size )
1961 {
1962  long *ptr;
1963  long *p;
1964  size *= nmemb;
1965  ptr = (long *) malloc( size );
1966  if ( !ptr )
1967  return ( 0 );
1968 
1969 #if !__POWERPC__
1970 
1971  for ( size = ( size / sizeof ( long ) ) + 1, p = ptr; --size; )
1972  *p++ = 0;
1973 
1974 #else
1975 
1976  for ( size = ( size / sizeof ( long ) ) + 1, p = ptr - 1; --size; )
1977  *++p = 0;
1978 
1979 #endif
1980 
1981  return ( ptr );
1982 }
char * displayName
Definition: pltkwd.h:50
#define PLESC_REDRAW
Definition: plplot.h:276
XPoint pts[5]
Definition: plplotter.c:161
#define PLSTATE_CMAP0
Definition: plplotP.h:366
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
void PLColor_to_TkColor(PLColor *plcolor, XColor *xcolor)
int width
Definition: plplotter.c:119
Tk_Window tkwin
Definition: plplotter.c:104
PLINT icol1
Definition: plstrm.h:539
static int plplot_tkwin_ccmap
Definition: pltkwd.h:41
short ylen
Definition: pltkwd.h:89
Display * display
Definition: pltkwd.h:52
long window_id
Definition: plstrm.h:634
Visual * visual
Definition: pltkwd.h:53
unsigned char b
Definition: plplot.h:550
int height
Definition: plplotter.c:121
int ncol0
Definition: pltkwd.h:58
#define PLESC_FILL
Definition: plplot.h:279
#define PL_RGB_COLOR
Definition: plplotP.h:285
plD_esc_fp pl_esc
Definition: disptab.h:90
unsigned int height
Definition: plplot.h:462
long init_width
Definition: pltkwd.h:79
void * ckcalloc(size_t nmemb, size_t size)
Definition: tkwin.c:1960
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
short xlen
Definition: pltkwd.h:89
PLINT dev_npts
Definition: plstrm.h:581
XColor curcolor
Definition: pltkwd.h:75
const char * pl_MenuStr
Definition: disptab.h:79
PLINT color
Definition: plstrm.h:569
double xscale
Definition: pltkwd.h:86
void plcol_interp(PLStream *pls, PLColor *newcolor, int i, int ncol)
Definition: plctrl.c:2530
int flags
Definition: pltkwd.h:78
plD_tidy_fp pl_tidy
Definition: disptab.h:88
PLINT plbuf_write
Definition: plstrm.h:567
#define MAX(a, b)
Definition: dsplint.c:28
unsigned border
Definition: pltkwd.h:82
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
int ncol1
Definition: pltkwd.h:59
unsigned depth
Definition: pltkwd.h:56
void PlplotterAtBop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2517
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
const char * pl_DevName
Definition: disptab.h:80
#define PLSTATE_COLOR0
Definition: plplotP.h:363
plD_init_fp pl_init
Definition: disptab.h:83
static int error
Definition: plcont.c:61
Pixmap pixmap
Definition: pltkwd.h:73
PLINT colorset
Definition: plstrm.h:569
#define PLSTATE_COLOR1
Definition: plplotP.h:364
int color
Definition: pltkwd.h:57
int pldummy_tkwin()
Definition: tkwin.c:1953
XColor cmap1[256]
Definition: pltkwd.h:61
short * dev_x
Definition: plstrm.h:582
#define PLSTATE_WIDTH
Definition: plplotP.h:362
static int color
Definition: ps.c:78
int PLINT
Definition: plplot.h:181
#define MIN(a, b)
Definition: dsplint.c:29
void plD_open_tkwin(PLStream *pls)
int nstreams
Definition: pltkwd.h:48
long init_height
Definition: pltkwd.h:80
GC gcXor
Definition: pltkwd.h:54
static int synchronize
Definition: tkMain.c:132
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
double xscale_init
Definition: pltkwd.h:84
double yscale
Definition: pltkwd.h:87
int PLColor_from_TkColor_Changed(PLColor *plcolor, XColor *xcolor)
PLINT ncol0
Definition: plstrm.h:539
unsigned char g
Definition: plplot.h:549
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
int db
Definition: plstrm.h:635
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
int ixwd
Definition: pltkwd.h:49
PLINT termin
Definition: plstrm.h:568
#define PLSTATE_CMAP1
Definition: plplotP.h:367
PLINT icol0
Definition: plstrm.h:539
double yscale_init
Definition: pltkwd.h:85
#define PIXELS_X
Definition: plplotP.h:304
#define dbug_enter(a)
Definition: tclMatrix.c:59
#define DPMM
Definition: plplotP.h:306
int instr
Definition: pltkwd.h:94
unsigned int x
Definition: plplot.h:461
#define PLESC_RESIZE
Definition: plplot.h:275
char * FileName
Definition: plstrm.h:576
plD_bop_fp pl_bop
Definition: disptab.h:87
#define PLESC_EH
Definition: plplot.h:282
#define LPAGE_Y
Definition: plplotP.h:309
struct PlPlotter PlPlotter
PLINT verbose
Definition: plstrm.h:527
plD_line_fp pl_line
Definition: disptab.h:84
static PLINT * buffer
Definition: plfill.c:74
GC gc
Definition: pltkwd.h:74
PLDLLIMPEXP_DRIVER void plD_dispatch_init_tkwin(PLDispatchTable *pdt)
void PlplotterAtEop(Tcl_Interp *interp, register PlPlotter *plPlotterPtr)
Definition: plplotter.c:2507
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
PLColor * cmap0
Definition: plstrm.h:544
int screen
Definition: pltkwd.h:51
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
#define LPAGE_X
Definition: plplotP.h:308
int nopixmap
Definition: plstrm.h:635
PLStream * pls
Definition: plplotter.c:132
short * dev_y
Definition: plstrm.h:582
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition: plctrl.c:2985
unsigned width
Definition: pltkwd.h:82
XColor fgcolor
Definition: pltkwd.h:62
#define PIXELS_Y
Definition: plplotP.h:305
plD_wait_fp pl_wait
Definition: disptab.h:91
void plRemakePlot(PLStream *pls)
Definition: plbuf.c:1397
float PLFLT
Definition: plplot.h:163
Colormap map
Definition: pltkwd.h:55
PLINT page
Definition: plstrm.h:578
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
int write_to_window
Definition: pltkwd.h:91
#define free_mem(a)
Definition: plplotP.h:182
TkwDisplay * tkwd
Definition: pltkwd.h:70
void PLColor_from_TkColor(PLColor *plcolor, XColor *xcolor)
PLDisplay pldis
Definition: plplotter.c:145
unsigned char r
Definition: plplot.h:548
struct PlPlotter * plPlotterPtr
Definition: plstrm.h:742
#define PLTKDISPLAYS
Definition: pltkwd.h:31
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
int max_instr
Definition: pltkwd.h:95
void pltkwin_setBGFG(PLStream *pls)
Display * display
Definition: plplotter.c:108
PLColor curcolor
Definition: plstrm.h:543
unsigned height
Definition: pltkwd.h:82
plD_state_fp pl_state
Definition: disptab.h:89
Definition: pltkwd.h:68
plD_eop_fp pl_eop
Definition: disptab.h:86
int write_to_pixmap
Definition: pltkwd.h:92
XColor cmap0[16]
Definition: pltkwd.h:60
PLINT debug
Definition: plstrm.h:527
Window window
Definition: pltkwd.h:72
PLINT ncol1
Definition: plstrm.h:539
#define PLESC_GETC
Definition: plplot.h:283
unsigned int width
Definition: plplot.h:462
PLINT dev_flush
Definition: plstrm.h:571
unsigned int y
Definition: plplot.h:461
plD_polyline_fp pl_polyline
Definition: disptab.h:85
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
void * dev
Definition: plstrm.h:594
Tcl_Interp * interp
Definition: plplotter.c:111
#define PLESC_EXPOSE
Definition: plplot.h:274
PLINT dev_fill0
Definition: plstrm.h:571
#define PL_MAXPOLY
Definition: plplotP.h:283
void Tkw_StoreColor(PLStream *pls, TkwDisplay *tkwd, XColor *col)
#define PLESC_FLUSH
Definition: plplot.h:281