GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__init_gnuplot__.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2007-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 /*
27 
28 To initialize:
29 
30  graphics_toolkit ("gnuplot");
31  plot (randn (1e3, 1));
32 
33 */
34 
35 #if defined (HAVE_CONFIG_H)
36 # include "config.h"
37 #endif
38 
39 #include <string>
40 
41 #include "dMatrix.h"
42 #include "file-stat.h"
43 #include "oct-env.h"
44 
45 #include "build-env.h"
46 #include "builtin-defun-decls.h"
47 #include "defun-dld.h"
48 #include "error.h"
49 #include "graphics.h"
50 #include "interpreter-private.h"
51 #include "interpreter.h"
52 #include "ov.h"
53 #include "ovl.h"
54 #include "utils.h"
55 #include "variables.h"
56 
57 // PKG_ADD: if (__have_gnuplot__ ()) register_graphics_toolkit ("gnuplot"); endif
58 
60 
61 class gnuplot_graphics_toolkit : public octave::base_graphics_toolkit
62 {
63 public:
64 
65  gnuplot_graphics_toolkit (octave::interpreter& interp)
66  : octave::base_graphics_toolkit ("gnuplot"), m_interpreter (interp)
67  {
68  static bool warned = false;
69 
70  if (! warned)
71  {
73  ("Octave:gnuplot-graphics",
74  "using the gnuplot graphics toolkit is discouraged\n\
75 \n\
76 The gnuplot graphics toolkit is not actively maintained and has a number\n\
77 of limitations that are unlikely to be fixed. Communication with gnuplot\n\
78 uses a one-directional pipe and limited information is passed back to the\n\
79 Octave interpreter so most changes made interactively in the plot window\n\
80 will not be reflected in the graphics properties managed by Octave. For\n\
81 example, if the plot window is closed with a mouse click, Octave will not\n\
82 be notified and will not update its internal list of open figure windows.\n\
83 The qt toolkit is recommended instead.\n");
84 
85  warned = true;
86  }
87  }
88 
89  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gnuplot_graphics_toolkit)
90 
91  ~gnuplot_graphics_toolkit () = default;
92 
93  bool is_valid () const { return true; }
94 
95  bool initialize (const graphics_object& go)
96  {
97  return go.isa ("figure");
98  }
99 
100  void finalize (const graphics_object& go)
101  {
102  if (go.isa ("figure"))
103  {
104  const figure::properties& props
105  = dynamic_cast<const figure::properties&> (go.get_properties ());
106 
107  send_quit (props.get___plot_stream__ ());
108  }
109  }
110 
111  void update (const graphics_object& go, int id)
112  {
113  if (go.isa ("figure"))
114  {
115  graphics_object obj (go);
116 
117  figure::properties& props
118  = dynamic_cast<figure::properties&> (obj.get_properties ());
119 
120  switch (id)
121  {
123  if (! props.is_visible ())
124  {
125  send_quit (props.get___plot_stream__ ());
126  props.set___plot_stream__ (Matrix ());
127  props.set_graphicssmoothing (false);
128  }
129  break;
130  }
131  }
132  }
133 
134  void redraw_figure (const graphics_object& go) const
135  {
136  static bool drawnow_executing = false;
137 
138  // Prevent recursion
139  if (! drawnow_executing)
140  {
141  octave::unwind_protect_var<bool> restore_var (drawnow_executing, true);
142 
143  octave_value_list args;
144  args(0) = go.get_handle ().as_octave_value ();
145  m_interpreter.feval ("__gnuplot_drawnow__", args);
146  }
147  }
148 
149  void print_figure (const graphics_object& go, const std::string& term,
150  const std::string& file,
151  const std::string& debug_file) const
152  {
153  octave_value_list args;
154  if (! debug_file.empty ())
155  args(3) = debug_file;
156  args(2) = file;
157  args(1) = term;
158  args(0) = go.get_handle ().as_octave_value ();
159  m_interpreter.feval ("__gnuplot_drawnow__", args);
160  }
161 
162  Matrix get_canvas_size (const graphics_handle&) const
163  {
164  Matrix sz (1, 2, 0.0);
165  return sz;
166  }
167 
168  double get_screen_resolution () const
169  { return 72.0; }
170 
171  Matrix get_screen_size () const
172  { return Matrix (1, 2, 0.0); }
173 
174  void close ()
175  {
176  if (m_interpreter.mislocked ("__init_gnuplot__"))
177  m_interpreter.munlock ("__init_gnuplot__");
178  }
179 
180 private:
181 
182  void send_quit (const octave_value& pstream) const
183  {
184  if (! pstream.isempty ())
185  {
186  octave_value_list args;
187  Matrix fids = pstream.matrix_value ();
188 
189  octave::Ffputs (m_interpreter, ovl (fids(0), "\nquit;\n"));
190 
191  octave::Ffflush (m_interpreter, ovl (fids(0)));
192  octave::Fpclose (m_interpreter, ovl (fids(0)));
193 
194  if (fids.numel () > 1)
195  {
196  octave::Fpclose (m_interpreter, ovl (fids(1)));
197 
198  if (fids.numel () > 2)
199  octave::Fwaitpid (ovl (fids(2)));
200  }
201  }
202  }
203 
204  octave::interpreter& m_interpreter;
205 };
206 
207 static bool
208 have_gnuplot_binary (interpreter& interp)
209 {
210  const std::string exeext = octave::build_env::EXEEXT;
211  const std::string path = octave::sys::env::getenv ("PATH");
212  bool retval = false;
213 
214  try
215  {
217  = interp.feval ("gnuplot_binary", octave_value_list ());
218 
219  if (tmp(0).is_string () && ! tmp(0).isempty ())
220  {
221  std::string gnuplot_binary = tmp(0).string_value ();
222 
223  string_vector args (gnuplot_binary);
224  std::string gnuplot_path = octave::search_path_for_file (path, args);
225 
226  octave::sys::file_stat fs (gnuplot_path);
227 
228  if (! fs.exists () && ! exeext.empty ())
229  {
230  args[0] += exeext;
231 
232  gnuplot_path = octave::search_path_for_file (path, args);
233 
234  fs = octave::sys::file_stat (gnuplot_path);
235  }
236 
237  retval = fs.exists ();
238  }
239  }
240  catch (const octave::execution_exception&)
241  {
242  interp.recover_from_exception ();
243  }
244 
245  return retval;
246 }
247 
248 // Initialize the gnuplot graphics toolkit.
249 
250 DEFMETHOD_DLD (__init_gnuplot__, interp, , ,
251  doc: /* -*- texinfo -*-
252 @deftypefn {} {} __init_gnuplot__ ()
253 Undocumented internal function.
254 @end deftypefn */)
255 {
256  if (! have_gnuplot_binary (interp))
257  error ("__init_gnuplot__: the gnuplot program is not available, see 'gnuplot_binary'");
258  else if (! interp.mislocked ("__init_gnuplot__"))
259  {
260  gtk_manager& gtk_mgr = interp.get_gtk_manager ();
261 
262  graphics_toolkit tk (new gnuplot_graphics_toolkit (interp));
263  gtk_mgr.load_toolkit (tk);
264 
265  interp.mlock ();
266  }
267 
268  return octave_value_list ();
269 }
270 
271 DEFMETHOD_DLD (__have_gnuplot__, interp, , ,
272  doc: /* -*- texinfo -*-
273 @deftypefn {} {@var{gnuplot_available} =} __have_gnuplot__ ()
274 Undocumented internal function.
275 @end deftypefn */)
276 {
277  return ovl (have_gnuplot_binary (interp));
278 }
279 
280 /*
281 ## No test needed for internal helper function.
282 %!assert (1)
283 */
284 
285 OCTAVE_END_NAMESPACE(octave)
const char * EXEEXT
Definition: build-env.cc:116
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Definition: dMatrix.h:42
bool is_visible() const
Definition: graphics.h:2559
octave_value get___plot_stream__() const
Definition: graphics.h:3979
void set_graphicssmoothing(const octave_value &val)
Definition: graphics.h:4070
void set___plot_stream__(const octave_value &val)
Definition: graphics.h:4413
base_properties & get_properties()
Definition: graphics.h:3120
bool isa(const std::string &go_name) const
Definition: graphics.h:3118
graphics_handle get_handle() const
Definition: graphics.h:3106
void load_toolkit(const graphics_toolkit &tk)
Definition: gtk-manager.h:61
void mlock(bool skip_first=false) const
gtk_manager & get_gtk_manager()
Definition: interpreter.h:323
bool mislocked(bool skip_first=false) const
octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
void recover_from_exception()
octave_value as_octave_value() const
Definition: oct-handle.h:80
bool isempty() const
Definition: ov.h:601
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:853
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFMETHOD_DLD(name, interp_name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin method.
Definition: defun-dld.h:99
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1078
void() error(const char *fmt,...)
Definition: error.cc:988
octave_value_list Fpclose(octave::interpreter &interp, const octave_value_list &args, int)
Definition: file-io.cc:2908
std::string search_path_for_file(const std::string &path, const string_vector &names)
Definition: utils.cc:517
octave_value_list Ffflush(octave::interpreter &interp, const octave_value_list &args, int)
Definition: file-io.cc:232
octave_value_list Fwaitpid(const octave_value_list &args, int)
Definition: syscalls.cc:1228
octave_value_list Ffputs(octave::interpreter &interp, const octave_value_list &args, int)
Definition: file-io.cc:927
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219