/*******************************************************************/
// "Меркурий"-"Правда" - open source переводчик
// распространяется в соответсвии с лицензией GNU v 2.0
//
// Последовательный выбор вариантов перевода
// Анисимов Д.В. сегодня
/*******************************************************************/
# include <string.h>
# include <mylib.h>
# include <video.h>
# include <s_defkey.h>
# include <color.h>
# include <core.h>
# include <slowo2.h>
# include <window.h>
# include <edit2.h>
# include <path.h>
extern t_Slowo2 *SlowoT ;
extern short *i_FormatT ;
void word_source( short i_struct, char *Word, char *Source, e_Half H );
void Window_help( void *Void );
void figna( char *str );
# define no_trans(r) (E_NULL==(r) || E_NO==(r) || E_FIGNA==(r) || E_ERROR==(r) )
/************************************************************************/
// заменить в строке '\n' и '\t' на ' ' (для форматирования)
/************************************************************************/
void remove_wk( char *Str )
{
for( long i=0 ; Str[i]!=0 ; i++ )
if( Str[i]=='\n' || Str[i]=='\t' )
Str[i]=' ' ;
}
/************************************************************************/
long t_pVariant :: word_to_aword( long i_word )
{ long i ;
for( i=0 ; i<aWord.j ; i++ )
if( i_word<=aWord[i].i_word ) break ;
return i ;
}
/************************************************************************/
t_Path :: t_Path( void ) : t_Win()
{
strcpy( Name,"Ручной перевод" );
Up =NULL ;
Variant=NULL ;
Tree =NULL ;
aWord =NULL ;
n_Tree =0 ;
n_Variant=0 ;
Antwort[0]=StrUp[0]=0 ;
z_Tree=i_down=0 ;
}
/************************************************************************/
t_Path :: t_Path( t_Path *Up1, long z_Tree1 )
{
strcpy( Name,Up1->Name );
x1=Up1->x1 ; x2=Up1->x2 ; size_x=Up1->size_x ;
y1=Up1->y1 ; y2=Up1->y2 ; size_y=Up1->size_y ;
Up=Up1 ;
Variant=NULL ;
Tree =NULL ;
aWord =NULL ;
n_Tree =0 ;
n_Variant=0 ;
Antwort[0]=StrUp[0]=0 ;
Up1->print1( StrUp,z_Tree1 );
z_Tree=i_down=0 ;
}
/************************************************************************/
t_Path :: ~t_Path()
{
del();
}
/************************************************************************/
void t_Path :: del()
{
for( long i=0 ; i<n_Tree ; i++ )
if( Tree[i].Down!=NULL )
{ delete(Tree[i].Down); Tree[i].Down=NULL ; }
Free(aWord);
Free(Variant);
Free(Tree);
n_Tree =0 ;
n_Variant=0 ;
}
/***************************************************************************/
// рисовалка
/***************************************************************************/
void t_Path :: paint( )
{
long i,j,j1,n,z,z1,Begin,n_Down ;
short yy ;
char f,f1 ;
e_Result r ;
t_pTree *T ;
char Str[LFRASA] ;
try
{
// ------ нарисовать рамки --------------------------
t_Win :: paint();
s_rame2_F( y1, x1, y2, x2, 0x07 );
s_rame2_F( y1, x1, y1+4, x2, 0x07 );
s_rame2_F( y1, x1, y1+2, x2, 0x07 );
s_text_yxf( y1 , x1+3, 0x0a, "Оригинал" );
s_text_yxf( y1+2, x1+3, 0x0a, "Перевод" );
s_text_yxf( y1+4, x1+3, 0x0a, "Варианты продолжения" );
s_goto_xy( y1+1,x1+1 );
T=&Tree[z_Tree] ;
// ------ нарисовать оригинал -----------------------
{
short z1,z2,halb=size_x/2 ;
z1=sou_length1( );
z2=z1+x1+2 ;
r=Core.result();
if( r==E_NULL || r==E_ERROR )
Strcpy( Str,"",LFRASA ) ;
else Strcpy( Str,Core.sou(),LFRASA ) ;
if( size_x-5<z1+halb )
{ strcpy( Str,Str+z1-(size_x-5-halb) );
z2=x1+2+size_x-5-halb ;
}
Str[size_x-5]=0 ;
remove_wk( Str );
s_text_yxf( y1+1, x1+2, 0x07, Str );
uchar t[2]={ 0x3d ,0 };
s_color_yxt( y1+1, z2+6, t,"0" );
}
// ------ нарисовать перевод -----------------------
if( no_trans(r) )
Strcpy( Str,Core.antwort().str(),LFRASA );
else print1( Str,z_Tree );
n=strlen( Str );
if( size_x-4<n ) Begin=n-size_x+4 ;
else Begin=0 ;
remove_wk( Str );
s_text_yxf( y1+3, x1+2, 0x07, Str+Begin );
if( no_trans(r) ) return ;
// ------ нарисовать варианты перевода --------------
n_Down=0 ;
for( i=0 ; i<T->n_down ; i++ )
if( 0<Tree[T->down+i].n_slowo )
n_Down+=Tree[T->down+i].n_slowo ;
z=size_y-6 ;
Begin=0 ;
if( i_down<Begin ) Begin=i_down ;
if( Begin+z<i_down ) Begin=i_down-z ;
long L ;
for( i=j=j1=n=0 ; i<n_Down ; i++ )
{ j++ ;
if( Tree[T->down+j1].n_slowo<j )
{ j1++ ; j=1 ; }
if( Begin+z<i ) break ;
if( i<Begin ) continue ;
if( i==i_down ) { f=0x60 ; f1=0x70 ; }
else { f=0x0e ; f1=0x07 ; }
Strcpy( Str,emptystr(size_x-3),LFRASA );
yy=y1+5+i-Begin ;
s_text_yxf( yy, x1+2, f1, Str );
print2( Str, z_Tree, j1, j-1 );
Str[size_x-3]=0 ;
remove_wk( Str );
s_text_yxf( yy, x1+2, f, Str );
z1=strlen( Str );
L=print3( Str, z_Tree, j1, j-1 );
Str[size_x-4-z1]=0 ;
remove_wk( Str );
s_text_yxf( yy, x1+3+z1, f1, Str );
if( L<size_x-4-z1 ) Str[L]=0 ;
s_text_yxf( yy, x1+3+z1, 0x0a, Str );
}
}
catch( int E )
{
error_add( "t_Path :: paint( )\n" );
throw(E);
}
}
/************************************************************************/
// переведенный кусок источника
// (надо же как сложно сделать такое простое действие)
/************************************************************************/
long t_Path :: sou_length1( )
{ long i,z1,z2 ;
if( n_Variant<=0 ) return 0 ;
t_pTree *T=&Tree[z_Tree] ;
t_pVariant *V=&Variant[T->first] ;
if( V->aWord.j<=0 )
{ if( Up!=NULL ) return Up->sou_length1( );
return 0 ;
}
t_aWord *W=&V->aWord[0] ;
if( T->i_last_aword< V->aWord.j )
{
if( 0<T->i_last_aword )
{ for( i=T->i_last_aword-1 ; 0<=i ; i-- )
{ W=&V->aWord[i] ;
if( 0<=W->i_last_word ) break ;
}
z1=sou_length( W->i_last_word );
}
else
{ for( i=T->i_last_aword ; 0<=i ; i-- )
{ W=&V->aWord[i] ;
if( 0<=W->i_last_word ) break ;
}
z1=sou_length( W->i_word );
}
}
else
{
for( i=V->aWord.j-1 ; 0<=i ; i-- )
{ W=&V->aWord[i] ;
if( 0<=W->i_last_word ) break ;
}
z1=sou_length( W->i_last_word );
}
return z1 ;
}
/***************************************************************************/
long t_Path :: sou_length( long i_word )
{ short i,L ;
if( i_word<0 ) return 0 ;
if( Core.fn_word()<=i_word ) return strlen( Core.sou() );
return Core.from()[i_word].z_str ;
}
/***************************************************************************/
// нарисовать фразу (уже переведенный кусок)
/***************************************************************************/
# define add_ws(Str) if( ' '!=Str[strlen(Str)-1] ) Strcat( Str," ",LFRASA );
void t_Path :: print1( char *Str1, long i_Node )
{ long i,i1,j,z,i_slowo1 ;
t_pTree *T ;
long index[100] ;
try
{ z=i_Node ;
j=0 ;
while( 1 )
{ index[j++]=z ;
z=Tree[z].up ;
if( z<0 ) break ;
}
Str1[0]=0 ;
if( StrUp[0]!=0 )
{ strcat( Str1,StrUp ); add_ws( Str1 );
}
for( i=j-1 ; 0<=i ; i-- )
{
T=&Tree[index[i]] ;
for( i1=T->i_aword ; i1<T->i_last_aword ; i1++ )
{ if( Variant[T->first].aWord.j<=i1 ) return ;
if( T->i_aword<i1 ) i_slowo1=0 ;
else i_slowo1=T->i_slowo1 ;
Strcat( Str1, print_serv( &Variant[T->first].aWord[i1], i_slowo1 ),LFRASA );
add_ws( Str1 );
}
}
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: print1( Str1,%d )\n",i_Node );
error_add( EStr );
throw(E);
}
}
/***************************************************************************/
// нарисовать ближайший шаг
/***************************************************************************/
void t_Path :: print2( char *Str1, long i_Node, long i_down1, long i_slowo1 )
{ long i ;
t_pTree *T ;
try
{ T=&Tree[Tree[i_Node].down+i_down1] ;
Str1[0]=0 ;
for( i=T->i_aword ; i<T->i_last_aword ; i++ )
{ if( Variant[T->first].aWord.j<=i ) return ;
if( T->i_aword<i ) i_slowo1=0 ;
Strcat( Str1, print_serv( &Variant[T->first].aWord[i], i_slowo1 ),LFRASA );
Strcat( Str1," ",LFRASA );
}
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: print2( Str1,%d,%d,%d )\n",i_Node, i_down1, i_slowo1 );
error_add( EStr );
throw(E);
}
}
/***************************************************************************/
// нарисовать дальнейшие шаги
/***************************************************************************/
# ifdef NEW
long t_Path :: print3( char *Str1, long i_Node, long i_down1, long i_slowo1 )
{
long i,i1,z ;
long f,L,L1 ;
t_pVariant *V ;
t_pTree *T ;
try
{
Str1[0]=0 ;
f=0 ; L=0 ;
z=Tree[i_Node].down+i_down1 ;
if( Tree[z].n_down<=0 ) goto M_Ende ;
// if( Tree[z].fselect2==1 ) f=1 ;
z=Tree[z].down ;
while( 1 )
{
T=&Tree[z] ;
V=&Variant[T->first] ;
for( i=T->i_aword ; i<T->i_last_aword ; i++ )
{ if( i==V->aWord.j ) break ;
Strcat( Str1, print_serv( &V->aWord[i], 0 ),LFRASA );
Strcat( Str1," ",LFRASA );
// if( 1<V->aWord[i].n_slowo ) f=1 ;
// if( f==0 ) L=strlen( Str1 );
// if( T->fselect2==1 ) f=1 ;
}
// if( 1<T->n_down ) f=1 ;
if( T->ende==1 ) break ;
z=Tree[z].down ;
}
M_Ende:
if( Up!=NULL )
{ char Str2[LFRASA] ;
split_final( Tree[i_Node].down+i_down1,&i,&i1 );
// zz_Tree индекс этого дерева в вышестоящем дереве
L1=Up->print3( Str2, Up->z_Tree ,i, 0 );
Strcat( Str1,Str2,LFRASA );
// if( f==0 ) L+=L1 ;
}
return L ;
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: print2( Str1,%d,%d,%d )\n",i_Node, i_down1, i_slowo1 );
error_add( EStr );
throw(E);
}
}
# endif
/************************************************************************/
//# ifdef OLD
long t_Path :: print3( char *Str1, long i_Node, long i_down1, long i_slowo1 )
{
long i,i1 ;
t_pVariant *V ;
t_pTree *T ;
try
{ T=&Tree[Tree[i_Node].down+i_down1] ;
V=&Variant[T->first] ;
Str1[0]=0 ;
for( i=T->i_last_aword ; i<V->aWord.j ; i++ )
{ Strcat( Str1, print_serv( &V->aWord[i], 0 ),LFRASA );
Strcat( Str1," ",LFRASA );
}
if( Up!=NULL )
{ char Str2[LFRASA] ;
split_final( Tree[i_Node].down+i_down1,&i,&i1 );
// zz_Tree индекс этого дерева в вышестоящем дереве
Up->print3( Str2, Up->z_Tree ,i, 0 );
Strcat( Str1,Str2,LFRASA );
}
return 0 ;
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: print2( Str1,%d,%d,%d )\n",i_Node, i_down1, i_slowo1 );
error_add( EStr );
throw(E);
}
}
//# endif
/***************************************************************************/
char
* t_Path :: print_serv( t_aWord *W, short i_slowo1 )
{
t_Slowo2 *Slowo2 ;
t_sStruct *S ;
short i,is ;
char *Str ;
static char Str2[LFRASA] ;
static char Str3[LFRASA] ;
try
{
if( W->i_struct<0 )
// ---- если это константа --------
if( W->meaning<0 ) return W->Str ;
else return Meaning.get( W->meaning ) ;
else
{ if( W->n_slowo<=1 ) i_slowo1=0 ;
if( W->i_slowo<0 || W->n_slowo<=0 )
{ // ----- какой-то загадочный случай (убрать смелости не хватило) -----
if( W->meaning<0 ) Str=W->Str ;
else Str=Meaning.get( W->meaning ) ;
is=i_FormatT[W->i_struct] ;
if( 0<=is )
{ word_source( W->i_struct, Str, Str2, TO );
Slowo2=&SlowoT[ is ];
return Slowo2->form( Str2, &W->Form );
}
else
return Str ;
}
else
{ // ----- слово или структура -------------------
t_Form Form[10] ;
t_Struct *SS ;
t_sWord *W1 ;
t_RelationList1 RR ;
t_Relation R ;
S=Perevod.get_to( W->i_slowo, i_slowo1 );
// ----- вычисление параметров -----------------
SS=&Grammar[S->i_struct].To ;
if( SS->type==TSTRUCT2 )
RR=Perevod.get_relation( W->i_slowo, i_slowo1 );
else RR=SS->Relation ;
Form[0]=W->Form ;
for( i=0 ; i<S->n_Word ;i++ )
Form[i+1]=S->Word[i].Param ;
if( 0<=W->i_struct && Grammar[W->i_struct].To.type==TWORD )
Form[1]=Form[0] ;
for( i=0 ; i<RR.j ; i++ )
{ R=RR.list[i] ;
Form[R.s2].value[R.p2]=Form[R.s1].value[R.p1] ;
}
// ----- сложение составляющих -----------------
Str3[0]=0 ;
for( i=0 ; i<S->n_Word ;i++ )
{ W1=&S->Word[i] ;
Str=W1->str ;
if( 0<=W1->i_struct )
is=i_FormatT[W1->i_struct] ;
else is=-1 ;
if( 0<i ) strcat( Str3," " ) ;
if( 0<=is )
{ word_source( W1->i_struct, Str, Str2, TO );
Slowo2=&SlowoT[ is ];
Strcat( Str3,Slowo2->form( Str2, &Form[i+1] ),LFRASA );
}
else
Strcat( Str3,Str,LFRASA ) ;
}
return Str3 ;
}
}
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: print_serv( Str1,%d )\n", i_slowo1 );
error_add( EStr );
throw(E);
}
}
/***************************************************************************/
// вызов окна ручного выбора перевода
/***************************************************************************/
e_WinMsg t_Path :: loop( void )
{
e_WinMsg r1 ;
try
{
e_Result r=Core.result( );
del();
if( no_trans(r) )
{ Strcpy( Antwort,Core.antwort().str(),LFRASA );
r1=universe() ;
provokator( );
return r1 ;
}
else
{ Antwort[0]=0 ;
make_variant1( );
make_tree( );
z_Tree=i_down=0 ;
r1=universe( );
provokator( );
return r1 ;
}
}
catch( int E )
{
error_add( "t_Path :: ВНУТРЕННЯЯ ОШИБКА ПРОГРАММЫ" );
figna( error_get() );
return WM_ESC ;
}
}
/***************************************************************************/
// формирование ответа
// (ужасная повторяемость текста надо в if переделать)
/***************************************************************************/
e_WinMsg t_Path :: universe( )
{
short ZZ,key1,key2,Level ;
long z1_Tree,i,i1,i2,n_Down ;
char *s1,*s2 ;
t_pTree *T,*T1 ;
e_WinMsg r ;
e_Result r1 ;
char Sign[2]=".";
char StrTree[60] ;
try
{
Sign[0]=Core.sign();
// -------- определение уровня дерева (для отладки) ----------
t_Path *P=this ;
for( Level=0 ; Level<100 ; Level++ )
{ if( P->Up==NULL ) break ;
P=P->Up ;
}
r1=Core.result();
if( !no_trans(r1) )
{ if( Tree[z_Tree].ende==1 )
{ // ---- дерево состоит из единственной вершины (вырожденный собиратель)
if( z_Tree==0 )
{ print1( Antwort, z_Tree );
if( Up==NULL ) strcat( Antwort, Sign );
return WM_OK ;
}
z_Tree=Tree[z_Tree].up ;
}
}
while( 1 )
{
if( !no_trans(r1) )
{ T=&Tree[z_Tree] ;
if( T->fselect2 )
{ // ----- если попали в собиратель ----------
if( T->Down==NULL )
{ T->Down=new t_Path( this, z_Tree ) ;
T->Down->make_variant2( this,z_Tree );
T->Down->make_tree( );
}
r=T->Down->universe( );
switch( r )
{ case WM_OK:
T->Down->split_final( T->Down->z_Tree,&i1, &i2 );
// в этом месте ошибка
goto M_OK;
case WM_PREV : goto M_PREV;
case WM_ESC : return WM_ESC ;
}
continue ;
}
}
paint( );
sprintf( StrTree," Level=%2d z_Tree =%4d i_down=%2d",Level,z_Tree,i_down );
s_text_yxf( y2,10,0xf0,StrTree );
s_getch( &key1,&key2 ) ;
ZZ=s_shiftstatus();
if( (ZZ&(S_Ctrl_L|S_Ctrl_R))!=0 )
{
if( key1==0 && key2==S_key_Left ) return WM_P_FRASA ;
if( key1==0 && key2==S_key_Right ) return WM_N_FRASA ;
continue ;
}
switch( key1 )
{
case S_key_TabR : return WM_NEXT ;
case 0:
switch( key2 )
{ case S_key_F1 :
Window_help( (void *)"path.html") ;
break ;
// ------------ переход в другие окна ------------
case S_key_F2 : return WM_FIRST ;
case S_key_F3 : return WM_SRC ;
case S_key_F4 : return WM_DST ;
case S_key_F5 : return WM_DEBUG ;
case S_key_F6 : print_all( );
figna("отладочные деревья записаны");
break ;
case S_key_F10: return WM_ESC ;
case S_key_Left : if( no_trans(r1) ) return WM_P_FRASA ;
break ;
case S_key_Right: if( no_trans(r1) ) return WM_OK ;
break ;
}
}
if( no_trans(r1) ) continue ;
T=&Tree[z_Tree] ;
for( n_Down=i=0 ; i<T->n_down ; i++ )
if( 0<Tree[T->down+i].n_slowo )
n_Down+=Tree[T->down+i].n_slowo ;
switch( key1 )
{ case S_key_Esc : case S_key_Back : return WM_ESC ;
case 0:
switch( key2 )
{ case S_key_Left : goto M_PREV ;
case S_key_Right :
split_down( z_Tree, i_down, &i1, &i2 );
goto M_OK;
case S_key_Up : if( 0<i_down ) i_down-- ; break ;
case S_key_Down : if( i_down<n_Down-1 ) i_down++ ; break ;
}
}
continue ;
M_OK: // ---- шаг вперед -------
z1_Tree=T->down+i1 ;
T1=&Tree[z1_Tree] ;
z_Tree=z1_Tree ;
T1->i_slowo1=i2 ;
if( T1->i_struct!=-2 && T->Down!=NULL )
{ t_aWord *W=&Variant[T1->first].aWord[T1->i_aword] ;
s1=W->Str ;
s2=T->Down->Antwort+strlen( T->Down->StrUp ) ;
if( LWORD<=strlen(s2) ) W->meaning=Meaning.set( s2 ) ;
else Strcpy( s1,s2,LWORD );
}
if( T1->ende==1 )
{ print1( Antwort, z1_Tree );
if( Up==NULL )
{
t_pVariant *V=&Variant[T1->first] ;
short n_word=0,z ;
for( z=V->aWord.j-1 ; 0<=z ; z-- )
if( 0<=V->aWord[z].i_last_word )
{ n_word=V->aWord[z].i_last_word ; break ; }
if( n_word<Core.fn_word() )
{ t_Antwort A ;
Strcat( Antwort, A.translate_simple( n_word ), LFRASA );
}
short L=strlen(Antwort) ;
if( ' '==Antwort[L-1] ) Antwort[L-1]=0 ;
Strcat( Antwort, Sign, LFRASA );
}
return WM_OK ;
}
i_down=0 ;
continue ;
M_PREV: // ---- шаг назад -------
if( 0<=T->up )
{ i_down=merge_down( z_Tree,z_Tree-Tree[T->up].down )+T->i_slowo1 ;
z_Tree=T->up ;
M1: T1=&Tree[z_Tree] ;
if( T1->fselect2!=0 && T1->Down->n_Tree<=1 && 0<=T1->up )
// ------ вырожденный собиратель -------
{ z_Tree=T1->up ; goto M1 ; }
}
else
{ if( Up!=NULL ) return WM_PREV ;
}
continue ;
}
}
catch( int E )
{
error_add( "t_Path :: universe\n" );
throw(E);
}
}
/************************************************************************/
// сосчитать число вариантов i_down сыновей
/************************************************************************/
long t_Path :: merge_down( long i_Tree, long i_down1 )
{ long i,n ;
t_pTree *T ;
try
{
T=&Tree[i_Tree] ;
for( n=i=0 ; i<i_down1 ; i++ )
n=Tree[T->down+i].n_slowo ;
return n ;
}
catch( int E )
{
error_add( "t_Path :: merge_down\n" );
throw(E);
}
}
/************************************************************************/
// расщепить индекс потомка на "старший" (индекс потомка)
// и "младший" (индекс варианта потомка)
/************************************************************************/
void t_Path :: split_down( long i_Tree, long i_down1, long *i1, long *i2 )
{ long i,n,n_Down ;
t_pTree *T ;
try
{
T=&Tree[i_Tree] ;
n_Down=0 ;
for( i=0 ; i<T->n_down ; i++ )
{ n=Tree[T->down+i].n_slowo ;
if( i_down1<n_Down+n )
{ *i1=i ; *i2=i_down1-n_Down ; return ; }
n_Down+=n ;
}
*i1=-1 ; *i2=-1 ;
}
catch( int E )
{
error_add( "t_Path :: split_down\n" );
throw(E);
}
}
/************************************************************************/
void t_Path :: split_final( long i_Tree, long *i1, long *i2 )
{ long z,up ;
try
{ z=i_Tree ;
while( 0<z )
{ up=Tree[z].up ;
if( up==0 ) break ;
z=up ;
}
//*i1=Variant[Tree[z].first].i_down ;
*i1=Variant[Tree[i_Tree].first].i_down ;
*i2=Tree[z].i_slowo1 ;
}
catch( int E )
{
error_add( "t_Path :: split_final\n" );
throw(E);
}
}
/************************************************************************/
// сравнить два варианта перевода (для упорядочивания)
/************************************************************************/
int varcmp( const void *_a , const void *_b )
{ t_pVariant *a,*b ;
long i,i1 ;
char f=0 ;
try
{ a=(t_pVariant *)_a ; b=(t_pVariant *)_b ;
if( a->aWord.j != b->aWord.j ) { f=1 ; goto M_End ; }
for( i=0 ; i<a->aWord.j ; i++ )
{ if( a->aWord[i].i_struct != b->aWord[i].i_struct ) { f=1 ; break ; }
if( a->aWord[i].i_slowo != b->aWord[i].i_slowo ) { f=1 ; break ; }
if( a->aWord[i].i_struct<0 && 0!=Strcmp( a->aWord[i].Str, b->aWord[i].Str ) )
{ f=1 ; break ; }
t_Form &F1 = a->aWord[i].Form ;
t_Form &F2 = b->aWord[i].Form ;
for( i1=0 ; i1<10 ; i1++ )
if( F1.value[i1]!=F2.value[i1] ) { f=1 ; break ; }
}
M_End :
if( f==1 ) return a->index - b->index ;
else return 0 ;
}
catch( int E )
{
error_add( "t_Path :: varcmp\n" );
throw(E);
}
}
/************************************************************************/
// сравнить два варианта слова (для упорядочивания)
/************************************************************************/
int awordcmp( const void *_a , const void *_b )
{ t_aWord *a,*b ;
a=(t_aWord *)_a ; b=(t_aWord *)_b ;
if( a->i_struct != b->i_struct )
return a->i_struct - b->i_struct ;
if( a->i_slowo != b->i_slowo )
return a->i_slowo - b->i_slowo ;
if( a->i_word != b->i_word ) // только что вставил
return a->i_word - b->i_word ;
if( a->i_last_word != b->i_last_word ) // только что вставил
return a->i_last_word - b->i_last_word ;
if( a->i_struct<0 )
return Strcmp( a->Str, b->Str );
t_Form &F1 = a->Form ;
t_Form &F2 = b->Form ;
for( short i1=0 ; i1<10 ; i1++ )
if( F1.value[i1]!=F2.value[i1] )
{ return F1.value[i1]-F2.value[i1] ; }
return 0 ;
}
/************************************************************************/
t_aWord get_word( t_pVariant &V, short i_aword )
{
if( i_aword<V.aWord.j )
return V.aWord[i_aword] ;
else
{ t_aWord W ;
W.i_word = 0 ;
W.i_last_word= 0 ;
W.i_struct =-2 ;
W.i_slowo = 0 ;
W.n_slowo = 0 ;
W.Str[0] = 0 ;
W.meaning =-1 ;
return W ;
}
}
/************************************************************************/
// сделать дерево вариантов перевода
/************************************************************************/
void t_Path :: make_tree( void )
{ long i,i1,j ;
t_pTree T1,*T ;
t_aWord W,W1 ;
try
{
if( 0==Core.fn_word() )
{ n_Variant=0 ;
n_Tree =0 ;
return ;
}
Free(Tree);
if( n_Variant==0 ) { n_Tree=0 ; return ; }
Tree=(t_pTree *)Calloc( 1+Core.from().j*n_Variant,sizeof(t_pTree) );
// -------- внести первую вершину ------------------
T1.up =-1 ;
T1.down = 1 ;
T1.n_down = 0 ;
T1.first= 0 ;
T1.last = n_Variant ;
T1.ende = 0 ;
T1.i_struct = i_main_struct ;
T1.i_aword =-1 ;
T1.i_last_aword =0 ;
T1.i_slowo1 =0 ;
T1.n_slowo =0 ;
T1.Down =NULL ;
Tree[0]=T1 ;
// -------- внести последующие вершины -------------
char f_split,f_exist ;
short i_aword ;
for( i=0,j=1 ; i<j ; i++ )
{ T=&Tree[i] ;
// ----- выяснить есть ли "разветвления" на этой ветке ------
if( T->last-T->first<=1 )
{ for( i1=T->i_aword+1 ; i1<Variant[T->first].aWord.j ; i1++ )
{ W = get_word( Variant[T->first], i1 );
if( 1<W.n_slowo ) goto M_Need ;
if( 0<=W.i_struct && Grammar[W.i_struct].From.type==TSELECT2 )
goto M_Need ;
}
T->ende=1 ; T->i_last_aword=100 ; continue ;
M_Need : ;
}
T->down=j ;
// ---- пройти вдоль ветки, и сделать в нужном слове разветвление ----
for( i_aword=T->i_aword+1 ; i_aword<100 ; i_aword++ )
{ f_split=f_exist=0 ;
// ---- делать ли разветвление в слове i_word ----
if( 0<=T->i_struct && Grammar[T->i_struct].From.type==TSELECT2 )
f_split=1 ;
W = get_word( Variant[T->first], i_aword );
for( i1=T->first ; i1<T->last ; i1++ )
{ W1 = get_word( Variant[i1], i_aword );
if( i_aword<Variant[i1].aWord.j ) f_exist=1 ;
if( 0!=awordcmp( &W,&W1 ) ) { f_split=1 ; break ; }
if( 1<W1.n_slowo ) { f_split=1 ; break ; }
if( 0<=W1.i_struct && Grammar[W1.i_struct].From.type==TSELECT2 )
{ f_split=1 ; break ; }
}
if( f_exist==0 ) break ;
if( f_split==0 ) continue ;
// ---- если делать, то какие варианты в какие ветки попадают ----
W.i_struct=-2 ;
for( i1=T->first ; i1<T->last ; i1++ )
{
W1 = get_word( Variant[i1], i_aword );
if( 0!=awordcmp( &W,&W1 ) || W.i_struct==-2 )
{
if( T->first<i1 ) Tree[j-1].last=i1 ;
T1.up = i ;
T1.n_down = 0 ;
T1.first = i1 ;
T1.last = n_Variant ;
T1.ende = 0 ;
T1.i_struct= W1.i_struct ;
T1.i_aword = i_aword ;
T1.i_slowo1= 0 ;
T1.n_slowo = W1.n_slowo ;
Tree[j++]=T1 ;
W=W1 ;
}
}
if( f_split==1 )
{ T->i_last_aword=i_aword ;
Tree[j-1].last=T->last ;
}
if( f_split==1 ) break ;
}
T->n_down=j-T->down ;
}
if( 1+Core.from().j*n_Variant<j )
{ error_set("t_Path :: make_tree Ошибка памяти при заполнении Tree\n");
throw(-1);
}
n_Tree=j ;
Tree=(t_pTree *)Realloc( Tree,n_Tree*sizeof(t_pTree) ); // Memory Leak
Tree[0].i_aword=0 ;
// ---- проставить n_slowo и fselect2 -------
for( i=0 ; i<n_Tree ; i++ )
{
if( Tree[i].n_slowo<=0 )
Tree[i].n_slowo=1 ;
Tree[i].fselect2=0 ;
if( 0<=Tree[i].i_struct && Grammar[Tree[i].i_struct].From.type==TSELECT2 &&
0<=Tree[i].up )
Tree[Tree[i].up].fselect2=1 ;
}
// print_tree( "Tree0" );
}
catch( int E )
{
error_add( "t_Path :: make_tree\n" );
throw(E);
}
}
/************************************************************************/
// подсчет сыновей для "пред-собирателя"
/************************************************************************/
long t_Path :: n_variant_calc( t_Path *Up1, long z_Tree1 )
{ long i,i1,n ;
short i_struct ;
t_Struct *SS ;
t_pTree *T,*T1 ;
t_Variants *VV ;
try
{
T=&Up1->Tree[z_Tree1] ;
for( i=n=0 ; i<T->n_down ; i++ )
{ T1=&Up1->Tree[T->down+i] ;
i_struct=T1->i_struct ;
if( 0<=i_struct )
SS=&Grammar[i_struct].From ;
if( i_struct<0 || SS->type!=TSELECT2 )
n++ ;
else
{
for( i1=0 ; i1<SS->Word.j ; i1++ )
{ //t_aWord *W=&Up1->Variant[T->first].aWord[T->i_last_aword] ;
t_aWord *W=&Up1->Variant[T1->first].aWord[T1->i_aword] ;
if( W->i_word<0 || SS->Word[i1].i_struct<0 )
n++ ;
else
{ VV=Core.variants( W->i_word,SS->Word[i1].i_struct );
n+=VV->Variant.j ;
}
}
}
}
return n ;
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: n_variant_calc( Up1,%d )\n", z_Tree );
error_add( EStr );
throw(E);
}
}
/************************************************************************/
// сделать массив вариантов для последующего построения дерева
/************************************************************************/
void t_Path :: make_variant1( void )
{ long i,j ;
t_Variants *VV ;
t_Form Form0 ;
try
{
VV=Core.variants( 0, i_main_struct );
Free( Variant );
Variant=(t_pVariant *)Calloc( VV->Variant.j,sizeof(t_pVariant) );
for( i=j=0 ; i<VV->Variant.j ; i++ )
{
if( Core.f_full() && VV->Variant[i].i_last_word<Core.fn_word())
continue ;
Core.antwort().make( 0,i_main_struct,i,Form0 );
Variant[j].index =i ;
Variant[j].i_down=i ;
Variant[j].aWord =*Core.antwort().aword() ;
Core.antwort().del();
if( VV->Variant.j<=j )
{ error_set("t_Path :: make_variant Ошибка памяти при заполнении Variant\n");
throw(-1);
}
j++ ;
}
n_Variant=j ;
sort_variant();
}
catch( int E )
{
error_add( "t_Path :: make_variant1\n" );
throw(E);
}
}
/************************************************************************/
// сделать массив вариантов для последующего построения дерева
/************************************************************************/
void t_Path :: make_variant2( t_Path *Up1, long z_Tree1 )
{ long i,i1,i2,i3,j,n,i_struct,i_last_word ;
t_Variants *VV ;
t_Struct *SS ;
t_pTree *T,*T1 ;
t_aWord *W ;
t_RelationList1 RR ;
t_Relation R ;
try
{ n_Variant=n_variant_calc( Up1,z_Tree1 );
Free( Variant );
Variant=(t_pVariant *)Calloc( n_Variant,sizeof(t_pVariant) ); // Memory Leak
T=&Up1->Tree[z_Tree1] ;
for( j=i=n=0 ; i<T->n_down ; i++ )
{ T1=&Up1->Tree[T->down+i] ;
i_struct=T1->i_struct ;
if( 0<=i_struct )
SS=&Grammar[i_struct].From ;
if( 0<=i_struct && SS->type==TSELECT2 )
{ RR=Grammar[i_struct].To.Relation ;
W=&Up1->Variant[T1->first].aWord[T1->i_aword] ;
i_last_word=W->i_last_word ;
for( i1=0 ; i1<SS->Word.j ; i1++ )
{
if( SS->Word[i1].type==TWORD0 )
{
Variant[j].index=j ; // i
Variant[j].i_down=i ;
//Variant[j].aWord = ;
j++ ;
}
else
{
VV=Core.variants( W->i_word,SS->Word[i1].i_struct );
for( i2=0 ; i2<VV->Variant.j ; i2++ )
{ if( VV->Variant[i2].i_last_word!=i_last_word ) continue ;
t_Antwort A ;
// ---- госссподи, что я делаю, какой позор! -------
// ---- вычисляю параметры потомка, подменяя функции ядра ----
t_Form Form ;
Form.init();
for( i3=0 ; i3<RR.j ; i3++ )
{ R=RR.list[i3] ;
if( R.s1!=0 ) continue ;
if((R.s2-1)!=i1 ) continue ;
Form.value[R.p2] = W->Form.value[R.p1] ;
}
A.make( W->i_word, SS->Word[i1].i_struct, i2, Form );
if( n_Variant<=j )
{ error_set("t_Path :: make_variant2 Ошибка памяти при заполнении Variant\n");
throw(-1);
}
Variant[j].index=j ; // i
Variant[j].i_down=i ;
Variant[j].aWord =*A.aword() ;
A.del();
j++ ;
}
}
}
}
else
{
if( n_Variant<=j )
{ error_set("t_Path :: make_variant2 Ошибка памяти при заполнении Variant\n");
throw(-1);
}
Variant[j].index =j ;
Variant[j].i_down=i ;
// ну а вообще-то как отображать такой "вариант с пустым словом"???
if( T1->i_struct!=-2 )
Variant[j].aWord.add( Up1->Variant[T1->first].aWord[T1->i_aword] );
j++ ;
}
}
n_Variant=j ;
sort_variant();
}
catch( int E )
{
char EStr[200] ;
sprintf( EStr,"t_Path :: make_variant2( Up1,%d )\n", z_Tree1 );
error_add( EStr );
throw(E);
}
}
/************************************************************************/
// сортировка вариантов в удобном для человека порядке
/************************************************************************/
void t_Path :: sort_variant()
{
long i,i1,j,i_word,max_Word,End,m_Variant ;
t_pVariant **Var1,**Var2,**Var3,*zVar ;
t_aWord W1,W2 ;
// ------ Сделать массив ссылок на варианты -----------------
m_Variant=n_Variant ;
Var1=(t_pVariant **)Calloc( n_Variant,sizeof(t_pVariant *) );
Var2=(t_pVariant **)Calloc( n_Variant,sizeof(t_pVariant *) );
for( i=0 ; i<n_Variant ; i++ )
Var1[i]=&Variant[i] ;
// ------ Уничтожить одинаковые стоящие рядом варианты ------
for( i=j=1 ; i<n_Variant ; i++ )
if( 0!=varcmp( Var1[j-1],Var1[i] ) )
{ Var1[j++]=Var1[i] ; }
if( 0<n_Variant ) n_Variant=j ;
for( i=max_Word=0 ; i<n_Variant ; i++ )
if( max_Word<Var1[i]->aWord.j ) max_Word=Var1[i]->aWord.j ;
// ------ Цикл по номеру слова в варианте -------------------
for( i_word=0 ; i_word<max_Word ; i_word++ )
{
// ---- Цикл по номеру варианта ----------------------
for( i=j=0 ; i<n_Variant ; i++ )
{
// ----- Если вариант выбран - continue -----
if( Var1[i]==NULL ) continue ;
// ----- Переписать вариант во второй массив вариантов и
// ----- Установить на него стрелку
zVar=Var1[i] ; Var2[j++]=Var1[i] ; Var1[i]=NULL ;
// ----- Установить предел индекса End по неравенству предыдущего слова
if( i_word==0 )
End=n_Variant ;
else
{ W1=get_word( *zVar,i_word-1 );
for( End=i+1 ; End<n_Variant ; End++ )
{ if( Var1[End]==NULL ) continue ;
W2=get_word( *(Var1[End]),i_word-1 );
if( 0!=awordcmp( &W1,&W2 ) ) break ;
}
}
// ----- Еще цикл по номеру варианта i1=i+1 ; i1<End
for( i1=i+1 ; i1<End ; i1++ )
{ if( Var1[i1]==NULL ) continue ;
// -- Если вариант тождественен варианту на стрелке - переписать в другой массив
W1=get_word( *zVar,i_word );
W2=get_word( *(Var1[i1]),i_word );
if( 0==awordcmp( &W1,&W2 ) )
{ Var2[j++]=Var1[i1] ; Var1[i1]=NULL ; }
}
}
if( n_Variant<j )
printf("Аааа!!! Ошибка!!!!\n");
// ----- Поменять первый и второй массивы ссылок ------
Var3=Var1 ; Var1=Var2 ; Var2=Var3 ;
}
// ------ Уничтожить одинаковые стоящие рядом варианты ------
for( i=j=1 ; i<n_Variant ; i++ )
if( 0!=varcmp( Var1[j-1],Var1[i] ) )
{ Var1[j++]=Var1[i] ; }
if( 0<n_Variant ) n_Variant=j ;
// ------ Переписать массив вариантов ------------------------
t_pVariant *Variant1 ;
long n_aWord ;
for( i=n_aWord=0 ; i<n_Variant ; i++ )
n_aWord+=Var1[i]->aWord.j ;
Variant1=(t_pVariant *)Calloc( n_Variant,sizeof(t_pVariant) );
aWord =(t_aWord *)Calloc( n_aWord ,sizeof(t_aWord) );
for( i=j=0 ; i<n_Variant ; i++ )
{ Variant1[i].index =Var1[i]->index ;
Variant1[i].i_down=Var1[i]->i_down ;
Variant1[i].aWord.list=aWord+j ;
Variant1[i].aWord.j=Var1[i]->aWord.j ;
for( i1=0 ; i1<Var1[i]->aWord.j ; i1++ )
aWord[j++]=Var1[i]->aWord[i1] ;
}
for( i=0 ; i<m_Variant ; i++ )
Variant[i].aWord.del();
Free( Var1 ); Free( Var2 ); Free(Variant) ;
Variant=Variant1 ;
}
/************************************************************************/
// печать вариантов (для отладки)
/************************************************************************/
void t_Path :: print_variant( char *File )
{ long i,i1,j ;
FILE *fw ;
t_aWord W ;
fw=Fopen( File,"w");
for( i=0 ; i<n_Variant ; i++ )
{ fprintf( fw,"\n %3d i_down=%4d",i,Variant[i].i_down );
for( i1=0 ; i1<Variant[i].aWord.j ; i1++ )
{ W=Variant[i].aWord[i1] ;
fprintf( fw,", %d %s ",W.n_slowo, W.Str );
for( j=0 ; j<10 ; j++ )
fprintf( fw,"%c",'0'+W.Form.value[j] );
}
}
Fclose(fw);
}
/************************************************************************/
// печать дерева (для отладки)
/************************************************************************/
void t_Path :: print_tree( char *Name1 )
{ long i ;
t_pTree *T ;
FILE *fw=Fopen( Name1,"w");
char *s1 ;
fprintf( fw,"\n i up down n_down | first last | i_word i_word n_slowo ende select |" );
for( i=0 ; i<n_Tree ; i++ )
{ T=&Tree[i] ;
s1="" ;
if( 0<=T->i_aword && T->i_aword<Variant[T->first].aWord.j )
s1=Variant[T->first].aWord[T->i_aword].Str ;
fprintf( fw,"\n %5ld %5ld %5ld %5ld | %5ld %5ld | %5d %5d %5d %5d %d | %s",i,
T->up, T->down, T->n_down, T->first, T->last,
T->i_aword, T->i_last_aword, T->n_slowo, T->ende, T->fselect2, s1 );
}
Fclose(fw);
}
/************************************************************************/
void t_Path :: print_all( )
{ t_Path *P=this ;
short i,n ;
char Str[100] ;
for( i=0 ; i<100 ; i++ )
{ if( P->Up==NULL ) break ;
P=P->Up ;
}
n=i ;
P=this ;
for( i=0 ; i<100 ; i++ )
{ sprintf( Str,"Var%d",n-i );
P->print_variant( Str );
sprintf( Str,"Tree%d",n-i );
P->print_tree( Str );
if( P->Up==NULL ) break ;
P=P->Up ;
}
}
/************************************************************************/
t_Meaning :: t_Meaning()
{
Meaning =(char *)Calloc( l_Meaning=5000,1 );
j_Meaning=0 ;
}
/************************************************************************/
t_Meaning :: ~t_Meaning()
{
Free(Meaning);
}
/************************************************************************/
long t_Meaning :: set( char *Str )
{ long z,L,LL ;
L=strlen(Str);
if( L==0 ) return -1 ;
if( l_Meaning<=j_Meaning+L+1 )
{ LL=l_Meaning+max(l_Meaning>>2,L+1) ;
Meaning=(char *)Realloc( Meaning,LL );
l_Meaning=LL ;
}
z=j_Meaning ;
strcpy( Meaning+j_Meaning, Str );
j_Meaning+=L+1 ;
return z ;
}
/************************************************************************/
char
* t_Meaning :: get( long z )
{
if( z<0 ) return "" ;
return Meaning+z ;
}