%PRHELP2HTML Construct HTML file from help part of PRTools routine
%
%		S = PRHELP2HTML(COMMAND,RECREATE,SUBDIR)
%
% INPUT
%   COMMAND    String with PRTools command, default: all prtools m-files
%   RECREATE   0/1 flag indicating whether non-existing references
%              in the SEE ALSO section should be created as well
%   SUBDIR     String with desired sub-directory in which the HTML
%              file should be stored
%
% OUTPUT
%   S          HTML code written to file, empty in case of error
%
% DESCRIPTION
% This command takes the help part of a PRTools command and creates a HTML
% file in the desired sub-directory. In case it is not given, a
% sub-directory is used with the same name as the (sub-)directory of
% COMMAND.
%
% In creating HTML code the following formatting rules apply:
% - NAME is used for the title and the first heading
% - There are (slightly) different rules for standard sections of the
%   PRTools help: 
%   INPUT, OUTPUT, DESCRIPTION, REFERENCES, EXAMPLES, SEE ALSO
% - New sections are detected by their name in capitals starting at
%   position 1 or 2 of the line.
% - The first word of the first line is skipped (assuming it is identical 
%   to NAME).  The remaining part of the line is used as heading.
% - The next block of lines is assumed to be ways to call the command and
%   is printed as code (Courier size 3) on separate lines.
% - The INPUT and OUTPUT sections are printed as two-column tables. The
%   first column is printed as code.
% - Multiple spaces in the source are used to define column separators.
%   ACCIDENTAL MULTIPLE SPACES CAUSE ERRORS!!!! 
% - Blocks of lines in the following DESCRIPTION section are formatted as
%   separate paragraphs.
% - Lines starting with ' - ' will start a dotted list.
% - Lines following an empty line and starting with multiple spaces are
%   assumed to be code and printed as Courier_3.
% - Lines containing sets of multiple spaces after the first words start a
%   two-column table. Consecutive lines starting with multiple spaces are
%   placed in the second column.
% - Lines ending with a ':' force a break (<br>) in the paragraph.
% - An attempt is made to detect code in text (using the Matlab convention
%   of upper case characters only). This is printed as Courier 2.
% - Literature references in the REFERENCE section generater a break if the 
%   line starts with a number.
% - Code in the EXAMPLE section is printed as it is using Courier_2. 
% - Users are advised to neglect here the Matlab convention of capitals in
%   order to facilitate direct copying and execution.
% - References are created for command names in the EXAMPLE section that
%   are preceded by 'See', e.g. 'See PREX_PLOTC'.
% - References are created for all PRTools commands in the SEE ALSO
%   section.




function out = prhelp2html(name,recreate,subdir)

if nargin < 3, subdir = []; end
if nargin < 2 || isempty(recreate), recreate = 0; end
if nargin < 1
	run_all_files(mfilename); 
	s = prcontent2html('prtools');
	if nargout > 0
		out = s;
	end
	return; 
end

file = which(name);
if isempty(file)
	disp(['  ----->  ' name ' not found']);
	out = [];
	return
end
%[pp,name] = fileparts(file);
if isempty(subdir)
	[~,subdir] = fileparts(fileparts(file));
end
if isempty(strmatch(subdir,char('prtools','@dataset','@datafile','@mapping'),'exact'))
%	disp([name ' Not PRTools'])
	out = [];
	return
end

disp(file)
t = gethf(file); % help part

t = strrep(t,char([10 13]),char(10));
t = strrep(t,char([13 10]),char(10));
t = strrep(t,char(13),char(10));
t = strrep(t,char(9),char([32 32]));
n = length(strfind(t,10));
	
s = ['<html>' content_manual '<head><title>' name '</title></head>' newline];

s = [s '<body bgcolor="#ffffff"><p align="center"><font face="Courier" ' ... 
   'size=5><strong>' upper(name) '</strong></font></p>' newline];

title = listn(t,1);
[~,title] = strtok(title); % get rid of first word, probably name
s = [s '<h3>' title '</h3>' newline];
s = [s '<p>' newline];
liston = false;
previous_empty = false;
coding = false;
cellopen = false;
tabstate = false;

if strfind(lower(title),'info')
	state = 'text';
else
	state = 'start';
end
nextlinespace = htmlspace;
for j=2:n                             % do for all lines
	newlinespace = nextlinespace;
	nextlinespace = htmlspace;
	r = listn(t,j);
	u = cleanstr(r);
