/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    Pump messages to logform.                                     *
 * modul:       FRM_ErrLog.cpp                                                *
 * dependency:  C++ Builder                                                   *
 * licency:     Shareware                                                     *
 ******************************************************************************/
#include <vcl.h>
#include <process.h>    /* _beginthread, _endthread */
#include <stdio.h>
#include <io.h>
#pragma hdrstop

#include "FRM_ErrLog.h"

#include "stringa.h"
#include "localiser/locale_set.h"
#ifdef __gettext__
 #include "libintl.h"
#endif
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"


TErrLog *ErrLog;

volatile int TErrLog::thread_id = -1;
FILE *FileIn = NULL;
FILE *FileOut = NULL;
int TErrLog::PipeHandles[2];
volatile int TErrLog::MsgFormState = -1;

//********************

/** This function acts as the 'main' function for each new thread */
void TErrLog::ThreadMain(void *arg)
{
unsigned char line[80];
string buffer;
TErrLog * const IntErrLog = (TErrLog *)arg;

  if(IntErrLog==NULL)
  {
    _endthread();
    return;
  }

  IntErrLog->Memo1->Text = _("WP2LaTeX Error log file");
  while(1)
  {
    const int i = read(PipeHandles[0],line,sizeof(line));
    if(i<=0)
	break;
    if(ErrLog==NULL) break;

    for(int j=0; j<i; j++)
    {
      const unsigned char c = line[j];
      switch(c)
      {
        case 0xFF: goto ExitLoop;
        case 0xFE: if(buffer.isEmpty()) break;
                        /// fall down do not break.
        case '\n':
        case 0:    if(MsgFormState<1) break;

                   IntErrLog->Lock->Acquire();
                   IntErrLog->LogErr += buffer();
          	   IntErrLog->Lock->Release();

                   IntErrLog->Timer1->Enabled = true;  // enable timer when full line is received.
                   buffer = "";
                   break;
        default:   buffer += c;
        break;
      }
    }
  }
ExitLoop:
  thread_id = -1;
  buffer.erase();
  _endthread();
  return;
}


//---------------------------------------------------------------------------
__fastcall TErrLog::TErrLog(TComponent* Owner): TForm(Owner), HELP(NULL)
{
  Lock = new TCriticalSection;
}


//---------------------------------------------------------------------------
__fastcall TErrLog::~TErrLog()
{
  TerminateWorker();	// Terminate worker before releasing Lock.
  if(Lock)
  {
    delete Lock;
    Lock = NULL;
  }
  if(ErrLog == this) ErrLog=NULL; 
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::Timer1Timer(TObject *Sender)
{
int i;
 Timer1->Enabled = false;
 if(!Visible) Show();

 if(LogErr.length()>0)
   {
   Lock->Acquire();
   try {    //copy a temporary buffer into a form
       Memo1->Lines->BeginUpdate();
       for(i=0; i<LogErr.length(); i++)
         {
           Memo1->Lines->Add(FixUTF8(LogErr[i]));
         }
       Memo1->Lines->EndUpdate();
       LogErr.erase();
       }
   catch(...) {}
   Lock->Release();
   }
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::FormCreate(TObject *Sender)
{
  if(thread_id>=0) return;	// Thread is already running.
  MsgFormState = 1;

#if defined(__WIN32__)
  if((thread_id = _beginthread(ThreadMain,4096,(void *)this)) == (unsigned long)-1)
#else
  if((thread_id = _beginthread(ThreadMain,4096,(void *)this)) == -1)
#endif
    {
    ShowMessage(_("Unable to create thread"));
    return;
    }
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::FormDestroy(TObject *Sender)
{
 MsgFormState = -1;
 //if(thread_id>=0) ShowMessage("ERROR: Internal thread was not cancelled!");
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::FormClose(TObject *Sender, TCloseAction &Action)
{
  Memo1->Lines->Clear();
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
 if(HELP==NULL) return;

 if(Key==VK_F1) // && Shift==0)
    HELP->showChm(HelpFile);
}


//---------------------------------------------------------------------------
void __fastcall TErrLog::TerminateWorker(int Timeout)
{
 MsgFormState = -1;
 if(FileOut)
    {
    int i=0;
    fputc(255,FileOut);
    fputc('\n',FileOut);
    fputc(255,FileOut);
    fputc('\n',FileOut);
    fflush(FileOut);

    while(i++<Timeout && thread_id>=0)  //wait for finishing thread
        Sleep(1);
    fclose(FileOut);
    FileOut = NULL;

    if(thread_id>=0) Sleep(1);
    }
}

//---------------------------------------------------------------------------

void __fastcall TErrLog::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
{
 if(WheelDelta > 0)
  {
    if(Memo1->Font->Size < 32)
      Memo1->Font->Size += 1;
  }
  if(WheelDelta < 0)
  {
    if(Memo1->Font->Size > 5)
      Memo1->Font->Size -= 1;
  }
}
//---------------------------------------------------------------------------

