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

# include <malloc.h>
# include <string.h>
# include <curses.h>
# include <mylib.h>
# include <s_defkey.h>
# include <video.h>

//# define _SUN_

# define  DEFOULT 0
# define  XTERM   1
# define  NXTERM  2
# define  RXVT    3
# define  CONSOLE 4
# define  SUN     5

   long  *Symbol ;
   uchar *Color ;
   short  max_x,max_y ;
   short  size_x,size_y ;
   char   TermName[40] ;
   char   TermType ;
   char   f_Color ;
   int    shift2=0 ;

class t_Save_Screen
{  long   *stek ;   // запоминание областей экрана
   long   l_stek ; // длинна массива Stek
   long   j_stek ; // указатель последнего свободного байта
public:
   t_Save_Screen( long l );
   ~t_Save_Screen( void );
   void   save   ( short y1, short x1, short y2, short x2 );
   void   save_rame( short y1, short x1, short y2, short x2 );
   void   restore( void );
} ;

# ifndef _SUN_
mmask_t     mm ;
#endif 
WINDOW     *Win ;
short       Cur_X=0,Cur_Y=0 ;
short       n_Line,n_Col ;
static char    TextFont[100] ;
t_Save_Screen  Save( 51200 ) ;

void s_rame( short y1, short x1, short y2, short x2, uchar f );
void s_quadro( short y1, short x1, short y2, short x2, uchar f );

