/*
 * ted2rtf - a very simple converter for extracting the text of an AMiga TED
 * file, to a format usuable in Word etc.
 * AT the moment it doesnt use any of the character formatting.
 *
 * TED files are in IFF text format
 * 'FORM' filesize 'FTXT' [ ChunkID ChunkSize CHunkData....... ]*
 *
 * Version:   1.0
 * Author:    John Donoghue <john.donoghue@ieee.org>
 * Copyright: John Donoghue, 2004.
 * Licence:   GPL - see www.gnu.org for the current licence.
 */
/* History
 * 1.0  18-Jan-2004  Initial version
 */
//-------------------------------------------------------------
#include <iostream>
#include <fstream>

//-------------------------------------------------------------
class TEDConverter
{
public:
  TEDConverter();
  virtual ~TEDConverter();

  bool convert(std::istream & str, std::ostream & out);

private:
  unsigned long readSize(std::istream & in);
  unsigned long readID(std::istream & in);
  unsigned long makeID(int * buff);

  bool onChunk(std::istream &in, std::ostream & out,
           unsigned long chunk, unsigned long size);

  // some of the main chunk types - only onCHRS is currently used
  bool onTCPP(std::istream &in, std::ostream & out,
           unsigned long sz);
  bool onTCPH(std::istream &in, std::ostream & out,
           unsigned long sz);
  bool onCHRS(std::istream &in, std::ostream & out,
           unsigned long sz);
};

//-------------------------------------------------------------
int main()
{
  std::cerr << "TED2RTF - Amiga Text Edit file to Rich Text Format Converter\n";
  std::cerr << "(c) John Donoghue, 2004.\n"; 

  TEDConverter c;

  c.convert(std::cin, std::cout);

  return 0;
}

//-------------------------------------------------------------
TEDConverter::TEDConverter()
{
}
//-------------------------------------------------------------
TEDConverter::~TEDConverter()
{
}
//-------------------------------------------------------------
bool TEDConverter::convert(std::istream & in, std::ostream & out)
{
  // dump start of rtf
  char * start =
  "{\\rtf1\n"
  "\\ansi\\deff0\n"
  "{\\fonttbl\n"
  " {\\f0\\fmodern\\fprq1\\fcharset0 Courier New;}\n"
  " {\\f1\fswiss\\fcharset0 Arial;}\n"
  "}\n"
  "\\f0\\fs20\n";

  out << start;

  // read firm
  unsigned long head = readID(in);
  
  int form[] = { 'F','O','R','M' };

  if(head != makeID(form))
  {
    std::cerr << "Error: not a IFF file - incorrect header.\n";

    return false;
  }
  unsigned long size = readSize(in);

  // IFF file type
  head = readID(in);
  int ftxt[] = { 'F','T','X','T' };

  if(head != makeID(ftxt))
  {
    std::cerr << "Error: not a FTXT format IFF file.\n";
    return false;
  }

  while(! in.eof())
  {
    head = readID(in);
    size = readSize(in);    

    if(size != 0)
    {
      if(onChunk(in, out, head, size) == false) break;
    }
  }
  char end[] = "\n}";

  out << end;
  return false;
}
//-------------------------------------------------------------

unsigned long TEDConverter::readSize(std::istream & in)
{
  unsigned long size;
  int a[4];

  if(in.eof()) return 0;
  a[0] = in.get();
  if(in.eof()) return 0;
  a[1] = in.get();
  if(in.eof()) return 0;
  a[2] = in.get();
  if(in.eof()) return 0;
  a[3] = in.get();

#ifdef DEBUG
  std::cerr << "Sz: " << a[0] << " " << a[1] << " " << a[2] << " " << a[3] 
            << std::endl;
#endif

  size = makeID(a);

  return size; 
}
//-------------------------------------------------------------
unsigned long TEDConverter::readID(std::istream & in)
{
  unsigned long id;
  int a[4];

  a[0] = in.get();
  a[1] = in.get();
  a[2] = in.get();
  a[3] = in.get();

#ifdef DEBUG
  std::cerr << "ID: " << a[0] << " " << a[1] << " " << a[2] << " " << a[3];
  std::cerr << " = " << (char)a[0] << (char)a[1] << (char)a[2] << (char)a[3] 
            << std::endl;
#endif
  return makeID(a);
}
//-------------------------------------------------------------


unsigned long TEDConverter::makeID(int * buff)
{
  unsigned int *tbuff = (unsigned int *)buff;
  unsigned long id = 0;
  unsigned long t;

  for(int i = 0; i < 4; i ++)
  {
    t = (unsigned long)(tbuff[0]);
    tbuff ++;

    id = id << 8;

    id |= (unsigned long)t;
  }

  return id;
}
//-------------------------------------------------------------

bool TEDConverter::onChunk(std::istream &in, std::ostream & out,
  unsigned long chunk, unsigned long size)
{
  static int tcpp_parts[] = { 'T','C','P','P' };
  static int tcph_parts[] = { 'T','C','P','H' };
  static int chrs_parts[] = { 'C','H','R','S' };

  if(chunk == makeID(tcpp_parts))
  {
      onTCPP( in, out, size);
  }
  else if(chunk == makeID(tcph_parts))
  {
      onTCPH( in, out, size);
  }
  else if(chunk == makeID(chrs_parts))
  {
      onCHRS( in, out, size);
  }
  else
  {
      in.seekg( (int)in.tellg() + size );
  }
  // must be even
  if(size & 1) in.get(); 
  return true; 
}
//-------------------------------------------------------------
bool TEDConverter::onTCPP(std::istream &in, std::ostream & out,unsigned long sz)
{
  in.seekg( (int)in.tellg() + sz );
  return true;
}
//-------------------------------------------------------------

bool TEDConverter::onTCPH(std::istream &in, std::ostream & out,unsigned long sz)
{
  in.seekg( (int)in.tellg() + sz );
  return true;
}
//-------------------------------------------------------------

bool TEDConverter::onCHRS(std::istream &in, std::ostream & out,unsigned long sz)
{
  int c;
  int last = 0;

  for(unsigned long i=0;i<sz;i++)
  {
    c = in.get();

    if(c == '\\') out << " \\\\";
    else if(c == '\n' || c == '\r') 
           out << "\\par\n";
    else if(c == '\t') out << " \\tab\n";
    else if(c == '{') out << " \\{";
    else if(c == '}') out << " \\}";
    else out << (char)c;  

    last = c;  
  }
  return true;
}
//-------------------------------------------------------------

