1 /* This file is part of the GNU plotutils package.  Copyright (C) 1995,
2    1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
3 
4    The GNU plotutils package is free software.  You may redistribute it
5    and/or modify it under the terms of the GNU General Public License as
6    published by the Free Software foundation; either version 2, or (at your
7    option) any later version.
8 
9    The GNU plotutils package is distributed in the hope that it will be
10    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with the GNU plotutils package; see the file COPYING.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17    Boston, MA 02110-1301, USA. */
18 
19 /* This file is specific to libplot, rather than libplotter.  It defines
20    the new (i.e., thread-safe) C API.  The new C API contains wrappers
21    around the operations that may be applied to any Plotter object, plus
22    two additional functions (pl_newpl_r, pl_deletepl_r) that are specific
23    to libplot.
24 
25    pl_newpl_r/pl_deletepl_r construct and destroy Plotter instances.  Their
26    names resemble the C++ operations `new' and `delete'.  When a new
27    Plotter of any type is constructed, the appropriate `default_init'
28    structure, which contains function pointers, is copied into it.  Then
29    its `initialize' method is invoked.  Before the Plotter is destroyed,
30    its `terminate' method is invoked similarly.
31 
32    The C API also includes the functions pl_newplparams/pl_deleteplparams,
33    which create/destroy PlotterParams instances, and wrappers around the
34    methods that may be applied to any PlotterParams object.  A pointer to a
35    PlotterParams object is passed to pl_newpl_r().  It specifies the
36    device-driver parameters of the Plotter that will be created. */
37 
38 #include "sys-defines.h"
39 #include "extern.h"
40 #include "plot.h"		/* header file for C API */
41 
42 /* Known Plotter types, indexed into by a short mnemonic case-insensitive
43    string: "generic"=generic (i.e. base Plotter class), "bitmap"=bitmap,
44    "meta"=metafile, "tek"=Tektronix, "regis"=ReGIS, "hpgl"=HP-GL/2,
45    "pcl"=PCL 5, "fig"=xfig, "cgm"=CGM, "ps"=PS, "ai"="AI", "svg"=SVG,
46    "gif"=GIF, "pnm"=PNM (i.e. PBM/PGM/PPM), "z"=PNG, "X"=X11,
47    "Xdrawable"=X11Drawable.  */
48 
49 typedef struct
50 {
51   const char *name;
52   const Plotter *default_init;
53 }
54 Plotter_data;
55 
56 /* Initializations for the function-pointer part of each type of Plotter.
57    Each of the initializing structures listed here is defined in the
58    corresponding ?_defplot.c file. */
59 static const Plotter_data _plotter_data[] =
60 {
61   {"generic", &_pl_g_default_plotter},
62   {"bitmap", &_pl_b_default_plotter},
63   {"meta", &_pl_m_default_plotter},
64   {"tek", &_pl_t_default_plotter},
65   {"regis", &_pl_r_default_plotter},
66   {"hpgl", &_pl_h_default_plotter},
67   {"pcl", &_pl_q_default_plotter},
68   {"fig", &_pl_f_default_plotter},
69   {"cgm", &_pl_c_default_plotter},
70   {"ps", &_pl_p_default_plotter},
71   {"ai", &_pl_a_default_plotter},
72   {"svg", &_pl_s_default_plotter},
73   {"gif", &_pl_i_default_plotter},
74   {"pnm", &_pl_n_default_plotter},
75 #ifdef INCLUDE_PNG_SUPPORT
76   {"png", &_pl_z_default_plotter},
77 #endif
78 #ifndef X_DISPLAY_MISSING
79   {"Xdrawable", &_pl_x_default_plotter},
80   {"X", &_pl_y_default_plotter},
81 #endif /* not X_DISPLAY_MISSING */
82   {(const char *)NULL, (const Plotter *)NULL}
83 };
84 
85 /* forward references */
86 static bool _string_to_plotter_data (const char *type, int *position);
87 static void _api_warning (const char *msg);
88 
89 /* These are two user-callable functions that are specific to the new
90    (i.e., thread-safe) C binding: pl_newpl_r, pl_deletepl_r. */
91 
92 Plotter *
pl_newpl_r(const char * type,FILE * infile,FILE * outfile,FILE * errfile,const PlotterParams * plotter_params)93 pl_newpl_r (const char *type, FILE *infile, FILE *outfile, FILE *errfile, const PlotterParams *plotter_params)
94 {
95   bool found;
96   int position;
97   Plotter *_plotter;
98 
99   /* determine initialization for specified plotter type */
100   found = _string_to_plotter_data (type, &position);
101   if (!found)
102     {
103       _api_warning ("ignoring request to create plotter of unknown type");
104       return NULL;
105     }
106 
107   /* create Plotter, copy function pointers to it */
108   _plotter = (Plotter *)_pl_xmalloc (sizeof(Plotter));
109   memcpy (_plotter, _plotter_data[position].default_init, sizeof(Plotter));
110 
111   /* create PlotterData structure, install it in Plotter */
112   _plotter->data = (plPlotterData *)_pl_xmalloc (sizeof(plPlotterData));
113 
114   /* copy parameters to it */
115   _plotter->data->infp = infile;
116   _plotter->data->outfp = outfile;
117   _plotter->data->errfp = errfile;
118   _pl_g_copy_params_to_plotter (_plotter, plotter_params);
119 
120   /* do any additional needed initializiations of the Plotter (e.g.,
121      initialize data members of the PlotterData structure in a
122      device-dependent way); also add the Plotter to the _plotters[] array */
123   _plotter->initialize (_plotter);
124 
125   return _plotter;
126 }
127 
128 /* utility function, used above; keys into table of Plotter types by a
129    short mnemonic string */
130 static bool
_string_to_plotter_data(const char * type,int * position)131 _string_to_plotter_data (const char *type, int *position)
132 {
133   const Plotter_data *p = _plotter_data;
134   bool found = false;
135   int i = 0;
136 
137   /* search table of known plotter type mnemonics */
138   while (p->name)
139     {
140       if (strcasecmp ((char *)type, (char *)p->name) == 0)
141 	{
142 	  found = true;
143 	  break;
144 	}
145       p++;
146       i++;
147     }
148   /* return pointer to plotter data through pointer */
149   if (found)
150     *position = i;
151   return found;
152 }
153 
154 int
pl_deletepl_r(Plotter * _plotter)155 pl_deletepl_r (Plotter *_plotter)
156 {
157   if (_plotter == NULL)
158     {
159       _api_warning ("ignoring request to delete a null Plotter");
160       return -1;
161     }
162 
163   /* if luser left the Plotter open, close it */
164   if (_plotter->data->open)
165     _API_closepl (_plotter);
166 
167   /* Invoke an internal Plotter method before deletion.  At a minimum, this
168      private `terminate' method, frees instance-specific copies of class
169      parameters, and also removes the pointer to the Plotter instance from
170      the _plotters[] array.
171 
172      Also, it writes any unwritten graphics to the Plotter's output stream.
173      This is the case for PSPlotters in particular, which write graphics
174      only when they are deleted.  For a PSPlotter, the terminate method
175      emits the Plotter's pages of graphics to its output stream and then
176      deallocates associated storage.  For an XPlotter, this method kills
177      the forked-off processes that are maintaining its popped-up windows
178      (if any), provided that the VANISH_ON_DELETE parameter is set.  */
179   _plotter->terminate (_plotter);
180 
181   /* tear down the PlotterData structure */
182   free (_plotter->data);
183 
184   /* tear down the Plotter itself */
185   free (_plotter);
186 
187   return 0;
188 }
189 
190 
191 /* function used in this file to print warning messages */
192 static void
_api_warning(const char * msg)193 _api_warning (const char *msg)
194 {
195   if (pl_libplot_warning_handler != NULL)
196     (*pl_libplot_warning_handler)(msg);
197   else
198     fprintf (stderr, "libplot: %s\n", msg);
199 }
200 
201 
202 /* These are two user-callable functions that are specific to the new
203    (i.e., thread-safe) C binding: pl_newplparams, pl_deleteplparams,
204    pl_copyplparams. */
205 
206 PlotterParams *
pl_newplparams(void)207 pl_newplparams (void)
208 {
209   int i;
210   PlotterParams *_plotter_params_p;
211 
212   /* create PlotterParams, copy function pointers to it */
213   _plotter_params_p = (PlotterParams *)_pl_xmalloc (sizeof(PlotterParams));
214   memcpy (_plotter_params_p, &_default_plotter_params, sizeof(PlotterParams));
215 
216   /* null out all parameters */
217   for (i = 0; i < NUM_PLOTTER_PARAMETERS; i++)
218     _plotter_params_p->plparams[i] = (void *)NULL;
219 
220   return _plotter_params_p;
221 }
222 
223 int
pl_deleteplparams(PlotterParams * _plotter_params_p)224 pl_deleteplparams (PlotterParams *_plotter_params_p)
225 {
226   int i;
227 
228   /* free all copied strings, and the structure itself */
229   for (i = 0; i < NUM_PLOTTER_PARAMETERS; i++)
230     if (_known_params[i].is_string && _plotter_params_p->plparams[i] != NULL)
231       free (_plotter_params_p->plparams[i]);
232   free (_plotter_params_p);
233 
234   return 0;
235 }
236 
237 PlotterParams *
pl_copyplparams(const PlotterParams * _plotter_params_p)238 pl_copyplparams (const PlotterParams *_plotter_params_p)
239 {
240   int i;
241   PlotterParams *new_plotter_params_p;
242 
243   /* create PlotterParams, copy function pointers to it */
244   new_plotter_params_p = (PlotterParams *)_pl_xmalloc (sizeof(PlotterParams));
245   memcpy (new_plotter_params_p, &_default_plotter_params, sizeof(PlotterParams));
246 
247   /* copy all parameters */
248   for (i = 0; i < NUM_PLOTTER_PARAMETERS; i++)
249     new_plotter_params_p->plparams[i] = _plotter_params_p->plparams[i];
250 
251   return new_plotter_params_p;
252 }
253 
254 /* The following are C wrappers around the public functions in the
255    PlotterParams class.  Together with the preceding functions, they are
256    part of the new (i.e., thread-safe) C API. */
257 
258 int
pl_setplparam(PlotterParams * plotter_params,const char * parameter,void * value)259 pl_setplparam (PlotterParams *plotter_params, const char *parameter, void * value)
260 {
261   return plotter_params->setplparam (plotter_params, parameter, value);
262 }
263 
264 /* END OF WRAPPERS AROUND PLOTTERPARAMS METHODS */
265