%     if strfind(r,'supplied')
%        disp(r)
%     end
	[tok,posttok] = strtok(u);
	single = isempty(strtok(posttok));
	emptyline = isempty(tok);
	if length(r) < 2,
		startspace = false;
		tabstartspace = false;
	else
		startspace = strcmp(r(1:2),'  ');
		if length(r) < 4 || ~tabstate
			tabstartspace = false;
		else
			tabstartspace = strcmp(r(1:4),'    ');
			colpos1 = find(r ~= ' ',1,'first');
		end
		if tabstartspace
			startspace = false;
		end
	end
	uppertoken = isupper(tok);
	upperline = isupper(u);
	functioncall = ~isempty(strfind(lower(r),name));
	input = strcmp(tok,'INPUT');
	output = strcmp(tok,'OUTPUT');
	listline = strcmp(tok,'-');
	description = strcmp(tok,'DESCRIPTION');
	example = strcmp(tok,'EXAMPLE') | strcmp(tok,'EXAMPLES');
	reference = strcmp(tok,'REFERENCE') | strcmp(tok,'REFERENCES');
	seealso = strcmpi(tok,'SEE') & strcmpi(strtok(posttok),'ALSO');
	inputstate = strcmp(state,'input');
	outputstate = strcmp(state,'output');
	tabstate = strcmp(state,'tab');
	startstate = strcmp(state,'start');
	commandstate = strcmp(state,'command');
	textstate = strcmp(state,'text');
	examplestate = strcmp(state,'examp');
	seealsostate = strcmp(state,'seealso');
	refstate = strcmp(state,'reference');
	iotabstate = inputstate | outputstate;
  ntabs = regexp(strtrim(r),'   *','start');
	tab = length(ntabs>1) | (length(ntabs)==1 && ntabs(1)>1);
	
	if seealso % get rid of also
		[~,posttok] = strtok(posttok);
		single = isempty(strtok(posttok));
	end
		
	if previous_empty && ~startspace && ~tabstartspace && ~tab && tabstate
		if cellopen
			s = closecell(s);
			cellopen = false;
		end
		s = endtable(s);
    s = [s '</p>' newline '<p>'];
		state = oldstate;
	end
	
	if emptyline                          % start new paragraph
		if liston, s = [s '</ul>']; liston = false; end
		if iotabstate
      s = endtable(s);
      state = 'text';
    else
			s = [s '</p>' newline '<p>']; %#ok<AGROW>
		end
		if ~examplestate
			coding = false;
		end
		
	elseif (startspace && ((functioncall && upperline) || commandstate)) || startstate
		                                    % command
		%n = findstr(u,'=');  % align =
		%n = min(n,17);       % but dont exeggarate
		n = find(r~=' ',1,'first');
		s  = [s code(u,n,3) '<br>' newline];
	 	state = 'command';
		
	elseif input && single                 % input
		if commandstate || textstate         % start table
			s = [s '</p><p>' newline];        % new paragraph
			s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
					' align="center" border="0"']; % start table
			s = [s '<tr> <td width="100"><font size="4"><strong>Input</strong></font></td>'];
		  state = 'input';
		end
	elseif output && single
		if inputstate
			s = endtable(s); % end inputtable
		end
		if inputstate || commandstate || textstate  % start table
			s = [s '</p><p>'];                      % new paragraph
			s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
					' align="center" border="0"']; % start table
			s = [s '<tr> <td width="120"><font size="4"><strong>Output</strong></font></td>'];
		end
		state = 'output';
	elseif iotabstate % input/output table
		
		
    if uppertoken  % next input/output parameter
      s = [s '<tr> <td width="120" valign="baseline">' makecode(tok,1) '</td>'];
			[f0,f1] = regexp(posttok,'^ *[:-] *');
			if ~isempty(f0)
				posttok = posttok(f1+1:end);
			end
      s = [s '<td valign="baseline">' findmakecode(posttok)];
    else % continuation of description
      s = [s htmlspace findmakecode(u)];
    end
		
	elseif (tab || tabstate) ...
			&& ~examplestate && ~startspace && ~tabstartspace % arbitrary table
		if ~tabstate     % start table
			if liston, s = [s '</ul>']; liston = false; end
  		s = [s '</p><p>'];                % new paragraph
			s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
				' align="center" border="0"']; % start table
			oldstate = state;
			state = 'tab';
			tabstate = true;
			cellopen = false;
		end
		if cellopen 
			s = closecell(s);
			cellopen = false;
		end
		% first cell
		s = [s '<tr> <td width="120" valign="baseline">' makecode(tok,1) '</td>'];
		% get rid of :
		[f0,f1] = regexp(posttok,'^ *: *');
		if ~isempty(f0)
			posttok = posttok(f1+1:end);
		end
		colpos0 = findstr(cleanstr(posttok),r); % store starting pos 2nd cell
		% second cell
		s = [s '<td valign="baseline">'];
		[tok2,posttok2] = strtok(posttok);
		if strcmp(tok2,'-') % possible start of list
			s = [s '<ul><li>' findmakecode(posttok2)];
			liston = true;
		else
			s = [s  findmakecode(posttok)];
			liston = false;
		end
		cellopen = true;
		
	elseif startspace && tab && ~textstate
		if liston, s = [s '</ul>']; liston = 0; end
		s = [s htmlspace findmakecode(u)];
	elseif description && single
		s = endtable(s,tab);
		s = [s '</p><h3> Description</h3><p>' newline];
		state = 'text';
	elseif reference && single
		s = endtable(s,tab);
		s = [s '</p><h3> Reference(s)</h3><p>' newline];
		nref = 0;
		state = 'reference';
	elseif example && single
		s = endtable(s,tab);
		s = [s '</p><h3> Example(s)</h3><p>' newline];
		state = 'examp';
