function [h, old_props] = hgload(filename, varargin)
% HGLOAD  Loads Handle Graphics object from a file
%
% H = HGLOAD('filename') loads handle graphics objects from the .fig
% file specified by 'filename,' and returns handles to the top-level
% objects. If 'filename' contains no extension, then the extension
% '.fig' is added.
%
% [H, OLD_PROPS] = HGLOAD(..., PROPERTIES) overrides the properties on
% the top-level objects stored in the .fig file with the values in
% PROPERTIES, and returns their previous values.  PROPERTIES must be a
% structure whose field names are property names, containing the
% desired property values.  OLD_PROPS are returned as a cell array the
% same length as H, containing the previous values of the overridden
% properties on each object.  Each cell contains a structure whose
% field names are property names, containing the original value of
% each property for that top-level object. Any property specified in
% PROPERTIES but not present on a top-level object in the file is
% not included in the returned structure of original values.
%
% HGLOAD(..., 'all') overrides the default behavior of excluding
% non-serializable objects saved in the file from being reloaded.
% Items such as the default toolbars and default menus are marked as
% non-serializable, and even if contained in the FIG-file, are
% normally not reloaded, because they are loaded from separate files
% at figure creation time.  This allows for revisioning of the default
% menus and toolbars without affecting existing FIG-files. Passing
% 'all' to HGLOAD insures that any non-serialzable objects contained
% in the file are also reloaded. The default behavior of HGSAVE is to
% exclude non-serializable objects from the file at save time, and
% that can be overridden using the 'all' flag with HGSAVE.
%
% See also HGSAVE HANDLE2STRUCT STRUCT2HANDLE.
%

%   Copyright 1984-2000 The MathWorks, Inc. 
%   $Revision: 1.20 $  $Date: 2000/06/08 21:50:07 $
%   D. Foti  11/10/97

if isempty(find(filename == '.'))
  filename = [filename '.fig'];
end

fileVars = load(filename,'-mat');
if isempty(fieldnames(fileVars));
  try
    % Try just loading if -mat switch fails
    fileVars = load(filename);
  end
end
varNames = fieldnames(fileVars);
index = strmatch('hgS', varNames);
if length(index) ~= 1
  error('invalid Figure file format');
end

varName = varNames{index};
versionStr = varName(find(varName == '_')+1:end);
versionNum = str2double(versionStr);

if versionNum > 50200
  fileVersion = sprintf('%d.%d.%d', str2double(versionStr(1:2)), ...
      str2double(versionStr(3:4)), str2double(versionStr(5:6)));
  warning(['Figure file created with a newer version (' fileVersion ')  of MATLAB']);
end

hgS = getfield(fileVars, varNames{index});

numHandles = prod(size(hgS));
parent = zeros(numHandles, 1);
for i = 1:numHandles
  switch(hgS(i).type) 
    case 'root'
      parent = 0;
    case 'figure' 
      parent(i) = 0;
    case {'axes' 'uimenu' 'uicontextmenu' 'uicontrol' 'uitoolbar'}
      parent(i) = gcf;
    case {'uipushtool' 'uitoggletool'}
      parent(i) = gctb;
    otherwise
      parent(i) = gca;
  end
end

flags = {'convert'};
for iv = 1:length(varargin)
  if ischar(varargin{iv})
    flags{end+1} = varargin{iv};
  elseif isstruct(varargin{iv})
    % replace property values on all objects, and return any prior values
    new_prop_struct = varargin{iv};
    new_prop_names = fieldnames(new_prop_struct);
    for ih = 1:numHandles
      prev_vals = [];
      for inp = 1:length(new_prop_names)
	this_prop = new_prop_names{inp};
	if isfield(hgS(ih).properties,this_prop)
	  prev_vals = setfield(prev_vals,...
          this_prop, ...
          getfield(hgS(ih).properties, this_prop));
	end
	hgS(ih).properties = setfield(hgS(ih).properties,...
				      this_prop, ...
				      getfield(new_prop_struct, this_prop))
      end
      if nargout > 1
	old_props{ih} = prev_vals;
      end
    end
      
  else
    error('optional input arguments must be strings or structs');
  end
end

h = struct2handle(hgS, parent, flags{:});

% If we loaded only one top-level object, and it was a figure,
% remember the name of the file from which it was loaded (including
% full path and extension) so the Save option from the File menu
% can overwrite it without having to prompt for a file name.
if (numHandles == 1) & strcmp(get(h,'type'),'figure')
  try
    fullpath = which(filename);
    if isempty(fullpath)
      fullpath = filename;
    end
  catch
    fullpath = filename;
  end    
  set(h,'FileName',fullpath);
end

function tb = gctb
% find the first uitoolbar in the current figure, creating one if
% necessary

tb = findobj(gcf,'type','uitoolbar');
if ~isempty(tb)
  tb = tb(1);
else
  tb = uitoolbar;
end
