// RTFBeamer reads RTF version of ppt and writes out as Beamer file

// stl includes first
#include<string>
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>  // for transform

using namespace std;

//globals
bool frameopen = false, dump = false;
int section;
string text;
int style, lastlevel,frames = 0;
 
 
ifstream Infile;
ofstream Outfile;
ofstream Dumpfile;

// function prototypes
void newframe(string text);
void item(int style, string text);
void WriteHeader(void);
void charedit(void);
string editclause(string clause);
void Greek(void);
string symbol(string clause);
string specials(string text);


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
int main()
{
    string infilename = "test.rtf",outfilename,dumpname,Line,newpar,strstyle;
    int lc=0,lb,sp,par,stpos;
    cout << "\nEnter File Name: "; 
    cin >> infilename;
    Infile.open(infilename.c_str());  
    if(Infile.is_open()) 
        cout << "\nFile Opened" << endl; 
        else {cout << "\nOpen Failed\n\n"; system("pause"); return(1);}
    int dot = infilename.find_last_of(".");
    outfilename = infilename.substr(0,dot) + "B.tex";
    Outfile.open(outfilename.c_str());
    dumpname = infilename.substr(0,dot) + ".txt";
    if(dump == true) Dumpfile.open(dumpname.c_str());
    
    WriteHeader();  // standard front end of beamer file
    int pard = -99;
    while(pard<0)
    {
        getline(Infile,Line);
        pard = Line.find("\\pard");
        }
    while(Infile.peek() != EOF)
    {
        lc++;
        int pos = Line.find("\pard");  // text lines begin with \pard
        if(pos>=0) newpar = Line; else newpar += Line;
        stpos = newpar.find("\\s",pos);
        strstyle = newpar.substr(stpos+2,1); // pull digit for \s1, \s2, etc
        style = atoi(strstyle.c_str());
        par = newpar.find("\\par",newpar.length()-5);
        newpar.replace(par,4,"}"); // replace \par with }
        int ln = newpar.find("\\line");
        if(ln>=0) newpar.replace(ln,5,""); // replace \line with }
        string clause[100];
        int nclause = 0;
        int curlyc = 0,curlyo = 0;
        while(curlyo>=0)
        {
                        curlyo = newpar.find("{",curlyc);
                        curlyc = newpar.find("}",curlyo);
                        if(curlyc>curlyo) nclause++;
                        clause[nclause] = newpar.substr(curlyo+1,curlyc-curlyo-1);
                        curlyo = newpar.find("{",curlyc);
        }
        text = "";
        for(int c=1;c<=nclause;c++)
        {
if(dump == true) Dumpfile <<c<<" "<<clause[c]<<endl;
             clause[c] = editclause(clause[c]);
             text += clause[c];
        } 
if(dump == true) Dumpfile <<"text= "<<text<<endl;
        charedit();  // replace certain symbols coded as \'hexhex
        Greek();     // replace Greek characters
        if(text != "") if(style == 1) newframe(text); else item(style,text);
        getline(Infile,Line);
        if(Line == "}") break;
        }
        for(int ll=2;ll<lastlevel;ll++) Outfile << "     \\ei\n";
        Outfile << "   \\ei\n\\end{frame}\n\\end{document}"<<endl;  //on EOF
        cout << endl << frames << " slides converted to frames\n";
        cout << "Written to file: " << outfilename<<endl;
        system("PAUSE");
        return(0);
}
    
    
///////////////////////////////////////////////////////////////////////////////
void newframe(string text)
{
     frames++;
     cout << "Slide: "<< frames << " "<< text << endl;
     string tab = "";
     for(int i=2;i<=lastlevel;i++) 
     {
         tab = "";    
         int tl = lastlevel - i +1;
         for(int t=1;t<=tl;t++) tab += "   ";
         Outfile << tab << "\\ei" << endl;
         }
//     if(lastlevel > 1) Outfile << "   \\ei" << endl;
     if(frameopen == true) Outfile << "\\end{frame}"<<endl<<endl;
     frameopen = true;
     if((frames-1) % 10 == 0) {section++; Outfile << "\\section{"<<section<<"}\n";}
     Outfile << "\\begin{frame}"<<endl<<"\\frametitle{"<<text<<"}\n\\pause"<<endl;
     lastlevel = 1;
     }

