## Copyright (C) 2012 pdiribarne
## 
## 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 Octave; see the file COPYING.  If not, see
## <http://www.gnu.org/licenses/>.

## hdlcmp (h1, h2) : compare the property fields of h1 and
## h2 (graphic object handles or structures struct.(PROP) = VAL)
## and returns a structure containing the following fields :
## - "nfields" : the number of fields in each object property structure (1x2 array),
## - "union": fields that are both in h1 and h2 (cell array),
## - "exclude2": fields that are in h1 not h2 (cell array),
## - "exclude1": fields that are in h2 not h1 (cell array),
## - "valdiff" : values that do not match among "union" fields (cell
## array of structs)
## Author: pdiribarne <pdiribarne@new-host.home>
## Created: 2012-03-27

function [strout ] = hdlcmp (h1, h2)
  if nargin !=2 && numel (h1) == 1 && numel (2) == 1
    error ("hdlcmp : expecting 2 scalar arguments")
  elseif (!ishandle (h1) && !isstruct (h1)) \
        || (!ishandle (h2) && !isstruct (h2))
    error ("hdlcmp : expecting either handle or struct arguments")
  endif

  s1 = h1;
  s2 = h2;
  if (ishandle (h1))
    s1 = get (h1);
  endif
  if (ishandle (h2))
    s2 = get (h2);
  endif

  tmp1 = sort (fieldnames (s1));
  tmp2 = sort (fieldnames (s2));
  union1 = cellfun (@(x) any(strcmp (x, tmp2)), tmp1);
  union2 = cellfun (@(x) any(strcmp (x, tmp1)), tmp2);
  
  ## nfields
  strout.nfields = [numel(tmp1), numel(tmp2)];

  ## union
  strout.union = tmp1 (find (union1));

  ## exclude2
  strout.exclude2 = tmp1 (find (union1 == 0));

  ## exclude1
  strout.exclude1 = tmp2 (find (union2 == 0));

  ## valdiff
  forget = {"deletefcn", "userdata"};
  strout.valdiff = {};
  nu = numel (strout.union);
  for ii = 1:nu    
    field = strout.union{ii};
    if (!gencmp (s1.(field), s2.(field))) &&\
          (!any (strcmp (field, forget)))
      strout.valdiff{1}.(field) = s1.(field);
      strout.valdiff{2}.(field) = s2.(field);
    endif
  endfor
endfunction


function [out] = gencmp (val1, val2)
  if  (numel (val1) != numel (val2))
    out = false;
  elseif (ishandle (val1) || ishandle (val2))
    ## omit handles
    out = true;
  elseif (isnumeric (val1) && isnumeric (val2) )
    out = all (val1 == val2);
  elseif (ischar (val1) && ischar (val2)  \
        || iscellstr (val1) && iscellstr (val2))
    out = all (strcmpi (val1, val2));
  else
    out = false;
  endif
endfunction
       
    