function hndl = autoline(sys,srcBlock,src,dstBlock,dst,blklocs,borient)
%AUTOLINE lays out lines "nicely" between two Simulink blocks.
%   AUTOLINE(SYS,SRCBLOCK,SRCPORT,DSTBLOCK,DSTPORT) connects port SRCPORT to port
%   DSTPORT in system SYS.
%   AUTOLINE(SYS,SRCBLOCK,SRCPORT,DSTBLOCK,DSTPORT,BLKLOCS) connects port SRCPORT
%   to port DSTPORT in system SYS with avoidance of the connection line across the
%   blocks indicated in BLKLOC. BLKLOCS is a nx4 matrix with every row of the matrix
%   indicate the location of a block's up-left x-y and bottom-right x-y. 
%   AUTOLINE(SYS,SRCBLOCK,SRCPORT,DSTBLOCK,DSTPORT,BLKLOCS,ORIENT) connects SRCPORT
%   and DSTPORT with their orietation indicated in ORIENT, where the first element
%   indicates the orietation of SRCPORT and the second element indicates the
%   orientation of DSTPORT. Orientation is represented by 0,1,2,3, which indicate
%   left-to-right, bottom-to-top, right-to-left, and top-to-bottom.
%   HNDL = AUTOLINE(...) returns the line handle.

