{$H+}
Program corridx;
(*
This makes corrections in a *.idx
file created by Latex as a raw index

in Latex we have these commands for making the index:

\begin{verbatim}
    % acronyms 2 Entries
    \newcommand{\ia}[2]{#1 (#2)\index{acr #2@#2!#1}}
    % chemical 1 Entry
    \newcommand{\ic}[1]{#1\index{chem #1@#1}}
    % general 1 Entry
    \newcommand{\ig}[1]{#1\index{gen #1@#1}}
    Example: \ia{Polyalkylene oxide}{PAO}

\end{verbatim}


To start the program 

with a command line parameter:

in winedt use as command line

c:\mypathto\corridx.exe "%P\%N.idx"
  %P     Input File's Path
  %N     Input File's Name

                             
Better put in your Windet directory and use:
to be clarified work out how it works really

% Exe('%B\Exec\MiKTeX\corridx.exe');                                            
% 
% Exe('%B\Exec\MiKTeX\TeX.edt');                                            

*)


const

cifn='in.txt'; 
cofn='out.txt';
ctfn='idx.tmp';
clfn='idx.log';


var
ifn,ofn,tfn,lfn: shortstring;
s,t,l: text;
str: string;
LineNumber : word;


Procedure Message(str: shortstring);
begin
    if str='' then
    begin
        Writeln;
        Writeln(l, str);
    end
    else
    begin
        Writeln('[',linenumber,'] ',str);
        Writeln(l, '[',linenumber,'] ',str);
    end;
end;

Procedure copytxt(str, tfn: shortstring);
var
    s,t: text;
    c: char;
begin
    Message('Copy '+ str + ' to '+ tfn);
    Assign(s,str);
    Assign(t,tfn);
    reset(s);
    rewrite(t);
    while not eof(s) do
    begin
        read(s,c);
        write(t,c);
    end;
    close(s);
    close(t);
end;





Procedure init;
begin
    LineNumber:=0; ;
    ifn:=cifn;
    ofn:=cofn;
    tfn:=ctfn;
    lfn:=clfn;
if paramcount=1 then 
begin
    ifn:=paramstr(1);
    tfn:=paramstr(1)+'.tmp';
    lfn:=paramstr(1)+'.log';
    ofn:=ifn;
end;
    Assign(l,lfn);
    rewrite(l);
    Message('This is corridx');
    Message('Preprocessor for the Latex File *.idx');
    Message('');
    Message('Program Info '+ paramstr(0));

    Message('Input File is '+ ifn);
    Message('Output File is '+ ofn);
    Message('Temp File is '+ tfn);
    Copytxt(ifn,tfn);
    Assign(s,tfn);
    Assign(t,ofn);
    reset(s);
    rewrite(t);
end;

Procedure finish;
begin

    close(s);
    close(t);

    Message('Finished corridx'); 
    close(l);
    if paramcount <> 1 then readln(input);

end;


Procedure Error(str: string);
begin

    close(s);
    close(t);

    Message('Error corridx'); 
    Message(str);
    Message('restoring input file');
    Copytxt(tfn,ifn);
    close(l);
    readln(input);
    halt;

end;


Procedure RepAll(var Mainstr: string; Findstr, Replacestr: string);
var
p: longint;
begin
p:=pos(Findstr,Mainstr); 
while  p>0 do
    begin
        delete(Mainstr,p,length(findstr));
        Insert(Replacestr, Mainstr,p);
        p:=pos(Findstr,Mainstr); 
    end;
end;



Function Pagestr(var str: string):string;
(*
    Here we extract the page number enclosed in curled brackets
    \indexentry{acr TDI@TDI!toluene diisocyanate }{49}
*)

var
s: string;
i, p: longint;
 
begin
    s:='{0}'; {Makeindex wants a valid pagenumber}
    if pos('\section',str)>0 then 
    begin
        Pagestr:=s;
        Message('an index subheading');
        exit;
    end;
    p:= pos('}{', str);
    if p>0 then 
    begin
    s:='';
    for i:= p+1 to length(str) do s:=s+str[i];
    end
    else Error('no page string');
    if s= '{}' then Error('invalid page string');
    Pagestr:=s;
end;


Function Sortstr(var str: string):string;
(*
    Here we extract what is behind 
    '\indexentry{' up to '@'
    \indexentry{acr TDI@TDI!toluene diisocyanate }{49}
*)

var
s: string;
i, p,q: longint;
 
begin
    
    s:='';
    p:= length('\indexentry{');
    q:= pos('@', str);
    if (p>0) and (q>0) then 
    begin
        inc(p);
        dec(q);
        for i:=  p to q do s:=s+str[i];
    end;
    Sortstr:=s;
end;


Function BeforeSubentry(var str: string):string;
(*
    Here we extract what is behind 
    '\indexentry{' up to '!'
    \indexentry{acr TDI@TDI!toluene diisocyanate }{49}
*)

var
s: string;
i, p,q: longint;
 
begin
   if pos('!',str)=0 then Error('no subindex');
   s:='';

    p:= length('\indexentry{');
    q:= pos('!', str);
    if (p>0) and (q>0) then 
    begin
        inc(p);
        dec(q);
        for i:=  p to q do s:=s+str[i];
    end;
    BeforeSubentry:=s;
end;

Function AfterSubentry(var str: string):string;
(*
    Here we extract what is behind 
    '!'up to '}{'
    \indexentry{acr TDI@TDI!toluene diisocyanate }{49}
*)

var
s: string;
i, p,q: longint;
 
begin
    if pos('!',str)=0 then Error('no subindex');
    s:='';
    p:= pos('!', str);
    q:= pos('}{', str);
    if (p>0) and (q>0) then 
    begin
        inc(p);
        dec(q);
        for i:=  p to q do s:=s+str[i];
    end;
    AfterSubentry:=s;
end;




Function indexstr(var str: string):string;
(*
    Here we extract what is behind 
    '@'up to '}{'
    \indexentry{acr TDI@TDI!toluene diisocyanate }{49}
*)

var
s: string;
i, p,q: longint;
 
begin
    s:='';
    p:= pos('@', str);
    q:= pos('}{', str);
    if (p>0) and (q>0) then 
    begin
        inc(p);
        dec(q);
        for i:=  p to q do s:=s+str[i];
    end;
    Indexstr:=s;
end;


Function Subheading(var str: string):boolean;
var 
b: boolean;
s: string;
begin

    b:= (pos('\section',str)>0) or
        (pos('\subsection',str)>0) or
        (pos('\subsubsection',str)>0) or
        (pos('\paragraph',str)>0);
    subheading:=b;
    if b then 
        begin
        s:='\indexentry{'+Sortstr(str)+'@'+indexstr(str) +'}'+Pagestr(str);    
        str:=s;
            
        
        end;
end;




Procedure CleanMath(var str: string);
var
    b: boolean;
    i: longint;
begin
    b:=false;
    for i:=1 to length(str) do
    begin
    if str[i] = '$' then b:= not b; {toggle b if a $ is in str}
    if b then str[i]:= ' ';
    end;    

end;

Procedure CleanSoftHyphen(var str: string);
begin
    RepAll(str,'\-','');
end;


Procedure CleanNonLetter(var str: string);
var
    i: longint;
begin
    for i:=1 to length(str) do
    begin
    if str[i] in ['A'..'Z', 'a'..'z','~'] then else str[i]:= ' ';
    end;    

end;


Procedure CleanSingleLetter(var str: string);
var
    i: longint;
begin
    if str[2]=' ' then str[1]:=' '; {remove a leading non space}
    for i:=2 to length(str)-1 do
    begin
    if (str[i-1] = ' ') and (str[i+1] = ' ')   then str[i]:= ' ';
    end;    

end;

Procedure CleanPrefix(var str: string);
begin
{I want to clean some prefixes}
    str:=lowercase(str);
    Repall(str,
           'tert ', 
           '     ');

    Repall(str,
           'sec ', 
           '    ');

    Repall(str,
           'cis ', 
           '    ');

    Repall(str,
           'trans ', 
           '      ');
    Repall(str,
           'syn ', 
           '    ');

    Repall(str,
           'anti ', 
           '     ');


    Repall(str,
           'exo ', 
           '    ');

    Repall(str,
           'endo ', 
           '     ');

    Repall(str,
           'cyclo ', 
           '      ');

    Repall(str,
           'spiro ', 
           '      ');

end;


Procedure CleanChem(var str: string);
begin
    CleanMath(str);
    CleanNonLetter(str);
    CleanSingleLetter(str);
    CleanPrefix(str);
end;


Procedure SetFirstCap(var istr,sstr: string); {Indexstring and Sortstring}
var
s: string;
i: longint;
begin
    s:=istr;
    CleanChem(s);
    sstr:=s;
    repall(sstr,' ','');
    sstr:=lowercase(sstr);
    for i:= 1 to length(s) do if s[i] <> ' ' then 
        begin
            istr[i]:= upcase(istr[i]); 
            exit;
        end;

end;

Procedure Corracr(var str: string);
var
    pstr, istr, sstr: string;
begin
    if pos('\indexentry{acr',str)=1 then 
    begin
        istr:=AfterSubentry(str);
        pstr:=pagestr(str);
        Setfirstcap(istr, sstr); {We do not use the sortstring here}
        sstr:=Beforesubentry(str);
        str:= '\indexentry{'+sstr+'!' + istr + '}' + pstr;
        
    end;
end;


Procedure Corrchem(var str: string);
var
    pstr, istr, sstr: string;
begin
    if pos('\indexentry{chem',str)=1 then 
    begin
        istr:=Indexstr(str);
        pstr:=pagestr(str);
        Setfirstcap(istr, sstr);

        str:= '\indexentry{chem '+sstr+'@' + istr + '}' + pstr;
        
    end;
end;


Procedure Corrgen(var str: string); 
var
    i,p: longint;
begin

    if pos('\indexentry{gen',str)=1 then 
    begin
        if pos('!',str) >0 then message('A subentry in general index');
        p:=pos('@',str);
        if p > 0 then 
        begin 
        {We look only to make small case before '@'}
        for i:= 13 to p do str[i]:= lowercase(str[i]);
        {We look only to capitalize the first letter after '@'}
        for i:= p to length(str) do if str[i] in ['A'..'Z', 'a'..'z'] then 
                begin
                str[i] :=Upcase(str[i]); exit;
                end;    
        end;
    end;
end;



begin

    init;
    Message('start processing');
    Message('from '+tfn+' into '+ofn);
    while not eof(s)
    do
    begin
        readln(s,str);
        inc(LineNumber);
        if pos('}{',str)=0 then Error('no pagestring');
        if pos('@',str)=0 then Error('no sortstring');
        CleanSoftHyphen(str);
        if not subheading(str) then
            begin
                corracr(str);
                corrchem(str);
                corrgen(str);
            end;    
            writeln(t,str);
    end;
    
    finish;


end.
