PLplot: ntk.c Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ntk.c
Go to the documentation of this file.
1 // $Id: ntk.c 12932 2014-01-12 02:18:40Z airwin $
2 //
3 // Experimental tk driver using a plain "wish"
4 //
5 // Copyright (C) 2001 Joao Cardoso
6 // Copyright (C) 2004 Rafael Laboissiere
7 //
8 // This file is part of PLplot.
9 //
10 // PLplot is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Library General Public License as published
12 // by the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // PLplot is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU Library General Public License
21 // along with PLplot; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 //
25
26 #include "plDevs.h"
27
28 #ifdef PLD_ntk
29
30 #include "plplotP.h"
31 #include "drivers.h"
32 #include "plevent.h"
33
34 #include <tk.h>
35
36 // Device info
37 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_ntk = "ntk:New tk driver:1:ntk:43:ntk\n";
38
39
40 void plD_dispatch_init_ntk( PLDispatchTable *pdt );
41
42 void plD_init_ntk( PLStream * );
43 void plD_line_ntk( PLStream *, short, short, short, short );
44 void plD_polyline_ntk( PLStream *, short *, short *, PLINT );
45 void plD_eop_ntk( PLStream * );
46 void plD_bop_ntk( PLStream * );
47 void plD_tidy_ntk( PLStream * );
48 void plD_state_ntk( PLStream *, PLINT );
49 void plD_esc_ntk( PLStream *, PLINT, void * );
50
51 void plD_dispatch_init_ntk( PLDispatchTable *pdt )
52 {
53 #ifndef ENABLE_DYNDRIVERS
54 pdt->pl_MenuStr = "New Tk device";
55 pdt->pl_DevName = "ntk";
56 #endif
57 pdt->pl_type = plDevType_Interactive;
58 pdt->pl_seq = 43;
59 pdt->pl_init = (plD_init_fp) plD_init_ntk;
60 pdt->pl_line = (plD_line_fp) plD_line_ntk;
61 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_ntk;
62 pdt->pl_eop = (plD_eop_fp) plD_eop_ntk;
63 pdt->pl_bop = (plD_bop_fp) plD_bop_ntk;
64 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_ntk;
65 pdt->pl_state = (plD_state_fp) plD_state_ntk;
66 pdt->pl_esc = (plD_esc_fp) plD_esc_ntk;
67 }
68
69 // hardwired window size
70 #define XPIXELS 600
71 #define YPIXELS 400
72
73 static PLFLT scale = 10.0; // Tk canvas units are in pixels, giving corse curves, fool plplot, and scale down when sending to tk
74 static PLFLT ppm; // device pixels per mm
75
76 static Tcl_Interp *interp = NULL; // tcl interpreter
77 static Tk_Window mainw; // tk main window
78
79 static char curcolor[80]; // current color in #rrggbb notation
80
81 // 12000 is large enough to satisfy example 27 needs without
82 // erroring out in plD_polyline_ntk. Quadruple that to be conservative.
83 #define PLPLOT_NTK_CMD_SIZE 48000
84 static char cmd[PLPLOT_NTK_CMD_SIZE]; // buffer to build command to interp
85 static int ccanv = 0; // current canvas number
86 static char base[80]; // name of frame that contains the canvas
87 static char dash[80]; // dash string, as <mark space>*
88
89 // line buffering
90 #define NPTS 1000
91 static short xold = -1, yold = -1; // last point of last 2 points line
92 static short xb[NPTS], yb[NPTS]; // buffer
93 static int curpts = 0; // current number of points buffered
94
95 static int local = 1; // "local" or "remote" interpreter
96 static char rem_interp[80]; // name of remote interp
97
98 // physical devices coordinates
99 static PLINT xmin = 0;
100 static PLINT xmax = XPIXELS;
101 static PLINT ymin = 0;
102 static PLINT ymax = YPIXELS;
103
104 // locator
105 static PLGraphicsIn gin;
106
107 static void
108 tk_cmd( const char *gcmd )
109 {
110 static char scmd[PLPLOT_NTK_CMD_SIZE];
111
112 if ( local )
113 Tcl_Eval( interp, gcmd );
114 else
115 {
116 // the -async option makes it block, some times! but is *much* faster!
117 // and was working OK till now :(
118 // sprintf(scmd, "send -async %s {%s}", rem_interp, cmd);
119 //
120 sprintf( scmd, "send %s {%s}", rem_interp, gcmd ); // mess! make it more efficient
121 if ( Tcl_Eval( interp, scmd ) != TCL_OK )
122 fprintf( stderr, "%s\n", Tcl_GetStringResult( interp ) );
123 }
124 }
125
126 static void
127 create_canvas( PLStream *pls )
128 {
129 int columnbreak;
130
131 ccanv++;
132 columnbreak = ( ccanv % 30 == 0 );
133
134 // create new canvas
135 sprintf( cmd, "set ccanv %d; canvas $plf.f2.c$ccanv -width $xmax -height $ymax -background #%02x%02x%02x -xscrollcommand \"$hs set\" -yscrollcommand \"$vs set\" -scrollregion \"0 0 $xmax $ymax\"", ccanv, pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b );
136 tk_cmd( cmd );
137
138 // add new canvas to option menu
139 sprintf( cmd, "$plf.f1.mb.menu add command -label \"Page $ccanv\" -columnbreak %d -command {\n"
140 "set w $plf.f2.c%d;\n"
141 "$hs configure -command \"$w xview\";\n"
142 "$vs configure -command \"$w yview\";\n"
143 "set dname \"Page %d\";\n"
144 "pack forget $ocanvas;\n"
145 "set ocanvas $plf.f2.c%d;\n"
146 "pack $ocanvas -fill both -expand 1;\n"
147 "scan [$w xview] \"%%f %%f\" i j;\n"
148 "$hs set $i $j;\n"
149 "scan [$w yview] \"%%f %%f\" i j;\n"
150 "$vs set $i $j;}",
151 columnbreak, ccanv, ccanv, ccanv );
152 tk_cmd( cmd );
153
154 sprintf( cmd, "set item(%d) 0", ccanv );
155 tk_cmd( cmd );
156
157 // Shif-B1, zooms in
158 // FIXME inform the core lib of the zoom, see plframe.c around line 2818
159
160 sprintf( cmd, "bind $plf.f2.c$ccanv <Shift-Button-1> {\n"
161 "set cc %d;\n"
162 "incr item($cc); set tt $item($cc);\n"
163 "if {$tt == 1} {\n"
164 "incr scroll_use;\n"
165 "pack $hs -side bottom -fill x;\n"
166 "pack $vs -side right -fill y;\n"
167 "pack forget %%W; pack %%W -fill both -expand 1}\n"
168 "set zx($cc,$tt) %%x;\n"
169 "set zy($cc,$tt) %%y;\n"
170 "%%W scale all %%x %%y 1.6 1.6;\n"
171 "%%W configure -scrollregion [%%W bbox all];\n"
172 "}", ccanv );
173
174 tk_cmd( cmd );
175
176 // Shif-B3, zooms out
177 sprintf( cmd, "bind $plf.f2.c$ccanv <Shift-Button-3> {\n"
178 "set cc %d; set tt $item($cc);\n"
179 "if {$tt != 0} {\n"
180 "%%W scale all $zx($cc,$tt) $zy($cc,$tt) 0.625 0.625\n"
181 "%%W configure -scrollregion [%%W bbox all];\n"
182 "set item($cc) [expr $tt - 1]}\n"
183 "if { $item($cc) == 0} {\n"
184 "set scroll_use [expr $scroll_use - 1];\n"
185 "if {$scroll_use == 0} {\n"
186 "pack forget $plf.f2.hscroll $plf.f2.vscroll}\n"
187 "%%W configure -scrollregion \"0 0 $xmax $ymax\"}}", ccanv );
188 tk_cmd( cmd );
189
190 // Shift-B2, resets
191 sprintf( cmd, "bind $plf.f2.c$ccanv <Shift-Button-2> {\n"
192 "set cc %d; set tt $item($cc); \n"
193 "while {$tt != 0} {\n"
194 "%%W scale all $zx($cc,$tt) $zy($cc,$tt) 0.625 0.625\n"
195 "set tt [expr $tt - 1]};\n"
196 "set item($cc) 0;\n"
197 "%%W configure -scrollregion \"0 0 $xmax $ymax\";\n"
198 "set scroll_use [expr $scroll_use - 1];\n"
199 "if {$scroll_use == 0} {\n"
200 "pack forget $plf.f2.hscroll $plf.f2.vscroll}}", ccanv );
201 tk_cmd( cmd );
202
203 // Control-B1-Motion, pan
204 sprintf( cmd, "bind $plf.f2.c$ccanv <Control-Button-1> \"$plf.f2.c%d scan mark %%x %%y\"", ccanv );
205 tk_cmd( cmd );
206
207 sprintf( cmd, "bind $plf.f2.c$ccanv <Control-Button1-Motion> \"$plf.f2.c%d scan dragto %%x %%y\"", ccanv );
208 tk_cmd( cmd );
209
210 // Control-B2, identify and (in the far future) edit object
211 tk_cmd( "bind $plf.f2.c$ccanv <Control-Button-2> {\n"
212 "set xx [ expr [winfo pointerx .] - [winfo rootx %W]];\n"
213 "set yy [ expr [winfo pointery .] - [winfo rooty %W]];\n"
214 "set near [%W find closest $xx $yy];\n"
215 "%W move $near 20 20;\n"
216 "after 500 \"%W move $near -20 -20\"}" );
217
218 // change view to the new canvas by invoking the menu buttom
219 sprintf( cmd, "$plf.f1.mb.menu invoke %d", ccanv - 1 );
220 tk_cmd( cmd );
221 }
222
223 //--------------------------------------------------------------------------
224 // plD_init_ntk()
225 //
226 // Initialize device (terminal).
227 //--------------------------------------------------------------------------
228
229 void
230 plD_init_ntk( PLStream *pls )
231 {
232 pls->dev_fill0 = 1; // Handle solid fills
233 pls->dev_fill1 = 1; // Driver handles pattern fills
234 pls->color = 1; // Is a color device
235 pls->dev_dash = 1; // Handle dashed lines
236 pls->plbuf_write = 1; // Use plot buffer
237
238 strcpy( curcolor, "black" ); // default color by name, not #rrggbb
239
240 if ( pls->server_name != NULL )
241 {
242 local = 0;
243 strcpy( rem_interp, pls->server_name );
244 }
245
246 if ( pls->geometry != NULL )
247 sscanf( pls->geometry, "%dx%d", &xmax, &ymax );
248
249 // if ( pls->plwindow != NULL )
250 // strcpy( base, pls->plwindow );
251 // else
252 strcpy( base, ".plf" ); // default frame containing the canvas
253
254 interp = Tcl_CreateInterp();
255
256 if ( Tcl_Init( interp ) != TCL_OK )
257 plexit( "Unable to initialize Tcl." );
258
259 if ( Tk_Init( interp ) )
260 plexit( "Unable to initialize Tk." );
261
262 mainw = Tk_MainWindow( interp );
263 Tcl_Eval( interp, "rename exec {}" );
264
265 Tcl_Eval( interp, "tk appname PLplot_ntk" ); // give interpreter a name
266
267 if ( !local )
268 {
269 Tcl_Eval( interp, "wm withdraw ." );
270
271 sprintf( cmd, "send %s \"set client [tk appname]; wm deiconify .\"", rem_interp );
272 if ( Tcl_Eval( interp, cmd ) != TCL_OK )
273 {
274 fprintf( stderr, "%s\n", Tcl_GetStringResult( interp ) );
275 plexit( "No such tk server." );
276 }
277 }
278
279 sprintf( cmd, "set scroll_use 0; set plf %s; set vs $plf.f2.vscroll; set hs $plf.f2.hscroll; set xmax %d; set ymax %d; set ocanvas .;", base, xmax, ymax );
280 tk_cmd( cmd );
281
282 tk_cmd( "catch \"frame $plf\"; pack $plf -fill both -expand 1" );
283
284 sprintf( cmd, "frame $plf.f1;\n"
285 "frame $plf.f2 -width %d -height %d;\n"
286 "pack $plf.f1 -fill x;\n"
287 "pack $plf.f2 -fill both -expand 1", xmax, ymax );
288 tk_cmd( cmd );
289
290 tk_cmd( "scrollbar $plf.f2.hscroll -orient horiz;\n"
291 "scrollbar $plf.f2.vscroll" );
292
293 tk_cmd( "menubutton $plf.f1.mb -text \"Page 1\" -textvariable dname -relief raised -indicatoron 1 -menu $plf.f1.mb.menu;\n"
294 "menu $plf.f1.mb.menu -tearoff 0;\n"
295 "pack $plf.f1.mb -side left" );
296
297 if ( local )
298 tk_cmd( "button $plf.f1.quit -text Quit -command exit;\n"
299 "pack $plf.f1.quit -side right" );
300 else
301 tk_cmd( "button $plf.f1.quit -text Quit -command {send -async $client exit;\n"
302 "destroy $plf;\n"
303 "wm withdraw .};\n"
304 "pack $plf.f1.quit -side right" );
305
306 // FIXME: I just discovered that Tcl_Eval is slower than Tcl_EvalObj. Fix it global-wide, `man Tcl_Eval'
307
308 // Set up device parameters
309
310 Tcl_Eval( interp, "tk scaling" ); // pixels per mm
311 ppm = (PLFLT) atof( Tcl_GetStringResult( interp ) ) / ( 25.4 / 72. );
312 plP_setpxl( ppm, ppm );
313 plP_setphy( xmin, (PLINT) ( xmax * scale ), ymin, (PLINT) ( ymax * scale ) );
314
315 tk_cmd( "update" );
316 }
317
318 static void
319 flushbuffer( PLStream *pls )
320 {
321 if ( curpts )
322 {
323 plD_polyline_ntk( pls, xb, yb, curpts );
324 // if (curpts != 2) fprintf(stderr,"%d ", curpts);
325 xold = yold = -1; curpts = 0;
326 }
327 }
328
329 void
330 plD_line_ntk( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
331 {
332 if ( xold == x1a && yold == y1a )
333 {
334 xold = xb[curpts] = x2a; yold = yb[curpts] = y2a; curpts++;
335 }
336 else
337 {
338 flushbuffer( pls );
339 xb[curpts] = x1a; yb[curpts] = y1a; curpts++;
340 xold = xb[curpts] = x2a; yold = yb[curpts] = y2a; curpts++;
341 }
342
343 if ( curpts == NPTS )
344 {
345 //fprintf( stderr, "\nflush: %d ", curpts );
346 flushbuffer( pls );
347 }
348 }
349
350 void
351 plD_polyline_ntk( PLStream * PL_UNUSED( pls ), short *xa, short *ya, PLINT npts )
352 {
353 PLINT i, j;
354
355 // there must exist a way to code this using the tk C API
356 j = sprintf( cmd, "$plf.f2.c%d create line ", ccanv );
357 for ( i = 0; i < npts; i++ )
358 {
359 // To be completely safe, assume 5 characters to the left of the
360 // decimal point ==> 2*(5+3) characters written per sprintf
361 // call.
362 if ( ( j + 16 ) > PLPLOT_NTK_CMD_SIZE )
363 plexit( "plD_polyline_ntk: too many x, y values to hold in static cmd array" );
364 j += sprintf( &cmd[j], "%.1f %.1f ", xa[i] / scale, ymax - ya[i] / scale );
365 }
366 j += sprintf( &cmd[j], " -fill %s", curcolor );
367 if ( dash[0] == '-' )
368 j += sprintf( &cmd[j], " %s", dash );
369
370 tk_cmd( cmd );
371 }
372
373 // an event loop has to be designed, getcursor() and waitforpage() are just experimental
374
375 static void
376 waitforpage( PLStream * PL_UNUSED( pls ) )
377 {
378 int key = 0, st = 0;
379 // why can't I bind to the canvas? or even any frame?
380 //tk_cmd("bind . <KeyPress> {set keypress %N; puts \"\n%k-%A-%K-%N\"}");
381 tk_cmd( "bind . <KeyPress> {set keypress %N}" );
382
383 while ( ( key & 0xff ) != PLK_Return && ( key & 0xff ) != PLK_Linefeed && key != PLK_Next && key != 'Q' )
384 {
385 while ( st != 1 )
386 {
387 tk_cmd( "update" );
388 tk_cmd( "info exists keypress" );
389 sscanf( Tcl_GetStringResult( interp ), "%d", &st );
390 }
391
392 tk_cmd( "set keypress" );
393 sscanf( Tcl_GetStringResult( interp ), "%d", &key );
394 //fprintf(stderr,"\n%d\n", key);fflush(stderr);
395 tk_cmd( "unset keypress" );
396 st = 0;
397 }
398
399 tk_cmd( "bind . <Key> {};" );
400 }
401
402 void
403 plD_eop_ntk( PLStream *pls )
404 {
405 flushbuffer( pls );
406 tk_cmd( "update" );
407 }
408
409 void
410 plD_bop_ntk( PLStream *pls )
411 {
412 create_canvas( pls );
413 }
414
415 void
416 plD_tidy_ntk( PLStream *pls )
417 {
418 if ( !pls->nopause )
419 waitforpage( pls );
420
421 tk_cmd( "destroy $plf; wm withdraw ." );
422 }
423
424 void
425 plD_state_ntk( PLStream *pls, PLINT op )
426 {
427 switch ( op )
428 {
429 case PLSTATE_COLOR0:
430 case PLSTATE_COLOR1:
431 flushbuffer( pls );
432 sprintf( curcolor, "#%02x%02x%02x",
433 pls->curcolor.r, pls->curcolor.g, pls->curcolor.b );
434 break;
435 }
436 }
437
438 static void
439 getcursor( PLStream * PL_UNUSED( pls ), PLGraphicsIn *ptr )
440 {
441 int st = 0;
442
443 plGinInit( &gin );
444
445 if ( 0 )
446 {
447 while ( st != 1 )
448 {
449 tk_cmd( "update" );
450 tk_cmd( "winfo exists $plf.f2.c$ccanv" );
451 sscanf( Tcl_GetStringResult( interp ), "%d", &st );
452 }
453 st = 0;
454 // this give a "Segmentation fault", even after checking for the canvas!
455 tk_cmd( "set ocursor [lindex [$plf.f2.c$ccanv configure -cursor] 4]" );
456 }
457
458 tk_cmd( "$plf.f2.c$ccanv configure -cursor cross;\n"
459 "bind $plf.f2.c$ccanv <Button> {set xloc %x; set yloc %y; set bloc %b; set sloc %s};\n"
460 "bind $plf.f2.c$ccanv <B1-Motion> {set xloc %x; set yloc %y; set bloc %b; set sloc %s};\n"
461 "bind $plf.f2.c$ccanv <B2-Motion> {set xloc %x; set yloc %y; set bloc %b; set sloc %s};\n"
462 "bind $plf.f2.c$ccanv <B3-Motion> {set xloc %x; set yloc %y; set bloc %b; set sloc %s};" );
463
464 while ( st != 1 )
465 {
466 tk_cmd( "update" );
467 tk_cmd( "info exists xloc" );
468 sscanf( Tcl_GetStringResult( interp ), "%d", &st );
469 }
470 tk_cmd( "set xloc" );
471 sscanf( Tcl_GetStringResult( interp ), "%d", &gin.pX );
472 tk_cmd( "set yloc" );
473 sscanf( Tcl_GetStringResult( interp ), "%d", &gin.pY );
474 tk_cmd( "set bloc" );
475 sscanf( Tcl_GetStringResult( interp ), "%ud", &gin.button );
476 tk_cmd( "set sloc" );
477 sscanf( Tcl_GetStringResult( interp ), "%ud", &gin.state );
478
479 gin.dX = (PLFLT) gin.pX / xmax;
480 gin.dY = 1. - (PLFLT) gin.pY / ymax;
481
482 tk_cmd( "bind $plf.f2.c$ccanv <ButtonPress> {};\n"
483 "bind $plf.f2.c$ccanv <ButtonMotion> {};\n"
484 "bind $plf.f2.c$ccanv <B2-Motion> {};\n"
485 "bind $plf.f2.c$ccanv <B3-Motion> {};\n"
486 "unset xloc" );
487
488 // seg fault, see above. tk_cmd("$plf.f2.c$ccanv configure -cursor $ocursor");
489 tk_cmd( "$plf.f2.c$ccanv configure -cursor {}" );
490
491 *ptr = gin;
492 }
493
494 void
495 plD_esc_ntk( PLStream *pls, PLINT op, void *ptr )
496 {
497 PLINT i, j;
498 short *xa, *ya;
499 //Pixmap bitmap;
500 static const unsigned char bit_pat[] = {
501 0x24, 0x01, 0x92, 0x00, 0x49, 0x00, 0x24, 0x00, 0x12, 0x00, 0x09, 0x00,
502 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
504 };
505
506 switch ( op )
507 {
508 case PLESC_DASH:
509 xa = (short *) malloc( sizeof ( short ) * (size_t) pls->dev_npts );
510 ya = (short *) malloc( sizeof ( short ) * (size_t) pls->dev_npts );
511 for ( i = 0; i < pls->dev_npts; i++ )
512 {
513 xa[i] = pls->dev_x[i];
514 ya[i] = pls->dev_y[i];
515 }
516
517 j = sprintf( dash, "-dash {" );
518 for ( i = 0; i < pls->nms; i++ )
519 j += sprintf( &dash[j], " %d %d",
520 (int) ceil( pls->mark[i] / 1e3 * ppm ),
521 (int) ceil( pls->space[i] / 1e3 * ppm ) );
522 sprintf( &dash[j], "}" );
523 plD_polyline_ntk( pls, xa, ya, pls->dev_npts );
524 free( xa ); free( ya );
525 dash[0] = 0;
526 break;
527
528 case PLESC_FLUSH:
529 tk_cmd( "update" );
530 break;
531
532 case PLESC_GETC:
533 getcursor( pls, (PLGraphicsIn *) ptr );
534 break;
535
536 case PLESC_FILL:
537 if ( pls->patt != 0 )
538 {
539 // this is a hack! The real solution is in the if(0) below
540 pls->xpmm *= scale;
541 pls->ypmm *= scale;
542 plfill_soft( pls->dev_x, pls->dev_y, pls->dev_npts );
543 pls->xpmm /= scale;
544 pls->ypmm /= scale;
545 }
546 else
547 {
548 j = sprintf( cmd, "$plf.f2.c%d create polygon ", ccanv );
549 for ( i = 0; i < pls->dev_npts; i++ )
550 j += sprintf( &cmd[j], "%.1f %.1f ", pls->dev_x[i] / scale,
551 ymax - pls->dev_y[i] / scale );
552 j += sprintf( &cmd[j], " -fill %s", curcolor );
553 tk_cmd( cmd );
554 }
555
556 if ( 0 )
557 {
558 if ( pls->patt != 0 )
559 {
560 Tk_DefineBitmap( interp, Tk_GetUid( "foo" ), (const char *) bit_pat, 16, 16 );
561 //bitmap = Tk_GetBitmap( interp, mainw, Tk_GetUid( "patt" ) );
562 }
563 j = sprintf( cmd, "$plf.f2.c%d create polygon ", ccanv );
564 for ( i = 0; i < pls->dev_npts; i++ )
565 j += sprintf( &cmd[j], "%.1f %.1f ", pls->dev_x[i] / scale,
566 ymax - pls->dev_y[i] / scale );
567 j += sprintf( &cmd[j], " -fill %s", curcolor );
568 if ( pls->patt != 0 )
569 sprintf( &cmd[j], " -stipple patt -outline black" );
570
571 tk_cmd( cmd );
572 //Tk_FreeBitmap(display, bitmap)
573 }
574 break;
575 }
576 }
577
578 #else
579 int
580 pldummy_ntk()
581 {
582 return 0;
583 }
584
585 #endif // PLD_ntkdev