/*******************************************************************/
//              "Меркурий"-"Правда" - open source переводчик
//          распространяется в соответсвии с лицензией GNU v 2.0
//
//     t_Windows - главный класс интерфейса (ничего общего с Микрософтом)
//     Анисимов Д.В.                               сегодня
/*******************************************************************/

# include <string.h>
# include <stdlib.h>
# include <unistd.h>

# include "mylib.h"
# include "video.h"
# include "color.h"
# include "core.h"
# include "face.h"
# include "menu.h"
# include "edit.h"
# include "edit1.h"
# include "edit2.h"
# include "debug.h"
# include "path.h"
# include "word.h"

t_Windows     Windows ;
t_Dir         Dir ;
t_HelpData    HelpData ;
t_Text        HelpText ;
t_Edit        HelpView ;
t_EditTrans   Edit1,Edit2 ;
t_Edit2       EditFrom ;
t_Edit3       EditTree1(0),EditTree2(1) ;
t_Debug       Debug ;
t_Path        Path ;
t_GrammarView GrammarView ;
t_SlowoView   SlowoView ;
t_Slowo3View  Slowo3View ;
t_NewWord     NewWord ;
t_AddWord     AddWord ;
t_Option      Option ;
char          FileName[100]="" ;
char          MercuryDir[200]="../" ;

/***************************************************************************/
//          функция определения "слова с точкой"
/***************************************************************************/
char   is_const( char *Str )
{
   short       part[20] ;
   if( 0<Perevod.part( Str,part ) ) return 1 ;
   return 0 ;
}
/***************************************************************************/
void  Window_menu( void *Void )
{
   switch( ((char *)Void)[0] )
   {
      case '1' : Windows.create( NULL );  break ;
      case 's' : Windows.save_src( );     break ;
      case '2' : Windows.save( );         break ;
      case '3' : Windows.save_as( );      break ;
      case '4' : Windows.exit( );         break ;
      case '5' : Windows.find_forward( ); break ;
      case '6' : Windows.find_backward( );break ;
      case '7' : Windows.replace( );      break ;
      case '8' : Windows.goto_str( );     break ;
      case 'T' : Windows.trans( );        break ;
      case 't' : Windows.trans_frasa( );  break ;
      case 'f' : Windows.win_firstlook(); break ;

      case 'R' : {  
		    if( 0>reread_grammar( MercuryDir ))
		         Edit1.read("mercury.err");
		    else Edit1.init("");
		 }
		 break ;
      case 'F' : if( Edit1.Text1.fformat==0 )
                 {   Edit1.Text1.fformat=1 ;
		     Edit2.Text1.fformat=1 ;
                     menu_set( "Спец Формат   [ ]","Спец Формат   [x]" );
		 }else
		 {   Edit1.Text1.fformat=0 ;
		     Edit2.Text1.fformat=0 ;
		     menu_set( "Спец Формат   [x]","Спец Формат   [ ]" );
		 }
                 break ;
   }
}
/***************************************************************************/
void  Window_help( void *Void )
{  char *Str=(char *)Void ;
   short sx,sy ;

   s_get_size( sx,sy );
   s_save( 1,1,sy-1,sx-1 );
   HelpView.init( HelpData.get_help( Str ) );
   HelpView.main( );
   s_restore();

}
/***************************************************************************/
t_Windows :: t_Windows( )
{
   Reg='1' ;
}
/***************************************************************************/

void t_Windows :: init( void )
{
   HelpView.set_text( &HelpText );
   HelpView.set_view( 1 ) ;
   Edit1.set_name("Исходный_текст");
   Edit2.set_name("Переведенный_текст");
   EditFrom.set_name("Первое чтение");
   EditTree1.set_name("Структура источника");
   EditTree2.set_name("Структура приемника");
   HelpView.set_name("Подсказка");
   AddWord.set_name("Новые слова");
   Edit1.set_funk_const( &is_const );
}
/***************************************************************************/

