PLplot: plcore.c Source File

PLplot 5.15.0

plcore.c
Go to the documentation of this file.
1 // Central dispatch facility for PLplot.
2 // Also contains the PLplot main data structures, external access
3 // routines, and initialization calls.
4 //
5 // This stuff used to be in "dispatch.h", "dispatch.c", and "base.c".
6 //
7 //
8 // Copyright (C) 1993-2001 Geoffrey Furnish
9 // Copyright (C) 1993-2006 Maurice LeBrun
10 // Copyright (C) 1996 Rady Shouman
11 // Copyright (C) 2000-2019 Alan W. Irwin
12 // Copyright (C) 2001-2003 Joao Cardoso
13 // Copyright (C) 2001-2005 Rafael Laboissiere
14 // Copyright (C) 2004-2007 Andrew Roach
15 // Copyright (C) 2004-2015 Andrew Ross
16 // Copyright (C) 2005 Thomas Duck
17 // Copyright (C) 2005-2015 Arjen Markus
18 // Copyright (C) 2006-2011 Hazen Babcock
19 // Copyright (C) 2008-2009 Werner Smekal
20 // Copyright (C) 2009-2011 Hezekiah M. Carty
21 // Copyright (C) 2015 Jim Dishaw
22 // Copyright (C) 2015 jdishaw
23 // Copyright (C) 2015-2017 Phil Rosenberg
24 //
25 // This file is part of PLplot.
26 //
27 // PLplot is free software; you can redistribute it and/or modify
28 // it under the terms of the GNU Library General Public License as published
29 // by the Free Software Foundation; either version 2 of the License, or
30 // (at your option) any later version.
31 //
32 // PLplot is distributed in the hope that it will be useful,
33 // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 // GNU Library General Public License for more details.
36 //
37 // You should have received a copy of the GNU Library General Public License
38 // along with PLplot; if not, write to the Free Software
39 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
40 //
41 //
42
43 #define DEBUG
44 #define NEED_PLDEBUG
45 #include "plcore.h"
46
47 #ifdef ENABLE_DYNDRIVERS
48 #ifndef LTDL_WIN32
49 #include <ltdl.h>
50 #else
51 #include "ltdl_win32.h"
52 #endif
53 #endif
54
55 #if HAVE_DIRENT_H
56 // The following conditional is a workaround for a bug in the MacOSX system.
57 // When the dirent.h file will be fixed upstream by Apple Inc, this should
58 // go away.
59 # ifdef NEED_SYS_TYPE_H
60 # include <sys/types.h>
61 # endif
62 # include <dirent.h>
63 # define NAMLEN( dirent ) strlen( ( dirent )->d_name )
64 #else
65 # if defined ( _MSC_VER )
66 # include "dirent_msvc.h"
67 # else
68 # define dirent direct
69 # define NAMLEN( dirent ) ( dirent )->d_namlen
70 # if HAVE_SYS_NDIR_H
71 # include <sys/ndir.h>
72 # endif
73 # if HAVE_SYS_DIR_H
74 # include <sys/dir.h>
75 # endif
76 # if HAVE_NDIR_H
77 # include <ndir.h>
78 # endif
79 # endif
80 #endif
81
82 // AM: getcwd has a somewhat strange status on Windows, its proper
83 // name is _getcwd, this is a problem in the case of DLLs, like with
84 // the Java bindings. The functions _getcwd() and chdir() are
85 // declared in direct.h for Visual C++. Since chdir() is deprecated
86 // (but still available) in Visual C++ we redefine chdir to _chdir.
87 //
88 #if defined ( _MSC_VER )
89 # include <direct.h>
90 # define getcwd _getcwd
91 # define chdir _chdir
92 #endif
93
94 #define BUFFER_SIZE 80
95 #define BUFFER2_SIZE 300
96 #define DRVSPEC_SIZE 400
97
98 #include <errno.h>
99
100 int
101 text2num( PLCHAR_VECTOR text, char end, PLUNICODE *num );
102
103 int
104 text2fci( PLCHAR_VECTOR text, unsigned char *hexdigit, unsigned char *hexpower );
105
106 //--------------------------------------------------------------------------
107 // Driver Interface
108 //
109 // These routines are the low-level interface to the driver -- all calls to
110 // driver functions must pass through here. For implementing driver-
111 // specific functions, the escape function is provided. The command stream
112 // gets duplicated to the plot buffer here.
113 //
114 // All functions that result in graphics actually being plotted (rather than
115 // just a change of state) are filtered as necessary before being passed on.
116 // The default settings do not require any filtering, i.e. PLplot physical
117 // coordinates are the same as the device physical coordinates (currently
118 // this can't be changed anyway), and a global view equal to the entire page
119 // is used.
120 //
121 // The reason one wants to put view-specific filtering here is that if
122 // enabled, the plot buffer should receive the unfiltered data stream. This
123 // allows a specific view to be used from an interactive device (e.g. TCL/TK
124 // driver) but be restored to the full view at any time merely by
125 // reprocessing the contents of the plot buffer.
126 //
127 // The metafile, on the other hand, *should* be affected by changes in the
128 // view, since this is a crucial editing capability. It is recommended that
129 // the initial metafile be created without a restricted global view, and
130 // modification of the view done on a per-plot basis as desired during
131 // subsequent processing.
132 //
133 //--------------------------------------------------------------------------
134
135 // Initialize device.
136 // The plot buffer must be called last.
137
138 // The following array of chars is used both here and in plsym.c for
139 // translating the Greek characters from the #g escape sequences into
140 // the Hershey and Unicode codings
141 //
142 const char plP_greek_mnemonic[] = "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw";
143
144 void
145 plP_init( void )
146 {
147 char * save_locale;
148 plsc->page_status = AT_EOP;
149 plsc->stream_closed = FALSE;
150
151 save_locale = plsave_set_locale();
152 ( *plsc->dispatch_table->pl_init )( (struct PLStream_struct *) plsc );
153 plrestore_locale( save_locale );
154
155 if ( plsc->plbuf_write )
156 plbuf_init( plsc );
157 }
158
159 // End of page
160 // The plot buffer must be called first.
161 // Ignore instruction if already at eop.
162
163 void
164 plP_eop( void )
165 {
166 int skip_driver_eop = 0;
167
168 if ( plsc->page_status == AT_EOP )
169 return;
170
171 plsc->page_status = AT_EOP;
172
173 if ( plsc->plbuf_write )
174 plbuf_eop( plsc );
175
176 // Call user eop handler if present.
177
178 if ( plsc->eop_handler != NULL )
179 ( *plsc->eop_handler )( plsc->eop_data, &skip_driver_eop );
180
181 if ( !skip_driver_eop )
182 {
183 char *save_locale = plsave_set_locale();
184 if ( !plsc->stream_closed )
185 {
186 ( *plsc->dispatch_table->pl_eop )( (struct PLStream_struct *) plsc );
187 }
188 plrestore_locale( save_locale );
189 }
190 }
191
192 // Set up new page.
193 // The plot buffer must be called last.
194 // Ignore if already at bop.
195 // It's not actually necessary to be AT_EOP here, so don't check for it.
196
197 void
198 plP_bop( void )
199 {
200 int skip_driver_bop = 0;
201
202 plP_subpInit();
203 if ( plsc->page_status == AT_BOP )
204 return;
205
206 plsc->page_status = AT_BOP;
207 plsc->nplwin = 0;
208
209 // Call user bop handler if present.
210
211 if ( plsc->bop_handler != NULL )
212 ( *plsc->bop_handler )( plsc->bop_data, &skip_driver_bop );
213
214 if ( !skip_driver_bop )
215 {
216 char *save_locale = plsave_set_locale();
217 if ( !plsc->stream_closed )
218 {
219 ( *plsc->dispatch_table->pl_bop )( (struct PLStream_struct *) plsc );
220 }
221 plrestore_locale( save_locale );
222 }
223
224 if ( plsc->plbuf_write )
225 plbuf_bop( plsc );
226 }
227
228 // Tidy up device (flush buffers, close file, etc).
229
230 void
231 plP_tidy( void )
232 {
233 char * save_locale;
234 if ( plsc->tidy )
235 {
236 ( *plsc->tidy )( plsc->tidy_data );
237 plsc->tidy = NULL;
238 plsc->tidy_data = NULL;
239 }
240
241 save_locale = plsave_set_locale();
242 ( *plsc->dispatch_table->pl_tidy )( (struct PLStream_struct *) plsc );
243 plrestore_locale( save_locale );
244
245 if ( plsc->plbuf_write )
246 {
247 plbuf_tidy( plsc );
248 }
249
250 plsc->OutFile = NULL;
251 }
252
253 // Change state.
254
255 void
256 plP_state( PLINT op )
257 {
258 char * save_locale;
259 if ( plsc->plbuf_write )
260 plbuf_state( plsc, op );
261
262 save_locale = plsave_set_locale();
263 if ( !plsc->stream_closed )
264 {
265 ( *plsc->dispatch_table->pl_state )( (struct PLStream_struct *) plsc, op );
266 }
267 plrestore_locale( save_locale );
268 }
269
270 // Escape function, for driver-specific commands.
271
272 void
273 plP_esc( PLINT op, void *ptr )
274 {
275 char * save_locale;
276 PLINT clpxmi, clpxma, clpymi, clpyma;
277 EscText* args;
278
279 // The plot buffer must be called first
280 if ( plsc->plbuf_write )
281 plbuf_esc( plsc, op, ptr );
282
283 // Text coordinates must pass through the driver interface filter
284 if ( ( op == PLESC_HAS_TEXT && plsc->dev_unicode ) ||
285 ( op == PLESC_END_TEXT && plsc->alt_unicode ) )
286 {
287 // Apply the driver interface filter
288 if ( plsc->difilt )
289 {
290 args = (EscText *) ptr;
291 difilt( &( args->x ), &( args->y ), 1, &clpxmi, &clpxma, &clpymi, &clpyma );
292 }
293 }
294
295 save_locale = plsave_set_locale();
296 if ( !plsc->stream_closed )
297 {
298 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc, op, ptr );
299 }
300 plrestore_locale( save_locale );
301 }
302
303 // Set up plot window parameters.
304 // The plot buffer must be called first
305 // Some drivers (metafile, Tk) need access to this data
306
307 void
308 plP_swin( PLWindow *plwin )
309 {
310 PLWindow *w;
311 PLINT clpxmi, clpxma, clpymi, clpyma;
312
313 // Provide plot buffer with unfiltered window data
314
315 if ( plsc->plbuf_write )
316 plbuf_esc( plsc, PLESC_SWIN, (void *) plwin );
317
318 w = &plsc->plwin[plsc->nplwin++ % PL_MAXWINDOWS];
319
320 w->dxmi = plwin->dxmi;
321 w->dxma = plwin->dxma;
322 w->dymi = plwin->dymi;
323 w->dyma = plwin->dyma;
324
325 if ( plsc->difilt )
326 {
327 xscl[0] = plP_dcpcx( w->dxmi );
328 xscl[1] = plP_dcpcx( w->dxma );
329 yscl[0] = plP_dcpcy( w->dymi );
330 yscl[1] = plP_dcpcy( w->dyma );
331
332 difilt( xscl, yscl, 2, &clpxmi, &clpxma, &clpymi, &clpyma );
333
334 w->dxmi = plP_pcdcx( xscl[0] );
335 w->dxma = plP_pcdcx( xscl[1] );
336 w->dymi = plP_pcdcy( yscl[0] );
337 w->dyma = plP_pcdcy( yscl[1] );
338 }
339
340 w->wxmi = plwin->wxmi;
341 w->wxma = plwin->wxma;
342 w->wymi = plwin->wymi;
343 w->wyma = plwin->wyma;
344
345 // If the driver wants to process swin commands, call it now
346 // It must use the filtered data, which it can get from *plsc
347
348 if ( plsc->dev_swin )
349 {
350 char *save_locale = plsave_set_locale();
351 if ( !plsc->stream_closed )
352 {
353 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
354 PLESC_SWIN, NULL );
355 }
356 plrestore_locale( save_locale );
357 }
358 }
359
360 // Calls the device specific wait for user input function. This
361 // action depends on the state of the nopause flag and whether
362 // user input is supported by the driver.
363
364 void
365 plP_wait( void )
366 {
367 // If the nopause is disabled (which means pauses are wanted) and the
368 // the device supports waiting for user input
369 if ( !plsc->nopause && *plsc->dispatch_table->pl_wait != NULL )
370 {
371 char *save_locale = plsave_set_locale();
372 if ( !plsc->stream_closed )
373 {
374 ( *plsc->dispatch_table->pl_wait )( (struct PLStream_struct *) plsc );
375 }
376 plrestore_locale( save_locale );
377 }
378 }
379
380 //--------------------------------------------------------------------------
381 // Drawing commands.
382 //--------------------------------------------------------------------------
383
384 // Draw line between two points
385 // The plot buffer must be called first so it gets the unfiltered data
386
387 void
388 plP_line( short *x, short *y )
389 {
390 PLINT i, npts = 2, clpxmi, clpxma, clpymi, clpyma;
391
392 plsc->page_status = DRAWING;
393
394 if ( plsc->plbuf_write )
395 plbuf_line( plsc, x[0], y[0], x[1], y[1] );
396
397 if ( plsc->difilt )
398 {
399 for ( i = 0; i < npts; i++ )
400 {
401 xscl[i] = x[i];
402 yscl[i] = y[i];
403 }
404 difilt( xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma );
405 plP_pllclp( xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma, grline );
406 }
407 else
408 {
409 grline( x, y, npts );
410 }
411 }
412
413 // Draw polyline
414 // The plot buffer must be called first
415
416 void
417 plP_polyline( short *x, short *y, PLINT npts )
418 {
419 PLINT i, clpxmi, clpxma, clpymi, clpyma;
420
421 plsc->page_status = DRAWING;
422
423 if ( plsc->plbuf_write )
424 plbuf_polyline( plsc, x, y, npts );
425
426 if ( plsc->difilt )
427 {
428 for ( i = 0; i < npts; i++ )
429 {
430 xscl[i] = x[i];
431 yscl[i] = y[i];
432 }
433 difilt( xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma );
434 plP_pllclp( xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma,
435 grpolyline );
436 }
437 else
438 {
439 grpolyline( x, y, npts );
440 }
441 }
442
443 // Fill polygon
444 // The plot buffer must be called first
445 // Here if the desired area fill capability isn't present, we mock up
446 // something in software
447
448 static int foo;
449
450 void
451 plP_fill( short *x, short *y, PLINT npts )
452 {
453 PLINT i, clpxmi, clpxma, clpymi, clpyma;
454
455 plsc->page_status = DRAWING;
456
457 if ( plsc->plbuf_write )
458 {
459 plsc->dev_npts = npts;
460 plsc->dev_x = x;
461 plsc->dev_y = y;
462 plbuf_esc( plsc, PLESC_FILL, NULL );
463 }
464
465 // Account for driver ability to do fills
466
467 if ( plsc->patt == 0 && !plsc->dev_fill0 )
468 {
469 if ( !foo )
470 {
471 plwarn( "Driver does not support hardware solid fills, switching to software fill.\n" );
472 foo = 1;
473 }
474 plsc->patt = 8;
475 plpsty( plsc->patt );
476 }
477 if ( plsc->dev_fill1 )
478 {
479 plsc->patt = -ABS( plsc->patt );
480 }
481
482 // Perform fill. Here we MUST NOT allow the software fill to pass through the
483 // driver interface filtering twice, else we get the infamous 2*rotation for
484 // software fills on orientation swaps.
485 //
486
487 if ( plsc->patt > 0 )
488 plfill_soft( x, y, npts );
489
490 else
491 {
492 if ( plsc->difilt )
493 {
494 for ( i = 0; i < npts; i++ )
495 {
496 xscl[i] = x[i];
497 yscl[i] = y[i];
498 }
499 difilt( xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma );
500 plP_plfclp( xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma,
501 grfill );
502 }
503 else
504 {
505 grfill( x, y, npts );
506 }
507 }
508 }
509
510 // Render a gradient
511 // The plot buffer must be called first
512 // N.B. plP_gradient is never called (see plgradient) unless the
513 // device driver has set plsc->dev_gradient to true.
514
515 void
516 plP_gradient( short *x, short *y, PLINT npts )
517 {
518 PLINT i, clpxmi, clpxma, clpymi, clpyma;
519
520 plsc->page_status = DRAWING;
521
522 if ( plsc->plbuf_write )
523 {
524 plsc->dev_npts = npts;
525 plsc->dev_x = x;
526 plsc->dev_y = y;
527 plbuf_esc( plsc, PLESC_GRADIENT, NULL );
528 }
529
530 // Render gradient with driver.
531 if ( plsc->difilt )
532 {
533 for ( i = 0; i < npts; i++ )
534 {
535 xscl[i] = x[i];
536 yscl[i] = y[i];
537 }
538 difilt( xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma );
539 plP_plfclp( xscl, yscl, npts, clpxmi, clpxma, clpymi, clpyma,
540 grgradient );
541 }
542 else
543 {
544 grgradient( x, y, npts );
545 }
546 }
547
548 // Account for driver ability to draw text itself
549 //
550 // #define DEBUG_TEXT
551 //
552
553 //--------------------------------------------------------------------------
554 // int text2num( char *text, char end, PLUNICODE *num)
555 // char *text - pointer to the text to be parsed
556 // char end - end character (i.e. ')' or ']' to stop parsing
557 // PLUNICODE *num - pointer to an PLUNICODE to store the value
558 //
559 // Function takes a string, which can be either hex or decimal,
560 // and converts it into an PLUNICODE, stopping at either a null,
561 // or the character pointed to by 'end'. This implementation using
562 // the C library strtoul replaces the original brain-dead version
563 // and should be more robust to invalid control strings.
564 //--------------------------------------------------------------------------
565
566 int text2num( PLCHAR_VECTOR text, char end, PLUNICODE *num )
567 {
568 char *endptr;
569 // This special base logic required to _avoid_ interpretation of
570 // numbers with leading zeroes as octal numbers if base = 0.
571 int base = 10;
572 if ( !strncmp( text, "0x", 2 ) || !strncmp( text, "0X", 2 ) )
573 base = 16;
574
575 *num = (PLUNICODE) strtoul( text, &endptr, base );
576
577 if ( end != endptr[0] )
578 {
579 char msgbuf[BUFFER2_SIZE];
580 snprintf( msgbuf, BUFFER2_SIZE, "text2num: for base = %d, strtoul found invalid non-numeric character \"%c\" detected in string \"%s\" when looking for \"%c\" ", base, *endptr, text, end );
581 plwarn( msgbuf );
582 }
583
584 return (int) ( endptr - text );
585 }
586
587 //--------------------------------------------------------------------------
588 // int text2fci( char *text, unsigned char *hexdigit, unsigned char *hexpower)
589 // char *text - pointer to the text to be parsed
590 // unsigned char *hexdigit - pointer to hex value that is stored.
591 // unsigned char *hexpower - pointer to hex power (left shift) that is stored.
592 //
593 // Function takes a pointer to a string, which is looked up in a table
594 // to determine the corresponding FCI (font characterization integer)
595 // hex digit value and hex power (left shift). All matched strings
596 // start with "<" and end with the two characters "/>".
597 // If the lookup succeeds, hexdigit and hexpower are set to the appropriate
598 // values in the table, and the function returns the number of characters
599 // in text that are consumed by the matching string in the table lookup.
600 //
601 // If the lookup fails, hexdigit is set to 0, hexpower is set to and
602 // impossible value, and the function returns 0.
603 //--------------------------------------------------------------------------
604
605 int text2fci( PLCHAR_VECTOR text, unsigned char *hexdigit, unsigned char *hexpower )
606 {
607 typedef struct
608 {
609 PLCHAR_VECTOR ptext;
610 unsigned char hexdigit;
611 unsigned char hexpower;
612 }
613 TextLookupTable;
614 // This defines the various font control commands and the corresponding
615 // hexdigit and hexpower in the FCI.
616 //
617 #define N_TextLookupTable 10
618 const TextLookupTable lookup[N_TextLookupTable] = {
619 { "<sans-serif/>", PL_FCI_SANS, PL_FCI_FAMILY },
620 { "<serif/>", PL_FCI_SERIF, PL_FCI_FAMILY },
621 { "<monospace/>", PL_FCI_MONO, PL_FCI_FAMILY },
622 { "<script/>", PL_FCI_SCRIPT, PL_FCI_FAMILY },
623 { "<symbol/>", PL_FCI_SYMBOL, PL_FCI_FAMILY },
624 { "<upright/>", PL_FCI_UPRIGHT, PL_FCI_STYLE },
625 { "<italic/>", PL_FCI_ITALIC, PL_FCI_STYLE },
626 { "<oblique/>", PL_FCI_OBLIQUE, PL_FCI_STYLE },
627 { "<medium/>", PL_FCI_MEDIUM, PL_FCI_WEIGHT },
628 { "<bold/>", PL_FCI_BOLD, PL_FCI_WEIGHT }
629 };
630 int i, length;
631 for ( i = 0; i < N_TextLookupTable; i++ )
632 {
633 length = (int) strlen( lookup[i].ptext );
634 if ( !strncmp( text, lookup[i].ptext, (size_t) length ) )
635 {
636 *hexdigit = lookup[i].hexdigit;
637 *hexpower = lookup[i].hexpower;
638 return ( length );
639 }
640 }
641 *hexdigit = 0;
642 *hexpower = PL_FCI_HEXPOWER_IMPOSSIBLE;
643 return ( 0 );
644 }
645
646 static
647 void alternate_unicode_processing( PLCHAR_VECTOR string, EscText * args )
648 {
649 size_t i, len;
650 char esc;
651 unsigned char hexdigit, hexpower;
652 PLUNICODE fci;
653 PLUNICODE orig_fci;
654 PLINT ig;
655 int skip;
656 PLUNICODE code;
657 int idx = -1;
658
659 // Initialize to an empty string
660 args->unicode_array_len = 0;
661
662 len = strlen( string );
663
664 // If the string is empty, return now
665 if ( len == 0 )
666 return;
667
668 // Get the current escape character
669 plgesc( &esc );
670
671 // Obtain FCI (font characterization integer) for start of string.
672 plgfci( &fci );
673 orig_fci = fci;
674
675 // Signal the begin of text processing to the driver
676 args->n_fci = fci;
677 plP_esc( PLESC_BEGIN_TEXT, args );
678
679 for ( i = 0; i < len; i++ )
680 {
681 skip = 0;
682
683 if ( string[i] == esc )
684 {
685 switch ( string[i + 1] )
686 {
687 case '(': // hershey code
688 i += 2 + text2num( &string[i + 2], ')', &code );
689 idx = plhershey2unicode( (int) code );
690 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
691 args->n_char = hershey_to_unicode_lookup_table[idx].Unicode;
692 else
693 args->n_char = (PLUNICODE) 0x00;
694
695 pldebug( "alternate_unicode_processing", "code, idx, args->n_char = %d, %d, %#x\n", (int) code, idx, args->n_char );
696 plP_esc( PLESC_TEXT_CHAR, args );
697
698 skip = 1;
699 break;
700
701 case '[': // unicode
702 i += 2 + text2num( &string[i + 2], ']', &code );
703 args->n_char = code;
704 plP_esc( PLESC_TEXT_CHAR, args );
705 skip = 1;
706 break;
707
708 case '<': // change font
709 if ( '0' <= string[i + 2] && string[i + 2] <= '9' )
710 {
711 i += 2 + text2num( &string[i + 2], '>', &code );
712 if ( code & PL_FCI_MARK )
713 {
714 // code is a complete FCI (font characterization
715 // integer): change FCI to this value.
716 //
717 fci = code;
718 skip = 1;
719
720 args->n_fci = fci;
721 args->n_ctrl_char = PLTEXT_FONTCHANGE;
722 plP_esc( PLESC_CONTROL_CHAR, args );
723 }
724 else
725 {
726 // code is not complete FCI. Change
727 // FCI with hex power in rightmost hex
728 // digit and hex digit value in second rightmost
729 // hex digit.
730 //
731 hexdigit = ( code >> 4 ) & PL_FCI_HEXDIGIT_MASK;
732 hexpower = code & PL_FCI_HEXPOWER_MASK;
733 plP_hex2fci( hexdigit, hexpower, &fci );
734 skip = 1;
735
736 args->n_fci = fci;
737 args->n_ctrl_char = PLTEXT_FONTCHANGE;
738 plP_esc( PLESC_CONTROL_CHAR, args );
739 }
740 }
741 else
742 {
743 i += text2fci( &string[i + 1], &hexdigit, &hexpower );
744 if ( hexpower < 7 )
745 {
746 plP_hex2fci( hexdigit, hexpower, &fci );
747 skip = 1;
748
749 args->n_fci = fci;
750 args->n_ctrl_char = PLTEXT_FONTCHANGE;
751 plP_esc( PLESC_CONTROL_CHAR, args );
752 }
753 }
754 break;
755
756 case 'f': // Deprecated Hershey-style font change
757 case 'F': // Deprecated Hershey-style font change
758 // We implement an approximate response here so that
759 // reasonable results are obtained for unicode fonts,
760 // but this method is deprecated and the #<nnn> or
761 // #<command string> methods should be used instead
762 // to change unicode fonts in mid-string.
763 //
764 fci = PL_FCI_MARK;
765 if ( string[i + 2] == 'n' )
766 {
767 // medium, upright, sans-serif
768 plP_hex2fci( PL_FCI_SANS, PL_FCI_FAMILY, &fci );
769 }
770 else if ( string[i + 2] == 'r' )
771 {
772 // medium, upright, serif
773 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
774 }
775 else if ( string[i + 2] == 'i' )
776 {
777 // medium, italic, serif
778 plP_hex2fci( PL_FCI_ITALIC, PL_FCI_STYLE, &fci );
779 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
780 }
781 else if ( string[i + 2] == 's' )
782 {
783 // medium, upright, script
784 plP_hex2fci( PL_FCI_SCRIPT, PL_FCI_FAMILY, &fci );
785 }
786 else
787 fci = PL_FCI_IMPOSSIBLE;
788
789 if ( fci != PL_FCI_IMPOSSIBLE )
790 {
791 i += 2;
792 skip = 1;
793
794 args->n_fci = fci;
795 args->n_ctrl_char = PLTEXT_FONTCHANGE;
796 plP_esc( PLESC_CONTROL_CHAR, args );
797 }
798 break;
799
800 case 'g': // Greek font
801 case 'G': // Greek font
802 // Get the index in the lookup table
803 // 527 = upper case alpha displacement in Hershey Table
804 // 627 = lower case alpha displacement in Hershey Table
805 //
806 ig = plP_strpos( plP_greek_mnemonic, string[i + 2] );
807 if ( ig >= 0 )
808 {
809 if ( ig >= 24 )
810 ig = ig + 100 - 24;
811 ig = ig + 527;
812 // Follow pldeco in plsym.c which for
813 // lower case epsilon, theta, and phi
814 // substitutes (684, 685, and 686) for
815 // (631, 634, and 647)
816 if ( ig == 631 )
817 ig = 684;
818 else if ( ig == 634 )
819 ig = 685;
820 else if ( ig == 647 )
821 ig = 686;
822 idx = plhershey2unicode( ig );
823 i += 2;
824 skip = 1; // skip is set if we have copied something
825 // into the unicode table
826
827 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
828 args->n_char = hershey_to_unicode_lookup_table[idx].Unicode;
829 else
830 args->n_char = (PLUNICODE) 0x00;
831
832 pldebug( "alternate_unicode_processing", "ig, idx, args->n_char = %d, %d, %#x\n", ig, idx, args->n_char );
833 plP_esc( PLESC_TEXT_CHAR, args );
834 }
835 else
836 {
837 // Use "unknown" unicode character if string[i+2]
838 // is not in the Greek array.
839 i += 2;
840 skip = 1; // skip is set if we have copied something
841 // into the unicode table
842
843 args->n_char = (PLUNICODE) 0x00;
844 plP_esc( PLESC_TEXT_CHAR, args );
845 }
846 break;
847
848 case 'u':
849 args->n_ctrl_char = PLTEXT_SUPERSCRIPT;
850 plP_esc( PLESC_CONTROL_CHAR, args );
851 i += 1;
852 skip = 1;
853 break;
854
855 case 'd':
856 args->n_ctrl_char = PLTEXT_SUBSCRIPT;
857 plP_esc( PLESC_CONTROL_CHAR, args );
858 i += 1;
859 skip = 1;
860 break;
861 case 'b':
862 args->n_ctrl_char = PLTEXT_BACKCHAR;
863 plP_esc( PLESC_CONTROL_CHAR, args );
864 i += 1;
865 skip = 1;
866 break;
867 case '+':
868 args->n_ctrl_char = PLTEXT_OVERLINE;
869 plP_esc( PLESC_CONTROL_CHAR, args );
870 i += 1;
871 skip = 1;
872 break;
873 case '-':
874 args->n_ctrl_char = PLTEXT_UNDERLINE;
875 plP_esc( PLESC_CONTROL_CHAR, args );
876 i += 1;
877 skip = 1;
878 break;
879 }
880 }
881
882 if ( skip == 0 )
883 {
884 PLUNICODE unichar = 0;
885 #ifdef HAVE_LIBUNICODE
886 PLCHAR_VECTOR ptr = unicode_get_utf8( string + i, &unichar );
887 #else
888 PLCHAR_VECTOR ptr = utf8_to_ucs4( string + i, &unichar );
889 #endif
890 if ( ptr == NULL )
891 {
892 char buf[BUFFER_SIZE];
893 char tmpstring[31];
894 strncpy( tmpstring, string, 30 );
895 tmpstring[30] = '\0';
896 snprintf( buf, BUFFER_SIZE, "UTF-8 string is malformed: %s%s",
897 tmpstring, strlen( string ) > 30 ? "[...]" : "" );
898 plabort( buf );
899 return;
900 }
901 i += (int) ( ptr - ( string + i ) - 1 );
902
903 // Search for escesc (an unescaped escape) in the input
904 // string and adjust unicode_buffer accordingly).
905 //
906 if ( string[i] == esc && string[i + 1] == esc )
907 {
908 i++;
909 args->n_char = (PLUNICODE) esc;
910 }
911 else
912 {
913 args->n_char = unichar;
914 }
915 plP_esc( PLESC_TEXT_CHAR, args );
916 }
917 }
918
919 // Signal the end of text string processing to the driver
920 plP_esc( PLESC_END_TEXT, args );
921 }
922
923 static
924 void encode_unicode( PLCHAR_VECTOR string, EscText *args )
925 {
926 char esc;
927 PLINT ig;
928 PLUNICODE fci;
929 PLUNICODE orig_fci;
930 unsigned char hexdigit, hexpower;
931 size_t i, j, len;
932 int skip;
933 PLUNICODE code;
934 int idx = -1;
935
936 // Initialize to an empty string
937 args->unicode_array_len = 0;
938
939 // this length is only used in the loop
940 // counter, we will work out the length of
941 // the unicode string as we go
942 len = strlen( string );
943
944 // If the string is empty, return now
945 if ( len == 0 )
946 return;
947
948 // Get the current escape character
949 plgesc( &esc );
950
951 // At this stage we will do some translations into unicode, like
952 // conversion to Greek , and will save other translations such as
953 // superscript for the driver to do later on. As we move through
954 // the string and do the translations, we will get
955 // rid of the esc character sequence, just replacing it with
956 // unicode.
957 //
958
959 // Obtain FCI (font characterization integer) for start of string.
960 plgfci( &fci );
961 orig_fci = fci;
962
963 // Walk through the string, and convert some stuff to unicode on the fly
964 for ( j = i = 0; i < len; i++ )
965 {
966 skip = 0;
967
968 if ( string[i] == esc )
969 {
970 // We have an escape character, so we need to look at the
971 // next character to determine what action needs to be taken
972 switch ( string[i + 1] )
973 {
974 case '(': // hershey code
975 i += ( 2 + text2num( &string[i + 2], ')', &code ) );
976 idx = plhershey2unicode( (int) code );
977 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
978 args->unicode_array[j++] = hershey_to_unicode_lookup_table[idx].Unicode;
979 else
980 args->unicode_array[j++] = (PLUNICODE) 0x00;
981
982 pldebug( "encode_unicode", "code, idx, args->unicode_array[j] = %d, %d, %#x\n", (int) code, idx, args->unicode_array[j] );
983
984 // if unicode_buffer[j-1] corresponds to the escape
985 // character must unescape it by appending one more.
986 // This will probably always be necessary since it is
987 // likely unicode_buffer will always have to contain
988 // escape characters that are interpreted by the device
989 // driver.
990 //
991 if ( args->unicode_array[j - 1] == (PLUNICODE) esc )
992 args->unicode_array[j++] = (PLUNICODE) esc;
993 j--;
994 skip = 1;
995 break;
996
997 case '[': // unicode
998 i += ( 2 + text2num( &string[i + 2], ']', &code ) );
999 args->unicode_array[j++] = code;
1000
1001 // if unicode_buffer[j-1] corresponds to the escape
1002 // character must unescape it by appending one more.
1003 // This will probably always be necessary since it is
1004 // likely unicode_buffer will always have to contain
1005 // escape characters that are interpreted by the device
1006 // driver.
1007 //
1008 if ( args->unicode_array[j - 1] == (PLUNICODE) esc )
1009 args->unicode_array[j++] = (PLUNICODE) esc;
1010 j--;
1011 skip = 1;
1012 break;
1013
1014 case '<': // change font
1015 if ( '0' <= string[i + 2] && string[i + 2] <= '9' )
1016 {
1017 i += 2 + text2num( &string[i + 2], '>', &code );
1018 if ( code & PL_FCI_MARK )
1019 {
1020 // code is a complete FCI (font characterization
1021 // integer): change FCI to this value.
1022 //
1023 fci = code;
1024 args->unicode_array[j] = fci;
1025 skip = 1;
1026 }
1027 else
1028 {
1029 // code is not complete FCI. Change
1030 // FCI with hex power in rightmost hex
1031 // digit and hex digit value in second rightmost
1032 // hex digit.
1033 //
1034 hexdigit = ( code >> 4 ) & PL_FCI_HEXDIGIT_MASK;
1035 hexpower = code & PL_FCI_HEXPOWER_MASK;
1036 plP_hex2fci( hexdigit, hexpower, &fci );
1037 args->unicode_array[j] = fci;
1038 skip = 1;
1039 }
1040 }
1041 else
1042 {
1043 i += text2fci( &string[i + 1], &hexdigit, &hexpower );
1044 if ( hexpower < 7 )
1045 {
1046 plP_hex2fci( hexdigit, hexpower, &fci );
1047 args->unicode_array[j] = fci;
1048 skip = 1;
1049 }
1050 }
1051 break;
1052
1053 case 'f': // Deprecated Hershey-style font change
1054 case 'F': // Deprecated Hershey-style font change
1055 // We implement an approximate response here so that
1056 // reasonable results are obtained for unicode fonts,
1057 // but this method is deprecated and the #<nnn> or
1058 // #<command string> methods should be used instead
1059 // to change unicode fonts in mid-string.
1060 //
1061 fci = PL_FCI_MARK;
1062 if ( string[i + 2] == 'n' )
1063 {
1064 // medium, upright, sans-serif
1065 plP_hex2fci( PL_FCI_SANS, PL_FCI_FAMILY, &fci );
1066 }
1067 else if ( string[i + 2] == 'r' )
1068 {
1069 // medium, upright, serif
1070 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
1071 }
1072 else if ( string[i + 2] == 'i' )
1073 {
1074 // medium, italic, serif
1075 plP_hex2fci( PL_FCI_ITALIC, PL_FCI_STYLE, &fci );
1076 plP_hex2fci( PL_FCI_SERIF, PL_FCI_FAMILY, &fci );
1077 }
1078 else if ( string[i + 2] == 's' )
1079 {
1080 // medium, upright, script
1081 plP_hex2fci( PL_FCI_SCRIPT, PL_FCI_FAMILY, &fci );
1082 }
1083 else
1084 fci = PL_FCI_IMPOSSIBLE;
1085
1086 if ( fci != PL_FCI_IMPOSSIBLE )
1087 {
1088 i += 2;
1089 args->unicode_array[j] = fci;
1090 skip = 1;
1091 }
1092 break;
1093
1094 case 'g': // Greek font
1095 case 'G': // Greek font
1096 // Get the index in the lookup table
1097 // 527 = upper case alpha displacement in Hershey Table
1098 // 627 = lower case alpha displacement in Hershey Table
1099 //
1100
1101 ig = plP_strpos( plP_greek_mnemonic, string[i + 2] );
1102 if ( ig >= 0 )
1103 {
1104 if ( ig >= 24 )
1105 ig = ig + 100 - 24;
1106 ig = ig + 527;
1107 // Follow pldeco in plsym.c which for
1108 // lower case epsilon, theta, and phi
1109 // substitutes (684, 685, and 686) for
1110 // (631, 634, and 647)
1111 if ( ig == 631 )
1112 ig = 684;
1113 else if ( ig == 634 )
1114 ig = 685;
1115 else if ( ig == 647 )
1116 ig = 686;
1117 idx = (int) plhershey2unicode( ig );
1118 if ( 0 <= idx && idx <= number_of_entries_in_hershey_to_unicode_table )
1119 args->unicode_array[j++] = hershey_to_unicode_lookup_table[idx].Unicode;
1120 else
1121 args->unicode_array[j++] = (PLUNICODE) 0x00;
1122
1123 pldebug( "encode_unicode", "ig, idx, args->unicode_array[j] = %d, %d, %#x\n", (int) ig, idx, args->unicode_array[j] );
1124
1125 i += 2;
1126 skip = 1; // skip is set if we have copied something
1127 // into the unicode table
1128 }
1129 else
1130 {
1131 // Use "unknown" unicode character if string[i+2]
1132 // is not in the Greek array.
1133 args->unicode_array[j++] = (PLUNICODE) 0x00;
1134 i += 2;
1135 skip = 1; // skip is set if we have copied something
1136 // into the unicode table
1137 }
1138 j--;
1139 break;
1140 }
1141 }
1142
1143 if ( skip == 0 )
1144 {
1145 PLUNICODE unichar = 0;
1146 #ifdef HAVE_LIBUNICODE
1147 PLCHAR_VECTOR ptr = unicode_get_utf8( string + i, &unichar );
1148 #else
1149 PLCHAR_VECTOR ptr = utf8_to_ucs4( string + i, &unichar );
1150 #endif
1151 if ( ptr == NULL )
1152 {
1153 char buf[BUFFER_SIZE];
1154 char tmpstring[31];
1155 strncpy( tmpstring, string, 30 );
1156 tmpstring[30] = '\0';
1157 snprintf( buf, BUFFER_SIZE, "UTF-8 string is malformed: %s%s",
1158 tmpstring, strlen( string ) > 30 ? "[...]" : "" );
1159 plabort( buf );
1160 return;
1161 }
1162 args->unicode_array[j] = unichar;
1163 i += (int) ( ptr - ( string + i ) - 1 );
1164
1165 // Search for escesc (an unescaped escape) in the input
1166 // string and adjust unicode_buffer accordingly).
1167 //
1168 if ( args->unicode_array[j] == (PLUNICODE) esc
1169 && string[i + 1] == esc )
1170 {
1171 i++;
1172 args->unicode_array[++j] = (PLUNICODE) esc;
1173 }
1174 }
1175 j++;
1176 }
1177
1178 // Much easier to set the length than
1179 // work it out later :-)
1180 args->unicode_array_len = (short unsigned int) j;
1181 }
1182
1183 static PLUNICODE unicode_buffer_static[1024];
1184
1185 void
1186 plP_text( PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y,
1187 PLINT refx, PLINT refy, PLCHAR_VECTOR string )
1188 {
1189 size_t len;
1190
1191 // First, check if the caller passed an empty string. If it is,
1192 // then we can return now
1193 if ( string == NULL )
1194 return;
1195
1196 if ( plsc->dev_text ) // Does the device render it's own text ?
1197 {
1198 EscText args;
1199
1200 args.text_type = PL_STRING_TEXT;
1201 args.base = base;
1202 args.just = just;
1203 args.xform = xform;
1204 args.x = x;
1205 args.y = y;
1206 args.refx = refx;
1207 args.refy = refy;
1208
1209 // Always store the string passed by the caller, even for unicode
1210 // enabled drivers. The plmeta driver will use this field to store
1211 // the string data in the metafile.
1212 args.string = string;
1213
1214 // Does the device also understand unicode?
1215 if ( plsc->dev_unicode )
1216 {
1217 if ( plsc->alt_unicode )
1218 {
1219 // We are using the alternate unicode processing
1220 alternate_unicode_processing( string, &args );
1221
1222 // All text processing is done, so we can exit
1223 return;
1224 }
1225 else
1226 {
1227 // Setup storage for the unicode array and
1228 // process the string to generate the unicode
1229 // representation of it.
1230 args.unicode_array = unicode_buffer_static;
1231 encode_unicode( string, &args );
1232
1233 len = (size_t) args.unicode_array_len;
1234 }
1235 }
1236 else
1237 {
1238 // We are using the char array, NULL out the unicode part
1239 args.unicode_array = NULL;
1240 args.unicode_array_len = 0;
1241
1242 len = strlen( string );
1243 }
1244
1245 // If the string is not empty, ask the driver to display it
1246 if ( len > 0 )
1247 plP_esc( PLESC_HAS_TEXT, &args );
1248
1249 #ifndef DEBUG_TEXT
1250 }
1251 else
1252 {
1253 #endif
1254 plstr( base, xform, refx, refy, string );
1255 }
1256 }
1257
1258 // convert utf8 string to ucs4 unichar
1259 static PLCHAR_VECTOR
1260 utf8_to_ucs4( PLCHAR_VECTOR ptr, PLUNICODE *unichar )
1261 {
1262 char tmp;
1263 int isFirst = 1;
1264 int cnt = 0;
1265
1266 do
1267 {
1268 // Get next character in string
1269 tmp = *ptr++;
1270 if ( isFirst ) // First char in UTF8 sequence
1271 {
1272 isFirst = 0;
1273 // Determine length of sequence
1274 if ( (unsigned char) ( tmp & 0x80 ) == 0x00 ) // single char
1275 {
1276 *unichar = (unsigned int) tmp & 0x7F;
1277 cnt = 0;
1278 }
1279 else if ( (unsigned char) ( tmp & 0xE0 ) == 0xC0 ) // 2 chars
1280 {
1281 *unichar = (unsigned int) tmp & 0x1F;
1282 cnt = 1;
1283 }
1284 else if ( (unsigned char) ( tmp & 0xF0 ) == 0xE0 ) // 3 chars
1285 {
1286 *unichar = (unsigned char) tmp & 0x0F;
1287 cnt = 2;
1288 }
1289 else if ( (unsigned char) ( tmp & 0xF8 ) == 0xF0 ) // 4 chars
1290 {
1291 *unichar = (unsigned char) tmp & 0x07;
1292 cnt = 3;
1293 }
1294 else if ( (unsigned char) ( tmp & 0xFC ) == 0xF8 ) // 5 chars
1295 {
1296 *unichar = (unsigned char) tmp & 0x03;
1297 cnt = 4;
1298 }
1299 else if ( (unsigned char) ( tmp & 0xFE ) == 0xFC ) // 6 chars
1300 {
1301 *unichar = (unsigned char) tmp & 0x01;
1302 cnt = 5;
1303 }
1304 else // Malformed
1305 {
1306 ptr = NULL;
1307 cnt = 0;
1308 }
1309 }
1310 else // Subsequent char in UTF8 sequence
1311 {
1312 if ( (unsigned char) ( tmp & 0xC0 ) == 0x80 )
1313 {
1314 *unichar = ( *unichar << 6 ) | ( (unsigned int) tmp & 0x3F );
1315 cnt--;
1316 }
1317 else // Malformed
1318 {
1319 ptr = NULL;
1320 cnt = 0;
1321 }
1322 }
1323 } while ( cnt > 0 );
1324 return ptr;
1325 }
1326
1327 // convert ucs4 unichar to utf8 string
1328 int
1329 ucs4_to_utf8( PLUNICODE unichar, char *ptr )
1330 {
1331 unsigned char *tmp;
1332 int len;
1333
1334 tmp = (unsigned char *) ptr;
1335
1336 if ( ( unichar & 0xffff80 ) == 0 ) // single byte
1337 {
1338 *tmp = (unsigned char) unichar;
1339 tmp++;
1340 len = 1;
1341 }
1342 else if ( ( unichar & 0xfff800 ) == 0 ) // two bytes
1343 {
1344 *tmp = (unsigned char) 0xc0 | (unsigned char) ( unichar >> 6 );
1345 tmp++;
1346 *tmp = (unsigned char) ( 0x80 | (unsigned char) ( unichar & (PLUINT) 0x3f ) );
1347 tmp++;
1348 len = 2;
1349 }
1350 else if ( ( unichar & 0xff0000 ) == 0 ) // three bytes
1351 {
1352 *tmp = (unsigned char) 0xe0 | (unsigned char) ( unichar >> 12 );
1353 tmp++;
1354 *tmp = (unsigned char) ( 0x80 | (unsigned char) ( ( unichar >> 6 ) & 0x3f ) );
1355 tmp++;
1356 *tmp = (unsigned char) ( 0x80 | ( (unsigned char) unichar & 0x3f ) );
1357 tmp++;
1358 len = 3;
1359 }
1360 else if ( ( unichar & 0xe0000 ) == 0 ) // four bytes
1361 {
1362 *tmp = (unsigned char) 0xf0 | (unsigned char) ( unichar >> 18 );
1363 tmp++;
1364 *tmp = (unsigned char) ( 0x80 | (unsigned char) ( ( unichar >> 12 ) & 0x3f ) );
1365 tmp++;
1366 *tmp = (unsigned char) ( 0x80 | (unsigned char) ( ( unichar >> 6 ) & 0x3f ) );
1367 tmp++;
1368 *tmp = (unsigned char) ( 0x80 | (unsigned char) ( unichar & 0x3f ) );
1369 tmp++;
1370 len = 4;
1371 }
1372 else // Illegal coding
1373 {
1374 len = 0;
1375 }
1376 *tmp = '\0';
1377
1378 return len;
1379 }
1380
1381 static void
1382 grline( short *x, short *y, PLINT PL_UNUSED( npts ) )
1383 {
1384 char *save_locale = plsave_set_locale();
1385 if ( !plsc->stream_closed )
1386 {
1387 ( *plsc->dispatch_table->pl_line )( (struct PLStream_struct *) plsc,
1388 x[0], y[0], x[1], y[1] );
1389 }
1390 plrestore_locale( save_locale );
1391 }
1392
1393 static void
1394 grpolyline( short *x, short *y, PLINT npts )
1395 {
1396 char *save_locale = plsave_set_locale();
1397 if ( !plsc->stream_closed )
1398 {
1399 ( *plsc->dispatch_table->pl_polyline )( (struct PLStream_struct *) plsc,
1400 x, y, npts );
1401 }
1402 plrestore_locale( save_locale );
1403 }
1404
1405 static void
1406 grfill( short *x, short *y, PLINT npts )
1407 {
1408 char * save_locale;
1409 plsc->dev_npts = npts;
1410 plsc->dev_x = x;
1411 plsc->dev_y = y;
1412
1413 save_locale = plsave_set_locale();
1414 if ( !plsc->stream_closed )
1415 {
1416 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
1417 PLESC_FILL, NULL );
1418 }
1419 plrestore_locale( save_locale );
1420 }
1421
1422 static void
1423 grgradient( short *x, short *y, PLINT npts )
1424 {
1425 char * save_locale;
1426 plsc->dev_npts = npts;
1427 plsc->dev_x = x;
1428 plsc->dev_y = y;
1429
1430 save_locale = plsave_set_locale();
1431 if ( !plsc->stream_closed )
1432 {
1433 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
1434 PLESC_GRADIENT, NULL );
1435 }
1436 plrestore_locale( save_locale );
1437 }
1438
1439 //--------------------------------------------------------------------------
1440 // void difilt
1441 //
1442 // Driver interface filter -- passes all coordinates through a variety
1443 // of filters. These include filters to change :
1444 //
1445 // - mapping of meta to physical coordinates
1446 // - plot orientation
1447 // - window into plot (zooms)
1448 // - window into device (i.e set margins)
1449 //
1450 // The filters are applied in the order specified above. Because the
1451 // orientation change comes first, subsequent window specifications affect
1452 // the new coordinates (i.e. after a 90 degree flip, what was x is now y).
1453 // This is the only way that makes sense from a graphical interface
1454 // (e.g. TCL/TK driver).
1455 //
1456 // Where appropriate, the page clip limits are modified.
1457 //--------------------------------------------------------------------------
1458
1459 void
1460 difilt( PLINT *xsc, PLINT *ysc, PLINT npts,
1461 PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma )
1462 {
1463 PLINT i, x, y;
1464
1465 // Map meta coordinates to physical coordinates
1466
1467 if ( plsc->difilt & PLDI_MAP )
1468 {
1469 for ( i = 0; i < npts; i++ )
1470 {
1471 xsc[i] = (PLINT) ( plsc->dimxax * xsc[i] + plsc->dimxb );
1472 ysc[i] = (PLINT) ( plsc->dimyay * ysc[i] + plsc->dimyb );
1473 }
1474 }
1475
1476 // Change orientation
1477
1478 if ( plsc->difilt & PLDI_ORI )
1479 {
1480 for ( i = 0; i < npts; i++ )
1481 {
1482 x = (PLINT) ( plsc->dioxax * xsc[i] + plsc->dioxay * ysc[i] + plsc->dioxb );
1483 y = (PLINT) ( plsc->dioyax * xsc[i] + plsc->dioyay * ysc[i] + plsc->dioyb );
1484 xsc[i] = x;
1485 ysc[i] = y;
1486 }
1487 }
1488
1489 // Change window into plot space
1490
1491 if ( plsc->difilt & PLDI_PLT )
1492 {
1493 for ( i = 0; i < npts; i++ )
1494 {
1495 xsc[i] = (PLINT) ( plsc->dipxax * xsc[i] + plsc->dipxb );
1496 ysc[i] = (PLINT) ( plsc->dipyay * ysc[i] + plsc->dipyb );
1497 }
1498 }
1499
1500 // Change window into device space and set clip limits
1501 // (this is the only filter that modifies them)
1502
1503 if ( plsc->difilt & PLDI_DEV )
1504 {
1505 for ( i = 0; i < npts; i++ )
1506 {
1507 xsc[i] = (PLINT) ( plsc->didxax * xsc[i] + plsc->didxb );
1508 ysc[i] = (PLINT) ( plsc->didyay * ysc[i] + plsc->didyb );
1509 }
1510 *clpxmi = plsc->diclpxmi;
1511 *clpxma = plsc->diclpxma;
1512 *clpymi = plsc->diclpymi;
1513 *clpyma = plsc->diclpyma;
1514 }
1515 else
1516 {
1517 *clpxmi = plsc->phyxmi;
1518 *clpxma = plsc->phyxma;
1519 *clpymi = plsc->phyymi;
1520 *clpyma = plsc->phyyma;
1521 }
1522 }
1523
1524
1525 // Function is unused except for commented out image code
1526 // If / when that is fixed, then reinstate this function.
1527 // Needs a prototype and the casting fixed.
1528 //
1529 // void
1530 // sdifilt( short *xscl, short *yscl, PLINT npts,
1531 // PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma )
1532 // {
1533 // int i;
1534 // short x, y;
1535
1536 // // Map meta coordinates to physical coordinates
1537
1538 // if ( plsc->difilt & PLDI_MAP )
1539 // {
1540 // for ( i = 0; i < npts; i++ )
1541 // {
1542 // xscl[i] = (PLINT) ( plsc->dimxax * xscl[i] + plsc->dimxb );
1543 // yscl[i] = (PLINT) ( plsc->dimyay * yscl[i] + plsc->dimyb );
1544 // }
1545 // }
1546
1547 // // Change orientation
1548
1549 // if ( plsc->difilt & PLDI_ORI )
1550 // {
1551 // for ( i = 0; i < npts; i++ )
1552 // {
1553 // x = (PLINT) ( plsc->dioxax * xscl[i] + plsc->dioxay * yscl[i] + plsc->dioxb );
1554 // y = (PLINT) ( plsc->dioyax * xscl[i] + plsc->dioyay * yscl[i] + plsc->dioyb );
1555 // xscl[i] = x;
1556 // yscl[i] = y;
1557 // }
1558 // }
1559
1560 // // Change window into plot space
1561
1562 // if ( plsc->difilt & PLDI_PLT )
1563 // {
1564 // for ( i = 0; i < npts; i++ )
1565 // {
1566 // xscl[i] = (PLINT) ( plsc->dipxax * xscl[i] + plsc->dipxb );
1567 // yscl[i] = (PLINT) ( plsc->dipyay * yscl[i] + plsc->dipyb );
1568 // }
1569 // }
1570
1571 // // Change window into device space and set clip limits
1572 // // (this is the only filter that modifies them)
1573
1574 // if ( plsc->difilt & PLDI_DEV )
1575 // {
1576 // for ( i = 0; i < npts; i++ )
1577 // {
1578 // xscl[i] = (PLINT) ( plsc->didxax * xscl[i] + plsc->didxb );
1579 // yscl[i] = (PLINT) ( plsc->didyay * yscl[i] + plsc->didyb );
1580 // }
1581 // *clpxmi = (PLINT) ( plsc->diclpxmi );
1582 // *clpxma = (PLINT) ( plsc->diclpxma );
1583 // *clpymi = (PLINT) ( plsc->diclpymi );
1584 // *clpyma = (PLINT) ( plsc->diclpyma );
1585 // }
1586 // else
1587 // {
1588 // *clpxmi = plsc->phyxmi;
1589 // *clpxma = plsc->phyxma;
1590 // *clpymi = plsc->phyymi;
1591 // *clpyma = plsc->phyyma;
1592 // }
1593 // }
1594
1595 //--------------------------------------------------------------------------
1596 // void difilt_clip
1597 //
1598 // This provides the transformed text clipping region for the benefit of
1599 // those drivers that render their own text.
1600 //--------------------------------------------------------------------------
1601
1602 void
1603 difilt_clip( PLINT *x_coords, PLINT *y_coords )
1604 {
1605 PLINT x1c, x2c, y1c, y2c;
1606
1607 x1c = plsc->clpxmi;
1608 y1c = plsc->clpymi;
1609 x2c = plsc->clpxma;
1610 y2c = plsc->clpyma;
1611 x_coords[0] = x1c;
1612 x_coords[1] = x1c;
1613 x_coords[2] = x2c;
1614 x_coords[3] = x2c;
1615 y_coords[0] = y1c;
1616 y_coords[1] = y2c;
1617 y_coords[2] = y2c;
1618 y_coords[3] = y1c;
1619 difilt( x_coords, y_coords, 4, &x1c, &x2c, &y1c, &y2c );
1620 }
1621
1622
1623 //--------------------------------------------------------------------------
1624 // void pldi_ini
1625 //
1626 // Updates driver interface, making sure everything is in order.
1627 // Even if filter is not being used, the defaults need to be set up.
1628 //--------------------------------------------------------------------------
1629
1630 static void
1631 setdef_diplt( void )
1632 {
1633 plsc->dipxmin = 0.0;
1634 plsc->dipxmax = 1.0;
1635 plsc->dipymin = 0.0;
1636 plsc->dipymax = 1.0;
1637 }
1638
1639 static void
1640 setdef_didev( void )
1641 {
1642 plsc->mar = 0.0;
1643 plsc->aspect = 0.0;
1644 plsc->jx = 0.0;
1645 plsc->jy = 0.0;
1646 }
1647
1648 static void
1649 setdef_diori( void )
1650 {
1651 plsc->diorot = 0.;
1652 }
1653
1654 static void
1655 pldi_ini( void )
1656 {
1657 if ( plsc->level >= 1 )
1658 {
1659 if ( plsc->plbuf_write )
1660 plbuf_di( plsc );
1661 if ( plsc->difilt & PLDI_MAP ) // Coordinate mapping
1662 calc_dimap();
1663
1664 if ( plsc->difilt & PLDI_ORI ) // Orientation
1665 calc_diori();
1666 else
1667 setdef_diori();
1668
1669 if ( plsc->difilt & PLDI_PLT ) // Plot window
1670 calc_diplt();
1671 else
1672 setdef_diplt();
1673
1674 if ( plsc->difilt & PLDI_DEV ) // Device window
1675 calc_didev();
1676 else
1677 setdef_didev();
1678 }
1679 }
1680
1681 //--------------------------------------------------------------------------
1682 // void pldid2pc
1683 //
1684 // Converts input values from relative device coordinates to relative plot
1685 // coordinates. This function must be called when selecting a plot window
1686 // from a display driver, since the coordinates chosen by the user are
1687 // necessarily device-specific.
1688 //--------------------------------------------------------------------------
1689
1690 void
1691 pldid2pc( PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax )
1692 {
1693 PLFLT pxmin, pymin, pxmax, pymax;
1694 PLFLT sxmin, symin, sxmax, symax;
1695 PLFLT rxmin, rymin, rxmax, rymax;
1696
1697 if ( plsc->difilt & PLDI_DEV )
1698 {
1699 pldebug( "pldid2pc",
1700 "Relative device coordinates (in): %f, %f, %f, %f\n",
1701 *xmin, *ymin, *xmax, *ymax );
1702
1703 pxmin = plP_dcpcx( *xmin );
1704 pymin = plP_dcpcy( *ymin );
1705 pxmax = plP_dcpcx( *xmax );
1706 pymax = plP_dcpcy( *ymax );
1707
1708 sxmin = ( pxmin - plsc->didxb ) / plsc->didxax;
1709 symin = ( pymin - plsc->didyb ) / plsc->didyay;
1710 sxmax = ( pxmax - plsc->didxb ) / plsc->didxax;
1711 symax = ( pymax - plsc->didyb ) / plsc->didyay;
1712
1713 rxmin = plP_pcdcx( (PLINT) sxmin );
1714 rymin = plP_pcdcy( (PLINT) symin );
1715 rxmax = plP_pcdcx( (PLINT) sxmax );
1716 rymax = plP_pcdcy( (PLINT) symax );
1717
1718 *xmin = ( rxmin < 0 ) ? 0 : rxmin;
1719 *xmax = ( rxmax > 1 ) ? 1 : rxmax;
1720 *ymin = ( rymin < 0 ) ? 0 : rymin;
1721 *ymax = ( rymax > 1 ) ? 1 : rymax;
1722
1723 pldebug( "pldid2pc",
1724 "Relative plot coordinates (out): %f, %f, %f, %f\n",
1725 rxmin, rymin, rxmax, rymax );
1726 }
1727 }
1728
1729 //--------------------------------------------------------------------------
1730 // void pldip2dc
1731 //
1732 // Converts input values from relative plot coordinates to relative
1733 // device coordinates.
1734 //--------------------------------------------------------------------------
1735
1736 void
1737 pldip2dc( PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax )
1738 {
1739 PLFLT pxmin, pymin, pxmax, pymax;
1740 PLFLT sxmin, symin, sxmax, symax;
1741 PLFLT rxmin, rymin, rxmax, rymax;
1742
1743 if ( plsc->difilt & PLDI_DEV )
1744 {
1745 pldebug( "pldip2pc",
1746 "Relative plot coordinates (in): %f, %f, %f, %f\n",
1747 *xmin, *ymin, *xmax, *ymax );
1748
1749 pxmin = plP_dcpcx( *xmin );
1750 pymin = plP_dcpcy( *ymin );
1751 pxmax = plP_dcpcx( *xmax );
1752 pymax = plP_dcpcy( *ymax );
1753
1754 sxmin = pxmin * plsc->didxax + plsc->didxb;
1755 symin = pymin * plsc->didyay + plsc->didyb;
1756 sxmax = pxmax * plsc->didxax + plsc->didxb;
1757 symax = pymax * plsc->didyay + plsc->didyb;
1758
1759 rxmin = plP_pcdcx( (PLINT) sxmin );
1760 rymin = plP_pcdcy( (PLINT) symin );
1761 rxmax = plP_pcdcx( (PLINT) sxmax );
1762 rymax = plP_pcdcy( (PLINT) symax );
1763
1764 *xmin = ( rxmin < 0 ) ? 0 : rxmin;
1765 *xmax = ( rxmax > 1 ) ? 1 : rxmax;
1766 *ymin = ( rymin < 0 ) ? 0 : rymin;
1767 *ymax = ( rymax > 1 ) ? 1 : rymax;
1768
1769 pldebug( "pldip2pc",
1770 "Relative device coordinates (out): %f, %f, %f, %f\n",
1771 rxmin, rymin, rxmax, rymax );
1772 }
1773 }
1774
1775 //--------------------------------------------------------------------------
1776 // void plsdiplt
1777 //
1778 // Set window into plot space
1779 //--------------------------------------------------------------------------
1780
1781 void
1782 c_plsdiplt( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
1783 {
1784 plsc->dipxmin = ( xmin < xmax ) ? xmin : xmax;
1785 plsc->dipxmax = ( xmin < xmax ) ? xmax : xmin;
1786 plsc->dipymin = ( ymin < ymax ) ? ymin : ymax;
1787 plsc->dipymax = ( ymin < ymax ) ? ymax : ymin;
1788
1789 if ( xmin == 0. && xmax == 1. && ymin == 0. && ymax == 1. )
1790 {
1791 plsc->difilt &= ~PLDI_PLT;
1792 return;
1793 }
1794
1795 plsc->difilt |= PLDI_PLT;
1796 pldi_ini();
1797 }
1798
1799 //--------------------------------------------------------------------------
1800 // void plsdiplz
1801 //
1802 // Set window into plot space incrementally (zoom)
1803 //--------------------------------------------------------------------------
1804
1805 void
1806 c_plsdiplz( PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax )
1807 {
1808 if ( plsc->difilt & PLDI_PLT )
1809 {
1810 xmin = plsc->dipxmin + ( plsc->dipxmax - plsc->dipxmin ) * xmin;
1811 ymin = plsc->dipymin + ( plsc->dipymax - plsc->dipymin ) * ymin;
1812 xmax = plsc->dipxmin + ( plsc->dipxmax - plsc->dipxmin ) * xmax;
1813 ymax = plsc->dipymin + ( plsc->dipymax - plsc->dipymin ) * ymax;
1814 }
1815
1816 plsdiplt( xmin, ymin, xmax, ymax );
1817 }
1818
1819 //--------------------------------------------------------------------------
1820 // void calc_diplt
1821 //
1822 // Calculate transformation coefficients to set window into plot space.
1823 //
1824 // Note: if driver has requested to handle these commands itself, we must
1825 // send the appropriate escape command. If the driver succeeds it will
1826 // cancel the filter operation. The command is deferred until this point
1827 // to ensure that the driver has been initialized.
1828 //--------------------------------------------------------------------------
1829
1830 static void
1831 calc_diplt( void )
1832 {
1833 PLINT pxmin, pxmax, pymin, pymax, pxlen, pylen;
1834
1835 if ( plsc->dev_di )
1836 {
1837 char *save_locale = plsave_set_locale();
1838 if ( !plsc->stream_closed )
1839 {
1840 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
1841 PLESC_DI, NULL );
1842 }
1843 plrestore_locale( save_locale );
1844 }
1845
1846 if ( !( plsc->difilt & PLDI_PLT ) )
1847 return;
1848
1849 pxmin = plP_dcpcx( plsc->dipxmin );
1850 pxmax = plP_dcpcx( plsc->dipxmax );
1851 pymin = plP_dcpcy( plsc->dipymin );
1852 pymax = plP_dcpcy( plsc->dipymax );
1853
1854 pxlen = pxmax - pxmin;
1855 pylen = pymax - pymin;
1856 pxlen = MAX( 1, pxlen );
1857 pylen = MAX( 1, pylen );
1858
1859 plsc->dipxax = plsc->phyxlen / (double) pxlen;
1860 plsc->dipyay = plsc->phyylen / (double) pylen;
1861 plsc->dipxb = plsc->phyxmi - plsc->dipxax * pxmin;
1862 plsc->dipyb = plsc->phyymi - plsc->dipyay * pymin;
1863 }
1864
1865 //--------------------------------------------------------------------------
1866 // void plgdiplt
1867 //
1868 // Retrieve current window into plot space
1869 //--------------------------------------------------------------------------
1870
1871 void
1872 c_plgdiplt( PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax )
1873 {
1874 *p_xmin = plsc->dipxmin;
1875 *p_xmax = plsc->dipxmax;
1876 *p_ymin = plsc->dipymin;
1877 *p_ymax = plsc->dipymax;
1878 }
1879
1880 //--------------------------------------------------------------------------
1881 // void plsdidev
1882 //
1883 // Set window into device space using margin, aspect ratio, and
1884 // justification. If you want to just use the previous value for any of
1885 // these, just pass in the magic value PL_NOTSET.
1886 //
1887 // It is unlikely that one should ever need to change the aspect ratio
1888 // but it's in there for completeness.
1889 //--------------------------------------------------------------------------
1890
1891 void
1892 c_plsdidev( PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy )
1893 {
1894 plsetvar( plsc->mar, mar );
1895 plsetvar( plsc->aspect, aspect );
1896 plsetvar( plsc->jx, jx );
1897 plsetvar( plsc->jy, jy );
1898
1899 if ( mar == 0. && aspect == 0. && jx == 0. && jy == 0. &&
1900 !( plsc->difilt & PLDI_ORI ) )
1901 {
1902 plsc->difilt &= ~PLDI_DEV;
1903 return;
1904 }
1905
1906 plsc->difilt |= PLDI_DEV;
1907 pldi_ini();
1908 }
1909
1910 //--------------------------------------------------------------------------
1911 // void calc_didev
1912 //
1913 // Calculate transformation coefficients to set window into device space.
1914 // Calculates relative window bounds and calls plsdidxy to finish the job.
1915 //--------------------------------------------------------------------------
1916
1917 static void
1918 calc_didev( void )
1919 {
1920 PLFLT lx, ly, aspect, aspdev;
1921 PLFLT xmin, xmax, xlen, ymin, ymax, ylen;
1922 PLINT pxmin, pxmax, pymin, pymax, pxlen, pylen;
1923
1924 if ( plsc->dev_di )
1925 {
1926 char *save_locale = plsave_set_locale();
1927 if ( !plsc->stream_closed )
1928 {
1929 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
1930 PLESC_DI, NULL );
1931 }
1932 plrestore_locale( save_locale );
1933 }
1934
1935 if ( !( plsc->difilt & PLDI_DEV ) )
1936 return;
1937
1938 // Calculate aspect ratio of physical device
1939
1940 lx = plsc->phyxlen / plsc->xpmm;
1941 ly = plsc->phyylen / plsc->ypmm;
1942 aspdev = lx / ly;
1943
1944 if ( plsc->difilt & PLDI_ORI )
1945 aspect = plsc->aspori;
1946 else
1947 aspect = plsc->aspect;
1948
1949 if ( aspect <= 0. )
1950 aspect = plsc->aspdev;
1951
1952 // Failsafe
1953
1954 plsc->mar = ( plsc->mar > 0.5 ) ? 0.5 : plsc->mar;
1955 plsc->mar = ( plsc->mar < 0.0 ) ? 0.0 : plsc->mar;
1956 plsc->jx = ( plsc->jx > 0.5 ) ? 0.5 : plsc->jx;
1957 plsc->jx = ( plsc->jx < -0.5 ) ? -0.5 : plsc->jx;
1958 plsc->jy = ( plsc->jy > 0.5 ) ? 0.5 : plsc->jy;
1959 plsc->jy = ( plsc->jy < -0.5 ) ? -0.5 : plsc->jy;
1960
1961 // Relative device coordinates that neutralize aspect ratio difference
1962
1963 xlen = ( aspect < aspdev ) ? ( aspect / aspdev ) : 1.0;
1964 ylen = ( aspect < aspdev ) ? 1.0 : ( aspdev / aspect );
1965
1966 xlen *= ( 1.0 - 2. * plsc->mar );
1967 ylen *= ( 1.0 - 2. * plsc->mar );
1968
1969 xmin = ( 1. - xlen ) * ( 0.5 + plsc->jx );
1970 xmax = xmin + xlen;
1971
1972 ymin = ( 1. - ylen ) * ( 0.5 + plsc->jy );
1973 ymax = ymin + ylen;
1974
1975 // Calculate transformation coefficients
1976
1977 pxmin = plP_dcpcx( xmin );
1978 pxmax = plP_dcpcx( xmax );
1979 pymin = plP_dcpcy( ymin );
1980 pymax = plP_dcpcy( ymax );
1981
1982 pxlen = pxmax - pxmin;
1983 pylen = pymax - pymin;
1984 pxlen = MAX( 1, pxlen );
1985 pylen = MAX( 1, pylen );
1986
1987 plsc->didxax = pxlen / (double) plsc->phyxlen;
1988 plsc->didyay = pylen / (double) plsc->phyylen;
1989 plsc->didxb = pxmin - plsc->didxax * plsc->phyxmi;
1990 plsc->didyb = pymin - plsc->didyay * plsc->phyymi;
1991
1992 // Set clip limits to conform to new page size
1993
1994 plsc->diclpxmi = (PLINT) ( plsc->didxax * plsc->phyxmi + plsc->didxb );
1995 plsc->diclpxma = (PLINT) ( plsc->didxax * plsc->phyxma + plsc->didxb );
1996 plsc->diclpymi = (PLINT) ( plsc->didyay * plsc->phyymi + plsc->didyb );
1997 plsc->diclpyma = (PLINT) ( plsc->didyay * plsc->phyyma + plsc->didyb );
1998 }
1999
2000 //--------------------------------------------------------------------------
2001 // void plgdidev
2002 //
2003 // Retrieve current window into device space
2004 //--------------------------------------------------------------------------
2005
2006 void
2007 c_plgdidev( PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy )
2008 {
2009 *p_mar = plsc->mar;
2010 *p_aspect = plsc->aspect;
2011 *p_jx = plsc->jx;
2012 *p_jy = plsc->jy;
2013 }
2014
2015 //--------------------------------------------------------------------------
2016 // void plsdiori
2017 //
2018 // Set plot orientation, specifying rotation in units of pi/2.
2019 //--------------------------------------------------------------------------
2020
2021 void
2022 c_plsdiori( PLFLT rot )
2023 {
2024 plsc->diorot = rot;
2025 if ( rot == 0. )
2026 {
2027 plsc->difilt &= ~PLDI_ORI;
2028 pldi_ini();
2029 return;
2030 }
2031
2032 plsc->difilt |= PLDI_ORI;
2033 pldi_ini();
2034 }
2035
2036 //--------------------------------------------------------------------------
2037 // void calc_diori
2038 //
2039 // Calculate transformation coefficients to arbitrarily orient plot.
2040 // Preserve aspect ratios so the output doesn't suck.
2041 //--------------------------------------------------------------------------
2042
2043 static void
2044 calc_diori( void )
2045 {
2046 PLFLT cost, sint;
2047 PLFLT x0, y0, lx, ly, aspect;
2048 PLFLT affine_result[NAFFINE], affine_left[NAFFINE];
2049
2050 if ( plsc->dev_di )
2051 {
2052 char *save_locale = plsave_set_locale();
2053 if ( !plsc->stream_closed )
2054 {
2055 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
2056 PLESC_DI, NULL );
2057 }
2058 plrestore_locale( save_locale );
2059 }
2060
2061 if ( !( plsc->difilt & PLDI_ORI ) )
2062 return;
2063
2064 // Center point of rotation
2065
2066 x0 = ( plsc->phyxma + plsc->phyxmi ) / 2.;
2067 y0 = ( plsc->phyyma + plsc->phyymi ) / 2.;
2068
2069 // Rotation
2070
2071 cost = ABS( cos( plsc->diorot * PI / 2. ) );
2072 sint = ABS( sin( plsc->diorot * PI / 2. ) );
2073
2074 // Flip aspect ratio as necessary. Grungy but I don't see a better way
2075
2076 aspect = plsc->aspect;
2077 if ( aspect == 0. )
2078 aspect = plsc->aspdev;
2079
2080 if ( plsc->freeaspect )
2081 plsc->aspori = aspect;
2082 else
2083 plsc->aspori = ( aspect * cost + sint ) / ( aspect * sint + cost );
2084
2085 if ( !( plsc->difilt & PLDI_DEV ) )
2086 {
2087 plsc->difilt |= PLDI_DEV;
2088 setdef_didev();
2089 }
2090 calc_didev();
2091
2092 // Compute scale factors for relative device coordinates. Only
2093 // the aspect ratio of lx to ly matters. Note, plsc->phyxlen and
2094 // plsc->phyylen are in PLplot core library coordinates and don't
2095 // know anything about device coordinates which are likely to have
2096 // a quite different aspect ratio. So to correct between the two
2097 // coordinate systems must divide plsc->phyxlen/plsc->phyylen by
2098 // plsc->aspori.
2099
2100 // N.B. comment out this correction because causes other issues.
2101
2102 //lx = plsc->phyxlen/plsc->aspori;
2103 lx = plsc->phyxlen;
2104 ly = plsc->phyylen;
2105
2106 // Transformation coefficients
2107
2108 //
2109 // plsc->dioxax = r11;
2110 // plsc->dioxay = r21 * ( lx / ly );
2111 // plsc->dioxb = ( 1. - r11 ) * x0 - r21 * y0 * ( lx / ly );
2112 //
2113 // plsc->dioyax = r12 * ( ly / lx );
2114 // plsc->dioyay = r22;
2115 // plsc->dioyb = ( 1. - r22 ) * y0 - r12 * x0 * ( ly / lx );
2116 //
2117
2118 // Calculate affine transformation as product of translate to middle
2119 // of device, scale to relative device coordinates, rotate, unscale
2120 // to physical coordinates, untranslate to original zero point.
2121 plP_affine_translate( affine_result, x0, y0 );
2122 plP_affine_scale( affine_left, lx, ly );
2123 plP_affine_multiply( affine_result, affine_left, affine_result );
2124 plP_affine_rotate( affine_left, plsc->diorot * 90. );
2125 plP_affine_multiply( affine_result, affine_left, affine_result );
2126 plP_affine_scale( affine_left, 1. / lx, 1. / ly );
2127 plP_affine_multiply( affine_result, affine_left, affine_result );
2128 plP_affine_translate( affine_left, -x0, -y0 );
2129 plP_affine_multiply( affine_result, affine_left, affine_result );
2130 plsc->dioxax = affine_result[0];
2131 plsc->dioxay = affine_result[2];
2132 plsc->dioxb = affine_result[4];
2133 plsc->dioyax = affine_result[1];
2134 plsc->dioyay = affine_result[3];
2135 plsc->dioyb = affine_result[5];
2136 }
2137
2138 //--------------------------------------------------------------------------
2139 // void plgdiori
2140 //
2141 // Get plot orientation
2142 //--------------------------------------------------------------------------
2143
2144 void
2145 c_plgdiori( PLFLT *p_rot )
2146 {
2147 *p_rot = plsc->diorot;
2148 }
2149
2150 //--------------------------------------------------------------------------
2151 // void plsdimap
2152 //
2153 // Set up transformation from metafile coordinates. The size of the plot is
2154 // scaled so as to preserve aspect ratio. This isn't intended to be a
2155 // general-purpose facility just yet (not sure why the user would need it,
2156 // for one).
2157 //--------------------------------------------------------------------------
2158
2159 void
2160 c_plsdimap( PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax,
2161 PLFLT dimxpmm, PLFLT dimypmm )
2162 {
2163 plsetvar( plsc->dimxmin, dimxmin );
2164 plsetvar( plsc->dimxmax, dimxmax );
2165 plsetvar( plsc->dimymin, dimymin );
2166 plsetvar( plsc->dimymax, dimymax );
2167 plsetvar( plsc->dimxpmm, dimxpmm );
2168 plsetvar( plsc->dimypmm, dimypmm );
2169
2170 plsc->difilt |= PLDI_MAP;
2171 pldi_ini();
2172 }
2173
2174 //--------------------------------------------------------------------------
2175 // void calc_dimap
2176 //
2177 // Set up transformation from metafile coordinates. The size of the plot is
2178 // scaled so as to preserve aspect ratio. This isn't intended to be a
2179 // general-purpose facility just yet (not sure why the user would need it,
2180 // for one).
2181 //--------------------------------------------------------------------------
2182
2183 static void
2184 calc_dimap()
2185 {
2186 PLFLT lx, ly;
2187 PLINT pxmin, pxmax, pymin, pymax;
2188 PLFLT dimxlen, dimylen, pxlen, pylen;
2189
2190 if ( ( plsc->dimxmin == plsc->phyxmi ) && ( plsc->dimxmax == plsc->phyxma ) &&
2191 ( plsc->dimymin == plsc->phyymi ) && ( plsc->dimymax == plsc->phyyma ) &&
2192 ( plsc->dimxpmm == plsc->xpmm ) && ( plsc->dimypmm == plsc->ypmm ) )
2193 {
2194 plsc->difilt &= ~PLDI_MAP;
2195 return;
2196 }
2197
2198 // Set default aspect ratio
2199
2200 lx = ( plsc->dimxmax - plsc->dimxmin + 1 ) / plsc->dimxpmm;
2201 ly = ( plsc->dimymax - plsc->dimymin + 1 ) / plsc->dimypmm;
2202
2203 plsc->aspdev = lx / ly;
2204
2205 // Build transformation to correct physical coordinates
2206
2207 dimxlen = plsc->dimxmax - plsc->dimxmin;
2208 dimylen = plsc->dimymax - plsc->dimymin;
2209
2210 pxmin = plsc->phyxmi;
2211 pxmax = plsc->phyxma;
2212 pymin = plsc->phyymi;
2213 pymax = plsc->phyyma;
2214 pxlen = pxmax - pxmin;
2215 pylen = pymax - pymin;
2216
2217 plsc->dimxax = pxlen / dimxlen;
2218 plsc->dimyay = pylen / dimylen;
2219 plsc->dimxb = pxmin - pxlen * plsc->dimxmin / dimxlen;
2220 plsc->dimyb = pymin - pylen * plsc->dimymin / dimylen;
2221 }
2222
2223 //--------------------------------------------------------------------------
2224 // void plflush()
2225 //
2226 // Flushes the output stream. Use sparingly, if at all.
2227 //--------------------------------------------------------------------------
2228
2229 void
2230 c_plflush( void )
2231 {
2232 if ( plsc->dev_flush )
2233 {
2234 char *save_locale = plsave_set_locale();
2235 if ( !plsc->stream_closed )
2236 {
2237 ( *plsc->dispatch_table->pl_esc )( (struct PLStream_struct *) plsc,
2238 PLESC_FLUSH, NULL );
2239 }
2240 plrestore_locale( save_locale );
2241 }
2242 else
2243 {
2244 if ( plsc->OutFile != NULL )
2245 fflush( plsc->OutFile );
2246 }
2247 }
2248
2249 //--------------------------------------------------------------------------
2250 // Startup routines.
2251 //--------------------------------------------------------------------------
2252
2253 //--------------------------------------------------------------------------
2254 // void pllib_init()
2255 //
2256 // Initialize library. Called internally by every startup routine.
2257 // Everything you want to always be initialized before plinit() is called
2258 // you should put here. E.g. dispatch table setup, rcfile read, etc.
2259 //--------------------------------------------------------------------------
2260
2261 void
2262 pllib_init()
2263 {
2264 if ( lib_initialized )
2265 return;
2266 lib_initialized = 1;
2267
2268 #ifdef ENABLE_DYNDRIVERS
2269 // Create libltdl resources
2270 lt_dlinit();
2271 #endif
2272
2273 // Initialize the dispatch table with the info from the static drivers table
2274 // and the available dynamic drivers.
2275
2276 plInitDispatchTable();
2277 }
2278
2279 //--------------------------------------------------------------------------
2280 // void plstar(nx, ny)
2281 //
2282 // Initialize PLplot, passing in the windows/page settings.
2283 //--------------------------------------------------------------------------
2284
2285 void
2286 c_plstar( PLINT nx, PLINT ny )
2287 {
2288 pllib_init();
2289
2290 if ( plsc->level != 0 )
2291 plend1();
2292
2293 plssub( nx, ny );
2294
2295 c_plinit();
2296 }
2297
2298 //--------------------------------------------------------------------------
2299 // void plstart(devname, nx, ny)
2300 //
2301 // Initialize PLplot, passing the device name and windows/page settings.
2302 //--------------------------------------------------------------------------
2303
2304 void
2305 c_plstart( PLCHAR_VECTOR devname, PLINT nx, PLINT ny )
2306 {
2307 pllib_init();
2308
2309 if ( plsc->level != 0 )
2310 plend1();
2311
2312 plssub( nx, ny );
2313 plsdev( devname );
2314
2315 c_plinit();
2316 }
2317
2318 //--------------------------------------------------------------------------
2319 // void plinit()
2320 //
2321 // Initializes PLplot, using preset or default options.
2322 //--------------------------------------------------------------------------
2323
2324 void
2325 c_plinit( void )
2326 {
2327 PLFLT lx, ly, xpmm_loc, ypmm_loc, aspect_old, aspect_new;
2328
2329 pllib_init();
2330
2331 if ( plsc->level != 0 )
2332 plend1();
2333
2334 // Set stream number
2335
2336 plsc->ipls = ipls;
2337
2338 // Set up devices
2339
2340 pllib_devinit();
2341
2342 // Auxiliary stream setup
2343
2344 plstrm_init();
2345
2346 // Set title for window to a sensible default if not defined
2347 if ( plsc->plwindow == NULL )
2348 {
2349 if ( plsc->program )
2350 {
2351 if ( ( plsc->plwindow = (char *) malloc( (size_t) ( 1 + strlen( plsc->program ) ) * sizeof ( char ) ) ) == NULL )
2352 {
2353 plexit( "plinit: Insufficient memory" );
2354 }
2355 strcpy( plsc->plwindow, plsc->program );
2356 }
2357 else
2358 {
2359 if ( ( plsc->plwindow = (char *) malloc( (size_t) 7 * sizeof ( char ) ) ) == NULL )
2360 {
2361 plexit( "plinit: Insufficient memory" );
2362 }
2363 strcpy( plsc->plwindow, "PLplot" );
2364 }
2365 }
2366
2367 // Initialize device & first page
2368
2369 plP_init();
2370 plP_bop();
2371 plsc->level = 1;
2372
2373
2374 // The driver options are freed after driver initialisation,
2375 // since it is assumed that in this function options are
2376 // processed and stored somewhere else. For further driver
2377 // initialisations (e.g. copy stream) there are no driver
2378 // options defined.
2379
2380 plP_FreeDrvOpts();
2381
2382 // Calculate factor such that the character aspect ratio is preserved
2383 // when the overall aspect ratio is changed, i.e., if portrait mode is
2384 // requested (only honored for subset of drivers) or if the aspect ratio
2385 // is specified in any way, or if a 90 deg rotation occurs with
2386 // -freeaspect.
2387
2388 // Case where plsc->aspect has a value.... (e.g., -a aspect on the
2389 // command line or 2nd parameter of plsdidev specified)
2390 if ( plsc->aspect > 0. )
2391 {
2392 lx = plsc->phyxlen / plsc->xpmm;
2393 ly = plsc->phyylen / plsc->ypmm;
2394 aspect_old = lx / ly;
2395 aspect_new = plsc->aspect;
2396 plsc->caspfactor = sqrt( aspect_old / aspect_new );
2397 }
2398 // Case of 90 deg rotations with -freeaspect (this is also how portrait
2399 // mode is implemented for the drivers that honor -portrait).
2400 else if ( plsc->freeaspect && ABS( cos( plsc->diorot * PI / 2. ) ) <= 1.e-5 )
2401 {
2402 lx = plsc->phyxlen / plsc->xpmm;
2403 ly = plsc->phyylen / plsc->ypmm;
2404 aspect_old = lx / ly;
2405 aspect_new = ly / lx;
2406 plsc->caspfactor = sqrt( aspect_old / aspect_new );
2407 }
2408
2409 else
2410 plsc->caspfactor = 1.;
2411
2412 // Load fonts
2413
2414 plsc->cfont = 1;
2415 plfntld( initfont );
2416
2417 // Set up subpages
2418
2419 plP_subpInit();
2420
2421 // Set up number of allowed digits before switching to scientific notation
2422 // The user can always change this
2423
2424 if ( plsc->xdigmax == 0 )
2425 plsc->xdigmax = 4;
2426
2427 if ( plsc->ydigmax == 0 )
2428 plsc->ydigmax = 4;
2429
2430 if ( plsc->zdigmax == 0 )
2431 plsc->zdigmax = 3;
2432
2433 if ( plsc->timefmt == NULL )
2434 c_pltimefmt( "%c" );
2435
2436 // Use default transformation between continuous and broken-down time
2437 // (and vice versa) if the transformation has not yet been defined
2438 // for this stream.
2439 if ( plsc->qsasconfig == NULL )
2440 c_plconfigtime( 0., 0., 0., 0x0, 0, 0, 0, 0, 0, 0, 0. );
2441
2442 // Switch to graphics mode and set color and arrow style
2443
2444 plgra();
2445 plcol0( 1 );
2446
2447 pllsty( 1 );
2448 plpsty( 0 );
2449
2450 // Set up default arrow style;
2451 plsvect( NULL, NULL, 6, 0 );
2452
2453 // Set clip limits.
2454
2455 plP_sclp( plsc->phyxmi, plsc->phyxma, plsc->phyymi, plsc->phyyma );
2456
2457 // Page aspect ratio.
2458
2459 lx = plsc->phyxlen / plsc->xpmm;
2460 ly = plsc->phyylen / plsc->ypmm;
2461 plsc->aspdev = lx / ly;
2462
2463 // Initialize driver interface
2464
2465 pldi_ini();
2466
2467 // Apply compensating factor to original xpmm and ypmm so that
2468 // character aspect ratio is preserved when overall aspect ratio
2469 // is changed. This must appear here in the code because previous
2470 // code in this routine and in routines that it calls must use the original
2471 // values of xpmm and ypmm before the compensating factor is applied.
2472
2473 plP_gpixmm( &xpmm_loc, &ypmm_loc );
2474 plP_setpxl( xpmm_loc * plsc->caspfactor, ypmm_loc / plsc->caspfactor );
2475 }
2476
2477 //--------------------------------------------------------------------------
2478 // void plend()
2479 //
2480 // End a plotting session for all open streams.
2481 //--------------------------------------------------------------------------
2482
2483 void
2484 c_plend( void )
2485 {
2486 PLINT i;
2487
2488 if ( lib_initialized == 0 )
2489 return;
2490
2491 for ( i = PL_NSTREAMS - 1; i >= 0; i-- )
2492 {
2493 if ( pls[i] != NULL )
2494 {
2495 plsstrm( i );
2496 c_plend1();
2497 }
2498 }
2499 plfontrel();
2500 #ifdef ENABLE_DYNDRIVERS
2501 // Release the libltdl resources
2502 lt_dlexit();
2503 // Free up memory allocated to the dispatch tables
2504 for ( i = 0; i < npldynamicdevices; i++ )
2505 {
2506 free_mem( loadable_device_list[i].devnam );
2507 free_mem( loadable_device_list[i].description );
2508 free_mem( loadable_device_list[i].drvnam );
2509 free_mem( loadable_device_list[i].tag );
2510 }
2511 free_mem( loadable_device_list );
2512 for ( i = 0; i < nloadabledrivers; i++ )
2513 {
2514 free_mem( loadable_driver_list[i].drvnam );
2515 }
2516 free_mem( loadable_driver_list );
2517 for ( i = nplstaticdevices; i < npldrivers; i++ )
2518 {
2519 free_mem( dispatch_table[i]->pl_MenuStr );
2520 free_mem( dispatch_table[i]->pl_DevName );
2521 free_mem( dispatch_table[i] );
2522 }
2523 #endif
2524 for ( i = 0; i < nplstaticdevices; i++ )
2525 {
2526 free_mem( dispatch_table[i] );
2527 }
2528 free_mem( dispatch_table );
2529
2530 lib_initialized = 0;
2531 }
2532
2533 //--------------------------------------------------------------------------
2534 // void plend1()
2535 //
2536 // End a plotting session for the current stream only. After the stream is
2537 // ended the memory associated with the stream's PLStream data structure is
2538 // freed (for stream > 0), and the stream counter is set to 0 (the default).
2539 //--------------------------------------------------------------------------
2540
2541 void
2542 c_plend1( void )
2543 {
2544 if ( plsc->level > 0 )
2545 {
2546 plP_eop();
2547 plP_wait();
2548 plP_tidy();
2549 plsc->level = 0;
2550 }
2551 // Move from plP_tidy because FileName may be set even if level == 0
2552 if ( plsc->FileName )
2553 free_mem( plsc->FileName );
2554
2555 // Free all malloc'ed stream memory
2556
2557 free_mem( plsc->cmap0 );
2558 free_mem( plsc->cmap1 );
2559 free_mem( plsc->plwindow );
2560 free_mem( plsc->geometry );
2561 free_mem( plsc->dev );
2562 free_mem( plsc->BaseName );
2563 free_mem( plsc->plbuf_buffer );
2564
2565 if ( plsc->program )
2566 free_mem( plsc->program );
2567 if ( plsc->server_name )
2568 free_mem( plsc->server_name );
2569 if ( plsc->server_host )
2570 free_mem( plsc->server_host );
2571 if ( plsc->server_port )
2572 free_mem( plsc->server_port );
2573 if ( plsc->user )
2574 free_mem( plsc->user );
2575 if ( plsc->plserver )
2576 free_mem( plsc->plserver );
2577 if ( plsc->auto_path )
2578 free_mem( plsc->auto_path );
2579
2580 if ( plsc->arrow_x )
2581 free_mem( plsc->arrow_x );
2582 if ( plsc->arrow_y )
2583 free_mem( plsc->arrow_y );
2584
2585 if ( plsc->timefmt )
2586 free_mem( plsc->timefmt );
2587
2588 // Close qsastime library for this stream that was opened by
2589 // plconfigtime call in plinit.
2590
2591 closeqsas( &( plsc->qsasconfig ) );
2592
2593 // Free memory used by the plot metafiles
2594 if ( plsc->mf_infile )
2595 free_mem( plsc->mf_infile );
2596 if ( plsc->mf_outfile )
2597 free_mem( plsc->mf_outfile );
2598
2599 // Free malloc'ed stream if not in initial stream, else clear it out
2600
2601 if ( ipls > 0 )
2602 {
2603 free_mem( plsc );
2604 pls[ipls] = NULL;
2605 plsstrm( 0 );
2606 }
2607 else
2608 {
2609 memset( (char *) pls[ipls], 0, sizeof ( PLStream ) );
2610 }
2611 }
2612
2613 //--------------------------------------------------------------------------
2614 // void plsstrm
2615 //
2616 // Set stream number. If the data structure for a new stream is
2617 // unallocated, we allocate it here.
2618 //--------------------------------------------------------------------------
2619
2620 void
2621 c_plsstrm( PLINT strm )
2622 {
2623 if ( strm < 0 || strm >= PL_NSTREAMS )
2624 {
2625 fprintf( stderr,
2626 "plsstrm: Illegal stream number %d, must be in [0, %d]\n",
2627 (int) strm, PL_NSTREAMS );
2628 }
2629 else
2630 {
2631 ipls = strm;
2632 if ( pls[ipls] == NULL )
2633 {
2634 pls[ipls] = (PLStream *) malloc( (size_t) sizeof ( PLStream ) );
2635 if ( pls[ipls] == NULL )
2636 plexit( "plsstrm: Out of memory." );
2637
2638 memset( (char *) pls[ipls], 0, sizeof ( PLStream ) );
2639 }
2640 plsc = pls[ipls];
2641 plsc->ipls = ipls;
2642 }
2643 }
2644
2645 //--------------------------------------------------------------------------
2646 // void plgstrm
2647 //
2648 // Get current stream number.
2649 //--------------------------------------------------------------------------
2650
2651 void
2652 c_plgstrm( PLINT *p_strm )
2653 {
2654 *p_strm = ipls;
2655 }
2656
2657 //--------------------------------------------------------------------------
2658 // void plmkstrm
2659 //
2660 // Creates a new stream and makes it the default. Differs from using
2661 // plsstrm(), in that a free stream number is found, and returned.
2662 //
2663 // Unfortunately, I /have/ to start at stream 1 and work upward, since
2664 // stream 0 is preallocated. One of the BIG flaws in the PLplot API is
2665 // that no initial, library-opening call is required. So stream 0 must be
2666 // preallocated, and there is no simple way of determining whether it is
2667 // already in use or not.
2668 //--------------------------------------------------------------------------
2669
2670 void
2671 c_plmkstrm( PLINT *p_strm )
2672 {
2673 int i;
2674
2675 for ( i = 1; i < PL_NSTREAMS; i++ )
2676 {
2677 if ( pls[i] == NULL )
2678 break;
2679 }
2680
2681 if ( i == PL_NSTREAMS )
2682 {
2683 fprintf( stderr, "plmkstrm: Cannot create new stream\n" );
2684 *p_strm = -1;
2685 }
2686 else
2687 {
2688 *p_strm = i;
2689 plsstrm( i );
2690 }
2691 plstrm_init();
2692 }
2693
2694 //--------------------------------------------------------------------------
2695 // void plstrm_init
2696 //
2697 // Does required startup initialization of a stream. Should be called right
2698 // after creating one (for allocating extra memory, etc). Users shouldn't
2699 // need to call this directly.
2700 //
2701 // This function can be called multiple times for a given stream, in which
2702 // case only the first call produces any effect. For streams >= 1, which
2703 // are created dynamically, this is called by the routine that allocates
2704 // the stream. Stream 0, which is preallocated, is much harder to deal with
2705 // because any of a number of different calls may be the first call to the
2706 // library. This is handled by just calling plstrm_init() from every
2707 // function that might be called first. Sucks, but it should work.
2708 //--------------------------------------------------------------------------
2709
2710 void
2711 plstrm_init( void )
2712 {
2713 if ( !plsc->initialized )
2714 {
2715 plsc->initialized = 1;
2716
2717 if ( plsc->cmap0 == NULL )
2718 plspal0( "" );
2719
2720 if ( plsc->cmap1 == NULL )
2721 plspal1( "", TRUE );
2722
2723 // Set continuous plots to use the full color map 1 range
2724 plsc->cmap1_min = 0.0;
2725 plsc->cmap1_max = 1.0;
2726 }
2727
2728 plsc->psdoc = NULL;
2729 }
2730
2731 //--------------------------------------------------------------------------
2732 // pl_cpcolor
2733 //
2734 // Utility to copy one PLColor to another.
2735 //--------------------------------------------------------------------------
2736
2737 void
2738 pl_cpcolor( PLColor *to, PLColor *from )
2739 {
2740 to->r = from->r;
2741 to->g = from->g;
2742 to->b = from->b;
2743 to->a = from->a;
2744 }
2745
2746 //--------------------------------------------------------------------------
2747 // void plcpstrm
2748 //
2749 // Copies state parameters from the reference stream to the current stream.
2750 // Tell driver interface to map device coordinates unless flags == 1.
2751 //
2752 // This function is used for making save files of selected plots (e.g.
2753 // from the TK driver). After initializing, you can get a copy of the
2754 // current plot to the specified device by switching to this stream and
2755 // issuing a plcpstrm() and a plreplot(), with calls to plbop() and
2756 // pleop() as appropriate. The plot buffer must have previously been
2757 // enabled (done automatically by some display drivers, such as X).
2758 //--------------------------------------------------------------------------
2759
2760 void
2761 c_plcpstrm( PLINT iplsr, PLINT flags )
2762 {
2763 int i;
2764 PLStream *plsr;
2765
2766 plsr = pls[iplsr];
2767 if ( plsr == NULL )
2768 {
2769 fprintf( stderr, "plcpstrm: stream %d not in use\n", (int) iplsr );
2770 return;
2771 }
2772
2773 // May be debugging
2774
2775 plsc->debug = plsr->debug;
2776
2777 // Plot buffer -- need to copy buffer pointer so that plreplot() works
2778 // This also prevents inadvertent writes into the plot buffer
2779 plsc->plbuf_buffer_grow = plsr->plbuf_buffer_grow;
2780 plsc->plbuf_buffer_size = plsr->plbuf_buffer_size;
2781 plsc->plbuf_top = plsr->plbuf_top;
2782 plsc->plbuf_readpos = plsr->plbuf_readpos;
2783 if ( ( plsc->plbuf_buffer = malloc( plsc->plbuf_buffer_size ) ) == NULL )
2784 plexit( "plcpstrm: Error allocating plot buffer." );
2785 memcpy( plsc->plbuf_buffer, plsr->plbuf_buffer, plsr->plbuf_top );
2786
2787 // Driver interface
2788 // Transformation must be recalculated in current driver coordinates
2789
2790 if ( plsr->difilt & PLDI_PLT )
2791 plsdiplt( plsr->dipxmin, plsr->dipymin, plsr->dipxmax, plsr->dipymax );
2792
2793 if ( plsr->difilt & PLDI_DEV )
2794 plsdidev( plsr->mar, plsr->aspect, plsr->jx, plsr->jy );
2795
2796 if ( plsr->difilt & PLDI_ORI )
2797 plsdiori( plsr->diorot );
2798
2799 // Map device coordinates
2800
2801 if ( !( flags & 0x01 ) )
2802 {
2803 pldebug( "plcpstrm", "mapping parameters: %d %d %d %d %f %f\n",
2804 plsr->phyxmi, plsr->phyxma, plsr->phyymi, plsr->phyyma,
2805 plsr->xpmm, plsr->ypmm );
2806 plsdimap( plsr->phyxmi, plsr->phyxma, plsr->phyymi, plsr->phyyma,
2807 plsr->xpmm, plsr->ypmm );
2808 }
2809
2810 // current color
2811
2812 pl_cpcolor( &plsc->curcolor, &plsr->curcolor );
2813
2814 // cmap 0
2815
2816 plsc->icol0 = plsr->icol0;
2817 plsc->ncol0 = plsr->ncol0;
2818 if ( plsc->cmap0 != NULL )
2819 free( (void *) plsc->cmap0 );
2820
2821 if ( ( plsc->cmap0 = (PLColor *) calloc( 1, (size_t) plsc->ncol0 * sizeof ( PLColor ) ) ) == NULL )
2822 {
2823 plexit( "c_plcpstrm: Insufficient memory" );
2824 }
2825
2826 for ( i = 0; i < plsc->ncol0; i++ )
2827 pl_cpcolor( &plsc->cmap0[i], &plsr->cmap0[i] );
2828
2829 // cmap 1
2830
2831 plsc->icol1 = plsr->icol1;
2832 plsc->ncol1 = plsr->ncol1;
2833 plsc->cmap1_min = plsr->cmap1_min;
2834 plsc->cmap1_max = plsr->cmap1_max;
2835 if ( plsc->cmap1 != NULL )
2836 free( (void *) plsc->cmap1 );
2837
2838 if ( ( plsc->cmap1 = (PLColor *) calloc( 1, (size_t) plsc->ncol1 * sizeof ( PLColor ) ) ) == NULL )
2839 {
2840 plexit( "c_plcpstrm: Insufficient memory" );
2841 }
2842
2843 for ( i = 0; i < plsc->ncol1; i++ )
2844 pl_cpcolor( &plsc->cmap1[i], &plsr->cmap1[i] );
2845
2846 // Initialize if it hasn't been done yet.
2847
2848 if ( plsc->level == 0 )
2849 plinit();
2850 }
2851
2852 //--------------------------------------------------------------------------
2853 // pllib_devinit()
2854 //
2855 // Does preliminary setup of device driver.
2856 //
2857 // This function (previously plGetDev) used to be what is now shown as
2858 // plSelectDev below. However, the situation is a bit more complicated now in
2859 // the dynloadable drivers era. We now have to:
2860 //
2861 // 1) Make sure the dispatch table is initialized to the union of static
2862 // drivers and available dynamic drivers (done from pllib_init now).
2863 // 2) Allow the user to select the desired device.
2864 // 3) Initialize the dispatch table entries for the selected device, in the
2865 // case that it is a dynloadable driver that has not yet been loaded.
2866 //
2867 // Also made non-static, in order to allow some device calls to be made prior
2868 // to calling plinit(). E.g. plframe needs to tell the X driver to create its
2869 // internal data structure during widget construction time (using the escape
2870 // function), but doesn't call plinit() until the plframe is actually mapped.
2871 //--------------------------------------------------------------------------
2872
2873 void
2874 pllib_devinit()
2875 {
2876 if ( plsc->dev_initialized )
2877 return;
2878 plsc->dev_initialized = 1;
2879
2880 plSelectDev();
2881
2882 plLoadDriver();
2883
2884 // offset by one since table is zero-based, but input list is not
2885 plsc->dispatch_table = dispatch_table[plsc->device - 1];
2886 }
2887
2888 int plInBuildTree()
2889 {
2890 static int inited = 0;
2891 static int inBuildTree = 0;
2892
2893 if ( inited == 0 )
2894 {
2895 int len_currdir, len_builddir;
2896 char currdir[PLPLOT_MAX_PATH], *pcurrdir = currdir;
2897 char builddir[PLPLOT_MAX_PATH], *pbuilddir = builddir;
2898
2899
2900 if ( getcwd( currdir, PLPLOT_MAX_PATH ) == NULL )
2901 {
2902 pldebug( "plInBuildTree():", "Not enough buffer space" );
2903 }
2904 else
2905 {
2906 pldebug( "plInBuildTree(): ", "current directory >%s<\n", currdir );
2907 pldebug( "plInBuildTree(): ", "build directory >%s<\n", BUILD_DIR );
2908 // The chdir / getcwd call is to ensure we get the physical
2909 // path without any symlinks
2910 // Ignore error in chdir - build tree may not exist
2911 if ( chdir( BUILD_DIR ) == 0 )
2912 {
2913 if ( getcwd( builddir, PLPLOT_MAX_PATH ) == NULL )
2914 {
2915 pldebug( "plInBuildTree():", "Not enough buffer space" );
2916 }
2917 else
2918 {
2919 len_currdir = strlen( currdir );
2920 len_builddir = strlen( builddir );
2921 #if defined ( IGNORECASE )
2922 pldebug( "plInBuildTree(): ", "comparing ignoring case\n" );
2923 // On Windows all parts of the path are case insensitive
2924 // so convert to lower case for the comparison.
2925 for (; *pcurrdir; ++pcurrdir )
2926 {
2927 *pcurrdir = tolower( *pcurrdir );
2928 if ( *pcurrdir == '\\' )
2929 {
2930 *pcurrdir = '/';
2931 }
2932 }
2933 for (; *pbuilddir; ++pbuilddir )
2934 {
2935 *pbuilddir = tolower( *pbuilddir );
2936 if ( *pbuilddir == '\\' )
2937 {
2938 *pbuilddir = '/';
2939 }
2940 }
2941 // builddir does not have trailing path delimiter
2942 // so the strncmp comparison checks if currdir is
2943 // exactly the builddir or builddir with a string
2944 // appended. So if that test succeeds, then check
2945 // further if the currdir is exactly the build_dir
2946 // or the appended string starts with the path
2947 // delimiter, i.e., whether currdir is the builddir or
2948 // a subdirectory of that directory.
2949 if ( strncmp( builddir, currdir, len_builddir ) == 0 &&
2950 ( len_currdir == len_builddir || currdir[len_builddir] == '\\' || currdir[len_builddir] == '/' ) )
2951 #else
2952 pldebug( "plInBuildTree(): ", "comparing respecting case\n" );
2953 if ( strncmp( builddir, currdir, len_builddir ) == 0 &&
2954 ( len_currdir == len_builddir || currdir[len_builddir] == '/' ) )
2955 #endif
2956 {
2957 inBuildTree = 1;
2958 }
2959 }
2960 if ( chdir( currdir ) != 0 )
2961 pldebug( "plInBuildTree():", "Unable to chdir to current directory" );
2962 }
2963 }
2964 inited = 1;
2965 }
2966 return inBuildTree;
2967 }
2968
2969 #ifdef ENABLE_DYNDRIVERS
2970
2971 PLCHAR_VECTOR
2972 plGetDrvDir()
2973 {
2974 PLCHAR_VECTOR drvdir;
2975
2976 // Get drivers directory in PLPLOT_DRV_DIR or DRV_DIR,
2977 // on this order
2978 //
2979
2980 if ( plInBuildTree() == 1 )
2981 {
2982 drvdir = BUILD_DIR "/drivers";
2983 pldebug( "plGetDrvDir", "Using %s as the driver directory.\n", drvdir );
2984 }
2985 else
2986 {
2987 pldebug( "plGetDrvDir", "Trying to read env var PLPLOT_DRV_DIR\n" );
2988 drvdir = getenv( "PLPLOT_DRV_DIR" );
2989
2990 if ( drvdir == NULL )
2991 {
2992 pldebug( "plGetDrvDir",
2993 "Will use drivers dir: " DRV_DIR "\n" );
2994 drvdir = DRV_DIR;
2995 }
2996 }
2997
2998 return drvdir;
2999 }
3000
3001 #endif
3002
3003
3004 //--------------------------------------------------------------------------
3005 // void plInitDispatchTable()
3006 //
3007 // ...
3008 //--------------------------------------------------------------------------
3009
3010 static int plDispatchSequencer( const void *p1, const void *p2 )
3011 {
3012 const PLDispatchTable* t1 = *(const PLDispatchTable * const *) p1;
3013 const PLDispatchTable* t2 = *(const PLDispatchTable * const *) p2;
3014
3015 // printf( "sorting: t1.name=%s t1.seq=%d t2.name=%s t2.seq=%d\n",
3016 // t1->pl_DevName, t1->pl_seq, t2->pl_DevName, t2->pl_seq );
3017
3018 return t1->pl_seq - t2->pl_seq;
3019 }
3020
3021 static void
3022 plInitDispatchTable()
3023 {
3024 int n;
3025
3026 #ifdef ENABLE_DYNDRIVERS
3027 char buf[BUFFER2_SIZE];
3028 PLCHAR_VECTOR drvdir;
3029 char *devnam, *devdesc, *devtype, *driver, *tag, *seqstr;
3030 int seq;
3031 int i, j, driver_found, done = 0;
3032 FILE *fp_drvdb = NULL;
3033 DIR * dp_drvdir = NULL;
3034 struct dirent * entry;
3035 // lt_dlhandle dlhand;
3036
3037 // Make sure driver counts are zeroed
3038 npldynamicdevices = 0;
3039 nloadabledrivers = 0;
3040
3041 // Open a temporary file in which all the plD_DEVICE_INFO_<driver> strings
3042 // will be stored
3043 fp_drvdb = pl_create_tempfile( NULL );
3044 if ( fp_drvdb == NULL )
3045 {
3046 plabort( "plInitDispatchTable: Could not open temporary file" );
3047 return;
3048 }
3049
3050 // Open the drivers directory
3051 drvdir = plGetDrvDir();
3052 dp_drvdir = opendir( drvdir );
3053 if ( dp_drvdir == NULL )
3054 {
3055 fclose( fp_drvdb );
3056 plabort( "plInitDispatchTable: Could not open drivers directory" );
3057 return;
3058 }
3059
3060 // Loop over each entry in the drivers directory
3061
3062 pldebug( "plInitDispatchTable", "Scanning dyndrivers dir\n" );
3063 while ( ( entry = readdir( dp_drvdir ) ) != NULL )
3064 {
3065 char * name = entry->d_name;
3066 // Suffix .driver_info has a length of 12 letters.
3067 size_t len = strlen( name ) - 12;
3068
3069 pldebug( "plInitDispatchTable",
3070 "Consider file %s\n", name );
3071
3072 // Only consider entries that have the ".driver_info" suffix
3073 if ( ( len > 0 ) && ( strcmp( name + len, ".driver_info" ) == 0 ) )
3074 {
3075 char path[PLPLOT_MAX_PATH];
3076 FILE * fd;
3077
3078 // Open the driver's info file
3079 snprintf( path, PLPLOT_MAX_PATH, "%s/%s", drvdir, name );
3080 fd = fopen( path, "r" );
3081 if ( fd == NULL )
3082 {
3083 closedir( dp_drvdir );
3084 fclose( fp_drvdb );
3085 snprintf( buf, BUFFER2_SIZE,
3086 "plInitDispatchTable: Could not open driver info file %s\n",
3087 name );
3088 plabort( buf );
3089 return;
3090 }
3091
3092 // Each line in the <driver>.driver_info file corresponds to a specific device.
3093 // Write it to the drivers db file and take care of leading newline
3094 // character
3095
3096 pldebug( "plInitDispatchTable",
3097 "Opened driver info file %s\n", name );
3098 while ( fgets( buf, BUFFER2_SIZE, fd ) != NULL )
3099 {
3100 fprintf( fp_drvdb, "%s", buf );
3101 if ( buf [strlen( buf ) - 1] != '\n' )
3102 fprintf( fp_drvdb, "\n" );
3103 npldynamicdevices++;
3104 }
3105 fclose( fd );
3106 }
3107 }
3108
3109 // Make sure that the temporary file containing the drivers database
3110 // is ready to read and close the directory handle
3111 fflush( fp_drvdb );
3112 closedir( dp_drvdir );
3113
3114 #endif
3115
3116 // Allocate space for the dispatch table.
3117 if ( ( dispatch_table = (PLDispatchTable **)
3118 malloc( (size_t) ( nplstaticdevices + npldynamicdevices ) * sizeof ( PLDispatchTable * ) ) ) == NULL )
3119 {
3120 #ifdef ENABLE_DYNDRIVERS
3121 fclose( fp_drvdb );
3122 #endif
3123 plexit( "plInitDispatchTable: Insufficient memory" );
3124 }
3125
3126 // Initialize the dispatch table entries for the static devices by calling
3127 // the dispatch table initialization function for each static device. This
3128 // is the same function that would be called at load time for dynamic
3129 // drivers.
3130
3131 for ( n = 0; n < nplstaticdevices; n++ )
3132 {
3133 if ( ( dispatch_table[n] = (PLDispatchTable *) malloc( sizeof ( PLDispatchTable ) ) ) == NULL )
3134 {
3135 #ifdef ENABLE_DYNDRIVERS
3136 fclose( fp_drvdb );
3137 #endif
3138 plexit( "plInitDispatchTable: Insufficient memory" );
3139 }
3140
3141 // Initialize to zero to force all function pointers to NULL. That way optional capabilities
3142 // (e.g. wait for user input) do not need to be explicitly set to NULL in the driver's
3143 // initialization function
3144 memset( dispatch_table[n], 0, sizeof ( PLDispatchTable ) );
3145
3146 ( *static_device_initializers[n] )( dispatch_table[n] );
3147 }
3148 npldrivers = nplstaticdevices;
3149
3150 #ifdef ENABLE_DYNDRIVERS
3151
3152 // Allocate space for the device and driver specs. We may not use all of
3153 // these driver descriptors, but we obviously won't need more drivers than
3154 // devices...
3155 if ( ( ( loadable_device_list = malloc( (size_t) npldynamicdevices * sizeof ( PLLoadableDevice ) ) ) == NULL ) ||
3156 ( ( loadable_driver_list = malloc( (size_t) npldynamicdevices * sizeof ( PLLoadableDriver ) ) ) == NULL ) )
3157 {
3158 fclose( fp_drvdb );
3159 plexit( "plInitDispatchTable: Insufficient memory" );
3160 }
3161
3162 rewind( fp_drvdb );
3163
3164 i = 0;
3165 done = !( i < npldynamicdevices );
3166 while ( !done )
3167 {
3168 char *p = fgets( buf, BUFFER2_SIZE, fp_drvdb );
3169
3170 if ( p == 0 )
3171 {
3172 done = 1;
3173 continue;
3174 }
3175
3176 devnam = strtok( buf, ":" );
3177 devdesc = strtok( 0, ":" );
3178 devtype = strtok( 0, ":" );
3179 driver = strtok( 0, ":" );
3180 seqstr = strtok( 0, ":" );
3181 tag = strtok( 0, "\n" );
3182
3183 if ( devnam == NULL || devdesc == NULL || devtype == NULL || driver == NULL ||
3184 seqstr == NULL || tag == NULL )
3185 {
3186 continue; // Ill-formatted line, most probably not a valid driver information file
3187 }
3188
3189 seq = atoi( seqstr );
3190
3191 n = npldrivers++;
3192
3193 if ( ( dispatch_table[n] = malloc( sizeof ( PLDispatchTable ) ) ) == NULL )
3194 {
3195 fclose( fp_drvdb );
3196 plexit( "plInitDispatchTable: Insufficient memory" );
3197 }
3198
3199 // Initialize to zero to force all function pointers to NULL. That way optional capabilities
3200 // (e.g. wait for user input) do not need to be explicitly set to NULL in the driver's
3201 // initialization function nor do we need to do it in this function.
3202 memset( dispatch_table[n], 0, sizeof ( PLDispatchTable ) );
3203
3204 // Fill in the dispatch table entries.
3205 dispatch_table[n]->pl_MenuStr = plstrdup( devdesc );
3206 dispatch_table[n]->pl_DevName = plstrdup( devnam );
3207 dispatch_table[n]->pl_type = atoi( devtype );
3208 dispatch_table[n]->pl_seq = seq;
3209
3210 // Add a record to the loadable device list
3211 loadable_device_list[i].devnam = plstrdup( devnam );
3212 loadable_device_list[i].description = plstrdup( devdesc );
3213 loadable_device_list[i].drvnam = plstrdup( driver );
3214 loadable_device_list[i].tag = plstrdup( tag );
3215
3216 // Now see if this driver has been seen before. If not, add a driver
3217 // entry for it.
3218 driver_found = 0;
3219 for ( j = 0; j < nloadabledrivers; j++ )
3220 if ( strcmp( driver, loadable_driver_list[j].drvnam ) == 0 )
3221 {
3222 driver_found = 1;
3223 break;
3224 }
3225
3226 if ( !driver_found )
3227 {
3228 loadable_driver_list[nloadabledrivers].drvnam = plstrdup( driver );
3229 loadable_driver_list[nloadabledrivers].dlhand = 0;
3230 nloadabledrivers++;
3231 }
3232
3233 loadable_device_list[i].drvidx = j;
3234
3235 // Get ready for next loadable device spec
3236 i++;
3237 }
3238
3239 // RML: close fp_drvdb
3240 fclose( fp_drvdb );
3241
3242 #endif
3243
3244 if ( npldrivers == 0 )
3245 {
3246 npldynamicdevices = 0;
3247 plexit( "No device drivers found - please check the environment variable PLPLOT_DRV_DIR" );
3248 }
3249
3250 // Finally, we need to sort the list into presentation order, based on the
3251 // sequence number in the dispatch ttable entries.
3252
3253 qsort( dispatch_table, (size_t) npldrivers, sizeof ( PLDispatchTable* ),
3254 plDispatchSequencer );
3255 }
3256
3257 //--------------------------------------------------------------------------
3258 // void plSelectDev()
3259 //
3260 // If the user has not already specified the output device, or the
3261 // one specified is either: (a) not available, (b) "?", or (c) NULL, the
3262 // user is prompted for it.
3263 //
3264 // Prompting quits after 10 unsuccessful tries in case the user has
3265 // run the program in the background with insufficient input.
3266 //--------------------------------------------------------------------------
3267
3268 static void
3269 plSelectDev()
3270 {
3271 int dev, i, count;
3272 size_t length;
3273 char response[80];
3274 char * devname_env;
3275
3276 // If device name is not already specified, try to get it from environment
3277
3278 if ( plsc->DevName[0] == '\0' )
3279 {
3280 devname_env = getenv( "PLPLOT_DEV" );
3281 if ( devname_env )
3282 {
3283 strncpy( plsc->DevName, devname_env, sizeof ( plsc->DevName ) - 1 );
3284 plsc->DevName[sizeof ( plsc->DevName ) - 1] = '\0';
3285 }
3286 }
3287
3288 // Device name already specified. See if it is valid.
3289
3290 if ( *( plsc->DevName ) != '\0' && *( plsc->DevName ) != '?' )
3291 {
3292 length = strlen( plsc->DevName );
3293 for ( i = 0; i < npldrivers; i++ )
3294 {
3295 if ( ( *plsc->DevName == *dispatch_table[i]->pl_DevName ) &&
3296 ( strncmp( plsc->DevName,
3297 dispatch_table[i]->pl_DevName, length ) == 0 ) )
3298 break;
3299 }
3300 if ( i < npldrivers )
3301 {
3302 plsc->device = i + 1;
3303 return;
3304 }
3305 else
3306 {
3307 fprintf( stderr, "Requested device %s not available\n",
3308 plsc->DevName );
3309 }
3310 }
3311
3312 dev = 0;
3313 count = 0;
3314
3315 if ( npldrivers == 1 )
3316 dev = 1;
3317
3318 // User hasn't specified it correctly yet, so we prompt
3319
3320 while ( dev < 1 || dev > npldrivers )
3321 {
3322 fprintf( stdout, "\nPlotting Options:\n" );
3323 for ( i = 0; i < npldrivers; i++ )
3324 {
3325 fprintf( stdout, " <%2d> %-10s %s\n", i + 1,
3326 dispatch_table[i]->pl_DevName,
3327 dispatch_table[i]->pl_MenuStr );
3328 }
3329 if ( ipls == 0 )
3330 fprintf( stdout, "\nEnter device number or keyword: " );
3331 else
3332 fprintf( stdout, "\nEnter device number or keyword (stream %d): ",
3333 (int) ipls );
3334
3335 plio_fgets( response, sizeof ( response ), stdin );
3336
3337 // First check to see if device keyword was entered.
3338 // Final "\n" in response messes things up, so ignore it.
3339
3340 length = strlen( response );
3341 if ( *( response - 1 + length ) == '\n' )
3342 length--;
3343
3344 for ( i = 0; i < npldrivers; i++ )
3345 {
3346 if ( !strncmp( response, dispatch_table[i]->pl_DevName,
3347 (unsigned int) length ) )
3348 break;
3349 }
3350 if ( i < npldrivers )
3351 {
3352 dev = i + 1;
3353 }
3354 else
3355 {
3356 if ( ( dev = atoi( response ) ) < 1 )
3357 {
3358 fprintf( stdout, "\nInvalid device: %s", response );
3359 dev = 0;
3360 }
3361 }
3362 if ( count++ > 10 )
3363 plexit( "plSelectDev: Too many tries." );
3364 }
3365 plsc->device = dev;
3366 strcpy( plsc->DevName, dispatch_table[dev - 1]->pl_DevName );
3367 }
3368
3369 //--------------------------------------------------------------------------
3370 // void plLoadDriver()
3371 //
3372 // Make sure the selected driver is loaded. Static drivers are already
3373 // loaded, but if the user selected a dynamically loadable driver, we may
3374 // have to take care of that now.
3375 //--------------------------------------------------------------------------
3376
3377 static void
3378 plLoadDriver( void )
3379 {
3380 #ifdef ENABLE_DYNDRIVERS
3381 int i, drvidx;
3382 char sym[BUFFER_SIZE];
3383 char *tag;
3384
3385 int n = plsc->device - 1;
3386 PLDispatchTable *dev = dispatch_table[n];
3387 PLLoadableDriver *driver = 0;
3388
3389 // If the dispatch table is already filled in, then either the device was
3390 // linked in statically, or else perhaps it was already loaded. In either
3391 // case, we have nothing left to do.
3392 if ( dev->pl_init )
3393 return;
3394
3395 pldebug( "plLoadDriver", "Device not loaded!\n" );
3396
3397 // Now search through the list of loadable devices, looking for the record
3398 // that corresponds to the requested device.
3399 for ( i = 0; i < npldynamicdevices; i++ )
3400 if ( strcmp( dev->pl_DevName, loadable_device_list[i].devnam ) == 0 )
3401 break;
3402
3403 // If we couldn't find such a record, then there is some sort of internal
3404 // logic flaw since plSelectDev is supposed to only select a valid device.
3405 //
3406 if ( i == npldynamicdevices )
3407 {
3408 fprintf( stderr, "No such device: %s.\n", dev->pl_DevName );
3409 plexit( "plLoadDriver detected device logic screwup" );
3410 }
3411
3412 // Note the device tag, and the driver index. Note that a given driver could
3413 // supply multiple devices, each with a unique tag to distinguish the driver
3414 // entry points for the different supported devices.
3415 tag = loadable_device_list[i].tag;
3416 drvidx = loadable_device_list[i].drvidx;
3417
3418 pldebug( "plLoadDriver", "tag=%s, drvidx=%d\n", tag, drvidx );
3419
3420 driver = &loadable_driver_list[drvidx];
3421
3422 // Load the driver if it hasn't been loaded yet.
3423 if ( !driver->dlhand )
3424 {
3425 char drvspec[ DRVSPEC_SIZE ];
3426 #if defined ( LTDL_WIN32 ) || defined ( __CYGWIN__ )
3427 snprintf( drvspec, DRVSPEC_SIZE, "%s", driver->drvnam );
3428 #else
3429 snprintf( drvspec, DRVSPEC_SIZE, "%s/%s", plGetDrvDir(), driver->drvnam );
3430 #endif // LTDL_WIN32
3431
3432 pldebug( "plLoadDriver", "Trying to load %s on %s\n",
3433 driver->drvnam, drvspec );
3434
3435 driver->dlhand = lt_dlopenext( drvspec );
3436
3437 // A few of our drivers do not depend on other libraries. So
3438 // allow them to be completely removed by plend to give clean
3439 // valgrind results. However, the (large) remainder of our
3440 // drivers do depend on other libraries so mark them resident
3441 // to prevent problems with atexit handlers / library
3442 // reinitialisation such as those seen with qt and cairo
3443 // drivers.
3444 if ( !( strcmp( driver->drvnam, "mem" ) == 0 ||
3445 strcmp( driver->drvnam, "null" ) == 0 ||
3446 strcmp( driver->drvnam, "plmeta" ) == 0 ||
3447 strcmp( driver->drvnam, "ps" ) == 0 ||
3448 strcmp( driver->drvnam, "svg" ) == 0 ||
3449 strcmp( driver->drvnam, "xfig" ) == 0 ) )
3450 lt_dlmakeresident( driver->dlhand );
3451 }
3452
3453 // If it still isn't loaded, then we're doomed.
3454 if ( !driver->dlhand )
3455 {
3456 pldebug( "plLoadDriver", "lt_dlopenext failed because of "
3457 "the following reason:\n%s\n", lt_dlerror() );
3458 fprintf( stderr, "Unable to load driver: %s.\n", driver->drvnam );
3459 plexit( "Unable to load driver" );
3460 }
3461
3462 // Now we are ready to ask the driver's device dispatch init function to
3463 // initialize the entries in the dispatch table.
3464
3465 snprintf( sym, BUFFER_SIZE, "plD_dispatch_init_%s", tag );
3466 {
3467 PLDispatchInit dispatch_init = (PLDispatchInit) lt_dlsym( driver->dlhand, sym );
3468 if ( !dispatch_init )
3469 {
3470 fprintf( stderr,
3471 "Unable to locate dispatch table initialization function for driver: %s.\n",
3472 driver->drvnam );
3473 return;
3474 }
3475
3476 ( *dispatch_init )( dev );
3477 }
3478 #endif
3479 }
3480
3481 //--------------------------------------------------------------------------
3482 // void plfontld()
3483 //
3484 // Load specified font set.
3485 //--------------------------------------------------------------------------
3486
3487 void
3488 c_plfontld( PLINT ifont )
3489 {
3490 if ( ifont != 0 )
3491 ifont = 1;
3492
3493 if ( plsc->level > 0 )
3494 plfntld( ifont );
3495 else
3496 initfont = ifont;
3497 }
3498
3499 //--------------------------------------------------------------------------
3500 // void plreplot()
3501 //
3502 // Replays contents of plot buffer to current device/file.
3503 //--------------------------------------------------------------------------
3504
3505 void
3506 c_plreplot( void )
3507 {
3508 if ( plsc->plbuf_buffer != NULL )
3509 {
3510 plRemakePlot( plsc );
3511 }
3512 else
3513 {
3514 plwarn( "plreplot: plot buffer not available" );
3515 }
3516 }
3517
3518 //--------------------------------------------------------------------------
3519 // void plgFileDevs()
3520 //
3521 // Returns a list of file-oriented device names and their menu strings,
3522 // for use in a graphical interface. The caller must allocate enough
3523 // space for (*p_menustr) and (*p_devname) to hold a pointer for each
3524 // device -- 20 or so is plenty. E.g. char *menustr[20]. The size of
3525 // these arrays should be passed in *p_ndev, which, on exit, holds the
3526 // number of devices actually present.
3527 //--------------------------------------------------------------------------
3528
3529 void
3530 plgFileDevs( const char ***p_menustr, const char ***p_devname, int *p_ndev )
3531 {
3532 plgdevlst( *p_menustr, *p_devname, p_ndev, 0 );
3533 }
3534
3535 //--------------------------------------------------------------------------
3536 // void plgDevs()
3537 //
3538 // Like plgFileDevs(), but returns names and menu strings for all devices.
3539 //--------------------------------------------------------------------------
3540
3541 void
3542 plgDevs( const char ***p_menustr, const char ***p_devname, int *p_ndev )
3543 {
3544 plgdevlst( *p_menustr, *p_devname, p_ndev, -1 );
3545 }
3546
3547 static void
3548 plgdevlst( const char **p_menustr, const char **p_devname, int *p_ndev, int type )
3549 {
3550 int i, j;
3551
3552 pllib_init();
3553
3554 for ( i = j = 0; i < npldrivers; i++ )
3555 {
3556 if ( type < 0 || dispatch_table[i]->pl_type == type )
3557 {
3558 p_menustr[j] = dispatch_table[i]->pl_MenuStr;
3559 p_devname[j] = dispatch_table[i]->pl_DevName;
3560 if ( ++j + 1 >= *p_ndev )
3561 {
3562 plwarn( "plgdevlst: too many devices" );
3563 break;
3564 }
3565 }
3566 }
3567 p_menustr[j] = NULL;
3568 p_devname[j] = NULL;
3569 *p_ndev = j;
3570 }
3571
3572 //--------------------------------------------------------------------------
3573 // Various external access routines.
3574 //--------------------------------------------------------------------------
3575
3576 // Get output device parameters.
3577
3578 void
3579 c_plgpage( PLFLT *p_xp, PLFLT *p_yp,
3580 PLINT *p_xleng, PLINT *p_yleng, PLINT *p_xoff, PLINT *p_yoff )
3581 {
3582 *p_xp = plsc->xdpi;
3583 *p_yp = plsc->ydpi;
3584 *p_xleng = plsc->xlength;
3585 *p_yleng = plsc->ylength;
3586 *p_xoff = plsc->xoffset;
3587 *p_yoff = plsc->yoffset;
3588 }
3589
3590 // Set output device parameters. Usually ignored by the driver.
3591
3592 void
3593 c_plspage( PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff )
3594 {
3595 if ( plsc->level > 0 )
3596 plwarn( "calling plspage() after plinit() may give unpredictable results" );
3597
3598 if ( xp )
3599 plsc->xdpi = xp;
3600 if ( yp )
3601 plsc->ydpi = yp;
3602
3603 if ( xleng )
3604 plsc->xlength = xleng;
3605 if ( yleng )
3606 plsc->ylength = yleng;
3607
3608 if ( xoff )
3609 plsc->xoffset = xoff;
3610 if ( yoff )
3611 plsc->yoffset = yoff;
3612 }
3613
3614 // Set the number of subwindows in x and y
3615
3616 void
3617 c_plssub( PLINT nx, PLINT ny )
3618 {
3619 if ( nx > 0 )
3620 plsc->nsubx = nx;
3621 if ( ny > 0 )
3622 plsc->nsuby = ny;
3623
3624 // Force a page advance
3625
3626 if ( plsc->level > 0 )
3627 {
3628 plP_subpInit();
3629 //AWI plP_eop();
3630 // plP_bop();
3631 }
3632 //write the sub pages to the buffer if required
3633 if ( plsc->plbuf_write )
3634 plbuf_ssub( plsc );
3635 }
3636
3637 // Set the device (keyword) name
3638
3639 void
3640 c_plsdev( PLCHAR_VECTOR devname )
3641 {
3642 if ( plsc->level > 0 )
3643 {
3644 plwarn( "plsdev: Must be called before plinit." );
3645 return;
3646 }
3647 if ( devname != NULL )
3648 {
3649 strncpy( plsc->DevName, devname, sizeof ( plsc->DevName ) - 1 );
3650 plsc->DevName[sizeof ( plsc->DevName ) - 1] = '\0';
3651 }
3652 }
3653
3654 // Get the current device (keyword) name
3655 // Note: you MUST have allocated space for this (80 characters is safe)
3656
3657 void
3658 c_plgdev( char *p_dev )
3659 {
3660 strcpy( p_dev, plsc->DevName );
3661 }
3662
3663 // Set the memory area to be plotted (with the 'mem' driver) as the 'dev'
3664 // member of the stream structure. Also set the number
3665 // of pixels in the memory passed in in 'plotmem'.
3666 // Plotmem is a block of memory maxy by maxx by 3 bytes long, say:
3667 // 480 x 640 x 3 (Y, X, RGB)
3668 //
3669 // This memory will be freed by the user!
3670 //
3671
3672 void
3673 c_plsmem( PLINT maxx, PLINT maxy, void *plotmem )
3674 {
3675 plsc->dev = plotmem;
3676 plsc->dev_mem_alpha = 0;
3677 plP_setphy( 0, maxx, 0, maxy );
3678 }
3679
3680 // Same as plsmem, but the buffer is (Y, X, RGBA)
3681
3682 void
3683 c_plsmema( PLINT maxx, PLINT maxy, void *plotmem )
3684 {
3685 plsc->dev = plotmem;
3686 plsc->dev_mem_alpha = 1;
3687 plP_setphy( 0, maxx, 0, maxy );
3688 }
3689
3690 // Get the current stream pointer
3691
3692 void
3693 plgpls( PLStream **p_pls )
3694 {
3695 *p_pls = plsc;
3696 }
3697
3698 // Get the (current) run level.
3699 // Valid settings are:
3700 // 0 uninitialized
3701 // 1 initialized
3702 // 2 viewport defined
3703 // 3 world coords defined
3704 //
3705
3706 void
3707 c_plglevel( PLINT *p_level )
3708 {
3709 *p_level = plsc->level;
3710 }
3711
3712 // Set the function pointer for the keyboard event handler
3713
3714 void
3715 plsKeyEH( void ( *KeyEH )( PLGraphicsIn *, void *, int * ),
3716 void *KeyEH_data )
3717 {
3718 plsc->KeyEH = KeyEH;
3719 plsc->KeyEH_data = KeyEH_data;
3720 }
3721
3722 // Set the function pointer for the (mouse) button event handler
3723
3724 void
3725 plsButtonEH( void ( *ButtonEH )( PLGraphicsIn *, void *, int * ),
3726 void *ButtonEH_data )
3727 {
3728 plsc->ButtonEH = ButtonEH;
3729 plsc->ButtonEH_data = ButtonEH_data;
3730 }
3731
3732 // Sets an optional user bop handler.
3733
3734 void
3735 plsbopH( void ( *handler )( void *, int * ), void *handler_data )
3736 {
3737 plsc->bop_handler = handler;
3738 plsc->bop_data = handler_data;
3739 }
3740
3741 // Sets an optional user eop handler.
3742
3743 void
3744 plseopH( void ( *handler )( void *, int * ), void *handler_data )
3745 {
3746 plsc->eop_handler = handler;
3747 plsc->eop_data = handler_data;
3748 }
3749
3750 // Set the variables to be used for storing error info
3751
3752 void
3753 plsError( PLINT *errcode, char *errmsg )
3754 {
3755 if ( errcode != NULL )
3756 plsc->errcode = errcode;
3757
3758 if ( errmsg != NULL )
3759 plsc->errmsg = errmsg;
3760 }
3761
3762 // Set orientation. Must be done before calling plinit.
3763
3764 void
3765 c_plsori( PLINT ori )
3766 {
3767 plsdiori( (PLFLT) ori );
3768 }
3769
3770 //
3771 // Set pen width. Can be done any time, but before calling plinit is best
3772 // since otherwise it may be volatile (i.e. reset on next page advance).
3773 // If width < 0 or is unchanged by the call, nothing is done.
3774 //
3775
3776 void
3777 c_plwidth( PLFLT width )
3778 {
3779 if ( width != plsc->width && width >= 0. )
3780 {
3781 plsc->width = width;
3782
3783 if ( plsc->level > 0 )
3784 {
3785 if ( !plsc->widthlock )
3786 plP_state( PLSTATE_WIDTH );
3787 }
3788 }
3789 }
3790
3791 // Set the output file pointer
3792
3793 void
3794 plgfile( FILE **p_file )
3795 {
3796 *p_file = plsc->OutFile;
3797 }
3798
3799 // Get the output file pointer
3800
3801 void
3802 plsfile( FILE *file )
3803 {
3804 plsc->OutFile = file;
3805 }
3806
3807 // Get the (current) output file name. Must be preallocated to >=80 bytes
3808 // Beyond that, I truncate it. You have been warned.
3809
3810 void
3811 c_plgfnam( char *fnam )
3812 {
3813 if ( fnam == NULL )
3814 {
3815 plabort( "filename string must be preallocated to >=80 bytes" );
3816 return;
3817 }
3818
3819 *fnam = '\0';
3820 if ( plsc->FileName != NULL )
3821 {
3822 strncpy( fnam, plsc->FileName, 79 );
3823 fnam[79] = '\0';
3824 }
3825 }
3826
3827 // Set the output file name.
3828
3829 void
3830 c_plsfnam( PLCHAR_VECTOR fnam )
3831 {
3832 plP_sfnam( plsc, fnam );
3833 }
3834
3835 // Set the pointer to the data used in driver initialisation
3836
3837 // N.B. Currently used only by the wxwidgets device driver and
3838 // associated binding. This function might be used for other device drivers
3839 // later on whether written in c++ or c. But this function is not part of the
3840 // common API and should not be propagated to any binding other than
3841 // c++.
3842
3843 void
3844 plsdevdata( void *data )
3845 {
3846 plsc->dev_data = data;
3847 }
3848
3849 // Set the pause (on end-of-page) status
3850
3851 void
3852 c_plspause( PLINT p )
3853 {
3854 plsc->nopause = !p;
3855 }
3856
3857 // Set the floating point precision (in number of places) in numeric labels.
3858
3859 void
3860 c_plprec( PLINT setp, PLINT prec )
3861 {
3862 plsc->setpre = setp;
3863 plsc->precis = prec;
3864 }
3865
3866 // Get the floating point precision (in number of places) in numeric labels.
3867
3868 void
3869 plP_gprec( PLINT *p_setp, PLINT *p_prec )
3870 {
3871 *p_setp = plsc->setpre;
3872 *p_prec = plsc->precis;
3873 }
3874
3875 PLCHAR_VECTOR
3876 plP_gtimefmt()
3877 {
3878 return (PLCHAR_VECTOR) plsc->timefmt;
3879 }
3880
3881 //
3882 // Set the escape character for text strings.
3883 // From C you can pass as a character, from Fortran it needs to be the decimal
3884 // ASCII value. Only selected characters are allowed to prevent the user from
3885 // shooting himself in the foot (a '\' isn't allowed since it conflicts with
3886 // C's use of backslash as a character escape).
3887 //
3888
3889 void
3890 c_plsesc( char esc )
3891 {
3892 switch ( esc )
3893 {
3894 case '!': // ASCII 33
3895 case '#': // ASCII 35
3896 case '$': // ASCII 36
3897 case '%': // ASCII 37
3898 case '&': // ASCII 38
3899 case '*': // ASCII 42
3900 case '@': // ASCII 64
3901 case '^': // ASCII 94
3902 case '~': // ASCII 126
3903 plsc->esc = esc;
3904 break;
3905
3906 default:
3907 plwarn( "plsesc: Invalid escape character, ignoring." );
3908 }
3909 }
3910
3911 // Get the escape character for text strings.
3912
3913 void
3914 plgesc( char *p_esc )
3915 {
3916 if ( plsc->esc == '\0' )
3917 plsc->esc = '#';
3918
3919 *p_esc = plsc->esc;
3920 }
3921
3922 // Set the FCI (font characterization integer) for unicode-enabled device
3923 // drivers.
3924 //
3925 void
3926 c_plsfci( PLUNICODE fci )
3927 {
3928 // Always mark FCI as such.
3929 plsc->fci = fci | PL_FCI_MARK;
3930 }
3931
3932 // Get the FCI (font characterization integer) for unicode-enabled device
3933 // drivers.
3934 //
3935 void
3936 c_plgfci( PLUNICODE *p_fci )
3937 {
3938 // Always mark FCI as such.
3939 *p_fci = plsc->fci | PL_FCI_MARK;
3940 }
3941 // Store hex digit value shifted to the left by hexdigit hexadecimal digits
3942 // into pre-existing FCI.
3943 //
3944 void
3945 plP_hex2fci( unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci )
3946 {
3947 PLUNICODE mask;
3948 hexpower = hexpower & PL_FCI_HEXPOWER_MASK;
3949 mask = ~( ( (PLUNICODE) PL_FCI_HEXDIGIT_MASK ) << ( (PLUNICODE) 4 * hexpower ) );
3950 *pfci = *pfci & mask;
3951 mask = ( ( (PLUNICODE) ( hexdigit & PL_FCI_HEXDIGIT_MASK ) ) << ( 4 * hexpower ) );
3952 *pfci = *pfci | mask;
3953 }
3954
3955 // Retrieve hex digit value from FCI that is masked out and shifted to the
3956 // right by hexpower hexadecimal digits.
3957 void
3958 plP_fci2hex( PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower )
3959 {
3960 PLUNICODE mask;
3961 hexpower = hexpower & PL_FCI_HEXPOWER_MASK;
3962 mask = ( ( (PLUNICODE) PL_FCI_HEXPOWER_MASK ) << ( (PLUNICODE) ( 4 * hexpower ) ) );
3963 *phexdigit = (unsigned char) ( ( fci & mask ) >>
3964 ( (PLUNICODE) ( 4 * hexpower ) ) );
3965 }
3966
3967 // Get the current library version number
3968 // Note: you MUST have allocated space for this (80 characters is safe)
3969 void
3970 c_plgver( char *p_ver )
3971 {
3972 strcpy( p_ver, PLPLOT_VERSION );
3973 }
3974
3975 // Set inferior X window
3976
3977 void
3978 plsxwin( PLINT window_id )
3979 {
3980 plsc->window_id = window_id;
3981 }
3982
3983 //--------------------------------------------------------------------------
3984 // These set/get information for family files, and may be called prior
3985 // to plinit to set up the necessary parameters. Arguments:
3986 //
3987 // fam familying flag (boolean)
3988 // num member number
3989 // bmax maximum member size
3990 //--------------------------------------------------------------------------
3991
3992 // Get family file parameters
3993
3994 void
3995 c_plgfam( PLINT *p_fam, PLINT *p_num, PLINT *p_bmax )
3996 {
3997 *p_fam = plsc->family;
3998 *p_num = plsc->member;
3999 *p_bmax = plsc->bytemax;
4000 }
4001
4002 // Set family file parameters
4003
4004 void
4005 c_plsfam( PLINT fam, PLINT num, PLINT bmax )
4006 {
4007 if ( plsc->level > 0 )
4008 plwarn( "plsfam: Must be called before plinit." );
4009
4010 if ( fam >= 0 )
4011 plsc->family = fam;
4012 if ( num >= 0 )
4013 plsc->member = num;
4014 if ( bmax >= 0 )
4015 plsc->bytemax = bmax;
4016 }
4017
4018 // Advance to the next family file on the next new page
4019
4020 void
4021 c_plfamadv( void )
4022 {
4023 plsc->famadv = 1;
4024 }
4025
4026 //--------------------------------------------------------------------------
4027 // Interface routines for axis labling parameters.
4028 // See pldtik.c for more info.
4029 //--------------------------------------------------------------------------
4030
4031 // Get x axis labeling parameters
4032
4033 void
4034 c_plgxax( PLINT *p_digmax, PLINT *p_digits )
4035 {
4036 *p_digmax = plsc->xdigmax;
4037 *p_digits = plsc->xdigits;
4038 }
4039
4040 // Set x axis labeling parameters
4041
4042 void
4043 c_plsxax( PLINT digmax, PLINT digits )
4044 {
4045 plsc->xdigmax = digmax;
4046 plsc->xdigits = digits;
4047 }
4048
4049 // Get y axis labeling parameters
4050
4051 void
4052 c_plgyax( PLINT *p_digmax, PLINT *p_digits )
4053 {
4054 *p_digmax = plsc->ydigmax;
4055 *p_digits = plsc->ydigits;
4056 }
4057
4058 // Set y axis labeling parameters
4059
4060 void
4061 c_plsyax( PLINT digmax, PLINT digits )
4062 {
4063 plsc->ydigmax = digmax;
4064 plsc->ydigits = digits;
4065 }
4066
4067 // Get z axis labeling parameters
4068
4069 void
4070 c_plgzax( PLINT *p_digmax, PLINT *p_digits )
4071 {
4072 *p_digmax = plsc->zdigmax;
4073 *p_digits = plsc->zdigits;
4074 }
4075
4076 // Set z axis labeling parameters
4077
4078 void
4079 c_plszax( PLINT digmax, PLINT digits )
4080 {
4081 plsc->zdigmax = digmax;
4082 plsc->zdigits = digits;
4083 }
4084
4085 // Get character default height and current (scaled) height
4086
4087 void
4088 c_plgchr( PLFLT *p_def, PLFLT *p_ht )
4089 {
4090 *p_def = plsc->chrdef;
4091 *p_ht = plsc->chrht;
4092 }
4093
4094 // Get viewport boundaries in normalized device coordinates
4095
4096 void
4097 c_plgvpd( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
4098 {
4099 *p_xmin = plsc->vpdxmi;
4100 *p_xmax = plsc->vpdxma;
4101 *p_ymin = plsc->vpdymi;
4102 *p_ymax = plsc->vpdyma;
4103 }
4104
4105 // Get viewport boundaries in world coordinates
4106
4107 void
4108 c_plgvpw( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
4109 {
4110 *p_xmin = plsc->vpwxmi;
4111 *p_xmax = plsc->vpwxma;
4112 *p_ymin = plsc->vpwymi;
4113 *p_ymax = plsc->vpwyma;
4114 }
4115
4116 // Get the viewport boundaries in world coordinates, expanded slightly
4117 void
4118 plP_xgvpw( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
4119 {
4120 PLFLT dx, dy;
4121
4122 dx = ( plsc->vpwxma - plsc->vpwxmi ) * 1.0e-5;
4123 dy = ( plsc->vpwyma - plsc->vpwymi ) * 1.0e-5;
4124
4125 // The plot window is made slightly larger than requested so that
4126 // the end limits will be on the graph
4127
4128 *p_xmin = plsc->vpwxmi - dx;
4129 *p_xmax = plsc->vpwxma + dx;
4130 *p_ymin = plsc->vpwymi - dy;
4131 *p_ymax = plsc->vpwyma + dy;
4132 }
4133
4134 //--------------------------------------------------------------------------
4135 // These should not be called by the user.
4136 //--------------------------------------------------------------------------
4137
4138 // Get x-y domain in world coordinates for 3d plots
4139
4140 void
4141 plP_gdom( PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax )
4142 {
4143 *p_xmin = plsc->domxmi;
4144 *p_xmax = plsc->domxma;
4145 *p_ymin = plsc->domymi;
4146 *p_ymax = plsc->domyma;
4147 }
4148
4149 // Get vertical (z) scale parameters for 3-d plot
4150
4151 void
4152 plP_grange( PLFLT *p_zscl, PLFLT *p_zmin, PLFLT *p_zmax )
4153 {
4154 *p_zscl = plsc->zzscl;
4155 *p_zmin = plsc->ranmi;
4156 *p_zmax = plsc->ranma;
4157 }
4158
4159 // Get parameters used in 3d plots
4160
4161 void
4162 plP_gw3wc( PLFLT *p_dxx, PLFLT *p_dxy, PLFLT *p_dyx, PLFLT *p_dyy, PLFLT *p_dyz )
4163 {
4164 *p_dxx = plsc->cxx;
4165 *p_dxy = plsc->cxy;
4166 *p_dyx = plsc->cyx;
4167 *p_dyy = plsc->cyy;
4168 *p_dyz = plsc->cyz;
4169 }
4170
4171 // Get clip boundaries in physical coordinates
4172
4173 void
4174 plP_gclp( PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax )
4175 {
4176 *p_ixmin = plsc->clpxmi;
4177 *p_ixmax = plsc->clpxma;
4178 *p_iymin = plsc->clpymi;
4179 *p_iymax = plsc->clpyma;
4180 }
4181
4182 // Set clip boundaries in physical coordinates
4183
4184 void
4185 plP_sclp( PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax )
4186 {
4187 plsc->clpxmi = ixmin;
4188 plsc->clpxma = ixmax;
4189 plsc->clpymi = iymin;
4190 plsc->clpyma = iymax;
4191 if ( plsc->plbuf_write )
4192 plbuf_clip( plsc );
4193 }
4194
4195 // Get physical device limits in physical coordinates
4196
4197 void
4198 plP_gphy( PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax )
4199 {
4200 *p_ixmin = plsc->phyxmi;
4201 *p_ixmax = plsc->phyxma;
4202 *p_iymin = plsc->phyymi;
4203 *p_iymax = plsc->phyyma;
4204 }
4205
4206 // Get number of subpages on physical device and current subpage
4207
4208 void
4209 plP_gsub( PLINT *p_nx, PLINT *p_ny, PLINT *p_cs )
4210 {
4211 *p_nx = plsc->nsubx;
4212 *p_ny = plsc->nsuby;
4213 *p_cs = plsc->cursub;
4214 }
4215
4216 // Set number of subpages on physical device and current subpage
4217
4218 void
4219 plP_ssub( PLINT nx, PLINT ny, PLINT cs )
4220 {
4221 plsc->nsubx = nx;
4222 plsc->nsuby = ny;
4223 plsc->cursub = cs;
4224 }
4225
4226 // Get number of pixels to a millimeter
4227
4228 void
4229 plP_gpixmm( PLFLT *p_x, PLFLT *p_y )
4230 {
4231 *p_x = plsc->xpmm;
4232 *p_y = plsc->ypmm;
4233 }
4234
4235 // All the drivers call this to set physical pixels/mm.
4236
4237 void
4238 plP_setpxl( PLFLT xpmm, PLFLT ypmm )
4239 {
4240 plsc->xpmm = xpmm;
4241 plsc->ypmm = ypmm;
4242 plsc->umx = (PLINT) ( 1000.0 / plsc->xpmm );
4243 plsc->umy = (PLINT) ( 1000.0 / plsc->ypmm );
4244 }
4245
4246 // Sets up physical limits of plotting device.
4247
4248 void
4249 plP_setphy( PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax )
4250 {
4251 if ( xmin > xmax || ymin > ymax )
4252 plexit( "plP_setphy: device minima must not exceed maxima" );
4253
4254 plsc->phyxmi = xmin;
4255 plsc->phyxma = xmax;
4256 plsc->phyymi = ymin;
4257 plsc->phyyma = ymax;
4258 plsc->phyxlen = xmax - xmin;
4259 plsc->phyylen = ymax - ymin;
4260 }
4261
4262 //--------------------------------------------------------------------------
4263 // void c_plscompression()
4264 //
4265 // Set compression.
4266 // Has to be done before plinit.
4267 //--------------------------------------------------------------------------
4268
4269 void
4270 c_plscompression( PLINT compression )
4271 {
4272 if ( plsc->level <= 0 )
4273 {
4274 plsc->dev_compression = compression;
4275 }
4276 }
4277
4278 //--------------------------------------------------------------------------
4279 // void c_plgcompression()
4280 //
4281 // Get compression
4282 //--------------------------------------------------------------------------
4283
4284 void
4285 c_plgcompression( PLINT *compression )
4286 {
4287 *compression = plsc->dev_compression;
4288 }
4289
4290
4291 //--------------------------------------------------------------------------
4292 // void plP_getinitdriverlist()
4293 //
4294 // Check to see if a driver/stream has been initialised
4295 // Returns a space separated list of matches streams/drivers
4296 // If more than one stream uses the same device, then the device name
4297 // will be returned for each stream.
4298 // Caller must allocate enough memory for "names" to hold the answer.
4299 //--------------------------------------------------------------------------
4300
4301 void
4302 plP_getinitdriverlist( char *names )
4303 {
4304 int i;
4305
4306 for ( i = 0; i < PL_NSTREAMS; ++i )
4307 {
4308 if ( pls[i] != NULL )
4309 {
4310 if ( i == 0 )
4311 strcpy( names, pls[i]->DevName );
4312 else
4313 {
4314 strcat( names, " " );
4315 strcat( names, pls[i]->DevName );
4316 }
4317 }
4318 else
4319 break;
4320 }
4321 }
4322
4323
4324 //--------------------------------------------------------------------------
4325 // PLINT plP_checkdriverinit()
4326 //
4327 // Checks from a list of given drivers which ones have been initialised
4328 // and returns the number of devices matching the list, or -1 if in error.
4329 // Effectively returns the number of streams matching the given stream.
4330 //--------------------------------------------------------------------------
4331
4332 PLINT plP_checkdriverinit( char *names )
4333 {
4334 char *buff;
4335 char *tok = NULL;
4336 PLINT ret = 0; // set up return code to 0, the value if no devices match
4337
4338 buff = (char *) malloc( (size_t) PL_NSTREAMS * 8 ); // Allocate enough memory for 8
4339 // characters for each possible stream
4340
4341 if ( buff != NULL )
4342 {
4343 memset( buff, 0, PL_NSTREAMS * 8 ); // Make sure we clear it
4344 plP_getinitdriverlist( buff ); // Get the list of initialised devices
4345
4346 for ( tok = strtok( buff, " ," ); // Check each device against the "name"
4347 tok; tok = strtok( 0, " ," ) ) // supplied to the subroutine
4348 {
4349 if ( strstr( names, tok ) != NULL ) // Check to see if the device has been initialised
4350 {
4351 ret++; // Bump the return code if it has
4352 }
4353 }
4354 free( buff ); // Clear up that memory we allocated
4355 }
4356 else
4357 ret = -1; // Error flag
4358
4359 return ( ret );
4360 }
4361
4362
4363 //--------------------------------------------------------------------------
4364 // plP_image
4365 //
4366 // Author: Alessandro Mirone, Nov 2001
4367 //
4368 // Updated by Hezekiah Carty, Mar 2008.
4369 // - Added support for pltr callback
4370 // - Commented out the "dev_fastimg" rendering path
4371 //
4372 //--------------------------------------------------------------------------
4373
4374 void
4375 plP_image( PLFLT *z, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
4376 void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ), PLPointer pltr_data )
4377 {
4378 plsc->page_status = DRAWING;
4379
4380 plimageslow( z, nx, ny, xmin, ymin, dx, dy, pltr, pltr_data );
4381
4382 //
4383 // COMMENTED OUT by Hezekiah Carty, March 2008
4384 // The current dev_fastimg rendering method does not work as-is with
4385 // the plimagefr coordinate transform support.
4386 // This is hopefully temporary, until the dev_fastimg rendering
4387 // path can be updated to work with the new plimage internals.
4388 // Until then, all plimage* rendering is done by the plimageslow
4389 // rendering path.
4390 //
4391 #if 0 // BEGIN dev_fastimg COMMENT
4392 PLINT i, npts;
4393 short *xscl, *yscl;
4394 int plbuf_write;
4395
4396 plsc->page_status = DRAWING;
4397
4398 if ( plsc->dev_fastimg == 0 )
4399 {
4400 plimageslow( x, y, z, nx - 1, ny - 1,
4401 xmin, ymin, dx, dy, zmin, zmax );
4402 return;
4403 }
4404
4405 if ( plsc->plbuf_write )
4406 {
4407 IMG_DT img_dt;
4408
4409 img_dt.xmin = xmin;
4410 img_dt.ymin = ymin;
4411 img_dt.dx = dx;
4412 img_dt.dy = dy;
4413
4414 plsc->dev_ix = x;
4415 plsc->dev_iy = y;
4416 plsc->dev_z = z;
4417 plsc->dev_nptsX = nx;
4418 plsc->dev_nptsY = ny;
4419 plsc->dev_zmin = zmin;
4420 plsc->dev_zmax = zmax;
4421
4422 plbuf_esc( plsc, PLESC_IMAGE, &img_dt );
4423 }
4424
4425 // avoid re-saving plot buffer while in plP_esc()
4426 plbuf_write = plsc->plbuf_write;
4427 plsc->plbuf_write = 0;
4428
4429 npts = nx * ny;
4430 if ( plsc->difilt ) // isn't this odd? when replaying the plot buffer, e.g., when resizing the window, difilt() is caled again! the plot buffer should already contain the transformed data--it would save a lot of time! (and allow for differently oriented plots when in multiplot mode)
4431 {
4432 PLINT clpxmi, clpxma, clpymi, clpyma;
4433
4434 if ( ( ( xscl = (short *) malloc( nx * ny * sizeof ( short ) ) ) == NULL ) ||
4435 ( ( yscl = (short *) malloc( nx * ny * sizeof ( short ) ) ) == NULL ) )
4436 {
4437 plexit( "plP_image: Insufficient memory" );
4438 }
4439
4440 for ( i = 0; i < npts; i++ )
4441 {
4442 xscl[i] = x[i];
4443 yscl[i] = y[i];
4444 }
4445 sdifilt( xscl, yscl, npts, &clpxmi, &clpxma, &clpymi, &clpyma );
4446 plsc->imclxmin = clpxmi;
4447 plsc->imclymin = clpymi;
4448 plsc->imclxmax = clpxma;
4449 plsc->imclymax = clpyma;
4450 grimage( xscl, yscl, z, nx, ny );
4451 free( xscl );
4452 free( yscl );
4453 }
4454 else
4455 {
4456 plsc->imclxmin = plsc->phyxmi;
4457 plsc->imclymin = plsc->phyymi;
4458 plsc->imclxmax = plsc->phyxma;
4459 plsc->imclymax = plsc->phyyma;
4460 grimage( x, y, z, nx, ny );
4461 }
4462 plsc->plbuf_write = plbuf_write;
4463 #endif // END dev_fastimg COMMENT
4464 }
4465
4466 //--------------------------------------------------------------------------
4467 // plstransform
4468 //
4469 // Set a universal coordinate transform function which will be applied to all
4470 // plotted items.
4471 //--------------------------------------------------------------------------
4472 void
4473 c_plstransform( PLTRANSFORM_callback coordinate_transform, PLPointer coordinate_transform_data )
4474 {
4475 plsc->coordinate_transform = coordinate_transform;
4476 plsc->coordinate_transform_data = coordinate_transform_data;
4477 }
npldynamicdevices
static int npldynamicdevices
Definition: plcore.h:258
pldi_ini
static void pldi_ini(void)
Definition: plcore.c:1655
PL_FCI_BOLD
#define PL_FCI_BOLD
Definition: plplot.h:391
dirent::data
WIN32_FIND_DATAA data
Definition: dirent_msvc.h:70
plsdevdata
void plsdevdata(void *data)
Definition: plcore.c:3844
c_plwidth
void c_plwidth(PLFLT width)
Definition: plcore.c:3777
name
static const char * name
Definition: tkMain.c:135
grfill
static void grfill(short *x, short *y, PLINT npts)
Definition: plcore.c:1406
opendir
static DIR * opendir(const char *dirname)
Definition: dirent_msvc.h:109
PLColor
Definition: plplot.h:546
PLWindow::dymi
PLFLT dymi
Definition: plplot.h:452
plgesc
void plgesc(char *p_esc)
Definition: plcore.c:3914
plsstrm
#define plsstrm
Definition: plplot.h:835
c_plsdidev
void c_plsdidev(PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy)
Definition: plcore.c:1892
plexit
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1958
PLTRANSFORM_callback
void(* PLTRANSFORM_callback)(PLFLT x, PLFLT y, PLFLT_NC_SCALAR xp, PLFLT_NC_SCALAR yp, PLPointer data)
Definition: plplot.h:257
PLTEXT_OVERLINE
#define PLTEXT_OVERLINE
Definition: plplot.h:318
plP_esc
void plP_esc(PLINT op, void *ptr)
Definition: plcore.c:273
PLStream::icol1
PLINT icol1
Definition: plstrm.h:539
PLESC_CONTROL_CHAR
#define PLESC_CONTROL_CHAR
Definition: plplot.h:300
c_plsyax
void c_plsyax(PLINT digmax, PLINT digits)
Definition: plcore.c:4061
c_plsdiori
void c_plsdiori(PLFLT rot)
Definition: plcore.c:2022
EscText::just
PLFLT just
Definition: plplotP.h:708
plsetvar
#define plsetvar(a, b)
Definition: plplotP.h:187
plbuf_state
void plbuf_state(PLStream *pls, PLINT op)
Definition: plbuf.c:295
pl_cpcolor
void pl_cpcolor(PLColor *to, PLColor *from)
Definition: plcore.c:2738
static_device_initializers
static PLDispatchInit static_device_initializers[]
Definition: plcore.h:114
plP_fci2hex
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition: plcore.c:3958
c_plssub
void c_plssub(PLINT nx, PLINT ny)
Definition: plcore.c:3617
PLStream::ypmm
PLFLT ypmm
Definition: plstrm.h:707
PL_FCI_UPRIGHT
#define PL_FCI_UPRIGHT
Definition: plplot.h:386
PLColor::b
unsigned char b
Definition: plplot.h:550
c_plstar
void c_plstar(PLINT nx, PLINT ny)
Definition: plcore.c:2286
plP_pcdcy
PLFLT plP_pcdcy(PLINT y)
Definition: plcvt.c:95
plsdev
#define plsdev
Definition: plplot.h:806
PL_FCI_MEDIUM
#define PL_FCI_MEDIUM
Definition: plplot.h:390
c_pltimefmt
void c_pltimefmt(PLCHAR_VECTOR fmt)
Definition: pltime.c:66
PLStream::plbuf_top
size_t plbuf_top
Definition: plstrm.h:650
c_plgchr
void c_plgchr(PLFLT *p_def, PLFLT *p_ht)
Definition: plcore.c:4088
c_plgzax
void c_plgzax(PLINT *p_digmax, PLINT *p_digits)
Definition: plcore.c:4070
c_plgxax
void c_plgxax(PLINT *p_digmax, PLINT *p_digits)
Definition: plcore.c:4034
PLWindow::dxma
PLFLT dxma
Definition: plplot.h:452
PLESC_FILL
#define PLESC_FILL
Definition: plplot.h:279
plP_pllclp
void plP_pllclp(PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void(*draw)(short *, short *, PLINT))
Definition: plline.c:599
plP_gprec
void plP_gprec(PLINT *p_setp, PLINT *p_prec)
Definition: plcore.c:3869
plbuf_di
void plbuf_di(PLStream *pls)
Definition: plbuf.c:571
c_plgstrm
void c_plgstrm(PLINT *p_strm)
Definition: plcore.c:2652
PLStream::mar
PLFLT mar
Definition: plstrm.h:659
plbuf_clip
void plbuf_clip(PLStream *pls)
Definition: plbuf.c:615
lib_initialized
static PLINT lib_initialized
Definition: plcore.h:74
PLWindow::dxmi
PLFLT dxmi
Definition: plplot.h:452
pldid2pc
void pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1691
PLUNICODE
PLUINT PLUNICODE
Definition: plplot.h:201
PL_FCI_SYMBOL
#define PL_FCI_SYMBOL
Definition: plplot.h:384
PL_FCI_SERIF
#define PL_FCI_SERIF
Definition: plplot.h:381
c_plgdev
void c_plgdev(char *p_dev)
Definition: plcore.c:3658
c_plgyax
void c_plgyax(PLINT *p_digmax, PLINT *p_digits)
Definition: plcore.c:4052
plseopH
void plseopH(void(*handler)(void *, int *), void *handler_data)
Definition: plcore.c:3744
pllsty
#define pllsty
Definition: plplot.h:763
c_plinit
void c_plinit(void)
Definition: plcore.c:2325
foo
static int foo
Definition: plcore.c:448
plfontrel
void plfontrel(void)
Definition: plsym.c:1463
NAFFINE
#define NAFFINE
Definition: plplotP.h:484
plP_greek_mnemonic
const char plP_greek_mnemonic[]
Definition: plcore.c:142
c_plend
void c_plend(void)
Definition: plcore.c:2484
PLDispatchTable::pl_seq
int pl_seq
Definition: disptab.h:82
PLTEXT_SUBSCRIPT
#define PLTEXT_SUBSCRIPT
Definition: plplot.h:316
ucs4_to_utf8
int ucs4_to_utf8(PLUNICODE unichar, char *ptr)
Definition: plcore.c:1329
c_plgvpw
void c_plgvpw(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition: plcore.c:4108
grpolyline
static void grpolyline(short *x, short *y, PLINT npts)
Definition: plcore.c:1394
PLStream::jy
PLFLT jy
Definition: plstrm.h:659
plfntld
void plfntld(PLINT fnt)
Definition: plsym.c:1394
pl_create_tempfile
FILE * pl_create_tempfile(char **fname)
Definition: plstdio.c:240
c_plend1
void c_plend1(void)
Definition: plcore.c:2542
yscl
static PLINT yscl[PL_MAXPOLY]
Definition: plcore.h:70
c_plsdev
void c_plsdev(PLCHAR_VECTOR devname)
Definition: plcore.c:3640
plP_grange
void plP_grange(PLFLT *p_zscl, PLFLT *p_zmin, PLFLT *p_zmax)
Definition: plcore.c:4152
PLCHAR_VECTOR
const char * PLCHAR_VECTOR
Definition: plplot.h:243
PLDispatchTable::pl_MenuStr
const char * pl_MenuStr
Definition: disptab.h:79
plP_swin
void plP_swin(PLWindow *plwin)
Definition: plcore.c:308
plP_dcpcx
PLINT plP_dcpcx(PLFLT x)
Definition: plcvt.c:31
c_plsfnam
void c_plsfnam(PLCHAR_VECTOR fnam)
Definition: plcore.c:3830
PLWindow
Definition: plplot.h:450
AT_BOP
Definition: plplotP.h:373
PL_FCI_OBLIQUE
#define PL_FCI_OBLIQUE
Definition: plplot.h:388
plP_text
void plP_text(PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition: plcore.c:1186
PLESC_END_TEXT
#define PLESC_END_TEXT
Definition: plplot.h:301
PL_FCI_HEXPOWER_MASK
#define PL_FCI_HEXPOWER_MASK
Definition: plplot.h:373
MAX
#define MAX(a, b)
Definition: dsplint.c:28
plP_tidy
void plP_tidy(void)
Definition: plcore.c:231
plsdiori
#define plsdiori
Definition: plplot.h:809
PL_FCI_IMPOSSIBLE
#define PL_FCI_IMPOSSIBLE
Definition: plplot.h:371
plsave_set_locale
char * plsave_set_locale(void)
Definition: plctrl.c:3101
PLStream::diorot
PLFLT diorot
Definition: plstrm.h:661
PLColor::a
PLFLT a
Definition: plplot.h:551
grline
static void grline(short *x, short *y, PLINT PL_UNUSED(npts))
Definition: plcore.c:1382
PLStream::jx
PLFLT jx
Definition: plstrm.h:659
PLStream::dipymin
PLFLT dipymin
Definition: plstrm.h:657
plinit
#define plinit
Definition: plplot.h:755
plsfile
void plsfile(FILE *file)
Definition: plcore.c:3802
PLDispatchTable::pl_DevName
const char * pl_DevName
Definition: disptab.h:80
pldip2dc
void pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition: plcore.c:1737
PLTEXT_SUPERSCRIPT
#define PLTEXT_SUPERSCRIPT
Definition: plplot.h:315
PLDispatchTable::pl_init
plD_init_fp pl_init
Definition: disptab.h:83
plabort
void plabort(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1894
plsdiplt
#define plsdiplt
Definition: plplot.h:810
plsvect
#define plsvect
Definition: plplot.h:849
plssub
#define plssub
Definition: plplot.h:836
plP_checkdriverinit
PLINT plP_checkdriverinit(char *names)
Definition: plcore.c:4332
c_plmkstrm
void c_plmkstrm(PLINT *p_strm)
Definition: plcore.c:2671
PL_FCI_ITALIC
#define PL_FCI_ITALIC
Definition: plplot.h:387
calc_didev
static void calc_didev(void)
Definition: plcore.c:1918
PLPointer
void * PLPointer
Definition: plplot.h:209
plspal1
#define plspal1
Definition: plplot.h:833
plimageslow
void plimageslow(PLFLT *idata, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy, PLTRANSFORM_callback pltr, PLPointer pltr_data)
Definition: plimage.c:91
dirent
Definition: dirent_msvc.h:64
PLTEXT_BACKCHAR
#define PLTEXT_BACKCHAR
Definition: plplot.h:317
c_plsmem
void c_plsmem(PLINT maxx, PLINT maxy, void *plotmem)
Definition: plcore.c:3673
PLESC_DI
#define PLESC_DI
Definition: plplot.h:280
ipls
static PLINT ipls
Definition: plcore.h:86
plP_gpixmm
void plP_gpixmm(PLFLT *p_x, PLFLT *p_y)
Definition: plcore.c:4229
PLPLOT_MAX_PATH
#define PLPLOT_MAX_PATH
Definition: plplotP.h:446
plbuf_init
void plbuf_init(PLStream *pls)
Definition: plbuf.c:89
plsError
void plsError(PLINT *errcode, char *errmsg)
Definition: plcore.c:3753
dirent::d_name
char d_name[MAX_PATH+1]
Definition: dirent_msvc.h:67
c_plgfci
void c_plgfci(PLUNICODE *p_fci)
Definition: plcore.c:3936
BUILD_DIR
#define BUILD_DIR
Definition: plplot_config.h:24
plstr
void plstr(PLINT base, PLFLT *xform, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition: plsym.c:810
PLStream::cmap1
PLColor * cmap1
Definition: plstrm.h:545
plbuf_esc
void plbuf_esc(PLStream *pls, PLINT op, void *ptr)
Definition: plbuf.c:494
PLDI_DEV
#define PLDI_DEV
Definition: plplotP.h:381
EscText::n_ctrl_char
PLINT n_ctrl_char
Definition: plplotP.h:728
PLESC_TEXT_CHAR
#define PLESC_TEXT_CHAR
Definition: plplot.h:299
setdef_didev
static void setdef_didev(void)
Definition: plcore.c:1640
PLSTATE_WIDTH
#define PLSTATE_WIDTH
Definition: plplotP.h:362
PLTEXT_FONTCHANGE
#define PLTEXT_FONTCHANGE
Definition: plplot.h:314
c_plfontld
void c_plfontld(PLINT ifont)
Definition: plcore.c:3488
nplstaticdevices
static int nplstaticdevices
Definition: plcore.h:256
plend1
#define plend1
Definition: plplot.h:710
PLINT
int PLINT
Definition: plplot.h:181
IMG_DT::ymin
PLFLT ymin
Definition: plplotP.h:1205
DRV_DIR
#define DRV_DIR
Definition: plplot_config.h:30
calc_dimap
static void calc_dimap()
Definition: plcore.c:2184
plSelectDev
static void plSelectDev()
Definition: plcore.c:3269
lt_dlexit
void lt_dlexit(void)
Definition: ltdl_win32.c:51
PLStream::aspect
PLFLT aspect
Definition: plstrm.h:659
plP_gclp
void plP_gclp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition: plcore.c:4174
plP_polyline
void plP_polyline(short *x, short *y, PLINT npts)
Definition: plcore.c:417
plP_bop
void plP_bop(void)
Definition: plcore.c:198
EscText::n_fci
PLUNICODE n_fci
Definition: plplotP.h:726
DIR
Definition: dirent_msvc.h:74
ltdl_win32.h
EscText::refy
PLINT refy
Definition: plplotP.h:717
plgDevs
void plgDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition: plcore.c:3542
c_plsdiplz
void c_plsdiplz(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
Definition: plcore.c:1806
plrestore_locale
void plrestore_locale(char *saved_lc_numeric_locale)
Definition: plctrl.c:3145
PLStream::ncol0
PLINT ncol0
Definition: plstrm.h:539
utf8_to_ucs4
static PLCHAR_VECTOR utf8_to_ucs4(PLCHAR_VECTOR ptr, PLUNICODE *unichar)
Definition: plcore.c:1260
PL_FCI_MONO
#define PL_FCI_MONO
Definition: plplot.h:382
DRVSPEC_SIZE
#define DRVSPEC_SIZE
Definition: plcore.c:96
PLColor::g
unsigned char g
Definition: plplot.h:549
PLDispatchInit
void(* PLDispatchInit)(PLDispatchTable *pdt)
Definition: plcore.h:41
plgdevlst
static void plgdevlst(const char **p_menustr, const char **p_devname, int *p_ndev, int type)
Definition: plcore.c:3548
c_plgfnam
void c_plgfnam(char *fnam)
Definition: plcore.c:3811
lt_dlmakeresident
int lt_dlmakeresident(lt_dlhandle handle)
Definition: ltdl_win32.c:141
c_plgver
void c_plgver(char *p_ver)
Definition: plcore.c:3970
PLWindow::wymi
PLFLT wymi
Definition: plplot.h:453
EscText
Definition: plplotP.h:699
c_plsfci
void c_plsfci(PLUNICODE fci)
Definition: plcore.c:3926
plP_sfnam
void plP_sfnam(PLStream *pls, PLCHAR_VECTOR fnam)
Definition: plctrl.c:2700
grgradient
static void grgradient(short *x, short *y, PLINT npts)
Definition: plcore.c:1423
plio_fgets
void plio_fgets(char *buf, int size, FILE *stream)
Definition: plstdio.c:142
c_plspause
void c_plspause(PLINT p)
Definition: plcore.c:3852
plbuf_polyline
void plbuf_polyline(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: plbuf.c:268
snprintf
#define snprintf
Definition: plplotP.h:235
plP_ssub
void plP_ssub(PLINT nx, PLINT ny, PLINT cs)
Definition: plcore.c:4219
PLStream::icol0
PLINT icol0
Definition: plstrm.h:539
calc_diori
static void calc_diori(void)
Definition: plcore.c:2044
c_plsesc
void c_plsesc(char esc)
Definition: plcore.c:3890
dispatch_table
static PLDispatchTable ** dispatch_table
Definition: plcore.h:111
plsdidev
#define plsdidev
Definition: plplot.h:807
c_plgfam
void c_plgfam(PLINT *p_fam, PLINT *p_num, PLINT *p_bmax)
Definition: plcore.c:3995
plspal0
#define plspal0
Definition: plplot.h:832
plInitDispatchTable
static void plInitDispatchTable()
Definition: plcore.c:3022
c_plgdiplt
void c_plgdiplt(PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax)
Definition: plcore.c:1872
c_plstart
void c_plstart(PLCHAR_VECTOR devname, PLINT nx, PLINT ny)
Definition: plcore.c:2305
PLDI_PLT
#define PLDI_PLT
Definition: plplotP.h:380
TRUE
#define TRUE
Definition: plplotP.h:176
EscText::text_type
enum EscText::@5 text_type
plP_gsub
void plP_gsub(PLINT *p_nx, PLINT *p_ny, PLINT *p_cs)
Definition: plcore.c:4209
PLStream::dipymax
PLFLT dipymax
Definition: plstrm.h:657
c_plsstrm
void c_plsstrm(PLINT strm)
Definition: plcore.c:2621
PL_MAXWINDOWS
#define PL_MAXWINDOWS
Definition: plplot.h:448
c_plflush
void c_plflush(void)
Definition: plcore.c:2230
text2fci
int text2fci(PLCHAR_VECTOR text, unsigned char *hexdigit, unsigned char *hexpower)
Definition: plcore.c:605
PLDI_ORI
#define PLDI_ORI
Definition: plplotP.h:379
c_plgdiori
void c_plgdiori(PLFLT *p_rot)
Definition: plcore.c:2145
PLDispatchTable
Definition: disptab.h:77
c_plgcompression
void c_plgcompression(PLINT *compression)
Definition: plcore.c:4285
plbuf_tidy
void plbuf_tidy(PLStream *PL_UNUSED(pls))
Definition: plbuf.c:225
PLStream::ipls
PLINT ipls
Definition: plstrm.h:527
setdef_diori
static void setdef_diori(void)
Definition: plcore.c:1649
FALSE
#define FALSE
Definition: plplotP.h:177
plcore.h
difilt_clip
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition: plcore.c:1603
plDispatchSequencer
static int plDispatchSequencer(const void *p1, const void *p2)
Definition: plcore.c:3010
PL_FCI_STYLE
#define PL_FCI_STYLE
Definition: plplot.h:377
setdef_diplt
static void setdef_diplt(void)
Definition: plcore.c:1631
PL_FCI_SCRIPT
#define PL_FCI_SCRIPT
Definition: plplot.h:383
PLStream::phyyma
PLINT phyyma
Definition: plstrm.h:705
plsButtonEH
void plsButtonEH(void(*ButtonEH)(PLGraphicsIn *, void *, int *), void *ButtonEH_data)
Definition: plcore.c:3725
plP_FreeDrvOpts
void plP_FreeDrvOpts()
Definition: plargs.c:1560
difilt
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
Definition: plcore.c:1460
plInBuildTree
int plInBuildTree()
Definition: plcore.c:2888
plstrm_init
void plstrm_init(void)
Definition: plcore.c:2711
c_plstransform
void c_plstransform(PLTRANSFORM_callback coordinate_transform, PLPointer coordinate_transform_data)
Definition: plcore.c:4473
plP_image
void plP_image(PLFLT *z, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy, void(*pltr)(PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data)
Definition: plcore.c:4375
plsxwin
void plsxwin(PLINT window_id)
Definition: plcore.c:3978
PLStream::cmap1_max
PLFLT cmap1_max
Definition: plstrm.h:541
xform
void xform(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
Definition: plplot_octaveOCTAVE_wrap.cxx:2917
plP_setpxl
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition: plcore.c:4238
BUFFER_SIZE
#define BUFFER_SIZE
Definition: plcore.c:94
c_plglevel
void c_plglevel(PLINT *p_level)
Definition: plcore.c:3707
plgFileDevs
void plgFileDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition: plcore.c:3530
PLStream::cmap0
PLColor * cmap0
Definition: plstrm.h:544
PLStream::plbuf_buffer_grow
size_t plbuf_buffer_grow
Definition: plstrm.h:647
plbuf_ssub
void plbuf_ssub(PLStream *pls)
Definition: plbuf.c:209
PLWindow::dyma
PLFLT dyma
Definition: plplot.h:452
calc_diplt
static void calc_diplt(void)
Definition: plcore.c:1831
PLWindow::wyma
PLFLT wyma
Definition: plplot.h:453
hershey_to_unicode_lookup_table
Hershey_to_Unicode_table hershey_to_unicode_lookup_table[]
Definition: plhershey-unicode.h:48
plP_affine_multiply
void plP_affine_multiply(PLFLT *affine_vectorA, PLFLT_VECTOR affine_vectorB, PLFLT_VECTOR affine_vectorC)
Definition: plaffine.c:184
closedir
static int closedir(DIR *dirp)
Definition: dirent_msvc.h:202
buf
static char buf[200]
Definition: tclAPI.c:873
plP_gtimefmt
PLCHAR_VECTOR plP_gtimefmt()
Definition: plcore.c:3876
pls
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
plP_setphy
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition: plcore.c:4249
c_plsori
void c_plsori(PLINT ori)
Definition: plcore.c:3765
plP_affine_rotate
void plP_affine_rotate(PLFLT *affine_vector, PLFLT angle)
Definition: plaffine.c:123
c_plreplot
void c_plreplot(void)
Definition: plcore.c:3506
plP_affine_translate
void plP_affine_translate(PLFLT *affine_vector, PLFLT xtranslate, PLFLT ytranslate)
Definition: plaffine.c:73
PLWindow::wxmi
PLFLT wxmi
Definition: plplot.h:453
plgfci
#define plgfci
Definition: plplot.h:735
IMG_DT::dx
PLFLT dx
Definition: plplotP.h:1205
grimage
void grimage(short *x, short *y, unsigned short *z, PLINT nx, PLINT ny)
Definition: plimage.c:150
PLESC_BEGIN_TEXT
#define PLESC_BEGIN_TEXT
Definition: plplot.h:298
PLStream::xpmm
PLFLT xpmm
Definition: plstrm.h:707
plP_pcdcx
PLFLT plP_pcdcx(PLINT x)
Definition: plcvt.c:87
plP_subpInit
void plP_subpInit(void)
Definition: plpage.c:134
c_plspage
void c_plspage(PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff)
Definition: plcore.c:3593
c_plprec
void c_plprec(PLINT setp, PLINT prec)
Definition: plcore.c:3860
plbuf_line
void plbuf_line(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: plbuf.c:237
PLStream::cmap1_min
PLFLT cmap1_min
Definition: plstrm.h:541
encode_unicode
static void encode_unicode(PLCHAR_VECTOR string, EscText *args)
Definition: plcore.c:924
EscText::unicode_array_len
unsigned short unicode_array_len
Definition: plplotP.h:736
pllib_devinit
void pllib_devinit()
Definition: plcore.c:2874
plpsty
#define plpsty
Definition: plplot.h:784
IMG_DT
Definition: plplotP.h:1203
PLStream
Definition: plstrm.h:523
alternate_unicode_processing
static void alternate_unicode_processing(PLCHAR_VECTOR string, EscText *args)
Definition: plcore.c:647
plhershey2unicode
int plhershey2unicode(int in)
Definition: plsym.c:1490
dirent_msvc.h
plstrdup
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition: plctrl.c:2985
N_TextLookupTable
#define N_TextLookupTable
plLoadDriver
static void plLoadDriver(void)
Definition: plcore.c:3378
text
static int text
Definition: ps.c:77
Hershey_to_Unicode_table::Unicode
PLUNICODE Unicode
Definition: plplotP.h:459
plP_state
void plP_state(PLINT op)
Definition: plcore.c:256
EscText::refx
PLINT refx
Definition: plplotP.h:716
plP_fill
void plP_fill(short *x, short *y, PLINT npts)
Definition: plcore.c:451
PLESC_SWIN
#define PLESC_SWIN
Definition: plplot.h:284
plfill_soft
void plfill_soft(short *x, short *y, PLINT n)
Definition: plfill.c:307
PLStream::phyymi
PLINT phyymi
Definition: plstrm.h:705
PL_UNUSED
#define PL_UNUSED(x)
Definition: plplot.h:138
plRemakePlot
void plRemakePlot(PLStream *pls)
Definition: plbuf.c:1397
PLFLT
float PLFLT
Definition: plplot.h:163
PLStream::dipxmax
PLFLT dipxmax
Definition: plstrm.h:657
plP_eop
void plP_eop(void)
Definition: plcore.c:164
plP_dcpcy
PLINT plP_dcpcy(PLFLT y)
Definition: plcvt.c:39
PL_FCI_FAMILY
#define PL_FCI_FAMILY
Definition: plplot.h:376
PLTEXT_UNDERLINE
#define PLTEXT_UNDERLINE
Definition: plplot.h:319
plP_gradient
void plP_gradient(short *x, short *y, PLINT npts)
Definition: plcore.c:516
plP_xgvpw
void plP_xgvpw(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition: plcore.c:4118
plP_hex2fci
void plP_hex2fci(unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci)
Definition: plcore.c:3945
free_mem
#define free_mem(a)
Definition: plplotP.h:182
PLStream::phyxma
PLINT phyxma
Definition: plstrm.h:705
plP_plfclp
void plP_plfclp(PLINT *x, PLINT *y, PLINT npts, PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax, void(*draw)(short *, short *, PLINT))
Definition: plfill.c:538
c_plsdimap
void c_plsdimap(PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax, PLFLT dimxpmm, PLFLT dimypmm)
Definition: plcore.c:2160
lt_dlopenext
lt_dlhandle lt_dlopenext(char *dllname)
Definition: ltdl_win32.c:74
PLPLOT_VERSION
#define PLPLOT_VERSION
Definition: plConfig.h:54
c_plgpage
void c_plgpage(PLFLT *p_xp, PLFLT *p_yp, PLINT *p_xleng, PLINT *p_yleng, PLINT *p_xoff, PLINT *p_yoff)
Definition: plcore.c:3579
PL_FCI_WEIGHT
#define PL_FCI_WEIGHT
Definition: plplot.h:378
unicode_buffer_static
static PLUNICODE unicode_buffer_static[1024]
Definition: plcore.c:1183
c_plszax
void c_plszax(PLINT digmax, PLINT digits)
Definition: plcore.c:4079
PI
#define PI
Definition: plplotP.h:290
plP_line
void plP_line(short *x, short *y)
Definition: plcore.c:388
plsbopH
void plsbopH(void(*handler)(void *, int *), void *handler_data)
Definition: plcore.c:3735
plcol0
#define plcol0
Definition: plplot.h:702
xscl
static PLINT xscl[PL_MAXPOLY]
Definition: plcore.h:70
plgfile
void plgfile(FILE **p_file)
Definition: plcore.c:3794
plbuf_eop
void plbuf_eop(PLStream *pls)
Definition: plbuf.c:122
plsKeyEH
void plsKeyEH(void(*KeyEH)(PLGraphicsIn *, void *, int *), void *KeyEH_data)
Definition: plcore.c:3715
initfont
static PLINT initfont
Definition: plcore.h:72
PL_NSTREAMS
#define PL_NSTREAMS
Definition: plplotP.h:284
plP_gw3wc
void plP_gw3wc(PLFLT *p_dxx, PLFLT *p_dxy, PLFLT *p_dyx, PLFLT *p_dyy, PLFLT *p_dyz)
Definition: plcore.c:4162
PLStream::difilt
PLINT difilt
Definition: plstrm.h:656
c_plsmema
void c_plsmema(PLINT maxx, PLINT maxy, void *plotmem)
Definition: plcore.c:3683
DRAWING
Definition: plplotP.h:373
lt_dlerror
PLCHAR_VECTOR lt_dlerror()
Definition: ltdl_win32.c:97
PLColor::r
unsigned char r
Definition: plplot.h:548
PLStream::phyxmi
PLINT phyxmi
Definition: plstrm.h:705
PLESC_HAS_TEXT
#define PLESC_HAS_TEXT
Definition: plplot.h:290
PLStream::plbuf_buffer
void * plbuf_buffer
Definition: plstrm.h:649
plwarn
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1863
PLWindow::wxma
PLFLT wxma
Definition: plplot.h:453
AT_EOP
Definition: plplotP.h:373
EscText::y
PLINT y
Definition: plplotP.h:713
plbuf_bop
void plbuf_bop(PLStream *pls)
Definition: plbuf.c:141
pllib_init
void pllib_init()
Definition: plcore.c:2262
plP_init
void plP_init(void)
Definition: plcore.c:145
readdir
static struct dirent * readdir(DIR *dirp)
Definition: dirent_msvc.h:159
PLDI_MAP
#define PLDI_MAP
Definition: plplotP.h:378
npldrivers
static int npldrivers
Definition: plcore.h:112
plP_getinitdriverlist
void plP_getinitdriverlist(char *names)
Definition: plcore.c:4302
PLESC_IMAGE
#define PLESC_IMAGE
Definition: plplot.h:291
PLUINT
unsigned int PLUINT
Definition: plplot.h:180
errmsg
static char errmsg[160]
Definition: tclAPI.c:158
PLStream::curcolor
PLColor curcolor
Definition: plstrm.h:543
PL_FCI_HEXDIGIT_MASK
#define PL_FCI_HEXDIGIT_MASK
Definition: plplot.h:372
c_plgvpd
void c_plgvpd(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition: plcore.c:4097
EscText::string
const char * string
Definition: plplotP.h:739
plP_sclp
void plP_sclp(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
Definition: plcore.c:4185
plbuf_write
void plbuf_write(PLStream *pls, void *data, size_t bytes)
Definition: plbuf.c:660
number_of_entries_in_hershey_to_unicode_table
int number_of_entries_in_hershey_to_unicode_table
Definition: plhershey-unicode.h:40
ABS
#define ABS(a)
Definition: plplotP.h:199
PLStream::plbuf_readpos
size_t plbuf_readpos
Definition: plstrm.h:651
PLStream::debug
PLINT debug
Definition: plstrm.h:527
PLStream::dipxmin
PLFLT dipxmin
Definition: plstrm.h:657
BUFFER2_SIZE
#define BUFFER2_SIZE
Definition: plcore.c:95
PLStream::ncol1
PLINT ncol1
Definition: plstrm.h:539
c_plgdidev
void c_plgdidev(PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy)
Definition: plcore.c:2007
text2num
int text2num(PLCHAR_VECTOR text, char end, PLUNICODE *num)
Definition: plcore.c:566
PLESC_GRADIENT
#define PLESC_GRADIENT
Definition: plplot.h:305
EscText::x
PLINT x
Definition: plplotP.h:712
c_plfamadv
void c_plfamadv(void)
Definition: plcore.c:4021
c_plsxax
void c_plsxax(PLINT digmax, PLINT digits)
Definition: plcore.c:4043
plP_wait
void plP_wait(void)
Definition: plcore.c:365
lt_dlinit
void lt_dlinit(void)
Definition: ltdl_win32.c:43
PL_FCI_SANS
#define PL_FCI_SANS
Definition: plplot.h:380
EscText::n_char
PLUNICODE n_char
Definition: plplotP.h:727
closeqsas
void closeqsas(QSASConfig **qsasconfig)
Definition: qsastime.c:1200
plP_gphy
void plP_gphy(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition: plcore.c:4198
EscText::unicode_array
PLUNICODE * unicode_array
Definition: plplotP.h:735
c_plscompression
void c_plscompression(PLINT compression)
Definition: plcore.c:4270
plgpls
void plgpls(PLStream **p_pls)
Definition: plcore.c:3693
c_plconfigtime
void c_plconfigtime(PLFLT scale, PLFLT offset1, PLFLT offset2, PLINT ccontrol, PLBOOL ifbtime_offset, PLINT year, PLINT month, PLINT day, PLINT hour, PLINT min, PLFLT sec)
Definition: pltime.c:36
PL_FCI_HEXPOWER_IMPOSSIBLE
#define PL_FCI_HEXPOWER_IMPOSSIBLE
Definition: plplot.h:374
PLStream::plbuf_buffer_size
size_t plbuf_buffer_size
Definition: plstrm.h:648
plP_affine_scale
void plP_affine_scale(PLFLT *affine_vector, PLFLT xscale, PLFLT yscale)
Definition: plaffine.c:93
plgra
#define plgra
Definition: plplot.h:740
plsdimap
#define plsdimap
Definition: plplot.h:808
plP_gdom
void plP_gdom(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition: plcore.c:4141
PLDispatchTable::pl_type
int pl_type
Definition: disptab.h:81
EscText::xform
PLFLT * xform
Definition: plplotP.h:709
c_plsfam
void c_plsfam(PLINT fam, PLINT num, PLINT bmax)
Definition: plcore.c:4005
c_plsdiplt
void c_plsdiplt(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
Definition: plcore.c:1782
c_plcpstrm
void c_plcpstrm(PLINT iplsr, PLINT flags)
Definition: plcore.c:2761
lt_dlsym
void * lt_dlsym(lt_dlhandle dlhandle, PLCHAR_VECTOR symbol)
Definition: ltdl_win32.c:112
IMG_DT::dy
PLFLT dy
Definition: plplotP.h:1205
EscText::base
PLINT base
Definition: plplotP.h:707
plP_strpos
PLINT plP_strpos(PLCHAR_VECTOR str, int chr)
Definition: plsym.c:1216
PLESC_FLUSH
#define PLESC_FLUSH
Definition: plplot.h:281
IMG_DT::xmin
PLFLT xmin
Definition: plplotP.h:1205
PL_FCI_MARK
#define PL_FCI_MARK
Definition: plplot.h:370
PLGraphicsIn
Definition: plplot.h:433