PLplot 5.15.0
Loading...
Searching...
No Matches
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
100int
101text2num( PLCHAR_VECTOR text, char end, PLUNICODE *num );
102
103int
104text2fci( 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//
142const char plP_greek_mnemonic[] = "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw";
143
144void
145plP_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
163void
164plP_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
197void
198plP_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
230void
231plP_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
255void
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
272void
273plP_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
307void
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
364void
365plP_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
387void
388plP_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
416void
417plP_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
448static int foo;
449
450void
451plP_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
515void
516plP_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
566int 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
605int 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
646static
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 )
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;
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;
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;
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
769 }
770 else if ( string[i + 2] == 'r' )
771 {
772 // medium, upright, serif
774 }
775 else if ( string[i + 2] == 'i' )
776 {
777 // medium, italic, serif
780 }
781 else if ( string[i + 2] == 's' )
782 {
783 // medium, upright, script
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;
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 )
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':
851 i += 1;
852 skip = 1;
853 break;
854
855 case 'd':
858 i += 1;
859 skip = 1;
860 break;
861 case 'b':
864 i += 1;
865 skip = 1;
866 break;
867 case '+':
870 i += 1;
871 skip = 1;
872 break;
873 case '-':
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
923static
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 )
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
1066 }
1067 else if ( string[i + 2] == 'r' )
1068 {
1069 // medium, upright, serif
1071 }
1072 else if ( string[i + 2] == 'i' )
1073 {
1074 // medium, italic, serif
1077 }
1078 else if ( string[i + 2] == 's' )
1079 {
1080 // medium, upright, script
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 )
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
1184
1185void
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.
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
1259static PLCHAR_VECTOR
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
1328int
1329ucs4_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
1381static void
1382grline( 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
1393static void
1394grpolyline( 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
1405static void
1406grfill( 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
1422static void
1423grgradient( 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
1459void
1460difilt( 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
1602void
1603difilt_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
1630static void
1632{
1633 plsc->dipxmin = 0.0;
1634 plsc->dipxmax = 1.0;
1635 plsc->dipymin = 0.0;
1636 plsc->dipymax = 1.0;
1637}
1638
1639static void
1641{
1642 plsc->mar = 0.0;
1643 plsc->aspect = 0.0;
1644 plsc->jx = 0.0;
1645 plsc->jy = 0.0;
1646}
1647
1648static void
1650{
1651 plsc->diorot = 0.;
1652}
1653
1654static 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
1690void
1691pldid2pc( 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
1736void
1737pldip2dc( 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
1781void
1782c_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
1805void
1806c_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
1830static 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
1871void
1872c_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
1891void
1892c_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
1917static 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
2006void
2007c_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
2021void
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
2043static 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
2144void
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
2159void
2160c_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
2183static void
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
2229void
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
2261void
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
2277}
2278
2279//--------------------------------------------------------------------------
2280// void plstar(nx, ny)
2281//
2282// Initialize PLplot, passing in the windows/page settings.
2283//--------------------------------------------------------------------------
2284
2285void
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
2304void
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
2324void
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
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
2483void
2484c_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 );
2522 }
2523#endif
2524 for ( i = 0; i < nplstaticdevices; i++ )
2525 {
2527 }
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
2541void
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
2620void
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
2651void
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
2670void
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
2710void
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
2737void
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
2760void
2761c_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
2873void
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
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
2972plGetDrvDir()
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
3010static 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
3021static void
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
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" );
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
3147 }
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 {
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* ),
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
3268static void
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
3377static 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;
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
3487void
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
3505void
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
3529void
3530plgFileDevs( 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
3541void
3542plgDevs( const char ***p_menustr, const char ***p_devname, int *p_ndev )
3543{
3544 plgdevlst( *p_menustr, *p_devname, p_ndev, -1 );
3545}
3546
3547static void
3548plgdevlst( 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
3578void
3579c_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
3592void
3593c_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
3616void
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
3639void
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
3657void
3658c_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
3672void
3673c_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
3682void
3683c_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
3692void
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
3706void
3708{
3709 *p_level = plsc->level;
3710}
3711
3712// Set the function pointer for the keyboard event handler
3713
3714void
3715plsKeyEH( 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
3724void
3725plsButtonEH( 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
3734void
3735plsbopH( 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
3743void
3744plseopH( 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
3752void
3753plsError( 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
3764void
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
3776void
3778{
3779 if ( width != plsc->width && width >= 0. )
3780 {
3781 plsc->width = width;
3782
3783 if ( plsc->level > 0 )
3784 {
3785 if ( !plsc->widthlock )
3787 }
3788 }
3789}
3790
3791// Set the output file pointer
3792
3793void
3794plgfile( FILE **p_file )
3795{
3796 *p_file = plsc->OutFile;
3797}
3798
3799// Get the output file pointer
3800
3801void
3802plsfile( 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
3810void
3811c_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
3829void
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
3843void
3844plsdevdata( void *data )
3845{
3846 plsc->dev_data = data;
3847}
3848
3849// Set the pause (on end-of-page) status
3850
3851void
3853{
3854 plsc->nopause = !p;
3855}
3856
3857// Set the floating point precision (in number of places) in numeric labels.
3858
3859void
3860c_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
3868void
3869plP_gprec( PLINT *p_setp, PLINT *p_prec )
3870{
3871 *p_setp = plsc->setpre;
3872 *p_prec = plsc->precis;
3873}
3874
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
3889void
3890c_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
3913void
3914plgesc( 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//
3925void
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//
3935void
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//
3944void
3945plP_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.
3957void
3958plP_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)
3969void
3970c_plgver( char *p_ver )
3971{
3972 strcpy( p_ver, PLPLOT_VERSION );
3973}
3974
3975// Set inferior X window
3976
3977void
3978plsxwin( 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
3994void
3995c_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
4004void
4005c_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
4020void
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
4033void
4034c_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
4042void
4043c_plsxax( PLINT digmax, PLINT digits )
4044{
4045 plsc->xdigmax = digmax;
4046 plsc->xdigits = digits;
4047}
4048
4049// Get y axis labeling parameters
4050
4051void
4052c_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
4060void
4061c_plsyax( PLINT digmax, PLINT digits )
4062{
4063 plsc->ydigmax = digmax;
4064 plsc->ydigits = digits;
4065}
4066
4067// Get z axis labeling parameters
4068
4069void
4070c_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
4078void
4079c_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
4087void
4088c_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
4096void
4097c_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
4107void
4108c_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
4117void
4118plP_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
4140void
4141plP_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
4151void
4152plP_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
4161void
4162plP_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
4173void
4174plP_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
4184void
4185plP_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
4197void
4198plP_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
4208void
4209plP_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
4218void
4220{
4221 plsc->nsubx = nx;
4222 plsc->nsuby = ny;
4223 plsc->cursub = cs;
4224}
4225
4226// Get number of pixels to a millimeter
4227
4228void
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
4237void
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
4248void
4249plP_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
4269void
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
4284void
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
4301void
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
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
4374void
4375plP_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//--------------------------------------------------------------------------
4472void
4473c_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}
static DIR * opendir(const char *dirname)
static int closedir(DIR *dirp)
static struct dirent * readdir(DIR *dirp)
#define MAX(a, b)
Definition dsplint.c:28
int lt_dlmakeresident(lt_dlhandle handle)
Definition ltdl_win32.c:141
void * lt_dlsym(lt_dlhandle dlhandle, PLCHAR_VECTOR symbol)
Definition ltdl_win32.c:112
void lt_dlexit(void)
Definition ltdl_win32.c:51
lt_dlhandle lt_dlopenext(char *dllname)
Definition ltdl_win32.c:74
PLCHAR_VECTOR lt_dlerror()
Definition ltdl_win32.c:97
void lt_dlinit(void)
Definition ltdl_win32.c:43
#define PLPLOT_VERSION
Definition plConfig.h:54
void plP_affine_rotate(PLFLT *affine_vector, PLFLT angle)
Definition plaffine.c:123
void plP_affine_translate(PLFLT *affine_vector, PLFLT xtranslate, PLFLT ytranslate)
Definition plaffine.c:73
void plP_affine_scale(PLFLT *affine_vector, PLFLT xscale, PLFLT yscale)
Definition plaffine.c:93
void plP_affine_multiply(PLFLT *affine_vectorA, PLFLT_VECTOR affine_vectorB, PLFLT_VECTOR affine_vectorC)
Definition plaffine.c:184
void plP_FreeDrvOpts()
Definition plargs.c:1560
void plbuf_eop(PLStream *pls)
Definition plbuf.c:122
void plbuf_clip(PLStream *pls)
Definition plbuf.c:615
void plbuf_state(PLStream *pls, PLINT op)
Definition plbuf.c:295
void plbuf_tidy(PLStream *PL_UNUSED(pls))
Definition plbuf.c:225
void plbuf_polyline(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition plbuf.c:268
void plbuf_esc(PLStream *pls, PLINT op, void *ptr)
Definition plbuf.c:494
void plbuf_di(PLStream *pls)
Definition plbuf.c:571
void plRemakePlot(PLStream *pls)
Definition plbuf.c:1397
void plbuf_line(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition plbuf.c:237
void plbuf_bop(PLStream *pls)
Definition plbuf.c:141
void plbuf_ssub(PLStream *pls)
Definition plbuf.c:209
void plbuf_init(PLStream *pls)
Definition plbuf.c:89
void plbuf_write(PLStream *pls, void *data, size_t bytes)
Definition plbuf.c:660
static void grline(short *x, short *y, PLINT PL_UNUSED(npts))
Definition plcore.c:1382
void c_plend(void)
Definition plcore.c:2484
void plgDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition plcore.c:3542
void plsButtonEH(void(*ButtonEH)(PLGraphicsIn *, void *, int *), void *ButtonEH_data)
Definition plcore.c:3725
void pllib_init()
Definition plcore.c:2262
void c_plglevel(PLINT *p_level)
Definition plcore.c:3707
void plP_fci2hex(PLUNICODE fci, unsigned char *phexdigit, unsigned char hexpower)
Definition plcore.c:3958
static void calc_dimap()
Definition plcore.c:2184
static int plDispatchSequencer(const void *p1, const void *p2)
Definition plcore.c:3010
void plP_state(PLINT op)
Definition plcore.c:256
void c_plgdidev(PLFLT *p_mar, PLFLT *p_aspect, PLFLT *p_jx, PLFLT *p_jy)
Definition plcore.c:2007
void plP_xgvpw(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition plcore.c:4118
void plP_polyline(short *x, short *y, PLINT npts)
Definition plcore.c:417
void plP_init(void)
Definition plcore.c:145
static void grpolyline(short *x, short *y, PLINT npts)
Definition plcore.c:1394
void c_plscompression(PLINT compression)
Definition plcore.c:4270
void pldip2dc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition plcore.c:1737
void c_plsfam(PLINT fam, PLINT num, PLINT bmax)
Definition plcore.c:4005
static void plSelectDev()
Definition plcore.c:3269
static void calc_didev(void)
Definition plcore.c:1918
void plP_text(PLINT base, PLFLT just, PLFLT *xform, PLINT x, PLINT y, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition plcore.c:1186
void plP_bop(void)
Definition plcore.c:198
void difilt_clip(PLINT *x_coords, PLINT *y_coords)
Definition plcore.c:1603
void c_plgver(char *p_ver)
Definition plcore.c:3970
void c_plstart(PLCHAR_VECTOR devname, PLINT nx, PLINT ny)
Definition plcore.c:2305
void c_plszax(PLINT digmax, PLINT digits)
Definition plcore.c:4079
void plP_eop(void)
Definition plcore.c:164
void c_plsdidev(PLFLT mar, PLFLT aspect, PLFLT jx, PLFLT jy)
Definition plcore.c:1892
void c_plsdiplt(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
Definition plcore.c:1782
void c_plstar(PLINT nx, PLINT ny)
Definition plcore.c:2286
void c_plssub(PLINT nx, PLINT ny)
Definition plcore.c:3617
void c_plstransform(PLTRANSFORM_callback coordinate_transform, PLPointer coordinate_transform_data)
Definition plcore.c:4473
#define N_TextLookupTable
static void plgdevlst(const char **p_menustr, const char **p_devname, int *p_ndev, int type)
Definition plcore.c:3548
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
const char plP_greek_mnemonic[]
Definition plcore.c:142
void plP_line(short *x, short *y)
Definition plcore.c:388
void plP_gsub(PLINT *p_nx, PLINT *p_ny, PLINT *p_cs)
Definition plcore.c:4209
void c_plsdimap(PLINT dimxmin, PLINT dimxmax, PLINT dimymin, PLINT dimymax, PLFLT dimxpmm, PLFLT dimypmm)
Definition plcore.c:2160
void c_plreplot(void)
Definition plcore.c:3506
void plgpls(PLStream **p_pls)
Definition plcore.c:3693
void c_plsmem(PLINT maxx, PLINT maxy, void *plotmem)
Definition plcore.c:3673
void pl_cpcolor(PLColor *to, PLColor *from)
Definition plcore.c:2738
void plP_tidy(void)
Definition plcore.c:231
static void pldi_ini(void)
Definition plcore.c:1655
static void setdef_diplt(void)
Definition plcore.c:1631
int plInBuildTree()
Definition plcore.c:2888
void c_plgchr(PLFLT *p_def, PLFLT *p_ht)
Definition plcore.c:4088
void c_plgvpw(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition plcore.c:4108
void plstrm_init(void)
Definition plcore.c:2711
void difilt(PLINT *xsc, PLINT *ysc, PLINT npts, PLINT *clpxmi, PLINT *clpxma, PLINT *clpymi, PLINT *clpyma)
Definition plcore.c:1460
void plsxwin(PLINT window_id)
Definition plcore.c:3978
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition plcore.c:4238
void c_plspause(PLINT p)
Definition plcore.c:3852
#define BUFFER_SIZE
Definition plcore.c:94
static void setdef_diori(void)
Definition plcore.c:1649
PLCHAR_VECTOR plP_gtimefmt()
Definition plcore.c:3876
void c_plgzax(PLINT *p_digmax, PLINT *p_digits)
Definition plcore.c:4070
void c_plgdev(char *p_dev)
Definition plcore.c:3658
void plsError(PLINT *errcode, char *errmsg)
Definition plcore.c:3753
static void plInitDispatchTable()
Definition plcore.c:3022
static void grgradient(short *x, short *y, PLINT npts)
Definition plcore.c:1423
void plP_gw3wc(PLFLT *p_dxx, PLFLT *p_dxy, PLFLT *p_dyx, PLFLT *p_dyy, PLFLT *p_dyz)
Definition plcore.c:4162
void c_plgfnam(char *fnam)
Definition plcore.c:3811
void c_plgfam(PLINT *p_fam, PLINT *p_num, PLINT *p_bmax)
Definition plcore.c:3995
int text2fci(PLCHAR_VECTOR text, unsigned char *hexdigit, unsigned char *hexpower)
Definition plcore.c:605
static void calc_diori(void)
Definition plcore.c:2044
void plP_gradient(short *x, short *y, PLINT npts)
Definition plcore.c:516
void c_plsmema(PLINT maxx, PLINT maxy, void *plotmem)
Definition plcore.c:3683
void c_plwidth(PLFLT width)
Definition plcore.c:3777
void c_plgxax(PLINT *p_digmax, PLINT *p_digits)
Definition plcore.c:4034
int text2num(PLCHAR_VECTOR text, char end, PLUNICODE *num)
Definition plcore.c:566
void c_plcpstrm(PLINT iplsr, PLINT flags)
Definition plcore.c:2761
static int foo
Definition plcore.c:448
void c_plend1(void)
Definition plcore.c:2542
void c_plgfci(PLUNICODE *p_fci)
Definition plcore.c:3936
static void setdef_didev(void)
Definition plcore.c:1640
static void grfill(short *x, short *y, PLINT npts)
Definition plcore.c:1406
void plsdevdata(void *data)
Definition plcore.c:3844
void plsfile(FILE *file)
Definition plcore.c:3802
void plP_gdom(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition plcore.c:4141
void plP_swin(PLWindow *plwin)
Definition plcore.c:308
void plP_hex2fci(unsigned char hexdigit, unsigned char hexpower, PLUNICODE *pfci)
Definition plcore.c:3945
void plP_gpixmm(PLFLT *p_x, PLFLT *p_y)
Definition plcore.c:4229
void c_plgcompression(PLINT *compression)
Definition plcore.c:4285
void c_plsstrm(PLINT strm)
Definition plcore.c:2621
void plP_grange(PLFLT *p_zscl, PLFLT *p_zmin, PLFLT *p_zmax)
Definition plcore.c:4152
int ucs4_to_utf8(PLUNICODE unichar, char *ptr)
Definition plcore.c:1329
void c_plflush(void)
Definition plcore.c:2230
void c_plgstrm(PLINT *p_strm)
Definition plcore.c:2652
static void calc_diplt(void)
Definition plcore.c:1831
void plsbopH(void(*handler)(void *, int *), void *handler_data)
Definition plcore.c:3735
void c_plsyax(PLINT digmax, PLINT digits)
Definition plcore.c:4061
void c_plprec(PLINT setp, PLINT prec)
Definition plcore.c:3860
void c_plinit(void)
Definition plcore.c:2325
void c_plgdiplt(PLFLT *p_xmin, PLFLT *p_ymin, PLFLT *p_xmax, PLFLT *p_ymax)
Definition plcore.c:1872
void pldid2pc(PLFLT *xmin, PLFLT *ymin, PLFLT *xmax, PLFLT *ymax)
Definition plcore.c:1691
void plP_gclp(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition plcore.c:4174
void plseopH(void(*handler)(void *, int *), void *handler_data)
Definition plcore.c:3744
void c_plsfci(PLUNICODE fci)
Definition plcore.c:3926
void plP_wait(void)
Definition plcore.c:365
void plP_sclp(PLINT ixmin, PLINT ixmax, PLINT iymin, PLINT iymax)
Definition plcore.c:4185
void c_plsxax(PLINT digmax, PLINT digits)
Definition plcore.c:4043
PLINT plP_checkdriverinit(char *names)
Definition plcore.c:4332
void c_plsdiori(PLFLT rot)
Definition plcore.c:2022
void plP_ssub(PLINT nx, PLINT ny, PLINT cs)
Definition plcore.c:4219
void c_plfamadv(void)
Definition plcore.c:4021
void c_plspage(PLFLT xp, PLFLT yp, PLINT xleng, PLINT yleng, PLINT xoff, PLINT yoff)
Definition plcore.c:3593
void plP_gphy(PLINT *p_ixmin, PLINT *p_ixmax, PLINT *p_iymin, PLINT *p_iymax)
Definition plcore.c:4198
void c_plsesc(char esc)
Definition plcore.c:3890
void plgfile(FILE **p_file)
Definition plcore.c:3794
void c_plmkstrm(PLINT *p_strm)
Definition plcore.c:2671
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
void plP_esc(PLINT op, void *ptr)
Definition plcore.c:273
void plgesc(char *p_esc)
Definition plcore.c:3914
void c_plfontld(PLINT ifont)
Definition plcore.c:3488
#define BUFFER2_SIZE
Definition plcore.c:95
void plgFileDevs(const char ***p_menustr, const char ***p_devname, int *p_ndev)
Definition plcore.c:3530
static PLCHAR_VECTOR utf8_to_ucs4(PLCHAR_VECTOR ptr, PLUNICODE *unichar)
Definition plcore.c:1260
void c_plgyax(PLINT *p_digmax, PLINT *p_digits)
Definition plcore.c:4052
static PLUNICODE unicode_buffer_static[1024]
Definition plcore.c:1183
void c_plsdiplz(PLFLT xmin, PLFLT ymin, PLFLT xmax, PLFLT ymax)
Definition plcore.c:1806
void c_plsdev(PLCHAR_VECTOR devname)
Definition plcore.c:3640
void c_plsfnam(PLCHAR_VECTOR fnam)
Definition plcore.c:3830
void c_plgvpd(PLFLT *p_xmin, PLFLT *p_xmax, PLFLT *p_ymin, PLFLT *p_ymax)
Definition plcore.c:4097
void pllib_devinit()
Definition plcore.c:2874
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition plcore.c:4249
static void encode_unicode(PLCHAR_VECTOR string, EscText *args)
Definition plcore.c:924
void plP_gprec(PLINT *p_setp, PLINT *p_prec)
Definition plcore.c:3869
void plP_fill(short *x, short *y, PLINT npts)
Definition plcore.c:451
#define DRVSPEC_SIZE
Definition plcore.c:96
static void alternate_unicode_processing(PLCHAR_VECTOR string, EscText *args)
Definition plcore.c:647
void c_plsori(PLINT ori)
Definition plcore.c:3765
static void plLoadDriver(void)
Definition plcore.c:3378
void plsKeyEH(void(*KeyEH)(PLGraphicsIn *, void *, int *), void *KeyEH_data)
Definition plcore.c:3715
void plP_getinitdriverlist(char *names)
Definition plcore.c:4302
void c_plgdiori(PLFLT *p_rot)
Definition plcore.c:2145
static PLINT xscl[PL_MAXPOLY]
Definition plcore.h:70
static int npldynamicdevices
Definition plcore.h:258
static PLINT initfont
Definition plcore.h:72
static int nplstaticdevices
Definition plcore.h:256
static int npldrivers
Definition plcore.h:112
void(* PLDispatchInit)(PLDispatchTable *pdt)
Definition plcore.h:41
static PLINT lib_initialized
Definition plcore.h:74
static PLDispatchTable ** dispatch_table
Definition plcore.h:111
static PLDispatchInit static_device_initializers[]
Definition plcore.h:114
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
static PLINT yscl[PL_MAXPOLY]
Definition plcore.h:70
static PLINT ipls
Definition plcore.h:86
void plwarn(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1863
void plexit(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1958
void plP_sfnam(PLStream *pls, PLCHAR_VECTOR fnam)
Definition plctrl.c:2700
char PLDLLIMPEXP * plstrdup(PLCHAR_VECTOR src)
Definition plctrl.c:2985
char * plsave_set_locale(void)
Definition plctrl.c:3101
void plrestore_locale(char *saved_lc_numeric_locale)
Definition plctrl.c:3145
void plabort(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1894
PLINT plP_dcpcx(PLFLT x)
Definition plcvt.c:31
PLFLT plP_pcdcy(PLINT y)
Definition plcvt.c:95
PLFLT plP_pcdcx(PLINT x)
Definition plcvt.c:87
PLINT plP_dcpcy(PLFLT y)
Definition plcvt.c:39
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
void plfill_soft(short *x, short *y, PLINT n)
Definition plfill.c:307
void grimage(short *x, short *y, unsigned short *z, PLINT nx, PLINT ny)
Definition plimage.c:150
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
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
void plP_subpInit(void)
Definition plpage.c:134
Hershey_to_Unicode_table hershey_to_unicode_lookup_table[]
#define PLPLOT_MAX_PATH
Definition plplotP.h:446
#define PLDI_MAP
Definition plplotP.h:378
#define plsetvar(a, b)
Definition plplotP.h:187
int number_of_entries_in_hershey_to_unicode_table
#define PI
Definition plplotP.h:290
#define PLDI_DEV
Definition plplotP.h:381
#define PLSTATE_WIDTH
Definition plplotP.h:362
#define PLDI_ORI
Definition plplotP.h:379
#define TRUE
Definition plplotP.h:176
#define FALSE
Definition plplotP.h:177
#define NAFFINE
Definition plplotP.h:484
@ AT_EOP
Definition plplotP.h:373
@ DRAWING
Definition plplotP.h:373
@ AT_BOP
Definition plplotP.h:373
#define PL_NSTREAMS
Definition plplotP.h:284
#define PLDI_PLT
Definition plplotP.h:380
#define ABS(a)
Definition plplotP.h:199
#define free_mem(a)
Definition plplotP.h:182
#define plgfci
Definition plplot.h:735
#define plinit
Definition plplot.h:755
#define PLESC_HAS_TEXT
Definition plplot.h:290
#define PL_FCI_MEDIUM
Definition plplot.h:390
#define PLESC_CONTROL_CHAR
Definition plplot.h:300
PLUINT PLUNICODE
Definition plplot.h:201
#define PLTEXT_SUPERSCRIPT
Definition plplot.h:315
#define PL_FCI_HEXPOWER_IMPOSSIBLE
Definition plplot.h:374
float PLFLT
Definition plplot.h:163
#define PL_FCI_SCRIPT
Definition plplot.h:383
#define plpsty
Definition plplot.h:784
#define PL_FCI_HEXDIGIT_MASK
Definition plplot.h:372
void(* PLTRANSFORM_callback)(PLFLT x, PLFLT y, PLFLT_NC_SCALAR xp, PLFLT_NC_SCALAR yp, PLPointer data)
Definition plplot.h:257
#define PLESC_END_TEXT
Definition plplot.h:301
#define PLTEXT_OVERLINE
Definition plplot.h:318
const char * PLCHAR_VECTOR
Definition plplot.h:243
#define PL_FCI_MONO
Definition plplot.h:382
#define plgra
Definition plplot.h:740
#define plspal1
Definition plplot.h:833
#define PL_FCI_WEIGHT
Definition plplot.h:378
#define plspal0
Definition plplot.h:832
#define PLESC_GRADIENT
Definition plplot.h:305
unsigned int PLUINT
Definition plplot.h:180
#define plsdev
Definition plplot.h:806
#define PLESC_FLUSH
Definition plplot.h:281
#define PL_FCI_IMPOSSIBLE
Definition plplot.h:371
#define PL_FCI_OBLIQUE
Definition plplot.h:388
#define PL_UNUSED(x)
Definition plplot.h:138
#define PLESC_IMAGE
Definition plplot.h:291
#define PLESC_DI
Definition plplot.h:280
#define PLTEXT_FONTCHANGE
Definition plplot.h:314
#define plsdiori
Definition plplot.h:809
#define pllsty
Definition plplot.h:763
#define PLESC_TEXT_CHAR
Definition plplot.h:299
#define PLTEXT_SUBSCRIPT
Definition plplot.h:316
#define PL_FCI_UPRIGHT
Definition plplot.h:386
#define PLTEXT_BACKCHAR
Definition plplot.h:317
#define plsvect
Definition plplot.h:849
#define plsstrm
Definition plplot.h:835
#define PL_FCI_HEXPOWER_MASK
Definition plplot.h:373
#define PLESC_FILL
Definition plplot.h:279
#define PL_FCI_BOLD
Definition plplot.h:391
#define plcol0
Definition plplot.h:702
#define plsdiplt
Definition plplot.h:810
#define PL_FCI_SERIF
Definition plplot.h:381
#define PL_FCI_STYLE
Definition plplot.h:377
#define PL_FCI_FAMILY
Definition plplot.h:376
#define PLESC_SWIN
Definition plplot.h:284
#define PL_MAXWINDOWS
Definition plplot.h:448
#define PLESC_BEGIN_TEXT
Definition plplot.h:298
int PLINT
Definition plplot.h:181
#define plend1
Definition plplot.h:710
#define plsdidev
Definition plplot.h:807
#define PL_FCI_SANS
Definition plplot.h:380
void * PLPointer
Definition plplot.h:209
#define plsdimap
Definition plplot.h:808
#define PL_FCI_ITALIC
Definition plplot.h:387
#define PLTEXT_UNDERLINE
Definition plplot.h:319
#define PL_FCI_SYMBOL
Definition plplot.h:384
#define PL_FCI_MARK
Definition plplot.h:370
#define plssub
Definition plplot.h:836
#define DRV_DIR
#define BUILD_DIR
void xform(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
void plio_fgets(char *buf, int size, FILE *stream)
Definition plstdio.c:142
FILE * pl_create_tempfile(char **fname)
Definition plstdio.c:240
void plstr(PLINT base, PLFLT *xform, PLINT refx, PLINT refy, PLCHAR_VECTOR string)
Definition plsym.c:810
void plfntld(PLINT fnt)
Definition plsym.c:1394
PLINT plP_strpos(PLCHAR_VECTOR str, int chr)
Definition plsym.c:1216
int plhershey2unicode(int in)
Definition plsym.c:1490
void plfontrel(void)
Definition plsym.c:1463
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
void c_pltimefmt(PLCHAR_VECTOR fmt)
Definition pltime.c:66
static int text
Definition ps.c:77
void closeqsas(QSASConfig **qsasconfig)
Definition qsastime.c:1200
unsigned short unicode_array_len
Definition plplotP.h:736
PLINT refy
Definition plplotP.h:717
PLUNICODE n_fci
Definition plplotP.h:726
PLINT base
Definition plplotP.h:707
PLINT refx
Definition plplotP.h:716
PLUNICODE n_char
Definition plplotP.h:727
PLINT n_ctrl_char
Definition plplotP.h:728
PLFLT just
Definition plplotP.h:708
PLINT x
Definition plplotP.h:712
const char * string
Definition plplotP.h:739
PLUNICODE * unicode_array
Definition plplotP.h:735
PLINT y
Definition plplotP.h:713
enum EscText::@5 text_type
PLFLT * xform
Definition plplotP.h:709
PLFLT dy
Definition plplotP.h:1205
PLFLT xmin
Definition plplotP.h:1205
PLFLT ymin
Definition plplotP.h:1205
PLFLT dx
Definition plplotP.h:1205
PLFLT a
Definition plplot.h:551
unsigned char r
Definition plplot.h:548
unsigned char g
Definition plplot.h:549
unsigned char b
Definition plplot.h:550
const char * pl_DevName
Definition disptab.h:80
plD_init_fp pl_init
Definition disptab.h:83
const char * pl_MenuStr
Definition disptab.h:79
PLFLT dipymax
Definition plstrm.h:657
PLINT ncol1
Definition plstrm.h:539
size_t plbuf_buffer_grow
Definition plstrm.h:647
PLINT ncol0
Definition plstrm.h:539
PLColor * cmap0
Definition plstrm.h:544
size_t plbuf_top
Definition plstrm.h:650
size_t plbuf_readpos
Definition plstrm.h:651
PLINT ipls
Definition plstrm.h:527
PLFLT cmap1_min
Definition plstrm.h:541
void * plbuf_buffer
Definition plstrm.h:649
PLFLT dipxmax
Definition plstrm.h:657
PLINT debug
Definition plstrm.h:527
PLFLT jy
Definition plstrm.h:659
PLFLT jx
Definition plstrm.h:659
PLFLT aspect
Definition plstrm.h:659
PLColor curcolor
Definition plstrm.h:543
PLINT icol1
Definition plstrm.h:539
PLFLT dipxmin
Definition plstrm.h:657
PLINT phyymi
Definition plstrm.h:705
PLINT phyyma
Definition plstrm.h:705
PLFLT dipymin
Definition plstrm.h:657
PLINT phyxmi
Definition plstrm.h:705
PLFLT mar
Definition plstrm.h:659
size_t plbuf_buffer_size
Definition plstrm.h:648
PLColor * cmap1
Definition plstrm.h:545
PLINT difilt
Definition plstrm.h:656
PLINT level
Definition plstrm.h:527
PLFLT cmap1_max
Definition plstrm.h:541
PLFLT ypmm
Definition plstrm.h:707
PLINT icol0
Definition plstrm.h:539
PLINT phyxma
Definition plstrm.h:705
PLFLT xpmm
Definition plstrm.h:707
PLFLT diorot
Definition plstrm.h:661
PLFLT dyma
Definition plplot.h:452
PLFLT wymi
Definition plplot.h:453
PLFLT wxmi
Definition plplot.h:453
PLFLT wyma
Definition plplot.h:453
PLFLT dxma
Definition plplot.h:452
PLFLT wxma
Definition plplot.h:453
PLFLT dymi
Definition plplot.h:452
PLFLT dxmi
Definition plplot.h:452
char d_name[MAX_PATH+1]
Definition dirent_msvc.h:67
static char errmsg[160]
Definition tclAPI.c:158
static char buf[200]
Definition tclAPI.c:873
static const char * name
Definition tkMain.c:135