function [controls, rc] = mfs_new_controls(msg, ls, cntrls)

# usage: [controls, rc] = mfs_new_controls(msg, ls, cntrls)
#
# Input  msg         File handle of message file
#        ls          Structure with lifting surfaces
#        cntlrs(:)   Structure array with definition of control
#                    surfaces
#
# Output controls    Structure with the control surface data
#        rc          Return code: 0 = no errors
#                                 1 = errors
#
# The function builds the controls structure. The names of the
# fields of this structure agree with the names of the control
# surfaces.
#
# controls.ncntrl              Number of control surfaces
# controls.<name>.nofls        Number of lifting surfaces
#                .P1(:, 3)     Coordinates of leading edge point 1
#                .P2(:, 3)     Coordinates of leading edge point 2
#                .pids(:, 2)   For each lifting surface:
#                              1 Index of first panel
#                              2 Index of last panel
#                .factors(:)   Factors for lifting surfaces
#
# --------------------------------------------------------------------

  leg_fields = {"name", "ls", "factors"};
  req_fields = {"name", "ls"};

# Check arguments

  if (nargin != 3 || nargout != 2)
     print_usage();
  end

# Initialize

  controls = struct();

# Check input data

  if ((rc = mfs_checkfields1(msg, cntrls, req_fields, 
                             "Control Surfaces")))
     return;
  end
  if ((rc = mfs_checkfields4(msg, cntrls, leg_fields, 
                             "Control Surfaces")))
     return;
  end

  isfact = isfield(cntrls, "factors");

# Process control surfaces

  ncntrl   = length(cntrls);
  controls = setfield(controls, "ncntrl", ncntrl);

  for n = 1 : ncntrl
      name = cntrls(n).name;
      if (! isempty(name))
         lsids = cntrls(n).ls;
         if (! isempty(lsids))
            nofls = length(lsids);
            pids  = zeros(nofls, 2);
            P1    = zeros(nofls, 3);
            P2    = zeros(nofls, 3);
            for l = 1 : nofls
                if ((ix = lookup(ls.ids, lsids(l), "m")))
                   P1(l, :)   = ls.surfs(ix).P(1, :);
                   P2(l, :)   = ls.surfs(ix).P(2, :);
                   pids(l, 1) = ls.surfs(ix).p1;
                   pids(l, 2) = ls.surfs(ix).pend;
                else
                   rc = 1;
                   fprintf(msg, "*E* Control surface \"%s\": ", name);
                   fprintf(msg, "Lifting surface %5d ", lsids(l));
                   fprintf(msg, "does not exist\n");
                end
            end
            if (isfact && ! isempty(cntrls(n).factors))
               factors = cntrls(n).factors;
               if (length(factors) != nofls)
                  rc = 1;
                  fprintf(msg, "*E* Control surface \"%s\": ", name);
                  fprintf(msg, "Number of factors does not match ");
                  fprintf(msg, "number of lifting surfaces\n");
               end
            else
               factors = ones(1, nofls);
            end
            cntl = struct("nofls", nofls, "P1", P1, "P2", P2,
                          "pids", pids, "factors", factors);
            controls = setfield(controls, name, cntl);
         else
            rc = 1;
            fprintf(msg, "*E* Control surface \"%s\": ", name);
            fprintf(msg, "No lifting surfaces defined\n");
         end  
      else
         rc = 1;
         fprintf(msg, "*E* Control surface no. %5d: ", n);
         fprintf(msg, "name undefined\n");
      end 
  end

end
