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 defines the initialization for any XPlotter object, including
20 both private data and public methods. There is a one-to-one
21 correspondence between public methods and user-callable functions in the
22 C API. */
23
24 #include "sys-defines.h"
25 #include <signal.h> /* for kill() */
26 #include "extern.h"
27
28 /* Sparse array of pointers to XPlotter instances, and its size. Should be
29 initialized to a NULL pointer, and 0, respectively.
30
31 In libplotter these are not global variables: in extern.h, they are
32 #define'd to be static data members of the XPlotter class.
33
34 Accessed by _pl_y_initialize() and _pl_y_terminate() in this file, by
35 _pl_y_maybe_handle_x_events() in y_openpl.c, and by _pl_y_closepl() in
36 y_closepl.c. */
37
38 XPlotter **_xplotters = NULL;
39 int _xplotters_len = 0;
40
41 /* initial size for "_xplotters", the sparse array of XPlotter instances */
42 #define INITIAL_XPLOTTERS_LEN 4
43
44 /* Mutex for locking _xplotters[] and _xplotters_len. */
45 #ifdef PTHREAD_SUPPORT
46 #ifdef HAVE_PTHREAD_H
47 pthread_mutex_t _xplotters_mutex = PTHREAD_MUTEX_INITIALIZER;
48 #endif
49 #endif
50
51 #ifndef LIBPLOTTER
52 /* In libplot, this is the initialization for the function-pointer part of
53 an XPlotter struct. */
54 const Plotter _pl_y_default_plotter =
55 {
56 /* initialization (after creation) and termination (before deletion) */
57 _pl_y_initialize, _pl_y_terminate,
58 /* page manipulation */
59 _pl_y_begin_page, _pl_y_erase_page, _pl_y_end_page,
60 /* drawing state manipulation */
61 _pl_x_push_state, _pl_x_pop_state,
62 /* internal path-painting methods (endpath() is a wrapper for the first) */
63 _pl_x_paint_path, _pl_x_paint_paths, _pl_x_path_is_flushable, _pl_x_maybe_prepaint_segments,
64 /* internal methods for drawing of markers and points */
65 _pl_g_paint_marker, _pl_x_paint_point,
66 /* internal methods that plot strings in Hershey, non-Hershey fonts */
67 _pl_g_paint_text_string_with_escapes, _pl_x_paint_text_string,
68 _pl_x_get_text_width,
69 /* private low-level `retrieve font' method */
70 _pl_x_retrieve_font,
71 /* `flush output' method, called only if Plotter handles its own output */
72 _pl_x_flush_output,
73 /* internal error handlers */
74 _pl_g_warning,
75 _pl_g_error,
76 };
77 #endif /* not LIBPLOTTER */
78
79 /* The private `initialize' method, which is invoked when a Plotter is
80 created. It is used for such things as initializing capability flags
81 from the values of class variables, allocating storage, etc. When this
82 is invoked, _plotter points to the Plotter that has just been
83 created. */
84
85 void
_pl_y_initialize(S___ (Plotter * _plotter))86 _pl_y_initialize (S___(Plotter *_plotter))
87 {
88 bool open_slot = false;
89 int i, j;
90
91 #ifndef LIBPLOTTER
92 /* in libplot, manually invoke superclass initialization method */
93 _pl_x_initialize (S___(_plotter));
94 #endif
95
96 #ifdef PTHREAD_SUPPORT
97 #ifdef HAVE_PTHREAD_H
98 /* lock the global variables _xplotters[] and _xplotters_len */
99 pthread_mutex_lock (&_xplotters_mutex);
100 #endif
101 #endif
102
103 /* If this is the first XPlotter to be created, initialize Xt library.
104 At least in X11R6, it's OK to initialize it more than once, but we're
105 careful. */
106 if (_xplotters_len == 0)
107 {
108 /* first initialize Xlib and Xt thread support if any */
109 #ifdef PTHREAD_SUPPORT
110 #ifdef HAVE_PTHREAD_H
111 #ifdef X_THREAD_SUPPORT
112 XInitThreads ();
113 XtToolkitThreadInitialize ();
114 #endif
115 #endif
116 #endif
117 /* initialize Xt library itself */
118 XtToolkitInitialize ();
119 }
120
121 /* ensure XPlotter array is set up */
122 if (_xplotters_len == 0)
123 {
124 _xplotters = (XPlotter **)_pl_xmalloc (INITIAL_XPLOTTERS_LEN * sizeof(XPlotter *));
125 for (i = 0; i < INITIAL_XPLOTTERS_LEN; i++)
126 _xplotters[i] = (XPlotter *)NULL;
127 _xplotters_len = INITIAL_XPLOTTERS_LEN;
128 }
129
130 /* be sure there is an open slot (slot i) */
131 for (i = 0; i < _xplotters_len; i++)
132 if (_xplotters[i] == NULL)
133 {
134 open_slot = true;
135 break;
136 }
137 if (!open_slot)
138 /* expand array, clearing upper half */
139 {
140 i = _xplotters_len;
141 _xplotters =
142 (XPlotter **)_pl_xrealloc (_xplotters,
143 2 * _xplotters_len * sizeof (XPlotter *));
144 for (j = _xplotters_len; j < 2 * _xplotters_len; j++)
145 _xplotters[j] = (XPlotter *)NULL;
146 _xplotters_len *= 2;
147 }
148
149 /* place just-created Plotter in open slot */
150 _xplotters[i] = _plotter;
151
152 #ifdef PTHREAD_SUPPORT
153 #ifdef HAVE_PTHREAD_H
154 /* unlock the global variables _xplotters[] and _xplotters_len */
155 pthread_mutex_unlock (&_xplotters_mutex);
156 #endif
157 #endif
158
159 /* override superclass initializations, as necessary */
160
161 #ifndef LIBPLOTTER
162 /* tag field, differs in derived classes */
163 _plotter->data->type = PL_X11;
164 #endif
165
166 /* output model */
167 _plotter->data->output_model = PL_OUTPUT_VIA_CUSTOM_ROUTINES_TO_NON_STREAM;
168
169 /* initialize data members specific to this derived class */
170 _plotter->y_app_con = (XtAppContext)NULL;
171 _plotter->y_toplevel = (Widget)NULL;
172 _plotter->y_canvas = (Widget)NULL;
173 _plotter->y_drawable4 = (Drawable)0;
174 _plotter->y_auto_flush = true;
175 _plotter->y_vanish_on_delete = false;
176 _plotter->y_pids = (pid_t *)NULL;
177 _plotter->y_num_pids = 0;
178 _plotter->y_event_handler_count = 0;
179
180 /* initialize certain data members from device driver parameters */
181
182 /* determine whether to do an XFlush() after each drawing operation */
183 {
184 const char *vanish_s;
185
186 vanish_s = (const char *)_get_plot_param (_plotter->data,
187 "X_AUTO_FLUSH");
188 if (strcasecmp (vanish_s, "no") == 0)
189 _plotter->y_auto_flush = false;
190 else
191 _plotter->y_auto_flush = true;
192 }
193
194 /* determine whether windows vanish on Plotter deletion */
195 {
196 const char *vanish_s;
197
198 vanish_s = (const char *)_get_plot_param (_plotter->data,
199 "VANISH_ON_DELETE");
200 if (strcasecmp (vanish_s, "yes") == 0)
201 _plotter->y_vanish_on_delete = true;
202 else
203 _plotter->y_vanish_on_delete = false;
204 }
205
206 }
207
208 /* The private `terminate' method, which is invoked when a Plotter is
209 deleted. It may do such things as write to an output stream from
210 internal storage, deallocate storage, etc. When this is invoked,
211 _plotter points to the Plotter that is about to be deleted. */
212
213 void
_pl_y_terminate(S___ (Plotter * _plotter))214 _pl_y_terminate (S___(Plotter *_plotter))
215 {
216 int i, j;
217
218 /* kill forked-off processes that are maintaining XPlotter's popped-up
219 windows, provided that the VANISH_ON_DELETE parameter was set to "yes"
220 at creation time */
221 if (_plotter->y_vanish_on_delete)
222 {
223 for (j = 0; j < _plotter->y_num_pids; j++)
224 kill (_plotter->y_pids[j], SIGKILL);
225 if (_plotter->y_num_pids > 0)
226 {
227 free (_plotter->y_pids);
228 _plotter->y_pids = (pid_t *)NULL;
229 }
230 }
231
232 /* remove XPlotter from sparse XPlotter array */
233
234 #ifdef PTHREAD_SUPPORT
235 #ifdef HAVE_PTHREAD_H
236 /* lock the global variables _xplotters[] and _xplotters_len */
237 pthread_mutex_lock (&_xplotters_mutex);
238 #endif
239 #endif
240 for (i = 0; i < _xplotters_len; i++)
241 if (_xplotters[i] == _plotter)
242 {
243 _xplotters[i] = (XPlotter *)NULL;
244 break;
245 }
246 #ifdef PTHREAD_SUPPORT
247 #ifdef HAVE_PTHREAD_H
248 /* unlock the global variables _xplotters[] and _xplotters_len */
249 pthread_mutex_unlock (&_xplotters_mutex);
250 #endif
251 #endif
252
253 #ifndef LIBPLOTTER
254 /* in libplot, manually invoke superclass termination method */
255 _pl_x_terminate (S___(_plotter));
256 #endif
257 }
258
259 #ifdef LIBPLOTTER
XPlotter(FILE * infile,FILE * outfile,FILE * errfile)260 XPlotter::XPlotter (FILE *infile, FILE *outfile, FILE *errfile)
261 :XDrawablePlotter (infile, outfile, errfile)
262 {
263 _pl_y_initialize ();
264
265 /* add to _xplotters sparse array */
266 }
267
XPlotter(FILE * outfile)268 XPlotter::XPlotter (FILE *outfile)
269 :XDrawablePlotter (outfile)
270 {
271 _pl_y_initialize ();
272
273 /* add to _xplotters sparse array */
274 }
275
XPlotter(istream & in,ostream & out,ostream & err)276 XPlotter::XPlotter (istream& in, ostream& out, ostream& err)
277 : XDrawablePlotter (in, out, err)
278 {
279 _pl_y_initialize ();
280
281 /* add to _xplotters sparse array */
282 }
283
XPlotter(ostream & out)284 XPlotter::XPlotter (ostream& out)
285 : XDrawablePlotter (out)
286 {
287 _pl_y_initialize ();
288
289 /* add to _xplotters sparse array */
290 }
291
XPlotter()292 XPlotter::XPlotter ()
293 {
294 _pl_y_initialize ();
295
296 /* add to _xplotters sparse array */
297 }
298
XPlotter(FILE * infile,FILE * outfile,FILE * errfile,PlotterParams & parameters)299 XPlotter::XPlotter (FILE *infile, FILE *outfile, FILE *errfile, PlotterParams ¶meters)
300 :XDrawablePlotter (infile, outfile, errfile, parameters)
301 {
302 _pl_y_initialize ();
303
304 /* add to _xplotters sparse array */
305 }
306
XPlotter(FILE * outfile,PlotterParams & parameters)307 XPlotter::XPlotter (FILE *outfile, PlotterParams ¶meters)
308 :XDrawablePlotter (outfile, parameters)
309 {
310 _pl_y_initialize ();
311
312 /* add to _xplotters sparse array */
313 }
314
XPlotter(istream & in,ostream & out,ostream & err,PlotterParams & parameters)315 XPlotter::XPlotter (istream& in, ostream& out, ostream& err, PlotterParams ¶meters)
316 : XDrawablePlotter (in, out, err, parameters)
317 {
318 _pl_y_initialize ();
319
320 /* add to _xplotters sparse array */
321 }
322
XPlotter(ostream & out,PlotterParams & parameters)323 XPlotter::XPlotter (ostream& out, PlotterParams ¶meters)
324 : XDrawablePlotter (out, parameters)
325 {
326 _pl_y_initialize ();
327
328 /* add to _xplotters sparse array */
329 }
330
XPlotter(PlotterParams & parameters)331 XPlotter::XPlotter (PlotterParams ¶meters)
332 : XDrawablePlotter (parameters)
333 {
334 _pl_y_initialize ();
335
336 /* add to _xplotters sparse array */
337 }
338
~XPlotter()339 XPlotter::~XPlotter ()
340 {
341 /* if luser left the Plotter open, close it */
342 if (_plotter->data->open)
343 _API_closepl ();
344
345 _pl_y_terminate ();
346
347 /* remove from _xplotters sparse array */
348 }
349 #endif
350