function Obj = subsasgn(Obj, Struct, Value)
%SUBSASGN Assign into serial port objects.
%
%    Supported syntax for serial port objects:
%
%    Dot Notation:                  Equivalent Set Notation:
%    =============                  ========================
%    obj.Tag='sydney';              set(obj, 'Tag', 'sydney');
%    obj(1).Tag='sydney';           set(get(obj,1), 'Tag', 'sydney');
%    obj(1:4).Tag='sydney';         set(get(obj,[1:4]), 'Tag', 'sydney');
%    obj(1)=obj(2);               
%    obj(2)=[];
%
%    See also SERIAL/SET.
%

%    MP 7-13-99
%    Copyright 1999-2000 The MathWorks, Inc. 
%    $Revision: 1.3 $  $Date: 2000/07/19 12:47:33 $

% Initialize variables.
prop1 = '';
index1 = {};
StructL = length(Struct);

% Define possible error messages
error1 = 'Inconsistently placed ''()'' in subscript expression.';
error2 = 'Cell contents reference from a non-cell array object.';
error3 = 'Inconsistently placed ''.'' in subscript expression.';

if isempty(Obj)
   % Ex. s(1) = serial('COM1');
   if isequal(Struct.type, '()') & isequal(Struct.subs{1}, 1:length(Value))
      Obj = Value;
      return;
   elseif length(Value) ~= length(Struct.subs{1})
      % Ex. s(1:2) = serial('COM1');
      error(['In an assignment A(I)=B, the number of elements',...
            ' in B and I must be the same.']);
   elseif Struct.subs{1}(1) <= 0
      error(['Index into matrix is negative or zero.',...
              '  See release notes on changes to ',sprintf('\n'),...
              'logical indices.']);
   else
      % Ex. s(2) = serial('COM1'); where s is originally empty.
      error('Gaps are not allowed in instrument array indexing.');
   end
end


% Parse the input.

% The first Struct can either be:
% obj(1) = obj(2); 
% obj.BaudRate = 9600;
switch Struct(1).type
case '.'
   prop1 = Struct(1).subs;
case '()'
   index1 = Struct(1).subs;
   if strcmp(index1, ':')
       index1 = [1:length(Obj)];
   end
case '{}'
   error(error2);
otherwise
   error(['Unknown type: ' Struct(1).type,'.']);
end

if StructL > 1
   % Ex. obj(1).BytesAvailableAction = 'myaction';
   switch Struct(2).type
   case '.'
      if isempty(index1)
         % Ex. obj.BytesAvailable.Prop2 = 5
         error(error3);
      else
         % Ex. obj(1).BytesAvailableAction = 'myaction';
         prop1 = Struct(2).subs;
      end
   case '()'
      error(error1);   
   case '{}'
      error(error2);
   otherwise
      error(['Unknown type: ' Struct(2).type,'.']);
   end  
end   

% Index1 will be entire object if not specified.
if isempty(index1)
   index1 = 1:length(Obj);
end

% Convert index1 to a cell if necessary.
if ~iscell(index1)
   index1 = {index1};
end

% Set the specified value.
if ~isempty(prop1)
   % Ex. obj.BaudRate = 9600
   % Ex. obj(2).BaudRate = 9600
   
   % Extract the object.
   [indexObj, errflag] = localIndexOf(Obj, index1);
   if errflag
      localCheckError;
      error(lasterr);
   end
   
   % Set the property.
   try
      set(indexObj, prop1, Value);
   catch
      localCheckError;
      error(lasterr);
   end
else
   % Ex. obj(2) = obj(1);
   if ~(isa(Value, 'instrument') | isempty(Value))
      error('Only instrument objects may be concatenated.');
   end
   
   % Ex. s(1) = [] and s is 1-by-1.
   if ((length(Obj) == 1) & isempty(Value))
       error('Use CLEAR to remove the object from the workspace.');
   end

   % Error if a gap will be placed in array.
   if (max(index1{:}) > length(Obj)+1)
       error('Index exceeds matrix dimensions.');
   end
   
   % If the objects are the same length replace.
   if (length(index1{:}) == length(Value)) | isempty(Value) | (length(Value) == 1)
      [Obj, errflag] = localReplaceElement(Obj, index1, Value);
      if errflag
         localCheckError;
         error(lasterr);
      end	
   else
      error(['In an assignment A(I)=B, the number of elements',...
            ' in B and I must be the same.']);
   end	
end

% *********************************************************************
% Index into an instrument array.
function [result, errflag] = localIndexOf(obj, index1)

% Initialize variables.
errflag = 0;

try
   % Get the field information of the entire object.
   jobj = igetfield(obj, 'jobject');
   type = igetfield(obj, 'type');
   
   % Create result with only the indexed elements.
   result = obj;
   result = isetfield(result, 'jobject', jobj(index1{:}));
   result = isetfield(result, 'type', type(index1{:}));
catch
   lasterr('Index exceeds matrix dimensions.');
   errflag = 1;
   return;
end

% *********************************************************************
% Replace the specified element.
function [obj, errflag] = localReplaceElement(obj, index, Value)

% Initialize variables.
errflag = 0;

try
   % Get the current state of the object.
   jobject = igetfield(obj, 'jobject');
   type = igetfield(obj, 'type');
   constructor = igetfield(obj, 'constructor');
   
   if ~iscell(type)
      type = {type};
   end
   
   if ~iscell(constructor)
       constructor = {constructor};
   end
   
   % Replace the specified index with Value.
   if ~isempty(Value)
       if ((length([index{1}]) > 1) & (length(Value) > 1))
           % Ex. y(:) = x(2:-1:1); where y and x are 1-by-2 instrument arrays.
           jobject(index{1}) = igetfield(Value, 'jobject');
      	   type(index{1}) = igetfield(Value, 'type');
           constructor(index{1}) = igetfield(Value, 'constructor');
       else
           % Ex. y(1) = x(2);
           % Ex. y(:) = x;
      	   jobject(index{1}) = igetfield(Value, 'jobject');
      	   type(index{1}) = {igetfield(Value, 'type')};
           constructor(index{1}) = {igetfield(Value, 'constructor')};
       end
   else
      jobject(index{1}) = [];
      type(index{1}) = [];
      constructor(index{1}) = [];
   end
   
   % Assign the new state back to the original object.
   obj = isetfield(obj, 'jobject', jobject);
   obj = isetfield(obj, 'type', type);
   obj = isetfield(obj, 'constructor', constructor);
catch
   errflag = 1;
   return
end

% *************************************************************************
% Remove any extra carriage returns.
function localCheckError

% Initialize variables.
errmsg = lasterr;

% Remove the trailing carriage returns.
while errmsg(end) == sprintf('\n')
   errmsg = errmsg(1:end-1);
end

lasterr(errmsg);