% 	elseif seealso && single
% 		s = endtable(s,tab);
% 		s = [s '</p><h3> See also</h3><p>' newline];
% 		state = 'seealso';
	elseif seealso
		s = endtable(s,tab);
		s = [s '</p><h3> See also</h3><p>' newline];
		state = 'seealso';
		if ~single
			s = [s commandrefs(posttok,recreate)];
		end
	else % undefined lines
		if examplestate
			if length(u) > 3 && strcmpi(u(1:4),'see ')
				s = [s '</p>' commandrefs(u(5:end),recreate) '<p>'];
			else
				s = [s strrep(code(strrep(r,' ','#$!'),0,3),'#$!','&nbsp;') '<br>'];
	%			s = [s code(r) '<br>'];
			end
		elseif refstate
			if abs(u(1)>=48) && abs(u(1)<=57) && nref > 0
				s = [s '<br>' u];
			else
				s = [s htmlspace u];
				nref = 1;
			end
		elseif seealsostate
			if listline
				s = [s '<strong><font size="4">' findmakecode(u(3:end)) '</font></strong><br>'];
			else
				s = [s commandrefs(u,recreate)];		
			end
		elseif tabstartspace && tabstate && (colpos1 > colpos0) ...
				&& (previous_empty || coding) % start code in table
			s = [s  strrep(code(strrep(r(colpos0:end),' ','#$!'),0,3),'#$!','&nbsp;') '<br>'];
			coding = true;
		elseif startspace && ~tabstate && ~liston ...
				&& (previous_empty || coding) % code line
			s = [s strrep(code(strrep(r,' ','#$!'),2,3),'#$!','&nbsp;') '<br>'];
			nextlinespace = '';
      coding = true;
		elseif listline
			if ~liston
				s = [s '<ul>'];
				liston = true;
			end
			if u(end) == ':'
				s = [s '<li>' findmakecode(u(3:end-1)) '<br>'];
				nextlinespace = '';
			else
				s = [s '<li>' findmakecode(u(3:end))];
			end
% 		elseif tabstate && ~startspace && ~tabstartspace % end of table
% 			s = endtable(s);
% 			state = oldstate;
% 			s = [s findmakecode(u)];
		elseif tabstate % next line in table, store starting position
			colpos0 = colpos1;
			s = [s newlinespace findmakecode(cleanstr(u))];
		else % just a line
			if u(end) == ':'
				s = [s newlinespace findmakecode(cleanstr(u(1:end-1))) '<br>'];
				nextlinespace = '';
			else
				s = [s newlinespace findmakecode(cleanstr(u))];
			end
		%	s = [s newlinespace findmakecode(cleanstr(u))];
		end
	end
	
	if emptyline
		previous_empty = true;
	else
		previous_empty = false;
	end
	
end

if cellopen
	s = closecell(s);
end
if tabstate
	s = endtable(s);
end


s = strrep(s,'<p>&nbsp;','<p>');
s = strrep(s,' </font>&nbsp;',' </font>');
s = strrep(s,['<p>' newline '&nbsp;'],'<p>');
s = [s '</p>' content_manual '</body></html>'];
[~,name] = fileparts(name); % allows for names like dataset/show
if exist(['./' subdir],'file') ~= 7
	mkdir(subdir);
end
writf([fullfile(subdir,name) '.html'],s);
disp([int2str(recreate) ' ' name ' html created'])
if nargout > 0
	out = s;
end
	
return

function i = isupper(s)
% true if s doesnot change by upper
i = strcmp(s,upper(s));
return

