function theResult = subsref(self, theStruct)

% ncvar/subsref -- Overloaded "{}", ".", and "()" operators.
%  subsref(self, theStruct) processes the subscripting
%   operator () for self, an "ncvar" object referenced on
%   the righthand side of an assignment, such as in
%   result = self(i, j, ...), where the sole operator
%   is '()'.  If the syntax is result = self.theAttname
%   or result = self.theAttname(...), the named attribute
%   object of self is processed.  If fewer than the full
%   number of indices are provided, the silent ones
%   default to 1, unless the last one provided is ':',
%   in which case the remainder default to ':' as well.
%   Indices beyond the full number needed are ignored.
%   ## Only a constant stride is permitted at present.
%
%   If the "quick" flag is set, faster "vanilla-flavored"
%   processing is forced.  Except for autoscaling, no
%   special treatments are performed, such as virtual
%   indexing, implicit indexing (including ":"), unsigned
%   conversions, or auto-NaNing.

% Also see: ncvar/subsasgn.
 
% Copyright (C) 1996-7 Dr. Charles R. Denham, ZYDECO.
%  All Rights Reserved.
%   Disclosure without explicit written consent from the
%    copyright owner does not constitute publication.
 
% Version of 07-Aug-1997 15:55:19.
% Updated    20-Jul-1999 18:02:39.

if nargin < 1, help(mfilename), return, end

if length(theStruct) < 1
   result = self;
   if nargout > 0
      theResult = result;
   else
      disp(result)
   end
   return
end

% Quick processing.
%  The NetCDF file must already be in "data" mode.

isQuick = quick(self) & ...
	length(theStruct) == 1 & isequal(theStruct.type, '()');

if isQuick
	indices = theStruct.subs;
	if ~iscell(indices), indices = {indices}; end
	if (0)   % Slow, but proper.
		theNCid = ncid(self);
		theVarid = varid(self);
		theSize = ncsize(self);   % Slow.
		start = zeros(size(theSize));
		count = zeros(size(theSize));
		theAutoscaleflag = autoscale(self);
	else   % Fast, but very bad manners.
		s = struct(self);
		s = s.ncitem;
		s = struct(s);
		theNCid = s.itsNCid;
		theVarid = s.itsVarid;
		start = zeros(1, length(indices));
		count = zeros(1, length(indices));
		theAutoscaleflag = s.itIsAutoscaling;
	end
	for i = 1:length(indices)
		k = indices{i};
		start(i) = min(k) - 1;
		count(i) = length(k);
	end
	[result, status] = ncmex('varget', theNCid, theVarid, ...
								start, count, theAutoscaleflag);
	if status >= 0
		result = permute(result, length(size(result)):-1:1);
	end
	if nargout > 0
	   theResult = result;
	else
	   disp(result)
	end
	return
end

% Composite-variable processing.
%  We map the source-indices to the destination-indices
%  for each composite-variable participant.  The indices
%  are in cells of cells, arranged in the same order as
%  the variables, which themselves are in a cell.

theVars = var(self);   % A cell.
if ~isempty(theVars)
   [theSrcsubs, theDstsubs] = subs(self);  % The mappings.
   result = [];
   for i = length(theVars):-1:1
      src = theSrcsubs{i};   % A cell.
      dst = theDstsubs{i};   % A cell.
%     x = theVars{i}(src{:});
      x = ncsubsref(theVars{i}, '()', src);
      result(dst{:}) = x;
   end
   theSize = size(result);
   theSubs = theStruct(1).subs;
   if length(theSize) > length(theSubs)
      if isequal(theSubs{length(theSubs)}, ':')
         extra = ':';
      else
         extra = 1;
      end
      for i = length(theSubs)+1:length(theSize)
         theSubs{i} = extra;
      end
   end
   result = result(theSubs{:});  % Subset.
   if nargout > 0
      theResult = result;
   else
      disp(result)
   end
   return
end

% Regular processing.

result = [];
if nargout > 0, theResult = result; end
   
s = theStruct;
theType = s(1).type;
theSubs = s(1).subs;
s(1) = [];