void t_Windows :: set_pos( void )
{
   short sx,sy,y ;
   s_get_size( sx,sy );
   y=sy/2 ;

   Edit1.set_pos      ( 0, 1  , sx-1, y    );
   Edit2.set_pos      ( 0, y+1, sx-1, sy-1 );
   EditFrom.set_pos   ( 1, 2  , sx-2, sy-2 );
   EditTree1.set_pos  ( 1, 2  , sx-2, sy-2 );
   EditTree2.set_pos  ( 1, 2  , sx-2, sy-2 );
   Debug.set_pos      ( 1, 2  , sx-2, sy-2 );
   Path.set_pos       ( 1, 2  , sx-2, sy-2 );
   GrammarView.set_pos( 1, 2  , sx-2, sy-2 );
   SlowoView.set_pos  ( 1, 2  , sx-2, sy-2 );
   Slowo3View.set_pos ( 1, 2  , sx-2, sy-2 );
   HelpView.set_pos   ( 1, 2  , sx-2, sy-2 );
   AddWord.set_pos    ( 1, 2  , sx-2, sy-2 );
}
/***************************************************************************/

void t_Windows :: main_loop( void )
{  e_WinMsg r ;

   init();
   set_pos();
   null_menu( );

   while( 1 )
   {
      paint( );
      switch( Reg )
      {  case '1': r=Edit1.main_loop( ); Reg1=Reg ; break ;
	 case '2': r=Edit2.main_loop( ); Reg1=Reg ; break ;
	 case '3': r=EditFrom.loop( );   break ;
	 case '4': r=EditTree1.loop( );  break ;
	 case '5': r=EditTree2.loop( );  break ;
	 case '6': r=Debug.loop( );      break ;
	 case '7': r=GrammarView.loop( );break ;
	 case '8': r=SlowoView.loop( );  break ;
	 case '9': r=Slowo3View.loop( ); break ;
         case 'b': r=win_path( );        break ;
         case 'c': r=win_path2( );       break ;
         case 'd': r=AddWord.loop( );    break ;
      }      
      switch( r )
      {
         case WM_NEXT :
	      if( Reg=='1' ) { Reg='2' ; break ; }
	      if( Reg=='2' ) { Reg='1' ; break ; }
         case WM_ESC    : Reg=Reg1 ; break ;
	 case WM_EDIT1  : Reg='1' ; break ;
	 case WM_EDIT2  : Reg='2' ; break ;
	 case WM_FIRST  : Reg='3' ; break ;
	 case WM_SRC    : Reg='4' ; break ;
	 case WM_DST    : Reg='5' ; break ;
	 case WM_DEBUG  : Reg='6' ; break ;
	 case WM_PATH   : Reg='b' ; break ;
	 case WM_PATH2  : Reg='c' ; break ;
	 case WM_GRAMMAR: Reg='7' ; break ;
	 case WM_SLOWO  : Reg='8' ; break ;
	 case WM_BASE   : Reg='9' ; break ;
         case WM_ADD_WORD: Reg='d' ; break ;
      }
   }
}
/***************************************************************************/

