/*******************************************************************/ // "Меркурий"-"Правда" - open source переводчик // распространяется в соответсвии с лицензией GNU v 2.0 // // Последовательный выбор вариантов перевода // Анисимов Д.В. сегодня /*******************************************************************/ # include # include # include # include # include # include # include # include # include # include # include 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 ; iName ); 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 ; in_down ; i++ ) if( 0down+i].n_slowo ) n_Down+=Tree[T->down+i].n_slowo ; z=size_y-6 ; Begin=0 ; if( i_downdown+j1].n_slowofirst] ; 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( 0i_last_aword ) { z2=T->i_last_aword-1 ; z3=W->i_last_word ; } else { z2=T->i_last_aword ; z3=W->i_word ; } } else { z2=V->aWord.j-1 ; z3=W->i_last_word ; } for( i=z2 ; 0<=i ; i-- ) { W=&V->aWord[i] ; if( 0<=z3 ) break ; } return sou_length( W->i_last_word ); } /***************************************************************************/ 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 ; i1i_last_aword ; i1++ ) { if( Variant[T->first].aWord.j<=i1 ) return ; if( T->i_awordi_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 ; ii_last_aword ; i++ ) { if( Variant[T->first].aWord.j<=i ) return ; if( T->i_awordfirst].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); } } /***************************************************************************/ // нарисовать дальнейшие шаги /***************************************************************************/ 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 ; iaWord.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); } } /***************************************************************************/ 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 ) ; if( Grammar[W->i_struct].To.type==TWORD ) is=i_FormatT[W->i_struct] ; else is=-1 ; 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 ; in_Word ;i++ ) Form[i+1]=S->Word[i].Param.form() ; if( 0<=W->i_struct && Grammar[W->i_struct].To.type==TWORD ) Form[1]=Form[0] ; for( i=0 ; in_Word ;i++ ) { W1=&S->Word[i] ; Str=W1->str ; if( 0<=W1->i_struct ) is=i_FormatT[W1->i_struct] ; else is=-1 ; if( 0i_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 ; } } /***************************************************************************/ enum e_Step // что делает universe в данный момент { Step_Up, Step_Down, Step_Nothing }; /***************************************************************************/ // формирование ответа // (ужасная повторяемость текста надо в 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 ; e_Step Step=Step_Nothing ; 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( n_Tree<=0 || Tree[z_Tree].ende==1 ) { // ---- дерево состоит из единственной вершины (вырожденный собиратель) if( z_Tree==0 ) { print1( Antwort, z_Tree ); if( Up==NULL ) strcat( Antwort, Sign ); return WM_SELECT2 ; } 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_SELECT2: switch( Step ) { case Step_Up : goto M_PREV; case Step_Down : T->Down->split_final( T->Down->z_Tree,&i1, &i2 ); goto M_OK; case Step_Nothing : goto M_Nothing ; } break ; case WM_PREV : goto M_PREV; case WM_ESC : return WM_ESC ; } continue ; } } M_Nothing: 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(); Step=Step_Nothing ; 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 ; in_down ; i++ ) if( 0down+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 : Step=Step_Up ; goto M_PREV ; case S_key_Right : split_down( z_Tree, i_down, &i1, &i2 ); Step=Step_Down ; goto M_OK; case S_key_Up : if( 0down+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_wordup ) { 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 ; idown+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 ; in_down ; i++ ) { n=Tree[T->down+i].n_slowo ; if( i_down1aWord.j != b->aWord.j ) { f=1 ; goto M_End ; } for( i=0 ; iaWord.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_awordlast-T->first<=1 ) { for( i1=T->i_aword+1 ; i1first].aWord.j ; i1++ ) { W = get_word( Variant[T->first], i1 ); if( 1ende=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 ; i1last ; i1++ ) { W1 = get_word( Variant[i1], i_aword ); if( i_awordfirst ; i1last ; i1++ ) { W1 = get_word( Variant[i1], i_aword ); if( 0!=awordcmp( &W,&W1 ) || W.i_struct==-2 ) { if( T->firsti_last_aword=i_aword ; Tree[j-1].last=T->last ; } if( f_split==1 ) break ; } T->n_down=j-T->down ; } if( n_TreeTree[z_Tree1] ; for( i=n=0 ; in_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 ; i1Word.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 ; iVariant.j ; i++ ) { if( Core.f_full() && VV->Variant[i].i_last_wordVariant.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 ; in_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 ; i1Word.j ; i1++ ) { if( SS->Word[i1].type==TWORD0 ) { Variant[j].index=j ; // i Variant[j].i_down=i ; j++ ; } else { VV=Core.variants( W->i_word,SS->Word[i1].i_struct ); for( i2=0 ; i2Variant.j ; i2++ ) { if( VV->Variant[i2].i_last_word!=i_last_word ) continue ; t_Antwort A ; // ---- госссподи, что я делаю, какой позор! ------- // ---- вычисляю параметры потомка, подменяя функции ядра ---- t_Form Form ; Form.init(); for( i3=0 ; i3Form.value[R.p1] ; } A.make( W->i_word, SS->Word[i1].i_struct, i2, Form ); if( n_Variant<=j ) goto M_Err_Mem ; Variant[j].index=j ; // i Variant[j].i_down=i ; Variant[j].aWord =*A.aword() ; A.del(); j++ ; } } } } else { if( n_Variant<=j ) goto M_Err_Mem ; 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(); return ; M_Err_Mem: error_set("t_Path :: make_variant2 Ошибка памяти при заполнении Variant\n"); throw(-1); } 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 ; iaWord.j ) max_Word=Var1[i]->aWord.j ; // ------ Цикл по номеру слова в варианте ------------------- for( i_word=0 ; i_wordaWord.j ; Variant1=(t_pVariant *)Calloc( n_Variant,sizeof(t_pVariant) ); aWord =(t_aWord *)Calloc( n_aWord ,sizeof(t_aWord) ); for( i=j=0 ; iindex ; 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 ; i1aWord.j ; i1++ ) aWord[j++]=Var1[i]->aWord[i1] ; } for( i=0 ; ii_aword && T->i_awordfirst].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 ; }