///////////////////////////////////////////////////////////////////////////////
void item(int style, string text)
{
     string tab = "",tab2 = "";
     for(int i=2;i<=style;i++) tab += "   ";
     for(int i=2;i<=lastlevel;i++) tab2 += "   ";
     for(int i=style+1;i<=lastlevel;i++) Outfile << tab2 <<"\\ei" << endl;
     for(int i=lastlevel+1;i<=style;i++) // set itemize
     {
             Outfile << tab << "\\bi " << endl;
             }
     Outfile << tab << "\\item " << text << endl;
     lastlevel = style;
     }
    
///////////////////////////////////////////////////////////////////////////////
void WriteHeader(void)
{
    Outfile << "\\documentclass{beamer} %Converted by RTFBeamer (c) 2005 James A. Stimson\n";    
    Outfile << "\\usepackage{dcolumn}\n\\newcolumntype{.}{D{.}{.}{-1}}\n\\newcolumntype{d}[1]{D{.}{.}{#1}}\n\\usetheme{Berkeley}\n\n";
    Outfile << "\\newcommand{\\be}{\\begin{enumerate}[<+->]}\n\\newcommand{\\ee}{\\end{enumerate}}\n";
    Outfile << "\\newcommand{\\bq}{\\begin{quote}}\n\\newcommand{\\eq}{\\end{quote}}\n";
    Outfile << "\\newcommand{\\bd}{\\begin{description}[<+->]}\n\\newcommand{\\ed}{\\end{description}}\n";
    Outfile << "\\newcommand{\\bi}{\\begin{itemize}[<+->]}\n\\newcommand{\\ei}{\\end{itemize}}\n\n";
    Outfile << "\\title[]{TITLE}\n\\author{AUTHOR}\n\\institute{INSTITUTION}\n\\date{\\today}\n\n";   
    Outfile << "\\begin{document}\n\n\\begin{frame}\n   \\titlepage\n\\end{frame}\n\n";
    Outfile << "\\begin{frame}\n   \\frametitle{Lecture Outline}\n   \\tableofcontents[pausesections]\n\\end{frame}\n\n";
    Outfile << "\\AtBeginSection[] % Do nothing for \\section*\n{\n\\begin{frame}<beamer>\n\\frametitle{Outline}\n\\tableofcontents[currentsection]\n\\end{frame}}\n\n";
}

///////////////////////////////////////////////////////////////////////////////
void charedit(void)
{
     string sstring[10],rstring[10]; // search and replace strings
     sstring[0] = "\\'92"; rstring[0] = "'";   // apostrophe
     sstring[1] = "\\'96"; rstring[1] = "--"; //minus
     sstring[2] = "\\'93"; rstring[2] = "``"; // left quote marks
     sstring[3] = "\\'94"; rstring[3] = "''"; //right quote marks
     sstring[4] = "\\'97"; rstring[4] = "---"; // em dash
     sstring[5] = "\\tab"; rstring[5] = "  "; // tab
     int nedits=5,pos;
     for(int i=0;i<=nedits;i++)
     {
             pos = 1; //for while
             int slength = 4;
             while(pos>=0)
             {
             pos = text.find(sstring[i]);
             if(i==5) slength = 5;
             if(pos>=0) text.replace(pos,slength,rstring[i]);
             }
     }
if(dump == true) Dumpfile <<"Edit: text= "<<text<<endl;     
     
}
///////////////////////////////////////////////////////////////////////////////
string symbol(string clause) 
{
       int pos,n,sp;
       string hex,nstr,digit="0123456789abcdef";
       pos = clause.find("SYMBOL ");
       if(pos<0) return("");
       sp = clause.find(" ",pos+7);
       if(sp<0) return("");
       nstr = clause.substr(pos+7,sp-pos-7);  // symbol number
       n = atoi(nstr.c_str()) - 80;
       if(n<32) hex = "\\'e" + digit.substr(n % 16,1);
       if(n>31 && n<48) hex = "\\'f" + digit.substr(n % 16,1);
       return(hex);
}
       