%   Initial coding by Wes Wang 10-28-92
%   Modifications by A S Bozin
%   Copyright 1997-2000 The MathWorks, Inc.
%   $Revision: 1.10 $ $Date: 2000/06/30 15:01:03 $

   %
   % Handle input arguments
   %
   error(nargchk(5,7,nargin));
   if (nargin < 7)
      borient = [0 0];				   % default left to right position
      if (nargin < 6)
	 blklocs = [];				   % default don't care cross blocks
   end, end
   if (isempty(blklocs))
      blklocs = zeros(1,4);
   end
   ons = ones(2,1);
   %
   % Get all of positions
   %
   outPorts = get_param(srcBlock,'OutputPorts');
   noo = size(outPorts,1);
   inpPorts = get_param(dstBlock,'InputPorts');
   noi = size(inpPorts,1);
   points = [outPorts(src,:);inpPorts(dst,:)];
   srcRect = get_param(srcBlock,'Position');
   dstRect = get_param(dstBlock,'Position');
   %
   % Make all of the block as []>-------> position, where the inport is at (0,0).
   % Match srcRect,dstRect,points,tmp,and sys to the same
   % and at the very end,make points back.
   x0 = points(1,1);
   y0 = points(1,2);
   z0 = borient(1);
   %
   % For all of orientation, do
   %
   points(:,1) = points(:,1)-x0;
   points(:,2) = points(:,2)-y0;
   blklocs(:,[1,3]) = blklocs(:,[1,3])-x0;
   blklocs(:,[2,4]) = blklocs(:,[2,4])-y0;

   srcRect([1,3]) = srcRect([1,3])-x0;
   srcRect([2,4]) = srcRect([2,4])-y0;
   dstRect([1,3]) = dstRect([1,3])-x0;
   dstRect([2,4]) = dstRect([2,4])-y0;

   if ((z0 == 1) | (z0 == 3))
      %
      % Swap x and y
      %
      points(:,1:2)  = [-points(:,2) points(:,1)];
      blklocs(:,1:4) = [-blklocs(:,4) blklocs(:,1) -blklocs(:,2) blklocs(:,3)];
      srcRect(:,1:4) = [-srcRect(:,4) srcRect(:,1) -srcRect(:,2) srcRect(:,3)];
      dstRect(:,1:4) = [-dstRect(:,4) dstRect(:,1) -dstRect(:,2) dstRect(:,3)];
   end
   if ((z0 == 2) | (z0 == 1))
      %
      % Reverse direction
      %
      points(:,1:2)  = -points(:,1:2);
      blklocs(:,1:4) = -blklocs(:,[3 4 1 2]);
      srcRect(:,1:4) = -srcRect(:,[3 4 1 2]);
      dstRect(:,1:4) = -dstRect(:,[3 4 1 2]);
   end
   tmp = points(2,:);
   borient(:) = [0 rem(4+borient(2)-borient(1),4)];
   %
   % Find the "best rout" regardless across block and line
   %
   switch (borient(2))
   case 0
      if ((points(1,1)+5 >= tmp(1)) & ...
	  ~((abs(points(1,1)-tmp(1)) < 20) & (abs(points(1,2)-tmp(2)) < 20)))
	 %
	 % get around position
	 % rout       []>-|
	 %                |
	 %    |-----------|
	 %    |
	 %    |->[]
	 tmp1 = max(srcRect(4)+4*rem(src-1,noo),dstRect(4)+4*rem(dst-1,noo))+15;
	 tmp2 = min(srcRect(2)-4*rem(src-1,noo),dstRect(2)-4*rem(dst-1,noo))-10;
	 if (srcRect(4) < dstRect(2))
	    %
	    % Below srcBlock above dstBlock
	    %
	    alpha = 2/3-(noo-src)/noo/3;
	    points(3:4,2) = ceil(dstRect(2)*(1-alpha)+srcRect(4)*alpha)*ons;
	    pos = [-1 1];
	 elseif (srcRect(2) > dstRect(4))
	    % Below dstBlock above srcBlock
	    alpha = 1/3+(src-1)/noo/3;
	    points(3:4,2) = (srcRect(2)*(1-alpha)+dstRect(4)*alpha)*ons;
	    pos = [1 -1];
	 elseif (src*dst >= (noo-src+1)*(noi-dst+1))
	    % Below both blocks
	    points(3:4,2) = tmp1*ons;
	    pos = [-1 -1];
	 else
	    % Above both blocks
	    points(3:4,2) = tmp2*ons;
	    pos = [1 1];
	 end
	 points(2,2) = points(1,2);
	 points(5,2) = tmp(2);
	 points(6,:) = tmp;
	 if ((points(3,2) > points(2,2)) & (z0 < 2)) | ((points(3,2) < points(2,2)) & (z0 >= 2))
	    % Going down
	    points(2:3,1) = (points(1,1)+7+4*abs(rem(noo-src,noo)))*ons;
	 else
	    % Going up
	    points(2:3,1) = (points(1,1)+5+4*rem(src-1,noo))*ons;
	 end
	 if ((points(4,2) > points(5,2)) & (z0 < 2)) | ((points(4,2) < points(5,2)) & (z0 >= 2))
	    % Going up
	    points(4:5,1) = (tmp(1)-7-4*abs(rem(noi-dst,noi)))*ons;
	 else
	    % Going down
	    points(4:5,1) = (tmp(1)-5-4*rem(dst-1,noi))*ons;
	 end
      else 					   % Straight position
	 ons = [1;1];
	 % rout  []>---|
	 %             |
	 %             |--------->[]
	 points(2,:)   = tmp;
	 if (points(2,2) ~= points(1,2))
	    points(2,2) = points(1,2);
	    points(3,2) = tmp(2);
	    points(4,:) = tmp;
	    if ((points(3,2) > points(2,2)) & (z0 < 2)) | ((points(3,2) < points(2,2)) & (z0 >= 2))
	       % Going down
	       alpha = 2/3-(noo-src)/noo/3;
	    else
	       % Going up
	       alpha = 1/3+(src-1)/noo/3;
	    end
	    points(2:3,1) = ceil(points(1,1)*(1-alpha)+tmp(1)*alpha)*ons;
	 end
      end
      points = lineext(points,blklocs,[0,src,noo],[0,dst,noi]);
   case 1
      if (points(1,1) < tmp(1,1)) & (points(1,2) <= (tmp(1,2)-10))
	 % rout     []--|   
	 %              |   
	 %              v   
	 %             [ ]  
	 %           (1)    
	 points(2,1) = tmp(1,1);
	 points(2,2) = points(1,2);
	 points(3,:) = tmp(1,:);
      elseif (points(1,1) < tmp(1,1)) & (points(1,2) > (tmp(1,2)-10))
	 % rout         |--|
	 %              |  v 
	 %              | [ ]
	 %          []---
	 %           (2)
	 points(2,1) = points(1,1)+10+4*rem(src-1,noo);
	 points(3,1) = points(2,1);
	 points(2,2) = points(1,2);
	 points(3,2) = tmp(1,2)-10-4*rem(dst-1,noi);
	 points(4,2) = points(3,2);
	 points(4,1) = tmp(1,1);
	 points(5,:) = tmp;
      elseif (points(1,1) >= tmp(1,1))
	 % rout         []--|     |-----------|
	 %           |------|     v           |
	 %           v           [ ]          |
	 %          [ ]                   []->|
	 %            (3)             (4) 
	 points(2,1) = points(1,1)+15+4*rem(src-1,noo);
	 points(2,2) = points(1,2);
	 points(3,1) = points(2,1);
	 points(5,:) = tmp;
	 points(4,1) = points(5,1);
	 if (srcRect(4) < dstRect(2))
	    points(3,2) = (srcRect(4)+dstRect(2))/2;
	 else
	    points(3,2) = min((srcRect(2)-10-4*rem(src-1,noo)),(dstRect(2)-10-4*rem(dst-1,noi)));
	 end
	 points(4,2) = points(3,2);
      else
	 disp('something wrong')
      end
      points = lineext(points,blklocs,[0,src,noo],[1,dst,noi]);
   case 2
      ons = [1;1];
      % rout    []>-|         []                  |------|   
      %             |         []>---|       []>---|  []  |
      %             |  []<--| []    |                []<-|
      %    []<------|       |-------|                []
      %       (1)            (2)                 (3)
      if (points(1,2) < dstRect(4)) & (points(1,2) > dstRect(2))
	 % Have to get around
	 if (srcRect(3) > dstRect(3))	   % Condition (2)
	    if (srcRect(4)-points(1,2)) <= (points(1,2)-srcRect(2))
	       % Go from the bottom
	       points(3:4,2) = (srcRect(4)+10+4*rem(src-1,noo))*ons;
	    else
	       % Go from the top
	       points(3:4,2) = (srcRect(2)-10-4*rem(src-1,noo))*ons;
	    end
	 else				   % Condition 3
	    if (dstRect(4)-tmp(2)) <= (tmp(2)-dstRect(2))
	       % Go from the bottom
	       points(3:4,2) = (dstRect(4)+10+4*rem(dst-1,noi))*ons;
	    else
	       % Go from the top
	       points(3:4,2) = (dstRect(2)-10-4*rem(dst-1,noi))*ons;
	    end
	 end
	 points(2,2) = points(1,2);
	 points(5,2) = tmp(2);
	 points(6,:) = tmp;
	 if ((points(3,2) > points(2,2)) & (z0 < 2)) | ((points(3,2) < points(2,2)) & (z0 >= 2))
	    % Going down
	    points(2:3,1) = (points(1,1)+10+4*rem(noo-src,noo))*ons;
	 else
	    % Going up
	    points(2:3,1) = (points(1,1)+10+4*rem(src-1,noo))*ons;
	 end
	 if ((points(4,2) > points(5,2)) & (z0 < 2)) | ((points(4,2) < points(5,2)) & (z0 >= 2))
	    % Going up
	    points(4:5,1) = (tmp(1)+10+4*abs(rem(noi-dst,noi)))*ons;
	 else
	    % Going down
	    points(4:5,1) = (tmp(1)+10+4*rem(dst-1,noi))*ons;
	 end
      else
	 points(2,2) = points(1,2);
	 points(3,2) = tmp(2);
	 points(4,:) = tmp;
	 if ((points(3,2) > points(2,2)) & (z0 < 2)) | ((points(3,2) < points(2,2)) & (z0 >= 2))
	    % Going down
	    tmp1 = points(1,1)+rem(noo-src,noo)*4; %start point
	    tmp2 = tmp(1)+rem(dst-1,noi)*4+7;     %end point
	    points(2:3,1) =  ons*(max(tmp1,tmp2));
	 else
	    % Going up
	    tmp1 = points(1,1)+rem(src-1,noo)*4+10;
	    tmp2 = tmp(1)+rem(noi-dst,noi)*4+10;
	    points(2:3,1) = ons*max(tmp1,tmp2);
	 end
      end
      points = lineext(points,blklocs,[0,src,noo],[2,dst,noi]);
   case 3
      if (points(1,1) < tmp(1,1)) & (points(1,2) >= (tmp(1,2)+10))
	 % rout        [ ]
	 %              ^   
	 %              |   
	 %      []------|
	 %           (1)    
	 points(2,1) = tmp(1,1);
	 points(2,2) = points(1,2);
	 points(3,:) = tmp(1,:);
      elseif (points(1,1) < tmp(1,1)) & (points(1,2) < (tmp(1,2)+10))
	 % rout   []--|
	 %            |   [ ]
	 %            |    ^
	 %            |----|
	 %           (2)
	 points(2,1) = points(1,1)+10+4*rem(src-1,noo);
	 points(3,1) = points(2,1);
	 points(2,2) = points(1,2);
	 points(3,2) = tmp(1,2)+10+4*rem(dst-1,noi);
	 points(4,2) = points(3,2);
	 points(4,1) = tmp(1,1);
	 points(5,:) = tmp;
      elseif (points(1,1) >= tmp(1,1))
	 % rout     [ ]                   []--|  
	 %           ^              [ ]       |
	 %           |------|        ^        |
	 %               []-|        |--------|
	 %            (3)             (4) 
	 points(2,1) = points(1,1)+15+4*rem(src-1,noo);
	 points(2,2) = points(1,2);
	 points(3,1) = points(2,1);
	 points(5,:) = tmp;
	 points(4,1) = points(5,1);
	 if (srcRect(2) > dstRect(4))
	    points(3,2) = (srcRect(2)+dstRect(4))/2;
	 else
	    points(3,2) = max((srcRect(4)+15+4*rem(src-1,noo)),(dstRect(4)+15+4*rem(dst-1,noi)));
	 end
	 points(4,2) = points(3,2);
      else
	 disp('something wrong in case 3')
      end
      points = lineext(points,blklocs,[0,src,noo],[3,dst,noi]);
   otherwise
   end  
   %
   % Check if we have the right result
   %
   tmp(:) = size(points);
   if (tmp(1) <= 1)
      disp(borient);
      error('is a wrong orientation information. AUTOLINE does not support it');
   end
   if ((z0 == 2) | (z0 == 1))
      points = -points;
   end
   if ((z0 == 1) | (z0 == 3))
      %
      % Swap x and y
      %
      points(:,1) = -points(:,1);
      points = fliplr(points);
   end
   points(:,1) = points(:,1)+x0;
   points(:,2) = points(:,2)+y0;
   ind = find(points <= 0);
   points(ind) = points(ind)-points(ind)+5;
   % Round non-integer values. This is now required for the points passed
   % to add_line.
   points = round(points);
   % Add the line
   hndl = add_line(sys,points);
   return					   % Last card of AUTOLINE