function out = code(s,n,fsize)
	%convert s to Courier, add n spaces in front, fontsize fsize
	if nargin < 3, fsize = 2; end
	if nargin < 2, n = 0; end
	out = ['<font face="Courier" size="' int2str(fsize) '">' htmlspace(n) s '</font>'];
return

function out = makecode(s,n,fsize)
	%convert any consequetive set of uppers and make them Courier size fsize,
	% add n spaces in front
	if strmatch(s(end),char(',','.'))
		send = s(end); s(end) = [];
	elseif length(s) > 1 && ~isempty(strmatch(s(end-1:end),char(', ','. ')))
		send = s(end-1:end); s(end-1:end) = [];
	else
		send = [];
	end
	if nargin < 3, fsize = 2; end
	if nargin < 2, n = 0; end
	out = [];
	if isupper(s)
		%out = code(lower(s),n);
		out = code(s,n,fsize);
	else
		while ~isempty(s)
			[t,s] = strtok(s);
			if isupper(t)
				%t = code(lower(t));
				t = code(t,n,fsize);
			end
			out = [out ' ' t];
		end
	end
	out = [out send];
return
	
function s = cleanstr(s)
	V = char([9 10 11 12 13 32]);
	for n=1:length(s)
		if all(V~=s(n))
			break;
		end
	end
	s = s(n:end);
	for n=length(s):-1:1
		if all(V~=s(n))
			break
		end
	end
	s = s(1:n);
return

function s = endtable(s,tab)
if strcmp(s(end-7:end),char([60 47 112 62 10 60 112  62]))
	s(end-7:end) = [];
end
if strcmp(s(end-6:end),char([60 47 112 62 60 112  62]))
	s(end-7:end) = [];
end
if nargin < 2 || tab % don't do this for tab = 0
	s = [s '</td></tr></table>' newline]; % end table
end

function s = commandrefs(r,recreate)
	if nargin < 2, recreate = 0; end
	s = [];
	r_debug = r;
	while ~isempty(r) && isempty(regexp(r,'^[ .,]*$', 'once' ))
		[tok,r] = strtok(r,' .,');
		tok = lower(tok);
		htmlname = [tok '.html'];
		file = which(tok);
		pp = fileparts(file);
		[~,subdir] = fileparts(pp);
		htmlname = fullfile(subdir,htmlname);
		if exist(htmlname,'file') == 2
			s = [s '<a href="../' htmlname '">' tok '</a>, '];
		elseif isempty(tok) || ~isempty(regexp(tok,'^ *', 'once' ))
			;
		elseif recreate
			tt = prhelp2html(tok); % don't iterate further!
			if ~isempty(tt)
				s = [s '<a href="../' htmlname '">' tok '</a>, '];
			else
				% disp([r_debug ' --> ' tok ])
				s = [s tok ', '];
			end
		else
			s = [s tok ', '];
		end
	end
	if ~isempty(s)
