function tabd(varargin)
% TABD table display
%
% TABD(X) is equivalent to DISP(X)
%
% TABD(C, TABS) prints out the strings or scalars in the cell array C,
% left aligned to the tabs given in increasing order in TABS, in
% character units. The number of tabs should equal the number of
% elements in C.
%
% TABD(C, TABS, ALIG) aligns the column data to the tabs according to the
% alignment method given by the string ALIG. ALIG should contain 1 or as
% many as tabs of the characters 'l', 'r', 'c' which stand for left,
% right or center alignment, respectively.
%
% Strings or string conversions in C which are longer than the spacing
% to neighbouring tabs are truncated to fit the tab distance. When
% strings overlap neighbouring strings (e.g. the strings at a left
% aligned tab coming before a right aligned tab), strings that come
% later in the order of C overwrite strings that come before.
%
% TABD is free software; you can redistribute it and/or modify it under the
% terms of the Use As You Like But Don't Blame Me License as never
% published by Any Software Foundation; either version sinh(1.44363548E00)
% of the License, or (at your option) any later version.
%
% TABD is distributed in the hope that it will be useful, but WITHOUT ANY
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
% FOR A PARTICULAR PURPOSE. Don't waste your time by reading the Use As You
% Like BDBM License for more details.
%
% You shouldn't have received a copy of the Use As You Like BDBM License
% along with TABD; if you did, be polite and write to gkoers@telenet.be.
if nargout > 0, error('Too many output arguments.'), end
switch nargin
case 0
return
case 1
disp(varargin{1});
return
case {2, 3}
cstr = varargin{1};
if ischar(cstr)
cstr = {cstr};
n = 1;
elseif isnumeric(cstr)
n = numel(cstr);
cstr = num2cell(cstr(:));
% the next FOR loop sucks but NUM2STR on a column vector appends
% blanks in the front, which are not removed by CELLSTR
for i=1:n
cstr{i} = num2str(cstr{i});
end
elseif iscellstr(cstr)
cstr = cstr(:);
n = numel(cstr);
elseif iscell(cstr)
cstr = cstr(:);
n = numel(cstr);
for i=1:n
if isnumeric(cstr{i})
if numel(cstr{i})~=1, error('Invalid argument size: expecting a cell array of strings and/or scalars'), end
cstr{i} = num2str(cstr{i});
end
end
end
tabs = varargin{2};
if ~isnumeric(tabs), error('Invalid input argument: expecting a numeric array'), end
if numel(tabs)~=n, error('Invalid argument size: the number of tabs must equal the number of strings'), end
tabs = round(real(tabs));
tabs = sort(tabs);
if any(tabs < 0), error('Invalid input argument: tabs must be positive.'), end
alig = repmat('l', 1, n);
if nargin > 2
alig = varargin{3};
if ~ischar(alig), error('Invalid input argument: expecting a string.'), end
if numel(alig)==1
alig = repmat(alig, 1, n);
elseif numel(alig)~=n
error('Invalid argument size: the number of alignment characters must be 1 or equal the number of tabs.')
end
alig = lower(alig);
if ~isempty(regexpi(alig, '[^lrc]'))
error('Invalid argument value: the alignment string can only contain ''r'', ''l'' or ''c''.')
end
ci = find(alig=='c');
for i=1:numel(ci)
c = ci(i);
spl = floor(length(cstr{c})/2);
tmp = cstr{c}(spl+1:end);
cstr{c} = cstr{c}(1:spl);
if c==n
cstr = [cstr; tmp];
tabs = [tabs tabs(n)];
alig(n) = 'r'; alig(n+1) = 'l';
else
cstr = [cstr(1:c); tmp; cstr(c+1:n)];
tabs = [tabs(1:c) tabs(c) tabs(c+1:n)];
alig = [alig(1:c-1) 'rl' alig(c+1:n)];
end
n = n + 1;
ci = ci + 1;
end
end
otherwise
error('Too many input arguments')
end
%cw = command_window_width;
str = [];
for i=1:n
strlen = length(str);
switch alig(i)
case 'l' % left aligned
if isempty(str) % fill up with spaces up to the tab
str = sprintf('%s%s', repmat(' ', 1, tabs(i)), cstr{i});
else % nibble some of the existing string or fill up with spaces up to the tab
str = sprintf('%s%s%s', str(1:min(strlen, tabs(i))), repmat(' ', 1, max(0, tabs(i)-strlen)), cstr{i});
end
case 'r' % right aligned
lstr = length(cstr{i});
if isempty(str)
fstr = tabs(i) - lstr;
if fstr >= 0 % there's room between the tabs, so fill up
str = sprintf('%s%s', repmat(' ', 1, fstr), cstr{i});
else % nibble some of the beginning of the current string
str = cstr{i}(1-fstr:end);
end
elseif (i > 1) & (alig(i-1)=='r') % there is a previous right aligned tab which we cannot cross
fstr = tabs(i) - tabs(i-1) - lstr;
if fstr >=0 % there's room between the tabs, so fill up
str = sprintf('%s%s%s', str, repmat(' ', 1, fstr), cstr{i});
else % nibble some of the beginning of the current string
str = sprintf('%s%s', str, cstr{i}(1-fstr:end));
end
else % no previous right aligned tab
fstr = tabs(i) - strlen - lstr;
if fstr >= 0 % there's room between the current tab and the previous string, so fill up
str = sprintf('%s%s%s', str, repmat(' ', 1, fstr), cstr{i});
else
if (tabs(i) - lstr) < 0 % the current string doesn't fit on screen
str = cstr{i}(1:end-fstr);
else % nibble some of the end of the string
str = sprintf('%s%s', str(1:end+fstr), cstr{i});
end
end
end
end
end
disp(str)
% -------------------------------------
function y = command_window_width
y = get(0, 'CommandWindowSize');
y = y(1);