function [pos,unit]=getpos(h,fmt,href,opt)
% GETPOS Get graphics object position in a flexible way.
%   GETPOS(H,FMT) gets the position property of graphics object 
%   with handle H, according to FMT that can be expressed using different
%   units. H must have a "Position" property.
%
%   FMT is a char array containing four "%2c" strings separated by colon or
%   space. The two characters specify the unit as :
%
%           px  for Pixels
%           nz  for Normalized
%           in  for Inches
%           cm  for Centimeters
%           pt  for Points
%           ch  for Characters
%
%   If FMT is only one format string from the above list, all returned values are
%   expressed using this unit.
%
%   Any string value of FMT can be replaced by a single '#' to not retrieve the
%   corresponding value. The returned value is NaN except if the optional last 
%   argument OPT is set to "compact" in GETPOS(H,FMT,[HREF],OPT).
%
%   Note that GETPOS(H) works as get(H,'Position') and return the position 
%   vector in the current unit of the graphics object H.
%
%   GETPOS(H,FMT,HREF,['compact']) gets the position of the graphics object H according 
%   to FMT, but using the position of the graphics object HREF as reference instead 
%   of the parent of H. HREF must be a valid handle and must have a "Position" 
%   property (except for the Root object). Returned values may be negative or 0.
%
%   [POS,UNIT]=GETPOS(H,...) returns an additional output argument UNIT that 
%   contained the unit list of the output vector position POS. It may be safer 
%   when different units are used.
% 
%   See also SETPOS, SET, GET.

%   Author: Jérôme Briot, Matlab 6.1.0.450 (R12.1)
%   Contact: dutmatlab@yahoo.fr
%   Revision: 1.0 (12-Feb-2007)
%             1.1 (14-Feb-2007) Third input argument HREF added.
%                               Minor corrections in the help section.
%             1.2 (21-Feb-2007) Bug fixed if HREF is the Root object
%                               Examples removed from the help section
%   Comments:
%

% Check the number of input arguments
error(nargchk(1,4, nargin));

% Check if H is a graphics object handle
if ~ishandle(h)
    error('First argument must be a graphic object handle');
end

% Store the current unit of the graphics object H
current_unit=get(h,'units');

% Init variables
unit={current_unit current_unit current_unit current_unit};
pos=[nan nan nan nan];

% If FMT input argument is not specified, works as GET(H,'Position')
if nargin==1
    pos=get(h,'position');
    return
end

% Check if FMT is a char string
if ~ischar(fmt)
	error('Second argument must be a string in GETPOS(H,FMT)')
end  

if nargin==2 % GETPOS(H,FMT)
    
    href=get(h,'parent');
    opt='full';
    
elseif nargin==3
    
    if ishandle(href) % GETPOS(H,FMT,HREF)
        
        opt='full';
        
    elseif strcmpi(href,'compact') % GETPOS(H,FMT,"compact")
        
        href=get(h,'parent');
        opt='compact';
        
    else % GETPOS(H,FMT,???)
        error('Wrong third argument in GETPOS(H,FMT,???). Must be a valid handle or "compact"');
        
    end
    
elseif nargin==4 % GETPOS(H,FMT,HREF,OPT)
    
    if ~ishandle(href) 
        error('Third argument must be a valid handle in GETPOS(H,FMT,HREF,OPT)');
    end
        
    if ~strcmpi(opt,'compact') 
        error('Last argument must be "compact" in GETPOS(H,FMT,HREF,OPT)'); 
    end
    
end

flag_href=0;
% Don't use HREF position if it is the parent of H        
if href~=get(h,'parent')
    href=h;
    flag_href=1;
end

% Store the current unit of the reference object HREF
current_ref_unit=get(href,'units');

% Extract 4 char strings from FMT
M=strread(fmt,'%s','delimiter',' ,');

% Only one FMT requested for output
if numel(M)==1
    [M{2:4}]=deal(M{1});    
end

% List available units
available_units={'inches' 'centimeters' 'normalized' 'points' 'pixels' 'characters'};

% Decode elements of FMT
for n=1:numel(M) 
    
    % If FMT(n) is not a "#"
    if ~strcmp(M{n},'#')
        
        % Check if the units paramter is valid
        idx=strcmpi(M{n},{'in' 'cm' 'nz' 'pt' 'px' 'ch'});
        
        if ~any(idx)
            error('Units must be one of "in", "cm", "nz", "pt", "px" or "ch"')
        end
        
        unit{n}=available_units{idx}; % Set the units to one from the list 
            
    end
    
end

% Get position of H using decoded FMT 
for n=1:numel(M)    

    % If FMT(n) is not a "#" => get the value
    if ~strcmp(M{n},'#')
       
        % Modify the "Units" property of H 
        set(h,'units',unit{n});
        % Modify the "Units" property of HREF
        set(href,'units',unit{n});
        % Get the current "Position" vector of H
        temp=get(h,'position');
        % Get the current "Position" vector of HREF
        if strcmp(get(href, 'type'), 'root') % HREF is the Root object (no 'Position' property)
            temp_href=get(href,'screensize'); %%% Should be safe here !
        else temp_href=get(href,'position');
        end
        % Get and store the specified field from the "Position" vector
        % If HREF is specified and is not the parent of H, flag_href=1 else flag_href=0
        pos(n)=temp(n)-temp_href(n)*flag_href;
        
    end
    
end

% Check for compact output format 
if strcmpi(opt,'compact')
    pos(isnan(pos))=[];
end

% Restore the unit of the graphics object H
set(h,'units',current_unit);
% Restore the unit of the reference object HREF
set(href,'units',current_ref_unit);