# HG changeset patch
# User Nicholas R. Jankowski <jankowskin@asme.org>
# Date 1588195679 14400
#      Wed Apr 29 17:27:59 2020 -0400
# Node ID 1508efb543f98824b5d044db538f62af44629ebe
# Parent  014e80a92d4fd2051e93f42dd56f10f509ce14b2
add datacursor function based on v3 file submission (patch #9280)

* adds to /draw/: /private/__datacursor__.m, /private/__datacursor_menu__.m
* edits in /draw/: /stairs.m, /private/__stem__.m, /private/__plt__.m

diff -r 014e80a92d4f -r 1508efb543f9 scripts/plot/draw/private/__datacursor__.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/private/__datacursor__.m	Wed Apr 29 17:27:59 2020 -0400
@@ -0,0 +1,119 @@
+## Copyright (C) 2017 Pantxo Diribarne
+## 
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+## 
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*- 
+## @deftypefn {} {@var{h} =} __datacursor__ ()
+## @deftypefnx {} {@var{h} =} __datacursor__ (@var{hax})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Pantxo Diribarne <pantxo@gre046552>
+## Created: 2017-02-10
+## Modified by R. Baudin, 2017-05-10
+
+function [htmp] = __datacursor__ (hf = [])
+  if (isempty (hf))
+    hf = get (0, "currentfigure")
+    if (isempty (hf))
+      error ("__datacursor__: no current figure")
+    endif
+  elseif (! ishandle (hf))
+    error ("__datacursor__: not a valid figure handle")
+  endif
+  
+  htmp = install_all_listeners (hf);
+endfunction
+
+function htmp = install_all_listeners (hf)
+    htmp = annotation (hf, "textarrow", [0 0], [eps eps], ...
+                       "headlength", 8, "headwidth", 8, "headstyle", "vback1", "fontsize", 14, ...
+                       "visible", "off");
+  install_listeners (hf, htmp);
+  cursors = getappdata (hf, "__datacursor__");
+  setappdata (hf, "__datacursor__", [cursors htmp]);
+endfunction
+
+function install_listeners (hf, htmp)
+  haxes = get (hf, "children");
+  haxes(! isaxes (haxes)) = [];
+  tag = get (haxes, "tag");
+  idx = strcmp (tag, "legend") | strcmp (tag, "colorbar") | ...
+        strcmp (tag, "scribeoverlay");
+  haxes(idx) = [];
+  for hax = haxes
+    dellistener (hax, "currentpoint")
+    
+    lsn = {@update_nearest, htmp};
+    addlistener (hax, "currentpoint", lsn)
+    addlistener (htmp, "beingdeleted", {@cleanlistener, hax, lsn})
+  endfor
+endfunction
+
+function cleanlistener (h, e, h2, lsn)
+  if (ishandle (h2))
+    dellistener (h2, "currentpoint", lsn);
+  endif
+endfunction
+
+function update_nearest (hax, e, ht)
+  hf = ancestor (hax, "figure");
+  if (getappdata (hf, "__datacursor__")(end) != ht)
+    return;
+  endif
+  hax = get (hf, "currentaxes");
+ 
+  set(0, "currentfigure", hf);
+  htype = get(gco(hf), "type");
+  
+  if (strcmp(htype, "line"))
+    xd = get (gco(hf), "xdata");
+    yd = get (gco(hf), "ydata");
+    if (iscell (xd))
+      xd = [xd{:}];
+      yd = [yd{:}];
+    endif
+    cp = get (hax, "currentpoint")(1,1:2);
+    if (! isempty (xd))
+      [~, idx] = min ((cp(1)-xd).^2 + (cp(2)-yd).^2);
+      [x, y] = axes2normalized (hax, xd(idx), yd(idx));
+      set (ht, "string", sprintf ("(%g, %g)", xd(idx), yd(idx)), ...
+           "x", [x+0.02 x], "y", [y+0.02 y],
+           "visible", "on", "userdata", [xd(idx) yd(idx)])
+    endif
+  endif
+endfunction
+
+function [x0, y0] = axes2normalized (hax, x, y)
+  xl = xlim (hax);
+  yl = ylim (hax);
+  
+  if (strcmp (get (hax, "xscale"), "log"))
+    xl = log10 (xl);
+    x0 = (log10(x) - xl(1)) / diff(xl);
+  else
+    x0 = (x - xl(1)) / diff(xl);
+  endif
+    
+  if (strcmp (get (hax, "yscale"), "log"))
+    yl = log10 (yl);
+    y0 = (log10(y) - yl(1)) / diff(yl);
+  else
+    y0 = (y - yl(1)) / diff(yl);
+  endif
+  
+  pos = get (hax, "position");
+  x0 = x0*pos(3) + pos(1);
+  y0 = y0*pos(4) + pos(2);
+endfunction
diff -r 014e80a92d4f -r 1508efb543f9 scripts/plot/draw/private/__datacursor_menu__.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/private/__datacursor_menu__.m	Wed Apr 29 17:27:59 2020 -0400
@@ -0,0 +1,72 @@
+## Copyright (C) 2017 Pantxo Diribarne
+## 
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+## 
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*- 
+## @deftypefn {} {@var{retval} =} __datacursor_menu__ ()
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Pantxo Diribarne <pantxo@gre046552>
+## Created: 2017-02-10
+## Modified by R. Baudin, 2017-05-10
+
+function hm = __datacursor_menu__ ()
+  
+  hf = get (0, "currentfigure");
+  
+  if (isempty (hf))
+    error ("__datacursor_menu__: no current figure");
+  endif
+  
+  # Don't add menu if custom property 'datamenu' already exist
+  if (isprop(hf, "datamenu") == 0)
+    addproperty("datamenu", hf, "boolean",true); # Add custom property 'datamenu'
+    hm = uimenu ("label", "&Data");
+    htmp = hm;  
+    htmp = uimenu (hm, "label", "New data cursor", "callback", {@update_new, htmp});
+    htmp = uimenu (hm, "label", "Show/hide data cursor(s)", "callback", @update_show);
+    htmp = uimenu (hm, "label", "Get cursor(s) data", "callback", @data_dlg);
+  endif
+
+endfunction
+
+function update_new (hmenu, e, hshow)
+  __datacursor__ (gcbf);
+  update_show (hshow, [], true);
+endfunction
+      
+function update_show (hmenu, e, on = [])
+  hc = getappdata (gcbf, "__datacursor__");
+  if (! isempty (hc))
+    if (isempty (on))
+      on = ifelse (all (strcmp (get (hc, "visible"), "on")), "off", "on");
+    endif
+    set (hc, "visible", on)
+    set (hmenu, "checked", on)
+  endif
+endfunction
+
+function data_dlg (hm, e)
+  pos = get (gcbf, "position");
+  hc = getappdata (gcbf, "__datacursor__");
+  nm = inputdlg ({"Name of the variable:"}, "Export data", 1, {"cursor_data"});
+  if (! isempty (nm))
+    for ii = 1:numel (hc)
+      xy = get (hc(ii), "userdata");
+      evalin ("base", sprintf ("%s.('%s') = [%16.16f; %16.16f];", ...
+                               nm{1}, ["cursor" num2str(ii)], xy(1), xy(2)));
+    endfor
+  endif
+endfunction
diff -r 014e80a92d4f -r 1508efb543f9 scripts/plot/draw/private/__plt__.m
--- a/scripts/plot/draw/private/__plt__.m	Tue Apr 28 16:24:10 2020 -0700
+++ b/scripts/plot/draw/private/__plt__.m	Wed Apr 29 17:27:59 2020 -0400
@@ -1,34 +1,29 @@
-########################################################################
-##
-## Copyright (C) 1993-2020 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
+## Copyright (C) 1993-2017 John W. Eaton
 ##
 ## This file is part of Octave.
 ##
-## Octave is free software: you can redistribute it and/or modify it
+## Octave is free software; you can redistribute it and/or modify it
 ## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
 ##
 ## Octave is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-##
-########################################################################
+## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} __plt__ (@var{caller}, @var{hparent}, @var{varargin})
+## @deftypefn {} {} __plt__ (@var{caller}, @var{h}, @var{varargin})
 ## Undocumented internal function.
 ## @end deftypefn
 
-function retval = __plt__ (caller, hp, varargin)
+## Author: jwe
+
+function retval = __plt__ (caller, h, varargin)
 
   persistent warned_callers = {};
   nargs = nargin - 2;
@@ -42,12 +37,18 @@
     property_set = false;
     properties = {};
 
-    ## Find any legend associated with this axes
-    try
-      hlegend = get (hp, "__legend_handle__");
-    catch
-      hlegend = [];
-    end_try_catch
+    hlegend = [];
+    fkids = get (gcf (), "children");
+    for i = 1 : numel (fkids)
+      if (   strcmp (get (fkids(i), "type"), "axes")
+          && strcmp (get (fkids(i), "tag"), "legend"))
+        udata = get (fkids(i), "userdata");
+        if (! isempty (intersect (udata.handle, gca ())))
+          hlegend = fkids(i);
+          break;
+        endif
+      endif
+    endfor
 
     setlgnd = false;
     if (isempty (hlegend))
@@ -109,17 +110,17 @@
             endwhile
           endif
           if (y_set)
-            htmp = __plt2__ (hp, x, y, options, properties);
+            tmp = __plt2__ (h, x, y, options, properties);
             [hlgnd, tlgnd, setlgnd] = ...
-              __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
+              __plt_key__ (tmp, options, hlgnd, tlgnd, setlgnd);
             properties = {};
-            retval = [retval; htmp];
+            retval = [retval; tmp];
           else
-            htmp = __plt1__ (hp, x, options, properties);
+            tmp = __plt1__ (h, x, options, properties);
             [hlgnd, tlgnd, setlgnd] = ...
-               __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
+               __plt_key__ (tmp, options, hlgnd, tlgnd, setlgnd);
             properties = {};
-            retval = [retval; htmp];
+            retval = [retval; tmp];
           endif
           x_set = false;
           y_set = false;
@@ -129,10 +130,10 @@
       elseif (x_set)
         if (y_set)
           options = __pltopt__ (caller, {""});
-          htmp = __plt2__ (hp, x, y, options, properties);
+          tmp = __plt2__ (h, x, y, options, properties);
           [hlgnd, tlgnd, setlgnd] = ...
-            __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
-          retval = [retval; htmp];
+            __plt_key__ (tmp, options, hlgnd, tlgnd, setlgnd);
+          retval = [retval; tmp];
           x = next_arg;
           y_set = false;
           properties = {};
@@ -154,11 +155,13 @@
     error ("__plt__: invalid number of arguments");
   endif
 
+  __datacursor_menu__;
+  
 endfunction
 
-function [hlgnd, tlgnd, setlgnd] = __plt_key__ (hp, options,
+function [hlgnd, tlgnd, setlgnd] = __plt_key__ (h, options,
                                                 hlgnd, tlgnd, setlgnd)
-  n = numel (hp);
+  n = numel (h);
   if (numel (options) == 1)
     options = repmat (options(:), n, 1);
   endif
@@ -166,7 +169,7 @@
   for i = 1 : n
     key = options(i).key;
     if (! isempty (key))
-      hlgnd = [hlgnd(:); hp(i)];
+      hlgnd = [hlgnd(:); h(i)];
       tlgnd = {tlgnd{:}, key};
       setlgnd = true;
     endif
@@ -174,7 +177,7 @@
 
 endfunction
 
-function retval = __plt1__ (hp, x1, options, properties = {})
+function retval = __plt1__ (h, x1, options, properties = {})
 
   if (nargin < 3 || isempty (options))
     options = __default_plot_options__ ();
@@ -203,11 +206,11 @@
     x1 = (1:nr)';
   endif
 
-  retval = __plt2__ (hp, x1, x2, options, properties);
+  retval = __plt2__ (h, x1, x2, options, properties);
 
 endfunction
 
-function retval = __plt2__ (hp, x1, x2, options, properties = {})
+function retval = __plt2__ (h, x1, x2, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -234,27 +237,27 @@
     retval = zeros (0, 1);
   elseif (isscalar (x1))
     if (isscalar (x2))
-      retval = __plt2ss__ (hp, x1, x2, options, properties);
+      retval = __plt2ss__ (h, x1, x2, options, properties);
     elseif (isvector (x2))
-      retval = __plt2sv__ (hp, x1, x2, options, properties);
+      retval = __plt2sv__ (h, x1, x2, options, properties);
     else
       error ("__plt2__: invalid data for plotting");
     endif
   elseif (isvector (x1))
     if (isscalar (x2))
-      retval = __plt2vs__ (hp, x1, x2, options, properties);
+      retval = __plt2vs__ (h, x1, x2, options, properties);
     elseif (isvector (x2))
-      retval = __plt2vv__ (hp, x1, x2, options, properties);
+      retval = __plt2vv__ (h, x1, x2, options, properties);
     elseif (ismatrix (x2))
-      retval = __plt2vm__ (hp, x1, x2, options, properties);
+      retval = __plt2vm__ (h, x1, x2, options, properties);
     else
       error ("__plt2__: invalid data for plotting");
     endif
   elseif (ismatrix (x1))
     if (isvector (x2))
-      retval = __plt2mv__ (hp, x1, x2, options, properties);
+      retval = __plt2mv__ (h, x1, x2, options, properties);
     elseif (ismatrix (x2))
-      retval = __plt2mm__ (hp, x1, x2, options, properties);
+      retval = __plt2mm__ (h, x1, x2, options, properties);
     else
       error ("__plt2__: invalid data for plotting");
     endif
@@ -264,7 +267,7 @@
 
 endfunction
 
-function retval = __plt2mm__ (hp, x, y, options, properties = {})
+function retval = __plt2mm__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -292,14 +295,14 @@
       color = __next_line_color__ ();
     endif
 
-    retval(i) = __go_line__ (hp, "xdata", x(:,i), "ydata", y(:,i),
-                             "color", color, "linestyle", linestyle,
-                             "marker", marker, properties{:});
+    retval(i) = line (x(:,i), y(:,i), "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   endfor
 
 endfunction
 
-function retval = __plt2mv__ (hp, x, y, options, properties = {})
+function retval = __plt2mv__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -333,14 +336,14 @@
       color = __next_line_color__ ();
     endif
 
-    retval(i) = __go_line__ (hp, "xdata", x(:,i), "ydata", y,
-                             "color", color, "linestyle", linestyle,
-                             "marker", marker, properties{:});
+    retval(i) = line (x(:,i), y, "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   endfor
 
 endfunction
 
-function retval = __plt2ss__ (hp, x, y, options, properties = {})
+function retval = __plt2ss__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -362,12 +365,13 @@
     color = __next_line_color__ ();
   endif
 
-  retval = __go_line__ (hp, "xdata", x, "ydata", y,
-                        "color", color, "linestyle", linestyle,
-                        "marker", marker, properties{:});
+  retval = line (x, y, "color", color,
+                 "linestyle", linestyle,
+                 "marker", marker, properties{:});
+
 endfunction
 
-function retval = __plt2sv__ (hp, x, y, options, properties = {})
+function retval = __plt2sv__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -391,14 +395,14 @@
       color = __next_line_color__ ();
     endif
 
-    retval(i) = __go_line__ (hp, "xdata", x, "ydata", y(i),
-                             "color", color, "linestyle", linestyle,
-                             "marker", marker, properties{:});
+    retval(i) = line (x, y(i), "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   endfor
 
 endfunction
 
-function retval = __plt2vm__ (hp, x, y, options, properties = {})
+function retval = __plt2vm__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -432,14 +436,14 @@
       color = __next_line_color__ ();
     endif
 
-    retval(i) = __go_line__ (hp, "xdata", x, "ydata", y(:,i),
-                             "color", color, "linestyle", linestyle,
-                             "marker", marker, properties{:});
+    retval(i) = line (x, y(:,i), "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   endfor
 
 endfunction
 
-function retval = __plt2vs__ (hp, x, y, options, properties = {})
+function retval = __plt2vs__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -463,14 +467,14 @@
       color = __next_line_color__ ();
     endif
 
-    retval(i) = __go_line__ (hp, "xdata", x(i), "ydata", y,
-                             "color", color, "linestyle", linestyle,
-                             "marker", marker, properties{:});
+    retval(i) = line (x(i), y, "color", color,
+                      "linestyle", linestyle,
+                      "marker", marker, properties{:});
   endfor
 
 endfunction
 
-function retval = __plt2vv__ (hp, x, y, options, properties = {})
+function retval = __plt2vv__ (h, x, y, options, properties = {})
 
   if (nargin < 4 || isempty (options))
     options = __default_plot_options__ ();
@@ -497,8 +501,8 @@
     color = __next_line_color__ ();
   endif
 
-  retval = __go_line__ (hp, "xdata", x, "ydata", y,
-                        "color", color, "linestyle", linestyle,
-                        "marker", marker, properties{:});
+  retval = line (x, y, "color", color,
+                 "linestyle", linestyle,
+                 "marker", marker, properties{:});
 
 endfunction
diff -r 014e80a92d4f -r 1508efb543f9 scripts/plot/draw/private/__stem__.m
--- a/scripts/plot/draw/private/__stem__.m	Tue Apr 28 16:24:10 2020 -0700
+++ b/scripts/plot/draw/private/__stem__.m	Wed Apr 29 17:27:59 2020 -0400
@@ -1,33 +1,29 @@
-########################################################################
-##
-## Copyright (C) 2006-2020 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
+## Copyright (C) 2006-2017 Michel D. Schmid
 ##
 ## This file is part of Octave.
 ##
-## Octave is free software: you can redistribute it and/or modify it
+## Octave is free software; you can redistribute it and/or modify it
 ## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
 ##
 ## Octave is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-##
-########################################################################
+## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
 ## @deftypefn {} {@var{h} =} __stem__ (@var{have_z}, @var{varargin})
 ## Undocumented internal function.
 ## @end deftypefn
 
+## Author: Michel D. Schmid <michaelschmid@users.sourceforge.net>
+## Adapted-by: jwe
+
 function h = __stem__ (have_z, varargin)
 
   if (have_z)
@@ -88,7 +84,7 @@
       endif
 
       ## Must occur after __next_line_color__ in order to work correctly.
-      hg = hggroup ("__appdata__", struct ("__creator__", "__stem__"));
+      hg = hggroup ();
       h = [h; hg];
       args = __add_datasource__ (caller, hg, {"x", "y", "z"}, varargin{:});
 
@@ -103,9 +99,7 @@
 
         x_axis_range = get (hax, "xlim");
         if (isempty (h_baseline))
-          h_baseline = __go_line__ (hax, "xdata", x_axis_range,
-                                         "ydata", [0, 0],
-                                         "color", [0, 0, 0]);
+          h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]);
           set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
           addproperty ("basevalue", h_baseline, "data", 0);
         else
@@ -159,10 +153,7 @@
 
     ## baseline listeners
     if (! isempty (h_baseline))
-      fcn_handle = @update_xlim;
-      addlistener (hax, "xlim", fcn_handle);
-      set (h_baseline, "deletefcn", {@rm_xlim_listener, hax, fcn_handle});
-
+      addlistener (hax, "xlim", @update_xlim);
       for hg = h'
         addlistener (hg, "showbaseline", @show_baseline);
         addlistener (hg, "visible", {@show_baseline, h});
@@ -180,13 +171,9 @@
         set (h, args{:});
     endif
 
-    if (! strcmp (hold_state, "add"))
-      if (! have_z)
-        set (hax, "box", "on");
-      else
-        set (hax, "view", [-37.5 30],
-                  "xgrid", "on", "ygrid", "on", "zgrid", "on");
-      endif
+    if (! strcmp (hold_state, "add") && have_z)
+      set (hax, "view", [-37.5 30],
+                "xgrid", "on", "ygrid", "on", "zgrid", "on");
     endif
     set (hax, "nextplot", hold_state);
 
@@ -196,6 +183,8 @@
     endif
   end_unwind_protect
 
+  __datacursor_menu__;
+
 endfunction
 
 function [x, y, z, dofill, lc, ls, mc, ms, args] = check_stem_arg (have_z, varargin)
@@ -378,12 +367,6 @@
 
 endfunction
 
-## Good practice to remove listeners when object is deleted.
-## In this case, required to avoid error in update_xlim callback (bug #57391).
-function rm_xlim_listener (~, ~, hax, fcn_handle)
-  dellistener (hax, "xlim", fcn_handle);
-endfunction
-
 function update_baseline (h, ~, src)
 
   visible = get (h, "visible");
@@ -429,7 +412,8 @@
   b0 = get (h, "basevalue");
   bl = get (h, "baseline");
 
-  set (bl, "ydata", [b0, b0], "basevalue", b0);
+  set (bl, "ydata", [b0, b0]);
+  set (bl, "basevalue", b0);
 
   kids = get (h, "children");
   yt = get (h, "ydata")(:)';
@@ -463,7 +447,7 @@
     x = x(1:sz(1),1:sz(2));
     y = y(1:sz(1),1:sz(2));
     z = z(1:sz(1),1:sz(2));
-  elseif (numel (x) != numel (y))
+  elseif (numel (x) != numel (y));
     sz = min ([size(x); size(y)]);
     x = x(1:sz(1),1:sz(2));
     y = y(1:sz(1),1:sz(2));
diff -r 014e80a92d4f -r 1508efb543f9 scripts/plot/draw/stairs.m
--- a/scripts/plot/draw/stairs.m	Tue Apr 28 16:24:10 2020 -0700
+++ b/scripts/plot/draw/stairs.m	Wed Apr 29 17:27:59 2020 -0400
@@ -1,27 +1,20 @@
-########################################################################
-##
-## Copyright (C) 1993-2020 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
+## Copyright (C) 1993-2017 John W. Eaton
 ##
 ## This file is part of Octave.
 ##
-## Octave is free software: you can redistribute it and/or modify it
+## Octave is free software; you can redistribute it and/or modify it
 ## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
 ##
 ## Octave is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-##
-########################################################################
+## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {} stairs (@var{y})
@@ -35,8 +28,7 @@
 ##
 ## The arguments @var{x} and @var{y} may be vectors or matrices.
 ## If only one argument is given, it is taken as a vector of Y values
-## and the X coordinates are taken to be the indices of the elements
-## (@code{@var{x} = 1:numel (@var{y})}).
+## and the X coordinates are taken to be the indices of the elements.
 ##
 ## The style to use for the plot can be defined with a line style @var{style}
 ## of the same format as the @code{plot} command.
@@ -44,8 +36,8 @@
 ## Multiple property/value pairs may be specified, but they must appear in
 ## pairs.
 ##
-## If the first argument @var{hax} is an axes handle, then plot into this axes,
-## rather than the current axes returned by @code{gca}.
+## If the first argument @var{hax} is an axis handle, then plot into this axis,
+## rather than the current axis handle returned by @code{gca}.
 ##
 ## If one output argument is requested, return a graphics handle to the
 ## created plot.  If two output arguments are specified, the data are generated
@@ -70,6 +62,8 @@
 ## @seealso{bar, hist, plot, stem}
 ## @end deftypefn
 
+## Author: jwe
+
 function [xs, ys] = stairs (varargin)
 
   [hax, varargin, nargin] = __plt_get_axis_arg__ ("stairs", varargin{:});
@@ -245,6 +239,8 @@
     h = 0;
   endif
 
+  __datacursor_menu__;
+
 endfunction
 
 function update_props (h, ~)