e_WinMsg t_Windows :: win_path2( void )
{
   // ------ установление размеров окошек ---------------
   short sx,sy,y1,y2 ;

   if( Read_Error!=0 )
   {  figna("Грамматика или словари не прочитаны.\n       Перевод невозможен!!!");
      return WM_ESC ;
   }
   s_get_size( sx,sy );
   y2=sy/2 ; y1=y2/2 ;

   Edit1.set_pos ( 0, 1   , sx-1, y1   );
   Edit2.set_pos( 0, y1+1, sx-1, y2   );
   Path.set_pos ( 0, y2+1, sx-1, sy-1 );

   // ------ чтение текущей фразы ----------------------
   char *Str,Str1[1000] ;
   
   Str =Edit1.get_frasa( Edit1.current_pos( ) );
   if( Str[0]!=0 ) Core.translate( Str,Str1 );

   e_WinMsg r ;
   char    Reg2 ,Reg3 ;

   Reg2=Reg3='b' ;

   null_menu( );
   while( 1 )
   {
      Edit1.raden_y3();
      Edit2.raden_y3();
      Edit1.paint_main();
      Edit2.paint_main();

      switch( Reg2 )
      {  case '1': r=Edit1.main_loop( ); Reg3=Reg2 ; break ;
	 case '2': r=Edit2.main_loop( ); Reg3=Reg2 ; break ;
         case 'b': r=Path.loop( );       Reg3=Reg2 ; break ;
      }
      switch( r )
      {
	 case WM_NEXT :
            switch( Reg2 ) 
            {   case '1' : Reg2='2' ; break ;
		case '2' : Reg2='b' ; break ;
		case 'b' : Reg2='1' ; break ;
	    }
            break ;  
	 case WM_ESC : 
	      if( Reg2=='1' || Reg2=='2' || Reg2=='b') goto M_End ;
	          else Reg2=Reg3 ;
	      break ;
	 case WM_OK :
	      if( Reg2!='b' ) break ;
	      Str=Path.Antwort ;
	      if( Str[0]==0 ) break ;
	      Edit2.put_frasa( Edit2.current_pos( ),Str );
	      Edit1.next_frasa();
	      Edit2.next_frasa();
	      Str =Edit1.get_frasa( Edit1.current_pos( ) );
	      if( Str[0]!=0 ) Core.translate( Str,Str1 );
              break ;
         case WM_N_FRASA:
	 case WM_P_FRASA:
 	      if( Reg2!='b' ) break ;
	      if( r==WM_N_FRASA )
	      {  Edit1.next_frasa();
	         Edit2.next_frasa();
	      }
	      else
	      {  Edit1.prev_frasa();
	         Edit2.prev_frasa();
	      }
	      Str =Edit1.get_frasa( Edit1.current_pos( ) );
	      if( Str[0]!=0 ) Core.translate( Str,Str1 );	      
 	      break ;
	 case WM_EDIT1  : Reg='1' ; break ;
	 case WM_EDIT2  : Reg='2' ; break ;
	 case WM_FIRST  : Reg='3' ; break ;
	 case WM_SRC    : Reg='4' ; break ;
	 case WM_DST    : Reg='5' ; break ;
	 case WM_DEBUG  : Reg='6' ; break ;
	 case WM_PATH   : Reg='b' ; break ;
	 case WM_PATH2  : Reg='c' ; break ;
	 case WM_GRAMMAR: Reg='7' ; break ;
	 case WM_SLOWO  : Reg='8' ; break ;
	 case WM_BASE   : Reg='a' ; break ;
      }
   }
M_End:
   Edit1.set_pos ( 0, 1   , sx-1, y2   );
   Edit2.set_pos( 0, y2+1, sx-1, sy-1 );
   Path.set_pos ( 1, 2   , sx-2, sy-2 );
   return WM_ESC ;
}
/***************************************************************************/

void t_Windows :: paint( void )
{  
   short sx,sy,yy ;
   static short sx1=80,sy1=25 ;

   s_get_size( sx,sy );
   yy=sy/2 ;
   s_rame2_f( 1,0,sy-1,sx-1,red_rame_Color );
   if( sx!=sx1 || sy!=sy1 )
   {  // ------------ переразместить все окошки ----------------
      set_pos( );
      null_menu();
   }
   Edit1.paint_main();
   Edit2.paint_main();
}
/***************************************************************************/

