function InsertOneBlockNewFrames(blk, blkLHPort, preOrPost, ...
                                insBlkHOffset, insBlkVOffset, blockType)
% Insert a specified block given the inport/outport handle of the block
% instance being updated. The inserted block has the same height (width)
% as the instance block and width (height) 20 when the instance block
% is oriented horizontally (vertically).
%
% Parameters:
%           blk: The instance block.
%     blkLHPort: The (input/output) port of the instance block that
%                is to be connected to the newly inserted block.
%     preOrPost: A string to indicate the inserted block is before or
%                after the instance block being updated.
% insBlkHOffset: A nonnegative value that is horizontal (vertical) distance
%                between the inserted block and the instance block
%                that is oriented horizontally (vertically).
% insBlkVOffset: A value that is vertical (horizontal) distance between the
%                inserted block and the instance block that is
%                oriented horizontally (vertically). There is no limitation
%                for this value, and the right/up direction is positive.
%     blockType: An enum specifying the block to be inserted. For now:
%                1 corresponds to Transpose, 2 for Reshape.
%
% Illustration for horizontally oriented instance block:
%
%                       |-------|
%                  |--->|  Blk  |---|                       ^
%                  |    |-------|   |                       |
%        'Pre'     |                |    |<- 20->|       VOffset
%      |-------|   |                |    |-------|          |
% ---->|  Ins  |---|                |--->|  Ins  |----->    v
%      |-------|                         |-------|
%          |<-- HOffset -->|              'Post'
%
% See also dspblks\private\InsertOneTpsBlockNewFrames.

%   Copyright 2010 The MathWorks, Inc.

% Get the parent block full name
blkParentName = get_param(blk, 'Parent');

% Get a random name for the Transpose block
[~ , insBlkName] = fileparts(tempname);
insBlkName = [blkParentName '/' insBlkName];

% Delete the line connecting from/to the port.
delete_line(blkLHPort.Handle);

% Orient the Transpose block w.r.t. the instance block being updated
blkPos    = get_param(blk, 'Position');
blkOrient = get_param(blk, 'Orientation');
blkCenter = mean([blkPos(1:2); blkPos(3:4)]);
blkWidth  = blkPos(3) - blkPos(1);
blkHeight = blkPos(4) - blkPos(2);

if strcmpi(blkOrient, 'left') || strcmpi(blkOrient, 'right')
    sign = (strcmpi(blkOrient, 'left')  && strcmpi(preOrPost, 'Pre')) ||...
           (strcmpi(blkOrient, 'right') && strcmpi(preOrPost, 'Post'));
    sign = sign * 2 - 1; % Map 0 to -1 and 1 to 1
    insBlkCenter = [blkCenter(1) + sign * (blkWidth/2 + insBlkHOffset),...
                    blkCenter(2) - insBlkVOffset];
    insBlkWidth  = 20;
    insBlkHeight = blkHeight;
elseif (strcmpi(blkOrient, 'up') || strcmpi(blkOrient, 'down'))
    sign = (strcmpi(blkOrient, 'up')   && strcmpi(preOrPost, 'Pre')) ||...
           (strcmpi(blkOrient, 'down') && strcmpi(preOrPost, 'Post'));
    sign = sign * 2 - 1; % Map 0 to -1 and 1 to 1
    insBlkCenter = [blkCenter(1) - insBlkVOffset,...
                    blkCenter(2) + sign * (blkHeight/2 + insBlkHOffset)];
    insBlkWidth  = blkWidth;
    insBlkHeight = 20;
end

insBlkPos = [insBlkCenter(1) - insBlkWidth  / 2, ...
             insBlkCenter(2) - insBlkHeight / 2, ...
             insBlkCenter(1) + insBlkWidth  / 2, ...
             insBlkCenter(2) + insBlkHeight / 2];

% Map the blockType to the actual block in the library        
switch blockType
    case 1
        load_system('simulink');
        insBlkSrc = 'simulink/Math Operations/Math Function';
        % Add the inserted block and hide its name
        insBlkHandle = add_block(insBlkSrc, insBlkName, ...
                         'Position', insBlkPos, ...
                         'Orientation', blkOrient, ...
                         'ShowName', 'off', ...
                         'Operator', 'Transpose');

    case 2
        load_system('simulink');    
        insBlkSrc = 'built-in/Reshape';
        % Add the inserted block and hide its name
        insBlkHandle = add_block(insBlkSrc,            insBlkName, ...
                         'Position',           insBlkPos, ...
                         'Orientation',        blkOrient, ...
                         'ShowName',           'off');

end
       

insBlkPortH = get_param(insBlkHandle, 'PortHandles');

% Reconnect lines from the original source block to the inserted block,
% and from the inserted block to the original destination block.
fromBlkName    = get_param(blkLHPort.SrcBlockHandle, 'Name');
% If the block's name contains '/', replace it by '//'.
fromBlkName    = regexprep(fromBlkName, '/', '//');
fromBlkPortNum = get_param(blkLHPort.SrcPortHandle, 'PortNumber');
toBlkName      = get_param(insBlkHandle, 'Name');
toBlkPortNum   = get_param(insBlkPortH.Inport, 'PortNumber');
add_line(blkParentName, [fromBlkName '/' int2str(fromBlkPortNum)], ...
                        [toBlkName   '/' int2str(toBlkPortNum)], ...
                        'autorouting', 'on');

fromBlkName    = get_param(insBlkHandle, 'Name');
fromBlkPortNum = get_param(insBlkPortH.Outport, 'PortNumber');
toBlkName      = get_param(blkLHPort.DstBlockHandle, 'Name');
% If the block's name contains '/', replace it by '//'.
toBlkName      = regexprep(toBlkName, '/', '//');
toBlkPortNum   = get_param(blkLHPort.DstPortHandle, 'PortNumber');
add_line(blkParentName, [fromBlkName '/' int2str(fromBlkPortNum)], ...
                        [toBlkName   '/' int2str(toBlkPortNum)], ...
                        'autorouting', 'on');
end