/***************************************************************************/
void   s_begin_schone( void )
{  short i,i1 ;

   max_x=256 ; max_y=100 ;
   Symbol=(long  *)Calloc( max_x*max_y,sizeof(long) );
   Color =(uchar *)Calloc( max_x*max_y,1 );
   for( i=0 ; i<max_x*max_y ; i++ )
      Symbol[i]=' ';

   Win=initscr();
   noecho( );
   keypad( Win, TRUE );
   strcpy( TermName,termname() );

   TermType=DEFOULT ;
   if( 0==strncmp( TermName,"xterm"  ,5) )   TermType=XTERM ; 
   if( 0==strncmp( TermName,"nxterm" ,6) )   TermType=NXTERM ;
   if( 0==strncmp( TermName,"rxvt"   ,4) )   TermType=RXVT ;
   if( 0==strncmp( TermName,"linux"  ,5) )   TermType=CONSOLE ; 
   if( 0==strncmp( TermName,"cmdtool",7) )   TermType=SUN ;

   getmaxyx( Win, size_y, size_x );
   n_Line=size_y ;
   n_Col =size_x ;

# ifndef _SUN_
//   mousemask( ALL_MOUSE_EVENTS,&mm );
   f_Color=has_colors();

   if( f_Color!=0 )
   {
      start_color();
      long Color[8] ;
      Color[0]=COLOR_BLACK ;
      Color[1]=COLOR_BLUE ;
      Color[2]=COLOR_GREEN ;
      Color[3]=COLOR_CYAN ;
      Color[4]=COLOR_RED ;
      Color[5]=COLOR_MAGENTA ;
      Color[6]=COLOR_YELLOW ;
      Color[7]=COLOR_WHITE ;

      for( i=0 ; i<8 ; i++ )
	 for( i1=0 ; i1<8 ; i1++ )
	    init_pair( 1+8*i1+i,Color[i],Color[i1] );
      color_set( 1,NULL );	    
   }
# endif
}
/* ----------------------------------------------------------------------- */
void   s_begin_schone( int argc, char *argv[] )
{  s_begin_schone( );  }
/* ----------------------------------------------------------------------- */
void   s_end_schone( void )
{  endwin();  }
/* ----------------------------------------------------------------------- */
void   s_nacht( void )
{  long i ;

   for( i=0 ; i<max_x*max_y ; i++ )
   {  Symbol[i]=' ' ; Color[i]=0 ;  }
}
/* ----------------------------------------------------------------------- */
void   s_get_size( short *sx, short *sy )
{  short size_y1, size_x1 ;

   getmaxyx( Win, size_y1, size_x1 );
   if( max_x<size_x1 ) size_x1=max_x ;
   if( max_y<size_y1 ) size_y1=max_y ;
   *sx=size_x1 ; *sy=size_y1 ;
   size_x=size_x1 ; size_y=size_y1 ;
}
/* ----------------------------------------------------------------------- */
void   s_text_yxf(  short y, short x, uchar f, char *str )
{  short i,r1 ;

   r1=max_x*y+x ;
   for( i=0 ; str[i]!=0 && str[i]!='\r' && str[i]!='\n' ; i++ )
   {  Symbol[ r1+i ]=str[i] ;
      Color [ r1+i ]=f ;
   }
}
/* ----------------------------------------------------------------------- */
void   s_text_yxf1( short y, short x, uchar f, char *str )
{  short i,r ;

   r = max_x*y+x ;
   Symbol[ r ] = '\"' ; Color[ r ] = f ;
   for( i=0 ; str[i]!=0 ; i++ )
   {  r=max_x*y+x+i+1 ;
      Symbol[ r ] = str[i] ; Color[ r ] = f ;
   }
   r=r+1 ;
   Symbol[ r ] = '\"' ; Color[ r ] = f ;
}
/* ----------------------------------------------------------------------- */
void   s_text_yxfl( short y, short x, uchar f, short L, char *str )
{  short i,r1 ;

   r1=max_x*y+x ;
   for( i=0 ; str[i]!=0 && i<L ; i++ )
   {  Symbol[ r1+i ]=str[i] ;
      Color [ r1+i ]=f ;
   }
}
/* ----------------------------------------------------------------------- */
void   s_text_yx( short y, short x, char *str )
{  short i,r1 ;

   r1=max_x*y+x ;
   for( i=0 ; str[i]!=0 ; i++ )
      Symbol[ r1+i ]=str[i] ;
}
/* ----------------------------------------------------------------------- */
void   s_color_yxt( short y, short x, uchar *t, char *str )
{  short i,r1,r2,f ;

   r1=max_x*y+x ;
   for( i=0 ; str[i]!=0 ; i++ )
   {  f=0x07 ; r2=str[i] ;
      if( '0'<=r2 && r2<= '9' ) f=t[r2-'0'] ;
      if( 'a'<=r2 && r2<= 'z' ) f=t[r2-'a'+10] ;
      Color[ r1+i ]=f ;
   }
}
/* ----------------------------------------------------------------------- */
void   s_foreground_yxt( short y, short x, uchar *t, char *str )
{  short i,r1,r2,f ;

   r1=max_x*y+x ;
   for( i=0 ; str[i]!=0 ; i++ )
   {  f=0x07 ; r2=str[i] ;
      if( '0'<=r2 && r2<= '9' ) f=t[r2-'0'] ;
      if( 'a'<=r2 && r2<= 'z' ) f=t[r2-'a'+10] ;
      Color[ r1+i ] = (0xf0 & Color[ r1+i ]) + (0x0f & f) ;
   }
}
/* ----------------------------------------------------------------------- */
void   s_rame1_f( short y1, short x1, short y2, short x2, uchar f )
{
   s_rame( y1, x1, y2, x2, f );
}
/* ----------------------------------------------------------------------- */
void   s_rame1_F( short y1, short x1, short y2, short x2, uchar f )
{
   s_quadro( y1, x1, y2, x2, f );
   s_rame  ( y1, x1, y2, x2, f );
}
/* ----------------------------------------------------------------------- */
void   s_rame2_f( short y1, short x1, short y2, short x2, uchar f )
{
   s_rame  ( y1, x1, y2, x2, f );
}
/* ----------------------------------------------------------------------- */
void   s_rame2_F( short y1, short x1, short y2, short x2, uchar f )
{
   s_quadro( y1, x1, y2, x2, f );
   s_rame  ( y1, x1, y2, x2, f );
}
/* ----------------------------------------------------------------------- */
void s_rame( short y1, short x1, short y2, short x2, uchar f )
{  short i,r ;

   for( i=x1+1 ; i<x2 ; i++ )
   {  r=max_x*y1+i ; Symbol[ r ]=ACS_HLINE ; Color[ r ]=f ;
      r=max_x*y2+i ; Symbol[ r ]=ACS_HLINE ; Color[ r ]=f ;
   }
   for( i=y1+1 ; i<y2 ; i++ )
   {  r=max_x*i+x1 ; Symbol[ r ]=ACS_VLINE ; Color[ r ]=f ;
      r=max_x*i+x2 ; Symbol[ r ]=ACS_VLINE ; Color[ r ]=f ;
   }
   r=max_x*y1+x1 ; Symbol[ r ]=ACS_ULCORNER ; Color[ r ]=f ;
   r=max_x*y2+x1 ; Symbol[ r ]=ACS_LLCORNER ; Color[ r ]=f ;
   r=max_x*y1+x2 ; Symbol[ r ]=ACS_URCORNER ; Color[ r ]=f ;
   r=max_x*y2+x2 ; Symbol[ r ]=ACS_LRCORNER ; Color[ r ]=f ;
}
/* ----------------------------------------------------------------------- */
void s_quadro( short y1, short x1, short y2, short x2, uchar f )
{  short i,j,r1 ;

   for( j=y1+1 ; j<y2 ; j++ )
   {  for( i=x1+1 ; i<x2 ; i++ )
      {   r1=max_x*j+i ;
	  Symbol[ r1 ]=' ' ;
	  Color [ r1 ]=f ;
      }
   }
}
/* ----------------------------------------------------------------------- */
void s_save_rame( short s1, short p1, short s2, short p2 )
{  Save.save_rame( s1, p1, s2, p2 );  }