void t_Windows :: trans( void )
{  long  i ;
   char *Str,Str1[1000] ;
   char *Text ;
   
   if( Read_Error!=0 )
   {  figna("Грамматика или словари не прочитаны.\n       Перевод невозможен!!!");
      return ;
   }
   Text=(char *)Calloc( 1000000,sizeof(char) );

   for( i=0 ; i<Edit1.text()->length() ; i=Edit1.text()->next_frasa(i) )
   {
      Str =Edit1.get_frasa(i);
      Core.translate( Str,Str1 );
      strcat( Text, Str1 );
      strcat( Text, "\n" );
   }
   Edit2.init( Text );
   Free( Text );
   
   Edit1.paint_main();
   Edit2.get_str();
   Edit2.paint_main();
}
/***************************************************************************/

void t_Windows :: trans_frasa( void )
{  
   char *Str ;
   long p ;
   static char Str1[1000] ;

   if( Read_Error!=0 )
   {  figna("Грамматика или словари не прочитаны.\n       Перевод невозможен!!!");
      return ;
   }
   p=Edit1.current_pos( ) ;
   Str =Edit1.get_frasa( p );
   Core.translate( Str,Str1 );
   Edit2.put_frasa( Edit2.current_pos( ),Str1 );

   Edit1.paint_main();
   Edit2.get_str();
   Edit2.paint_main();
}
/***************************************************************************/

void t_Windows :: win_firstlook( void )
{  
   char *Str ;
   static char Str1[1000] ;

   Str =Edit1.get_frasa( Edit1.current_pos( ) );
   Core.translate( Str,Str1 );
   paint( );
   EditFrom.loop( );
   paint( );
}
/***************************************************************************/

e_WinMsg t_Windows :: win_path( void )
{
   e_WinMsg r ;
   char *Str ;
   static char Str1[1000] ;

   if( Read_Error!=0 )
   {  figna("Грамматика или словари не прочитаны.\n       Перевод невозможен!!!");
      return WM_ESC ;
   }
   Str =Edit1.get_frasa( Edit1.current_pos( ) );
   if( Str[0]!=0 )
       Core.translate( Str,Str1 );

   r=Path.loop( );
   Str=Path.Antwort ;
   if( Str[0]!=0 )
       Edit2.put_frasa( Edit2.current_pos( ),Str );

   Edit1.paint_main();
   Edit2.get_str();
   Edit2.paint_main();
   return r ;
}
/***************************************************************************/

void t_Windows :: exit( void )
{
   if( 1==fragen( "Запомнить файл перевода? (1-Да 0-Нет)"  ) ) 
       save(  ) ;

   s_nacht( ) ;
   s_redraw( );
   s_end_schone( );
   ::exit(0);
}
/***************************************************************************/

void t_Windows :: save_src( void )
{  char Buf[200] ;

   Edit1.write( Edit1.Name );   
   sprintf( Buf,"Файл \"%s\" сохранен",Edit1.Name );
   figna( Buf );
}
/***************************************************************************/

void t_Windows :: save( void )
{
   Edit2.write("mercury_out.txt");
   figna( "Файл \"mercury_out.txt\" сохранен" );
}
/***************************************************************************/

void t_Windows :: save_as( void )
{  char f ;
   char Buf[200] ;

   f=Dir.direktor( Buf,1 );   
   if( f<0 )
      strcpy( Buf,"mercury_out.txt" );
   Edit2.set_name( Buf );
   Edit2.write( Buf );

   paint( );
}
/***************************************************************************/

void t_Windows :: find_forward( void )
{  
   if( Reg=='1') Edit1.find_forward( );
   if( Reg=='2') Edit2.find_forward( );
}
/***************************************************************************/

void t_Windows :: find_backward( void )
{  
   if( Reg=='1') Edit1.find_backward( );
   if( Reg=='2') Edit2.find_backward( );
}
/***************************************************************************/

void t_Windows :: replace( void )
{  
   if( Reg=='1') Edit1.replace( );
   if( Reg=='2') Edit2.replace( );
}
/***************************************************************************/

