1########################################################################
2##
3## Copyright (C) 2004-2021 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## -*- texinfo -*-
27## @deftypefn {} {[@var{x}, @var{y}, @var{buttons}] =} __gnuplot_ginput__ (@var{f}, @var{n})
28## Undocumented internal function.
29## @end deftypefn
30
31## This is ginput.m implementation for gnuplot and X11.
32## It requires gnuplot 4.1 and later.
33
34## This file initially bore the copyright statement
35## Petr Mikulik
36## History: June 2006; August 2005; June 2004; April 2004
37## License: public domain
38
39function [x, y, button] = __gnuplot_ginput__ (f, n)
40
41  if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
42    error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
43  endif
44
45  ostream = get (f, "__plot_stream__");
46  if (numel (ostream) < 1)
47    error ("ginput: stream to gnuplot not open");
48  elseif (ispc ())
49    if (numel (ostream) == 1)
50      error ("ginput: Need mkfifo that is not implemented under Windows");
51    endif
52    use_mkfifo = false;
53    istream = ostream(2);
54    ostream = ostream(1);
55  else
56    use_mkfifo = true;
57    ostream = ostream(1);
58  endif
59
60  if (nargin == 1)
61    x = zeros (100, 1);
62    y = zeros (100, 1);
63    button = zeros (100, 1);
64  else
65    x = zeros (n, 1);
66    y = zeros (n, 1);
67    button = zeros (n, 1);
68  endif
69
70  if (use_mkfifo)
71    gpin_name = tempname ();
72
73    [err, msg] = mkfifo (gpin_name, 600);
74
75    if (err)
76      error ("ginput: Can not open fifo (%s)", msg);
77    endif
78  endif
79
80  unwind_protect
81
82    k = 0;
83    while (true)
84      k += 1;
85
86      ## Notes: MOUSE_* can be undefined if user closes gnuplot by "q"
87      ## or Alt-F4.  Further, this abrupt close also requires the leading
88      ## "\n" on the next line.
89      if (use_mkfifo)
90        fprintf (ostream, ['set print "%s";' "\n"], gpin_name);
91        fflush (ostream);
92        [gpin, err] = fopen (gpin_name, "r");
93        if (err)
94          error ("ginput: Can not open FIFO (%s)", msg);
95        endif
96        fputs (ostream, "pause mouse any;\n\n");
97        fputs (ostream, ["\n" 'if (exists("MOUSE_KEY") && exists("MOUSE_X")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print "0 0 -1"' "\n"]);
98
99        ## Close output file, to force it to be flushed
100        fputs (ostream, "set print;\n");
101        fflush (ostream);
102
103        ## Now read from fifo.
104        [x(k), y(k), button(k), count] = fscanf (gpin, "%f %f %d", "C");
105        fclose (gpin);
106      else
107        fputs (ostream, ['set print "-";' "\n"]);
108        fflush (ostream);
109        fputs (ostream, "pause mouse any;\n\n");
110        fputs (ostream, ["\n" 'if (exists("MOUSE_KEY") && exists("MOUSE_X")) key = (MOUSE_KEY==1063 ? 1 : MOUSE_KEY); print "OCTAVE: ", MOUSE_X, MOUSE_Y, key; else print "0 0 -1"' "\n"]);
111
112        ## Close output file, to force it to be flushed
113        fputs (ostream, "set print;\n");
114        fflush (ostream);
115
116        str = {};
117        while (isempty (str))
118          str = fread (istream, "*char")';
119          if (isempty (str))
120            pause (0.05);
121          else
122            str = regexp (str, 'OCTAVE:\s+[-+.\d]+\s+[-+.\d]+\s+\d*', 'match');
123          endif
124          fclear (istream);
125        endwhile
126        [x(k), y(k), button(k), count] = ...
127          sscanf (str{end}(8:end), "%f %f %d", "C");
128      endif
129
130      if ([x(k), y(k), button(k)] == [0, 0, -1])
131        ## Mousing not active (no plot yet).
132        break;
133      endif
134
135      if (button(k) == 0x0D || button(k) == 0x0A)
136        ## Stop when hitting a RETURN or ENTER key.
137        x(k:end) = [];
138        y(k:end) = [];
139        button(k:end) = [];
140        break;
141      endif
142      if (nargin > 1 && k == n)
143        ## Input argument n was given, stop when k == n.
144        break;
145      endif
146
147    endwhile
148
149  unwind_protect_cleanup
150    if (use_mkfifo)
151      unlink (gpin_name);
152    endif
153  end_unwind_protect
154
155endfunction
156