function [mnvr, inflc, rc] = mfs_new_load_mnvr(msg, manoeuvre, controls, 
                                           panels, nofldc, inflc, cref);

# usage: [mnvr, inflc, rc] = mfs_new_load_mnvr(msg, manoeuvre, controls, 
#                                          panels, nofldc, inflc, cref);
#
# Input  msg           File handle of message file
#        manoeuvre(:)  Structure array with manoeuvre definitions
#        controls      Structure with control surface data
#        panels        Structure with panel data
#        nofldc        Number of loadcases
#        inflc(:)      Load case information
#        cref          Reference chord length
#
# Output mnvr          Structure with data of the manoeuvres
#        inflc(:)      Load case information 
#                      (Bit 2 indicates manoeuvre loads)
#        rc            Return code: 0 means no erros
#                                   1 means errors
#
# The function checks the definitions of the manoeuvres and builds
# structure mnvr with the data of the manoeuvres:
#
#  mnvr.qdyn(nofldc)         Dynamic pressure
#      .v(nofldc)            Velocity
#      .D1K(nofpan, ncntrl)  Downwash matrix D1K
#      .D2K(nofpan, ncntrl)  Downwash matrix D2K
#      .UK(ncntrl, nofldc)   Controller Matrix UK
#
# --------------------------------------------------------------------

  legal_fields = {"qdyn", "v", "lc"};
  req_fields   = {"qdyn", "v"};

# Check arguments

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

# Initialize

  mnvr   = struct();

  nofpan = panels.nofpan;
  ncntrl = controls.ncntrl;

  D1K = sparse(nofpan, ncntrl); D2K = sparse(nofpan, ncntrl);
  UK  = zeros(ncntrl, nofldc);

  qdyn  = zeros(1, nofldc); v = zeros(1, nofldc);
  lcdef = zeros(1, nofldc);

# Check fields

  names        = fieldnames(controls)';
  cntnames     = sort(names(2 : end));
  legal_fields = [legal_fields, cntnames];

  if ((rc = mfs_checkfields1(msg, manoeuvre, req_fields,
                             "loads.manoeuvre")))
     return;
  end

  if ((rc = mfs_checkfields4(msg, manoeuvre, legal_fields,
                             "loads.manoeuvre")))
     return;
  end

# Check data

  if (! cref)
     fprintf(msg, "*E* Reference chord length undefined or zero\n");
     rc = 1;
  end

  ndef  = length(manoeuvre);
  nflds = numfields(manoeuvre);

  for n = 1 : ndef

      if (! isfield(manoeuvre, "lc") || isempty(manoeuvre(n).lc))
         lc = 1; manoeuvre(n).lc = 1;
         inflc(1) = bitset(inflc(1), 2);
         nfound   = 2;
      else
         if ((lc = manoeuvre(n).lc) < 1)
            fprintf(msg, "*E* loads.manoeuvre(%d): bad definition of", n);
            fprintf(msg, " loadcase number\n");
            rc = 1;
         else
            inflc(lc) = bitset(inflc(lc), 2);
            nfound    = 3;
         end
      end

      if (lcdef(lc))
         fprintf(msg, "*E* loads.manoeuvre(%d): loadcase %d ", n, lc)
         fprintf(msg, "alread defined\n");
         rc = 1;
      else
         lcdef(lc) = 1;
      end

      qd = manoeuvre(n).qdyn;
      if (isempty(qd))
         fprintf(msg, "*E* loads.manoeuvre(%d): qdyn undefined\n", n);
         rc = 1;
      elseif (! isscalar(qd))
         fprintf(msg, "*E* loads.manoeuvre(%d): qdyn must be a scalar\n", n);
         rc = 1;
      elseif (qd <= 0)
         fprintf(msg, "*E* loads.manoeuvre(%d): qdyn not positive\n", n);
         rc = 1;
      end
      qdyn(lc) = qd;

      v1 = manoeuvre(n).v;
      if (isempty(v1))
         fprintf(msg, "*E* loads.gust(%d): v undefined\n", n);
         rc = 1;
      elseif (! isscalar(v1))
         fprintf(msg, "*E* loads.gust(%d): v must be a scalar\n", n);
         rc = 1;
      end
      v(lc) = v1;

      nundef   = sum(structfun(@isempty, manoeuvre(n)));
      leftflds = nflds - nfound - nundef;
      if (! leftflds)
         fprintf(msg, "*E* loads.manoeuvre(%d): no control surface ", n);
         fprintf(msg, "deflections defined\n");
         rc = 1;
      end

  end

  if (rc) return; end

# Build matrices

  cinv  = -2 / cref;
  dg2rd = pi / 180;

  for n = 1 : length(cntnames)

      name    = cntnames{n};
      cntl    = getfield(controls, name);
      nofls   = getfield(cntl, "nofls");
      P1      = getfield(cntl, "P1")';
      P2      = getfield(cntl, "P2")';
      pids    = getfield(cntl, "pids");
      factors = getfield(cntl, "factors");

      for l = 1 : nofls

          p = pids(l, 1) : pids(l, 2); np = length(p);

#     D1K

          D1K(p, n) = -factors(l)(ones(np, 1));

#     D2K

          eyL = [panels.nvec(3, pids(l, 1)), -panels.nvec(2, pids(l, 1))];
          dy  = eyL * (P2(2 : 3, l) - P1(2 : 3, l));
          yL  = (eyL / dy) * (panels.C(2 : 3, p) - P1(2 : 3, l));
          x0  = P1(1, l) * (1 - yL) + P2(1, l) * yL;

          D2K(p, n) = (cinv * factors(l)) * (panels.C(1, p) - x0)';

      end

#     UK

      for m = 1 : ndef

          lc = manoeuvre(m).lc;

          if (isfield(manoeuvre(m), name))
             data = getfield(manoeuvre(m), name);
             if (! isempty(data))
                data = data * dg2rd;
                if (length(data) == 1)
                   UK(n, lc) = data;
                elseif (length(data) == 2)
                   UK(n, lc) = data(1) * exp(i * data(2));
                else
                   fprintf(msg, "*E* loads.manoeuvre(%d): ", m);
                   fprintf(msg, "wrong definition of flap angle\n");
                   rc = 1; 
                end
             end
          end

      end 

  end

# Build the output structure

  mnvr = struct("qdyn", qdyn, "v", v, "D1K", D1K, "D2K", D2K, "UK", UK);

end