void s_save( short s1, short p1, short s2, short p2 )
{  Save.save( s1, p1, s2, p2 );  }

void s_restore( void )
{  Save.restore( );  
}
/* ----------------------------------------------------------------------- */
t_Save_Screen :: t_Save_Screen( long L )
{
   stek=(long *)Calloc( L,sizeof(long) );
   j_stek=0 ;
   l_stek=L ;

}
/* ----------------------------------------------------------------------- */
t_Save_Screen :: ~t_Save_Screen( void )
{
   if( stek!=NULL ){  free( stek ); stek=NULL ;  }
   j_stek=0 ;
   l_stek=0 ;
}
/* ----------------------------------------------------------------------- */

void t_Save_Screen :: save( short y1, short x1, short y2, short x2 )
{  short i,j,r ;

   for( i=y1 ; i<=y2 ; i++ )
   {  for( j=x1 ; j<=x2 ; j++ )
      {   r=max_x*i+j ;
	  stek[j_stek++] = Color [ r ] ; /* атрибут */
	  stek[j_stek++] = Symbol[ r ] ;   /* символ  */
      }
   }
   stek[j_stek++]=(uchar )x1 ; stek[j_stek++]=(uchar )y1 ;
   stek[j_stek++]=(uchar )x2 ; stek[j_stek++]=(uchar )y2 ;
   stek[j_stek++]=0 ;
   if( l_stek<=j_stek )
   {   printf("\n video_t.cpp : переполнение stek"); throw(-1);  }
}
/* ----------------------------------------------------------------------- */

void t_Save_Screen :: save_rame( short s1, short p1, short s2, short p2 )
{  short i,r,r1,r2 ;

   r1=max_x*s1 ; r2=max_x*s2 ;
   for( i=p1 ; i<=p2 ; i++ )
   {  r=r1+i ;
      stek[j_stek++]=Symbol[ r ] ;
      stek[j_stek++]=Color [ r ] ;
      r=r2+i ;
      stek[j_stek++]=Symbol[ r ] ;
      stek[j_stek++]=Color [ r ] ;
   }
   for( i=s1 ; i<=s2 ; i++ )
   {  r1=max_x*i+p1 ;
      stek[j_stek++]=Symbol[ r1 ] ;
      stek[j_stek++]=Color [ r1 ] ;
      r2=max_x*i+p2 ;
      stek[j_stek++]=Symbol[ r2 ] ;
      stek[j_stek++]=Color [ r2 ] ;
   }
   stek[j_stek++]=(uchar )p1 ; stek[j_stek++]=(uchar )s1 ;
   stek[j_stek++]=(uchar )p2 ; stek[j_stek++]=(uchar )s2 ;
   stek[j_stek++]=1 ;
   if( l_stek<=j_stek )
   {   printf("\n video_t.cpp : переполнение stek"); throw(-1);  }

}
/* ----------------------------------------------------------------------- */

