function res = Ranovakun(data,design,numlist,varargin)
%
% res = Ranovakun(data,design,numlist,...)
% 
% Windows環境でMatlabからRのanovakun()を実行します。
% rscript.exeにパスが通っていて、Rの起動時にanovakun()を読みこむ
% ように設定されている必要があります。
% 
% 引数
% data
%   データが格納された行列を指定します。
%   データの並べ方はanovakun()と同様です。
% design
%   実験のデザインを示す文字列を指定します。
%   指定方法はanovakun()と同様です。
% numlist
%   各要因の水準数を , で区切った文字列を
%   指定します。例えば2要因で水準数がそれぞれ
%   3と4であれば、'3,4'という文字列を指定します。
% オプション
% output
%   結果の出力方法を指定します。
%   'window'…ダイアログに出力します。
%   'text'…Matlabのコマンドウィンドウに出力します。
% title
%   outputがwindowの時のダイアログのタイトルに
%   表示する文字列を指定します。省略した場合は
%   'RAnovakun'になります。
% options
%   anovakun()に渡したいオプションを列挙した
%   文字列を指定します。省略した場合は何も
%   オプションを渡しません。
%   
% 更新履歴
% 2010/4/7
% ・出力ウィンドウのリサイズとテキストのコピーに対応。
% 
% 作者
%   十河宏行(愛媛大学法文学部)
%   http://www.s12600.net/psy/
% お断り
%   この関数の使用によって生じるいかなる結果に関しても責任を
%   負いかねます。
% 


if ((nargin == 0) && ~isempty(gcbo)), resizeOutput(gcbo); return; end
if ((nargin == 1) && isequal(data,'copy')), clipboard('copy', get(gcbf, 'UserData')); return; end

title = 'RAnovakun';
output = 'window';
options = [];

if ~isempty(varargin)
    if mod(length(varargin),2)~=0
        error('Options must be paired.')
    end
    for i=1:(length(varargin)/2)
        if strcmpi(varargin{2*i-1},'title')
            title = varargin{2*i};
        elseif strcmpi(varargin{2*i-1},'output')
            output = lower(varargin{2*i});
        elseif strcmpi(varargin{2*i-1},'options')
            options = varargin{2*i};
        else
            error('Invalid option.')
        end
    end
end

if ~(strcmp(output,'window') || strcmp(output,'text'))
    error('output must be window or text')
end

if ~isempty(options)
    options = [', ', options];
end

f = tempname;
df = dupfilesep(f);

save(f, 'data', '-ASCII', '-TABS');
[~, result] = system(['rscript --default-packages=stats,utils,methods -e "d<-read.table(\"' df '\"); anovakun(d,\"' design '\",' numlist options ')']);
system(['del ', f]);
if strcmp(output,'window')
    DisplayResult(result,title);
    res = [];
else
    res = result;
end

function df = dupfilesep(f)

df = [];
for i=1:length(f)
    if(f(i)==filesep)
        df = [df filesep filesep];
    else
        df = [df f(i)];
    end
end

function DisplayResult(result,varargin)
%単に改行コードを含むテキストをリストとして表示するだけ。

if ~isempty(varargin)
    title = varargin{1};
else
    title = 'DisplayResult';
end

f = figure;
set(f,'Name',title);
set(f,'UserData',result);
set(f,'ResizeFcn','Ranovakun');

s = get(f,'Position');

% Add "copy text" option to Edit menu unless already done
h = findall(f, 'Label','&Edit');
if (~isempty(h))
   hh = findobj(h,'Label','Copy Te&xt');
   if (isempty(hh))
      uimenu(h, 'Label','Copy Te&xt', 'Callback','Ranovakun(''copy'')');
   end
end

idx = find(uint8(result)==10);
if isempty(idx)
    r = result;
else
    r = cell(1,length(idx)+1);
    r{1} = expandTab( result(1:idx(1)), 8);
    for i=1:length(idx)-1
        r{i+1} = expandTab( result(idx(i)+1:idx(i+1)-1), 8);
    end
    r{length(idx)+1} = expandTab( result(idx(end)+1:end), 8);
end
uicontrol(f,'Style','ListBox','String',r,'Position',[0,0,s(3),s(4)],'FontName','FixedWidth','Tag','Output');

function r = expandTab(t,width)
%まずtが空ではないかチェック
if isempty(t)
    r = t;
    return
end

%Tabを検出
idx = find(uint8(t)==9);
if isempty(idx)
    r = t; %Tabがなければそのまま入力を返す
else
    r = t(1:idx(1)-1);
    r = [r  repmat(32,1,width-mod(idx(1)-1,width))];
    for i=1:length(idx)-1
        rtmp = t(idx(i)+1:idx(i+1));
        r = [r rtmp repmat(32,1,width-mod(idx(i+1)-idx(i)-1,width))];
    end
    r = [r t(idx(end)+1:end)]; %最後はTabをスペースに置き換える必要がない
end

function resizeOutput(f)
fpos = get(f,'Position');
u = findobj(f,'Tag','Output');
set(u,'Position',[0,0,fpos(3),fpos(4)]);