%		s(end-1:end) = [];
		s = code(s,0,3);
	end
	s = strrep(s,'\','/'); % avoid  \ in html addresses
return

function s = htmlspace(n)
	if nargin < 1, n=1; end
	if n > 0
		s = repmat('&nbsp;',1,n);
	else
		s = [];
	end
return

function s = findmakecode(r)
% find pieces of code (capitals only) and convert them to lower Courier
r = strrep(r,'. A ','. aA ');  % prevent conversion of A at the start of a sentence
r = [' ' r ' ']; % ending space may be helpful
r = strrep(r,'NaN',code('NaN'));

[f0,f1] = regexp(r,'[ ,(\[]+[A-Z0123456789=<>(){},.''''*+\\/;:\[\]_ ]+[ .,-]');

%[f0,f1,toks] = regexp(r,'[ ,(]+[A-Z0123456789=<>(){},*+\\/;:\[\]_ ]+[ .,-]');
if ~isempty(f0)
	if f0(1) > 1 % first part no code
		s = r(1:f0(1)-1);
	else
		s = [];
	end
	for j=1:length(f0)  % all code parts
		s = [s makecode(r(f0(j):f1(j)))];
		if j < length(f0) % between code parts
			s = [s r(f1(j)+1:f0(j+1)-1)];
		end
	end
	if f1(end) < length(r) % last part no code
		s = [s r(f1(end)+1:end)];
	end
else
	s = r;
end

if s(end) == ' ', s(end) = []; end % remove ending space
s = strrep(s,'. aA ','. A ');  % convert prevention back

function s = closecell(s)
if strcmp(s(end-7:end),char([60 47 112 62 10 60 112  62]))
	s(end-7:end) = [];
elseif strcmp(s(end-6:end),char([60 47 112 62 60 112  62]))
	s(end-7:end) = [];
end
s = [s '</td></tr>'];


%LISTN List lines specified by their line number
%
% t = listn(r,n)
% Get the lines in r given by the line numbers in n.
function t = listn(r,n)
k = [0,find(r==newline)];
t = [];
for j = n
	if j < length(k)
    t = [t,r(k(j)+1:k(j+1))];
	end
end
return

function run_all_files(command)

dirs = {'ldc','dataset','datafile','mapping'};
for n=1:length(dirs)
	prtools_dir = fileparts(which(dirs{n}));
	[~,prtools_dirname] = fileparts(prtools_dir); % get rid of root
	ff = dirnames(prtools_dir);
	for j=1:length(ff)
		[~,name] = fileparts(ff{j});
		if n==1
			feval(command,name); % prtools main commands
		else
			feval(command,fullfile(prtools_dirname,name)); % subdir commands
		end
	end
end

function files = dirnames(direct)
% get all m-files in dir

allnames = dir(fullfile(direct,'*.m'));
files = char(allnames(:).name);
files(strmatch('Contents.m',files),:) = [];
files(strmatch('Readme.m',files),:) = [];
files = cellstr(files);


function s = gethf(file)
%GETHF Create heading file from m-file
%
%	s = gethf(file)
%
% The heading of the given m-file consisting of all starting % lines
% is isolated and returned in s.
%
%	gethf(dir)
%
% All headings of the files in dir are merged into a file named headings.doc.
% Default dir is cd.
%
% Use mergeprt for restoring
if nargin == 0
	gethf(cd);
end
if isdir(file)
	files = dir(file);
	docfile = ['headings.doc'];
	m = size(files,1);
	for i = 1:m
		if (~files(i,:).isdir) & (files(i,:).name(end-1:end) == '.m')
			name = files(i,:).name;
			s = gethf(name);
			s = ['##1' name(1:end-2) newline s newline '##2' newline];
			%disp(s)
			appendf(docfile,s);
		end
	end
else
	%disp(file)
	[s,ns] = readf(file);
	p = grep(s,'%'); 
	if isempty(p) % no comments found
		s = [];
		return 
	end
	p = [p p(end)+10];  % trick
	I = find(p - [0,p(1:length(p)-1)] ~= 1);
	if p(1) == 1 & isempty(I), I = length(p) + 1; end
%	if length(I) > 0 & I(1) > 1
	if length(I) > 0
		if I(1) == 1 
			I(1) = [];
		end
		n = I(1) - 1;
		s = listn(s,p(1):n+p(1)-1);
		s = strrep(s,[newline '%'],newline);
		%s = strrep(s,[newline ' '],newline);
		%s = strrep(s,[newline newline],'&*&');
		%s = strrep(s,[newline '	'],'*&*	');
		%s = strrep(s,newline,' ');
		%s = strrep(s,'&*&',[newline newline]);
		%s = strrep(s,'*&*',newline);
		s = s(2:end);
	else 
		s = '';
	end
end

function [r,n] = readf(file,newline)
%READF Readfile
%
% [r,n] = readf(file,newline)
% Reads file into string r. The number of lines
% is returned in n.
if nargin < 2, newline = 13; end
fid = fopen(deblank(file),'r');
if fid < 0
   error(['Cann''t open ' file])
end
r = fscanf(fid,'%c');
fclose(fid);
n = length(find(r==newline));
if r(length(r)) ~= newline, n = n + 1; end
return



function writf(file,r)
%WRITF Write file
%
% writf(file,r)
% Write file from string r
fid = fopen(file,'w');
if fid < 0
   error(['Cannot open file ' file])
end
fprintf(fid,'%c',r);
fclose(fid);
return


function [k,z] = grep(r,s)
%GREP Get line specific lines
%
% [k,n] = grep(r,s)
% Get the numbers of all lines in the set of lines r 
% that contain s.
% n is the total number of lines.
n = [0,find(r==newline)];
m = findstr(r,s);
[i,j] = sort([n,m]);;
q = [0,j(1:length(j)-1)]-j;
k = j(find(q>0))-1;
z = length(n)-1; % # of lines
return


function t = content_manual
t = ['<table border="0" cellspacing="0" cellpadding="3" width="100%" '...
	   'align="center"><tr><td><a href="../prtools.html">contents</a>' ...
		 '</td><td><p align="right"><a '...
     'href="http://prtools.org/manual" target="_top">manual</a></p></td>'...
		 '</tr></table></p>'];
return