void t_Save_Screen :: restore( void )
{  short i,j,p1,p2,s1,s2,
	 r,r1,r2 ;
   uchar c,f ;

   f =stek[--j_stek] ;
   s2=stek[--j_stek] ; p2=stek[--j_stek] ;
   s1=stek[--j_stek] ; p1=stek[--j_stek] ;
   if( f==1 )
   {  for( i=s2 ; s1<=i ; i-- )
      {  r=max_x*i+p2 ;
	 f=Color [ r ] = stek[--j_stek] ;
	 c=Symbol[ r ] = stek[--j_stek] ;
	 r=max_x*i+p1 ;
	 f=Color [ r ] = stek[--j_stek] ;
	 c=Symbol[ r ] = stek[--j_stek] ;
      }
      r1=max_x*s1 ; r2=max_x*s2 ;
      for( i=p2 ; p1<=i ; i-- )
      {  r=r2+i ;
	 f=Color [ r ] = stek[--j_stek] ;
	 c=Symbol[ r ] = stek[--j_stek] ;
	 r=r1+i ;
	 f=Color [ r ] = stek[--j_stek] ;
	 c=Symbol[ r ] = stek[--j_stek] ;
      }
   }
   else
   {  for( i=s2 ; s1<=i ; i-- )
	 for( j=p2 ; p1<=j ; j-- )
	 {   r=max_x*i+j ;
	     c=Symbol[ r ] = stek[--j_stek] ; /* символ  */
	     f=Color [ r ] = stek[--j_stek] ; /* атрибут */
	 }
   }
}
/* ----------------------------------------------------------------------- */
void   s_redraw( void )
{  short x,y,r ;
   uchar f ;

   for( y=0 ; y<size_y ; y++ )
   {  r=max_x*y ;
      move( y,0 );
      for( x=0 ; x<size_x ; x++ )
      {  f=Color[r+x] ;
# ifndef _SUN_
	 color_set( 1+(f&0x07)+((f&0x70)>>1) ,NULL );
//	 if( (f&0x80)!=0 ) attr_on ( A_BLINK,NULL );
//	     else          attr_off( A_BLINK,NULL );
//	 if( (f&0x08)!=0 ) attr_on ( A_BOLD ,NULL );
//	     else          attr_off( A_BOLD ,NULL );
# endif
	 if( 256<=Symbol[r+x] )
	 {   addch( Symbol[r+x] );  }
	 else
	 {   addch( Symbol[r+x]&0x00ff ); }
      }
   }
   move( Cur_Y,Cur_X );
}
/* ----------------------------------------------------------------------- */
void   s_goto_xy( short y, short x )
{
   Cur_X=x ; Cur_Y=y ;
}
/* ----------------------------------------------------------------------- */
void   s_getch( short *key1, short *key2 )
{  short key ;

   getmaxyx( Win, size_y, size_x );
   shift2=0 ;
   n_Line=size_y ;
   n_Col =size_x ;

   s_redraw( );
   key=wgetch( Win );

   if( key== 10 ) {  *key1=S_key_Enter ; *key2=0 ; return ;  }
   if( key==127 ) {  *key1=0 ; *key2=S_key_Del ; return ;  }
   if( key <256 ) {  *key1=key ; *key2=0 ; return ;  }

   *key1=0 ;

   if( TermType==XTERM && 277<=key && key<=286 )
       shift2=S_Ctrl_L ;

   switch( key )
   {  case 259 : *key2=S_key_Up   ; break ;
      case 258 : *key2=S_key_Down ; break ;
      case 260 : *key2=S_key_Left ; break ;
      case 261 : *key2=S_key_Right; break ;
      case 265 : *key2=S_key_F1   ; break ;
      case 266 : *key2=S_key_F2   ; break ;
      case 267 : *key2=S_key_F3   ; break ;
      case 268 : *key2=S_key_F4   ; break ;
      case 269 : *key2=S_key_F5   ; break ;
      case 270 : *key2=S_key_F6   ; break ;
      case 271 : *key2=S_key_F7   ; break ;
      case 272 : *key2=S_key_F8   ; break ;
      case 273 : *key2=S_key_F9   ; break ;
      case 274 : *key2=S_key_F10  ; break ;
      case 331 : *key2=S_key_Ins  ; break ;
      case 339 : *key2=S_key_PgUp ; break ;
      case 338 : *key2=S_key_PgDn ; break ;
      case 263 : *key1=S_key_Back ; *key2=0 ; break ;
      // rxvt
      case 362 : *key2=S_key_Home ; break ;
      case 385 : *key2=S_key_End  ; break ;
      case 330 : *key2=S_key_Del  ; break ;
      // linux
      case 262 : *key2=S_key_Home ; break ;
      case 360 : *key2=S_key_End  ; break ;
      default: *key2=0 ;
   }
   if( TermType==CONSOLE )
   {   switch( key )
       {  case 275 : *key2=S_key_F1   ; break ;
	  case 276 : *key2=S_key_F2   ; break ;
	  case 277 : *key2=S_key_F3   ; break ;
	  case 278 : *key2=S_key_F4   ; break ;
	  case 279 : *key2=S_key_F5   ; break ;
	  case 280 : *key2=S_key_F6   ; break ;
	  case 281 : *key2=S_key_F7   ; break ;
	  case 282 : *key2=S_key_F8   ; break ;
	  case 283 : *key2=S_key_F9   ; break ;
	  case 284 : *key2=S_key_F10  ; break ;
       }
   }
   if( TermType==XTERM )
   {   switch( key )
       {  case 277 : *key2=S_key_F1   ; break ;
	  case 278 : *key2=S_key_F2   ; break ;
	  case 279 : *key2=S_key_F3   ; break ;
	  case 280 : *key2=S_key_F4   ; break ;
	  case 281 : *key2=S_key_F5   ; break ;
	  case 282 : *key2=S_key_F6   ; break ;
	  case 283 : *key2=S_key_F7   ; break ;
	  case 284 : *key2=S_key_F8   ; break ;
	  case 285 : *key2=S_key_F9   ; break ;
	  case 286 : *key2=S_key_F10  ; break ;
	  case 275 : *key2=S_key_F11  ; break ;
	  case 276 : *key2=S_key_F12  ; break ;
       }
   }
}
/***************************************************************************/
# include <sys/ioctl.h>

int    s_shiftstatus( void )
{  char shift=6 ;
   int  shift1=0 ;

# ifndef _SUN_
   if( TermType==CONSOLE )
   {
      ioctl( 0,TIOCLINUX,&shift );

      if( shift&0x01 ) shift1|=S_Shift_L ;
      if( shift&0x04 ) shift1|=S_Ctrl_L ;
      if( shift&0x08 ) shift1|=S_Alt_L ;
   }
# endif
   
   if( TermType==XTERM )
       return shift2 ;
       
   return shift1 ;
}
/***************************************************************************/

void   s_set_size( short sx, short sy ){ ; }
void   s_get_size( short &sx, short &sy ){  sx=n_Col ; sy=n_Line ;  }
short  s_get_sx( void ) {  return n_Col ; }
short  s_get_sy( void ) {  return n_Line ; }

void   x_set_fonts( void ){;}
void   s_set_font( char *F ){ strcpy( TextFont,F ); }
char  *s_get_font( void ){ return TextFont ; }
short  s_clear_cursor( void ){ return 0; }
void   s_refresh( void ){ refresh(); }