/*
 * File:     tex2rtf.cc
 * Purpose:  Converts Latex to RTF
 *
 *                       wxWindows 1.50
 * Copyright (c) 1993 Artificial Intelligence Applications Institute,
 *                   The University of Edinburgh
 *
 *                     Author: Julian Smart
 *                        Date: 7-9-93
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose is hereby granted without fee, provided
 * that the above copyright notice, author statement and this permission
 * notice appear in all copies of this software and related documentation.
 *
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
 * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
 * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
 * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
 * THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <wx.h>
#include <wx_help.h>
#include <ctype.h>
#include "tex2any.h"
#include "tex2rtf.h"
#include "rtfutils.h"

TexChunk *currentSection = NULL;
TexChunk *currentMember = NULL;
Bool startedSections = FALSE;
char *contentsString = NULL;
Bool suppressNameDecoration = FALSE;
Bool winHelp = FALSE;  // Output in Windows Help format if TRUE, linear otherwise
Bool isInteractive = FALSE;
Bool runTwice = FALSE;
Bool convertMode = TEX_RTF;
wxHelpInstance *HelpInstance = NULL;

FILE *Contents = NULL;   // Contents page
FILE *Chapters = NULL;   // Chapters (WinHelp RTF) or rest of file (linear RTF)
FILE *Sections = NULL;
FILE *Subsections = NULL;
FILE *Subsubsections = NULL;

char *InputFile = NULL;
char *OutputFile = NULL;
char *MacroFile = copystring("tex2rtf.ini");

char FileRoot[300];
char ContentsName[300];    // Contents page from last time around
char TmpContentsName[300]; // Current contents page
char RefName[300];         // Reference file name

wxMenuBar *menuBar = NULL;
MyFrame *frame = NULL;

Bool Go(void);

// This statement initializes the whole application and calls OnInit
MyApp myApp;

// `Main program' equivalent, creating windows and returning main app frame
wxFrame *MyApp::OnInit(void)
{
  // Use default list of macros defined in tex2any.cc
  DefineDefaultMacros();
  AddMacroDef("hardy", 0);

  TexInitialize();

  int n = 1;
  
  // Read input/output files
  if (argc > 1)
  {
    if (argv[1][0] != '-')
    {
      InputFile = argv[1];
      n ++;

      if (argc > 2)
      {
        if (argv[2][0] != '-')
        OutputFile = argv[2];
        n ++;
      }
    }
  }

  for (int i = n; i < argc;)
  {
    if (strcmp(argv[i], "-winhelp") == 0)
    {
      i ++;
      convertMode = TEX_RTF;
      winHelp = TRUE;
    }
    else if (strcmp(argv[i], "-interactive") == 0)
    {
      i ++;
      isInteractive = TRUE;
    }
    else if (strcmp(argv[i], "-rtf") == 0)
    {
      i ++;
      convertMode = TEX_RTF;
    }
    else if (strcmp(argv[i], "-html") == 0)
    {
      i ++;
      convertMode = TEX_HTML;
    }
    else if (strcmp(argv[i], "-xlp") == 0)
    {
      i ++;
      convertMode = TEX_XLP;
    }
    else if (strcmp(argv[i], "-twice") == 0)
    {
      i ++;
      runTwice = TRUE;
    }
    else if (strcmp(argv[i], "-macros") == 0)
    {
      i ++;
      if (i < argc)
      {
        MacroFile = copystring(argv[i]);
        i ++;
      }
    }
    else
    {
      char buf[100];
      sprintf(buf, "Invalid switch %s.\n", argv[i]);
      OnError(buf);
      i++;
    }
  }

  if (!InputFile && !OutputFile)
    isInteractive = TRUE;

  if (isInteractive)
  {
    // Create the main frame window
    frame = new MyFrame(NULL, "Tex2RTF", 0, 0, 400, 300);
    frame->CreateStatusLine(2);
    char buf[200];
    strcpy(buf, "In ");

    if (winHelp)
      strcat(buf, "linear ");
    if (convertMode == TEX_RTF) strcat(buf, "RTF");
    else if (convertMode == TEX_HTML) strcat(buf, "HTML");
    else if (convertMode == TEX_XLP) strcat(buf, "XLP");
    strcat(buf, " mode.");
    frame->SetStatusText(buf, 1);

    // Make a menubar
    wxMenu *file_menu = new wxMenu;
    file_menu->Append(TEX_GO, "&Go",                        "Run converter");
    file_menu->Append(TEX_SET_INPUT, "Set &Input File",     "Set the LaTeX input file");
    file_menu->Append(TEX_SET_OUTPUT, "Set &Output File",   "Set the output file");
    file_menu->Append(TEX_VIEW_LATEX, "View &LaTeX File",   "View the LaTeX input file");
    file_menu->Append(TEX_VIEW_OUTPUT, "View Output &File", "View output file");
    file_menu->Append(TEX_QUIT, "&Exit",                    "Exit Tex2RTF");

    wxMenu *macro_menu = new wxMenu;

    macro_menu->Append(TEX_LOAD_CUSTOM_MACROS, "&Load Custom Macros", "Load custom LaTeX macro file");
    macro_menu->Append(TEX_VIEW_CUSTOM_MACROS, "View &Custom Macros", "View custom LaTeX macros");

    wxMenu *mode_menu = new wxMenu;

    mode_menu->Append(TEX_MODE_RTF, "Output linear &RTF",   "Wordprocessor-compatible RTF");
    mode_menu->Append(TEX_MODE_WINHELP, "Output &WinHelp RTF", "WinHelp-compatible RTF");
    mode_menu->Append(TEX_MODE_HTML, "Output &HTML",        "HTML World Wide Web hypertext file");
    mode_menu->Append(TEX_MODE_XLP, "Output &XLP",          "wxHelp hypertext help file");

    wxMenu *help_menu = new wxMenu;

    help_menu->Append(TEX_HELP, "&Help", "Tex2RTF Contents Page");
    help_menu->Append(TEX_ABOUT, "&About Tex2RTF", "About Tex2RTF");

    menuBar = new wxMenuBar;
    menuBar->Append(file_menu, "&File");
    menuBar->Append(macro_menu, "&Macros");
    menuBar->Append(mode_menu, "&Conversion Mode");
    menuBar->Append(help_menu, "&Help");

    frame->SetMenuBar(menuBar);
    frame->textWindow = new wxTextWindow(frame);

    (*frame->textWindow) << "Welcome to Julian Smart's LaTeX to RTF converter.\n\n";
    
    (*frame->textWindow) << "Usage: tex2rtf [input] [output] [switches]\n\n";
    (*frame->textWindow) << "where valid switches are\n";
    (*frame->textWindow) << "    -interactive\n";
    (*frame->textWindow) << "    -twice\n";
    (*frame->textWindow) << "    -macros <filename>\n";
    (*frame->textWindow) << "    -winhelp\n";
    (*frame->textWindow) << "    -rtf\n";
    (*frame->textWindow) << "    -html\n";
    (*frame->textWindow) << "    -xlp\n\n";

    HelpInstance = new wxHelpInstance(TRUE);
    HelpInstance->Initialize("tex2rtf");

    frame->Show(TRUE);
    return frame;
  }
  else
  {
    Go();
    if (runTwice) Go();
    return NULL;
  }

  // Return the main frame window
  return frame;
}

// My frame constructor
MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
  wxFrame(frame, title, x, y, w, h)
{}

// Intercept menu commands
void MyFrame::OnMenuCommand(int id)
{
  switch (id) {
    case TEX_QUIT:
      delete this;
      break;
    case TEX_GO:
    {
      menuBar->EnableTop(0, FALSE);
      menuBar->EnableTop(1, FALSE);
      menuBar->EnableTop(2, FALSE);
      menuBar->EnableTop(3, FALSE);
      SetStatusText("Working, pass 1...");
      textWindow->Clear();
      wxYield();
      Go();
      if (runTwice)
      {
        SetStatusText("Working, pass 2...");
        wxYield();
        Go();
      }
      if (runTwice)
        SetStatusText("Done, 2 passes.");
      else
        SetStatusText("Done, 1 pass.");
      menuBar->EnableTop(0, TRUE);
      menuBar->EnableTop(1, TRUE);
      menuBar->EnableTop(2, TRUE);
      menuBar->EnableTop(3, TRUE);
      break;
    }
    case TEX_SET_INPUT:
    {
      ChooseInputFile(TRUE);
      break;
    }
    case TEX_SET_OUTPUT:
    {
      ChooseOutputFile(TRUE);
      break;
    }
    case TEX_VIEW_OUTPUT:
    {
      ChooseOutputFile();
      if (OutputFile && FileExists(OutputFile))
      {
        textWindow->LoadFile(OutputFile);
        char buf[300];
        sprintf(buf, "Tex2RTF [%s]", FileNameFromPath(OutputFile));
        frame->SetTitle(buf);
      }
      break;
    }
    case TEX_VIEW_LATEX:
    {
      ChooseInputFile();
      if (InputFile && FileExists(InputFile))
      {
        textWindow->LoadFile(InputFile);
        char buf[300];
        sprintf(buf, "Tex2RTF [%s]", FileNameFromPath(InputFile));
        frame->SetTitle(buf);
      }
      break;
    }
    case TEX_LOAD_CUSTOM_MACROS:
    {
      textWindow->Clear();
      char *s = wxFileSelector("Choose custom macro file", PathOnly(MacroFile), FileNameFromPath(MacroFile), "ini", "*.ini");
      if (s)
      {
        MacroFile = copystring(s);
        ReadCustomMacros(s);
        ShowCustomMacros();
      }
      break;
    }
    case TEX_VIEW_CUSTOM_MACROS:
    {
      textWindow->Clear();
      wxYield();
      ShowCustomMacros();
      break;
    }
    case TEX_MODE_RTF:
    {
      convertMode = TEX_RTF;
      winHelp = FALSE;
      InputFile = NULL;
      OutputFile = NULL;
      SetStatusText("In linear RTF mode.", 1);
      break;
    }
    case TEX_MODE_WINHELP:
    {
      convertMode = TEX_RTF;
      winHelp = TRUE;
      InputFile = NULL;
      OutputFile = NULL;
      SetStatusText("In WinHelp RTF mode.", 1);
      break;
    }
    case TEX_MODE_XLP:
    {
      convertMode = TEX_XLP;
      InputFile = NULL;
      OutputFile = NULL;
      SetStatusText("In XLP mode.", 1);
      break;
    }
    case TEX_MODE_HTML:
    {
      convertMode = TEX_HTML;
      InputFile = NULL;
      OutputFile = NULL;
      SetStatusText("In HTML mode.", 1);
      break;
    }
    case TEX_HELP:
    {
      HelpInstance->LoadFile();
      HelpInstance->DisplayContents();
      break;
    }
    case TEX_ABOUT:
    {
      wxMessageBox("Tex2RTF\nLaTeX to RTF, WinHelp, HTML and wxHelp Conversion\n\n(c) Julian Smart 1993", "About Tex2RTF");
      break;
    }
  }
}

void ChooseInputFile(Bool force)
{
  if (force || !InputFile)
  {
    char *s = wxFileSelector("Choose LaTeX input file", PathOnly(InputFile), FileNameFromPath(InputFile), "tex", "*.tex");
    if (s)
    {
      char buf[300];
      InputFile = copystring(s);
      sprintf(buf, "Tex2RTF [%s]", FileNameFromPath(InputFile));
      frame->SetTitle(buf);
      OutputFile = NULL;
    }
  }
}

void ChooseOutputFile(Bool force)
{
  char extensionBuf[10];
  char wildBuf[10];
  strcpy(wildBuf, "*.");
  char *path = NULL;
  if (OutputFile)
    path = PathOnly(OutputFile);
  else if (InputFile)
    path = PathOnly(InputFile);
    
  switch (convertMode)
  {
    case TEX_RTF:
    {
      strcpy(extensionBuf, "rtf");
      strcat(wildBuf, "rtf");
      break;
    }
    case TEX_XLP:
    {
      strcpy(extensionBuf, "xlp");
      strcat(wildBuf, "xlp");
      break;
    }
    case TEX_HTML:
    {
      strcpy(extensionBuf, "html");
      strcat(wildBuf, "html");
      break;
    }
  }
  if (force || !OutputFile)
  {
    char *s = wxFileSelector("Choose output file", path, FileNameFromPath(OutputFile),
                   extensionBuf, wildBuf);
    if (s)
      OutputFile = copystring(s);
  }
}

Bool Go(void)
{
  ChooseInputFile();
  ChooseOutputFile();
  if (!InputFile || !OutputFile)
    return FALSE;

  // Find extension-less filename
  strcpy(FileRoot, OutputFile);
  StripExtension(FileRoot);
  sprintf(ContentsName, "%s.con", FileRoot);
  sprintf(TmpContentsName, "%s.cn1", FileRoot);
  sprintf(RefName, "%s.ref", FileRoot);

  if (FileExists(RefName))
    ReadTexReferences(RefName);

  Bool success = FALSE;

  if (InputFile && OutputFile)
  {
    if (!FileExists(InputFile))
    {
      OnError("Cannot open input file!");
      TexCleanUp();
      return FALSE;
    }

    OnInform("Reading LaTeX file...");
    TexLoadFile(InputFile, MacroFile);

    switch (convertMode)
    {
      case TEX_RTF:
      {
        success = RTFGo();
        break;
      }
      case TEX_XLP:
      {
        success = XLPGo();
        break;
      }
      case TEX_HTML:
      {
        success = HTMLGo();
        break;
      }
    }
  }

  if (success)
  {
    WriteTexReferences(RefName);
    TexCleanUp();
    startedSections = FALSE;

    OnInform("Finished.");
    return TRUE;
  }

  TexCleanUp();
  startedSections = FALSE;

  OnInform("Sorry, unsuccessful.");
  return FALSE;
}

void OnError(char *msg)
{
  if (isInteractive)
    (*frame->textWindow) << "Error: " << msg << "\n";
  else
#ifdef wx_x
    cerr << "Error: " << msg << "\n";
#endif
#ifdef wx_msw
    wxError(msg);
#endif
  wxYield();
}

void OnInform(char *msg)
{
  if (isInteractive)
    (*frame->textWindow) << msg << "\n";
  else
#ifdef wx_x
    cerr << msg << "\n";
#endif
#ifdef wx_msw
    {}
#endif
  wxYield();
}

void OnMacro(char *name, int no_args, Bool start)
{
  switch (convertMode)
  {
    case TEX_RTF:
    {
      RTFOnMacro(name, no_args, start);
      break;
    }
    case TEX_XLP:
    {
      XLPOnMacro(name, no_args, start);
      break;
    }
    case TEX_HTML:
    {
      HTMLOnMacro(name, no_args, start);
      break;
    }
  }
}

Bool OnArgument(char *name, int arg_no, Bool start)
{
  switch (convertMode)
  {
    case TEX_RTF:
    {
      return RTFOnArgument(name, arg_no, start);
      break;
    }
    case TEX_XLP:
    {
      return XLPOnArgument(name, arg_no, start);
      break;
    }
    case TEX_HTML:
    {
      return HTMLOnArgument(name, arg_no, start);
      break;
    }
  }
  return TRUE;
}