void t_Windows :: goto_str( void )
{  
   if( Reg!='1' ) Edit1.goto_str( );
   if( Reg!='2' ) Edit2.goto_str( );
}
/***************************************************************************/

void t_Windows :: prev_frasa( void )
{
   Edit1.prev_frasa();
   Edit2.prev_frasa();
   Edit1.paint_main();
   Edit2.paint_main();
}
/***************************************************************************/

void t_Windows :: next_frasa( void )
{
   Edit1.next_frasa();
   Edit2.next_frasa();
   Edit1.paint_main();
   Edit2.paint_main();
}
/***************************************************************************/

void t_Windows :: create( char *Name )
{  char f ;
   char Buf[200] ;

   if( Name==NULL )
	{  f=Dir.direktor( Buf,0 );  }
   else {  strcpy(Buf,Name); f=0;  }
   if( f>=0 )
   {
      if( f==0 )
	 Edit1.read( Buf );
      Edit1.set_name( Buf );
   }
   else
      create( "new.txt" );
   
   paint( );
}
/************************************************************************/
void preproc_exe( void *S )
{  char Str[200] ;
   int  r ;

   if( Edit1.Text1.fformat==1 )
   {  figna("Вы уже запускали препроцессор. Хватит.");
      return ;
   }
   Strcpy( Str,MercuryDir, 200 );
   Strcat( Str,"/bin/", 200 );
   Strcat( Str,(char *)S, 200 );
   Strcat( Str," ", 200 );
   Strcat( Str,Edit1.Name, 200 );
   r=system( Str );
   if( r==0 )
   {   Strcpy( Str,Edit1.Name, 200 );
       Strcat( Str,".pre", 200 );
       Strcpy( Edit1.Name,Str, 200 );
       Edit1.read( Str );
       Edit1.Text1.fformat=1 ;
   }
   else
   {   figna("Препроцессор не смог нормально отработать.\nПочему - не знаю.");
   }
}
/************************************************************************/
void postproc_exe( void *S )
{  char Str[200] ;
   int  r ;

   Edit2.write( "tmp" );
   Strcpy( Str,MercuryDir, 200 );
   Strcat( Str,"/bin/postproc tmp", 200 );
   r=system( Str );
   if( r==0 )
   {
       Edit2.read( "tmp.post" );
   }
   else
   {   figna("Постпроцессор не смог нормально отработать.\nПочему - не знаю.");
   }
   unlink( "tmp" );
   unlink( "tmp.post" );
   Edit2.get_str();
   Edit2.paint_main();
}
/************************************************************************/
//                 построить данные для препроцессора
/************************************************************************/
void preproc_rc( char *File )
{  long   i,L ;
   char  *Mass ;
   FILE  *ff ;

   ff=fopen( File,"r" );
   if( ff==NULL ) return ;
   fclose(ff);
   L=file_to_mass( File,&Mass );

   t_Lexer Lexer ;

   Lexer.set_breaker((uchar *)":");
   Lexer.init( Mass,L );
   Lexer.remark();
   Lexer.make_words();

   t_Menu *PP_Menu=(t_Menu *)Calloc(1+Lexer.n_word(),sizeof(t_Menu) );

   for( i=0 ; i<Lexer.n_word(); i++ )
   {  PP_Menu[i].flag=F_FUNK ;
      PP_Menu[i].ret =0 ;
      PP_Menu[i].funk=preproc_exe ;
      PP_Menu[i].data=Calloc( 1+strlen(Lexer.word(i)),1 );
      strcpy( (char *)PP_Menu[i].data,Lexer.word(i) );
      Strcpy( PP_Menu[i].name,Lexer.word(i),30 );
   }
   PP_Menu[i].flag=F_ENDE ;
   t_Menu *PP1_Menu=menu_find( "Препроцессор" );
   if( PP1_Menu!=NULL )
   {   PP1_Menu->flag=F_MENU ;
       PP1_Menu->data=PP_Menu ;   
   }
}