function  [out_regs] = zinput(arg1)
% ZINPUT - Graphical input from mouse with zoom
%   
%   [OUT_REGS] = ZINPUT(N) gets N points or regions from the
%   current axes and returns the X- and Y-ranges in a length Nx4
%   matrix OUT_REGS. 
%   The cursor can be positioned using a mouse. Data points are entered by
%   pressing the right mouse button, the region of the current axis
%   are selected with the middle button, left button is for
%   zooming,  single cklick zooms in, click-and drag zooms to
%   region (and doubble-click should zoom out - feature pending).
%   Any key on the keyboard except carriage return zooms out to the
%   orignal axis except carriage return, which terminates the input
%   before N points are entered.
%   
%   [OUT_REGS] = ZINPUT gathers an unlimited number of points until the
%   return key is pressed.
%   
%   Usage:
%      [out_regs] = zinput(arg1)
%
%   See also GINPUT

% Copyright Bjorn Gustavsson 20050314

ax0 = axis;
out_regs = [];
c = computer;
if ~strcmp(c(1:2),'PC') 
  tp = get(0,'TerminalProtocol');
else
  tp = 'micro';
end

if ~strcmp(tp,'none') & ~strcmp(tp,'x') & ~strcmp(tp,'micro') & 0,
  % I dont know about this so better make short-cut and blindly try
  % what works for X in all environments - sorry about that.
else
  
  fig = gcf;
  figure(gcf);
  
  if nargin == 0
    how_many = inf;
    b = [];
  else
    how_many = arg1;
    b = [];
    if  isstr(how_many) ...
          | size(how_many,1) ~= 1 | size(how_many,2) ~= 1 ...
          | ~(fix(how_many) == how_many) ...
          | how_many < 0
      error('Requires a positive integer.');
    end
    if how_many == 0
      ptr_fig = 0;
      while(ptr_fig ~= fig)
        ptr_fig = get(0,'PointerWindow');
      end
      scrn_pt = get(0,'PointerLocation');
      loc = get(fig,'Position');
      pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)];
      out1 = pt(1); y = pt(2);
    elseif how_many < 0
      error('Argument must be a positive integer.');
    end
  end
  
  % Remove figure button functions
  state = uisuspend(fig);
  pointer = get(gcf,'pointer');
  set(gcf,'pointer','fullcrosshair');
  
  fig_units = get(fig,'units');
  char = 0;
  while  size(out_regs,1) < how_many
    % Use no-side effect WAITFORBUTTONPRESS
    waserr = 0;
    try
      keydown = wfbp;
    catch
      waserr = 1;
    end
    if(waserr == 1)
      if(ishandle(fig))
        set(fig,'units',fig_units);
        uirestore(state);
        error('Interrupted');
      else
        error('Interrupted by figure deletion');
      end
    end
    
    ptr_fig = get(0,'CurrentFigure');
    if(ptr_fig == fig)
      if keydown
        axis(ax0);
        char = get(fig, 'CurrentCharacter');
      else
        char = get(fig, 'CurrentCharacter');
        button = abs(get(fig, 'CurrentCharacter'));
        
        pnt = get(gcf,'currentpoint');
        xy1 = get(gca,'currentpoint');
        rbbox([pnt 0 0],pnt)
        xy2 = get(gca,'currentpoint');
        selection_type = get(gcf,'selectiontype');
        
        if all(xy1==xy2)
          ax1 = axis;
          
          dx = abs(ax1(2)-ax1(1));
          dy = abs(ax1(4)-ax1(3));
          
          xmin = max(ax1(1),xy1(1)-dx/4);
          xmax = min(ax1(2),xy1(1)+dx/4);
          ymin = max(ax1(3),xy1(1,2)-dy/4);
          ymax = min(ax1(4),xy1(1,2)+dy/4);
          zoom2ax = [xmin xmax ymin ymax];
        else
          %%% zoom to selected rectangle
          zoom2ax = [sort([xy1(1,1) xy2(1,1)]) sort([xy1(1,2) xy2(1,2)])];
        end
        
        switch selection_type
         case 'normal'
          axis(zoom2ax)
          reg = [];
         case 'alt'
          reg = axis;
          axis(ax0)
         case 'extend'
          reg = xy1(1,[1 1 2 2]);
          axis(ax0)
         otherwise %%% open (doubleclick in linux)
          axis(ax0);
          reg = [];
        end
      end
      pt = get(gca, 'CurrentPoint');
      
      if (char == 'r')
        rmi = size(out_regs,1);
        if rmi > 0
          out_regs(rmi,:) = [];
        end
        set(fig, 'CurrentCharacter','q')
        char = 'q';
        reg = [];
      end
      if(char == 13) % & how_many ~= 0)
                     % if the return key was pressed, char will == 13,
                     % and that's our signal to break out of here whether
                     % or not we have collected all the requested data
                     % points.  
                     % If this was an early breakout, don't include
                     % the <Return> key info in the return arrays.
                     % We will no longer count it if it's the last input.
        break;
      end
      
      if ~isempty(reg)
        out_regs = [out_regs;reg];
      end
    end
    %[size(out_regs,1), how_many, size(out_regs,1) < how_many]
  end
  
  uirestore(state);
  set(gcf,'pointer','arrow');
  set(fig,'units',fig_units);
  set(fig, 'CurrentCharacter','q');
  
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function key = wfbp
%WFBP   Replacement for WAITFORBUTTONPRESS that has no side effects.

fig = gcf;
current_char = [];

% Now wait for that buttonpress, and check for error conditions
waserr = 0;
try
  h=findall(fig,'type','uimenu','accel','C');   % Disabling ^C for edit menu so the only ^C is for
  set(h,'accel','');                            % interrupting the function.
  keydown = waitforbuttonpress;
  current_char = double(get(fig,'CurrentCharacter')); % Capturing the character.
  if~isempty(current_char) & (keydown == 1)           % If the character was generated by the 
    if(current_char == 3)                       % current keypress AND is ^C, set 'waserr'to 1
      waserr = 1;                             % so that it errors out. 
    end
  end
  
  set(h,'accel','C');                                 % Set back the accelerator for edit menu.
catch
  waserr = 1;
end
drawnow;
if(waserr == 1)
  set(h,'accel','C');                                % Set back the accelerator if it errored out.
  error('Interrupted');
end

selection_type = get(gcf,'selectiontype');
if strcmp(selection_type,'open')
  axis(ax0)
end
if nargout>0, key = keydown; end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