nccheck(self)
theAutoscaleflag = (autoscale(self) == 1);
theDatatype = datatype(self);
theTypelen = ncmex('typelen', theDatatype);
isUnsigned = unsigned(self);
theFillvalue = fillval(self);
theAutonanflag = (autonan(self) == 1) & ~isempty(theFillvalue);
if theAutonanflag
	theAutoscaleflag = 0;   % Do it locally.
	theScalefactor = scalefactor(self);
	theAddoffset = addoffset(self);
end

switch theType
case '()'   % Variable data by index: self(..., ...).
   indices = theSubs;
   theSize = ncsize(self);
   for i = 1:length(indices)
      if isa(indices{i}, 'double')
         if any(diff(diff(indices{i})))
            disp(' ## Indexing strides must be positive and constant.')
            return
         end
      end
   end
   
% Flip and permute indices before proceeding,
%  since we are using virtual indexing.
   
   theOrientation = orient(self);
   if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
      for i = 1:length(theOrientation)
         if theOrientation(i) < 0
            if isa(indices{i}, 'double')   % Slide the indices.
               indices{i} = fliplr(theSize(i) + 1 - indices{i});
            end
         end
      end
      indices(abs(theOrientation)) = indices;
      theSize(abs(theOrientation)) = theSize;
   end

   if prod(theSize) > 0
      start = zeros(1, length(theSize));
      count = ones(1, length(theSize));
      stride = ones(1, length(theSize));
      for i = 1:min(length(indices), length(theSize))
         k = indices{i};
         if ~isstr(k) & ~strcmp(k, ':') & ~strcmp(k, '-')
            start(i) = k(1)-1;
            count(i) =  length(k);
            d = 0;
            if length(k) > 1, d = diff(k); end
            stride(i) = max(d(1), 1);
         else
            count(i) = -1;
            if i == length(indices) & i < length(theSize)
               j = i+1:length(theSize);
               count(j) = -ones(1, length(j));
            end
         end
      end
      start(start < 0) = 0;
      stride(stride < 0) = 1;
      for i = 1:length(count)
         if count(i) == -1
            maxcount = fix((theSize(i)-start(i)+stride(i)-1) ./ stride(i));
            count(i) = maxcount;
         end
      end
      theNetCDF = parent(self);
      theNetCDF = endef(theNetCDF);
      count(count < 0) = 0;
      if any(count == 0), error(' ## Bad count.'), end
      if all(count == 1)
         [result, status] = ncmex('varget1', ncid(self), varid(self), ...
                                start, theAutoscaleflag);
      elseif all(stride == 1)
         [result, status] = ncmex('varget', ncid(self), varid(self), ...
                                start, count, theAutoscaleflag);
      else
         imap = [];
         [result, status] = ncmex('vargetg', ncid(self), varid(self), ...
                                 start, count, stride, imap, ...
                                 theAutoscaleflag);
      end
		if theAutonanflag & status >= 0
			f = find(result == theFillvalue);
			if any(f), result(f) = NaN; end
			result = result .* theScalefactor + theAddoffset;
		end
		if isUnsigned & prod(size(result)) > 0
			result(result < 0) = 2^(8*theTypelen) + result(result < 0);
		end
     else
      result = [];
      status = 0;
   end
   if status >= 0 & prod(size(result)) > 0
      result = permute(result, length(size(result)):-1:1);
      theOrientation = orient(self);
      if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
         for i = 1:length(theOrientation)
            if theOrientation(i) < 0
               result = flipdim(result, abs(theOrientation(i)));
            end
         end
         if length(theOrientation) < 2
            theOrientation = [theOrientation 2];
         end
         result = permute(result, abs(theOrientation));
      end
   elseif status >= 0 & prod(size(result)) == 0
      result = [];
   else
      warning(' ## ncvar/subsref failure.')
   end
case '.'   % Attribute: self.theAttname(...)
   theAttname = theSubs;
   while length(s) > 0   % Dotted name.
      switch s(1).type
      case '.'
         theAttname = [theAttname '.' s(1).subs];
         s(1) = [];
      otherwise
         break
      end
   end
   result = att(self, theAttname);
   if ~isempty(result), result = subsref(result, s); end
otherwise
   warning([' ## Illegal syntax: "' theType '"'])
end

if nargout > 0
   theResult = result;
else
   disp(result)
end