///////////////////////////////////////////////////////////////////////////////
 
void Greek()
{
     string Greekname[] = { "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", 
     "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", 
     "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
     "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", 
     "Upsilon", "Phi", "Psi", "Omega" };
     string Greekcode[] = { "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", 
     "eb", "ec", "ed", "ee",  "f0", "f1", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
     "c3", "c4", "c8", "cb", "ce", "d0", "d3", "d5", "d6", "d8", "d9" };
             int pos = 1; //for while
             int slength = 4;
             while(pos>=0)
             {
             pos = text.find("\\'"); //signals beginning of font change
             if(pos<0) return;
             string twochar =text.substr(pos+2,2);
             if(pos>=0) 
             {
                        int gchar = -1; //default is not found
                        for(int i=0;i<34;i++)
                        {
                                if(twochar == Greekcode[i])
                                {
                                           gchar = i;
                                           break;
                                }
                        }
                        if(gchar>=0)
                        {                       
                            string texeq =  Greekname[gchar] + "$";
                            texeq.replace(0,0,"$\\");
                            text.replace(pos,4,texeq);
                         } else return;
             }
             } // end while
     
}

///////////////////////////////////////////////////////////////////////////////
string specials(string text) // put \ in fron of latex special characters
{
     string spec[7] = {"#", "$", "%", "&", "~", "_", "^"};
     int pos;
         for(int i = 0;i<7;i++)
         {
                     pos=0;
                     while(pos>=0)
                     {
                     pos = text.find(spec[i],pos);
                     if(pos>=0) 
                     {
                            text.replace(pos,1,"\\"+spec[i]); 
                            pos++;
                            pos++;
                     }
                     } 
         }
         return(text);
}

///////////////////////////////////////////////////////////////////////////////
string editclause(string clause)
{
    string fmt="",ss="",text="",type="";
    int sl,sl1,sl2,sl3,blank,bl;
    sl1 = clause.find("\\field");
    if(sl1>=0) type="field";
    sl1 = clause.find("\\"); //find first backslash in clause
    sl2 = clause.find("\\",sl1+1);  //find second
    bl = clause.find(" ",sl1+1);  //find second
    if(bl>=0 && bl<sl2) sl2=bl; //if blank before \, use it as delimiter
    sl3 = clause.find("\\",sl2+1); //find third
    if(sl3<0) sl3 = clause.find(" ",sl2+1); //no \, look for blank instead
    if(dump == true) Dumpfile <<"sl1= "<<sl1<<" sl2= "<<sl2<<" sl3= "<<sl3<<endl;   
    if(sl3>sl2) ss = clause.substr(sl2+1,sl3-sl2-1);
    if(dump == true) Dumpfile <<"ss= "<<ss<<endl;
//    if(sl2>sl1+10) {fmt = clause.substr(sl1+1,2); sl2=sl1+2;}; //kludge, do better?
    sl = sl2 - sl1 - 1;
    if(sl>0) fmt = clause.substr(sl1+1,sl);  //extract fmt command
    if(fmt == "pntext" || fmt == "*" || fmt == "pntxtb" || fmt == "fldrslt") return(""); // exit with blank string
    blank = clause.find(" ",sl2); // find beginning of text
    if(dump == true) Dumpfile <<"fmt= "<<fmt<<" blank= "<<blank<<endl;
    text = "";
//    if(clause.length()-blank-1 >= blank+1) text = clause.substr(blank+1,clause.length()-blank-1);
    if(clause.length()-blank-1 > 0) text = clause.substr(blank+1,clause.length()-blank);
    if(dump == true) Dumpfile <<"text= "<<text<<endl;
    text = specials(text); //insert \ before special characters
    if(fmt == "b") text = " \\textbf{" + text + "}";
    if(fmt == "i") text = " \\emph{" + text + "}";
    if(ss == "super") text = " $^{" + text + "}$";
    if(ss == "sub") text = " $_{" + text + "}$";
    if(type == "field") text = symbol(clause);
    return(text);
}



