/*******************************************************************/ // "Меркурий"-"Правда" - open source переводчик // распространяется в соответсвии с лицензией GNU v 2.0 // // Часть моего текстового редактора // Анисимов Д.В. сегодня /*******************************************************************/ # include <string.h> # include <stdlib.h> # include "mylib.h" # include "edit.h" # include "video.h" # define max(a,b) (((a) > (b)) ? (a) : (b)) # define min(a,b) (((a) < (b)) ? (a) : (b)) # define size_Tab 8 # define max_Length 1000000L static char *Empty="" ; /***************************************************************************/ /* */ /***************************************************************************/ t_Text :: t_Text( void ) { Length = 0 ; Text = (char *)Calloc( max_Length,1 ); i_str=0 ; i_pos=0 ; str_Txt = 1 ; is_const=NULL ; fformat =0 ; } /***************************************************************************/ t_Text :: ~t_Text( void ) { Free( Text ); } /***************************************************************************/ void t_Text :: init( char *_Text ) { long i,j ; for( i=0 ; i<max_Length ; i++ ) Text[i]=0 ; str_Txt=1 ; for( i=j=0 ; i<max_Length ; i++ ) { if( _Text[i]==0 ) break ; if( _Text[i]!='\r' ) Text[j++] = _Text[i] ; if( _Text[i]=='\n' ) str_Txt++ ; } Length=j ; i_str=i_pos=0 ; } /***************************************************************************/ void t_Text :: clear( void ) { Length = 0 ; i_str = 0 ; i_pos = 0 ; str_Txt = 1 ; } /***************************************************************************/ void t_Text :: write_file( char *Name ) { FILE *fw=NULL ; try { fw=Fopen( Name,"wb" ); Fwrite( Text,Length,sizeof(char),fw ); Fclose( fw ); } catch( int E ) { Fclose( fw ); } } /***************************************************************************/ char t_Text :: read_file( char *Name ) { long i,i1,j,L ; FILE *fr=NULL ; char *m=NULL ; try { fr=Fopen( Name,"rb" ); L=FileLength( fr ); if( max_Length<L ) throw(-1) ; m=(char *)Calloc(L,sizeof(char)); Fread( m,L,sizeof(char),fr ); str_Txt=1 ; for( i=j=0 ; i<L ; i++ ) { if( m[i]=='\t' ) { for( i1=0 ; i1<size_Tab ; i1++ ) Text[j++]=' ' ; continue ; } if( m[i]!='\r' ) Text[j++]=m[i] ; if( m[i]=='\n' ) str_Txt++ ; } Length=j ; for( i=j ; i<max_Length ; i++ ) Text[i]=0 ; Free(m); Fclose( fr ); i_str=i_pos=0 ; return 0 ; } catch( int E ) { Free( m ); Fclose( fr ); return -1 ; } } /***************************************************************************/ char * t_Text :: get_str( long i_Str, char *Buf ) { char *s ; short i ; s=get_str( i_Str ); for( i=0 ; i<256 ; i++ ) Buf[i]=' ' ; for( i=0 ; i<256 ; i++ ) { if( s[i]==0 || s[i]=='\n' ) break ; Buf[i]=s[i] ; } return Buf ; } /***************************************************************************/ char * t_Text :: get_str( long i_Str ) { long p ; if( i_Str<0 || str_Txt<=i_Str ) return Empty ; p=pos_str( i_Str ); if( Length<=p ) return Empty ; return Text+p ; } /***************************************************************************/ long t_Text :: get_pos_xy( long py, long px ) { long i,p ; if( py<0 ) return 0 ; if( str_Txt<=py ) return Length ; p=pos_str( py ); for( i=0 ; i<px ; i++ ) { if( Length<=p+i ) break ; if( Text[p+i]=='\n' ) { i++ ; break ; } } return p+i ; } /***************************************************************************/ void t_Text :: get_xy_pos( long pos1, long *_py, long *_px ) { long i ; long px,py ; if( pos1<0 ) { *_py=0; *_px=0 ; return ; } if( Length<=pos1 ) { *_py=str_Txt-1; for( i=1 ; i<Length ; i++ ) if( Text[Length-i]=='\n' ) break ; *_px=i ; return ; } px=pos1 ; py=0 ; for( i=0 ; i<=pos1 ; i++ ) if( Text[i]=='\n' ) { py++ ; px=pos1-i-1 ; } *_py=py ; *_px=px ; } /***************************************************************************/ // вернуть индекс начала строки /***************************************************************************/ long t_Text :: pos_str( long i_Str ) { long i,i_str1 ; if( i_Str==0 ) return 0 ; for( i=i_str1=0 ; i<Length ; i++ ) { if( Text[i]=='\n' ) { i_str1++ ; if( i_str1==i_Str ) return i+1 ; } } return Length ; } /***************************************************************************/ // вставить строку в позицию (предыдущая строка исчезает) /***************************************************************************/ void t_Text :: put_str_ipos( long i1_pos, char *str ) { long l ; long i,j,i1,i2 ; // ---- вычислить l - длинну строки for( l=0 ; l<256 ; l++ ) if( str[l]==0 || str[l]=='\n' ) break ; j=l ; for( i=l=0 ; i<j ; i++ ) if( str[i]!=' ' ) l=i+1 ; // ---- проверить позицию на легальность if( i1_pos<0 || Length<i1_pos ) throw(-1); // ---- найти i1 - начало строки for( i1=i1_pos-1 ; 0<=i1 ; i1-- ) if( Text[i1]=='\n' ){ i1++ ; break ; } if( i1<0 ) i1=0 ; // ---- найти i2 - конец строки for( i2=i1_pos ; i2<Length ; i2++ ) if( Text[i2]=='\n' ){ i2++ ; break ; } if( l+1 <= i2-i1 ) { // ---- если вставляемая строка короче предыдущей for( i=0,j=i1 ; i<l ; i++ ) Text[j++]=str[i] ; Text[j++]='\n' ; for( i=i2 ; i<Length ; i++ ) Text[j++]=Text[i] ; } else { // ---- если вставляемая строка длиннее предыдущей for( i=Length-i2-1 ; 0<=i ; i-- ) Text[i1+l+1+i]=Text[i2+i] ; for( i=0,j=i1 ; i<l ; i++ ) Text[i1+i]=str[i] ; Text[i1+l]='\n' ; } Length+=(l+1)-(i2-i1); if( i1_pos<i_pos ) i_pos+=(l+1)-(i2-i1) ; } /***************************************************************************/ void t_Text :: put_str_istr( long i_Str, char *str ) { long pos ; pos=pos_str( i_Str ); put_str_ipos( pos, str ); } /***************************************************************************/ char * t_Text :: get_frasa( long pos ) { long i,j,z1,z2 ; static char Str[1000]="" ; if( Length<=pos ) return Str ; z1=begin_frasa( pos ); z2=end_frasa( pos ) ; for( i=z1,j=0 ; i<=z2 && j<999 ; i++ ) Str[j++]=Text[i] ; Str[j++]=0 ; return Str ; } /***************************************************************************/ char * t_Text :: get_word_punkt( long z ) { long i,j ; char c ; static char Str[1000]="" ; if( Length<=z ) return Str ; // ---- найти начало слова for( ; 0<=z ; z-- ) { c=Text[z] ; if( c==' ' || c=='\n' || c=='\t' ) break ; } z++ ; // ---- заполнить возвращаемую строку for( j=0,i=z ; i<Length ; i++ ) { c=Text[i] ; if( c==' ' || c=='\n' || c=='\t' ) break ; Str[j++]=c ; } Str[j++]=0 ; return Str ; } /***************************************************************************/ void t_Text :: put_frasa( long z, char *str ) { long i,j,i1,i2,l ; l=strlen( str ); if( Length<=z ) { Text[Length++]='\n' ; for( i=0 ; i<l ; i++ ) Text[Length++]=str[i] ; goto M_End ; } // ---- найти i1 - начало фразы i1=begin_frasa( z ) ; i2=end_frasa( z ); if( i2<z ) i1=i2=z ; // только что вставил (вставка после последней фразы) if( i1<0 ) i1=0 ; if( Text[i1]=='\n' ) i1++ ; if( l <= i2-i1 ) { // ---- если вставляемая строка короче предыдущей for( i=0,j=i1 ; i<l ; i++ ) Text[j++]=str[i] ; for( i=i2 ; i<Length ; i++ ) Text[j++]=Text[i] ; Text[j]=0 ; } else { // ---- если вставляемая строка длиннее предыдущей for( i=Length-i2-1 ; 0<=i ; i-- ) Text[i1+l+i]=Text[i2+i] ; for( i=0,j=i1 ; i<l ; i++ ) Text[i1+i]=str[i] ; } Length+=l-(i2-i1); Text[Length]=0 ; M_End : for( str_Txt=1,i=0 ; i<Length ; i++ ) str_Txt+=(Text[i]=='\n') ; } /***************************************************************************/ long t_Text :: prev_frasa( long pos ) { long i ; i=begin_frasa( pos ); i=begin_frasa( i-1 ); if( i<0 ) i=0 ; return i ; } /***************************************************************************/ long t_Text :: next_frasa( long pos ) { long i,z ; z=end_frasa( pos ) ; if( fformat==0 ) { return z+1 ; } else { for( i=z ; i<Length-4 ; i++ ) if( 0==strncmp(Text+i,"\\@@",3) || 0==strncmp(Text+i,"\\##",3) ) return i ; return Length ; } } /***************************************************************************/ long t_Text :: begin_frasa( long pos ) { long i ; char c ; if( fformat==0 ) { // ----- просто текст ----------- for( i=pos ; 0<=i ; i-- ) { c=Text[i] ; if( c=='.' || c=='!' || c=='?' ) { if( is_const==NULL ) return i+1 ; if( 0==is_const( get_word_punkt(i) ) ) return i+1 ; } } return 0 ; } else { // ----- текст с разметкой ------ for( i=pos ; 0<=i ; i-- ) if( 0==strncmp(Text+i,"\\@@",3) || 0==strncmp(Text+i,"\\##",3) ) break ; if( i<0 ) i=0 ; return i ; } } /***************************************************************************/ long t_Text :: end_frasa( long pos ) { long i,z ; char c,f=0 ; if( fformat==0 ) { // ----- просто текст ----------- for( i=pos ; i<Length ; i++ ) { c=Text[i] ; if( c=='.' || c=='!' || c=='?' ) { if( is_const==NULL ) return i+1 ; if( 0==is_const( get_word_punkt(i) ) ) return i+1 ; } } return Length ; } else { // ----- текст с разметкой ------ z=begin_frasa( pos ); for( i=z ; i<Length ; i++ ) if( Text[i]=='{' ) break ; for( i++ ; i<Length ; i++ ) { c=Text[i] ; if( c=='{' ) f++ ; if( c=='}' ) { if( f<=0 ) break ; f-- ; } } return i+1 ; } } /***************************************************************************/ // извлечь из текста строки с Str1 по Str2 с удалением из текста /***************************************************************************/ long t_Text :: get_text1( long Str1, long Str2, char *List ) { long i,pos1,pos2,L=0 ; pos2=pos_str( Str2+1 ); pos1=pos_str( Str1 ); L=pos2-pos1 ; for( i=0 ; i<L ; i++ ) List[i]=Text[pos1+i] ; Length-=L ; for( i=pos1 ; i<Length ; i++ ) Text[i]=Text[i+L] ; for( i=0,str_Txt=1 ; i<Length ; i++ ) if( Text[i]=='\n' ) str_Txt++ ; return pos2-pos1 ; } /***************************************************************************/ // извлечь из текста строки с Str1 по Str2 без удаления из текста /***************************************************************************/ long t_Text :: get_text2( long Str1, long Str2, char *List ) { long i,pos1,pos2,L=0 ; pos2=pos_str( Str1 ); pos1=pos_str( Str2 ); L=pos2-pos1 ; for( i=0 ; i<L ; i++ ) List[i]=Text[pos1+i] ; return L ; } /***************************************************************************/ // /***************************************************************************/ void t_Text :: put_text1( long Str, char *List, long l_List ) { long i,pos1 ; pos1 =pos_str( Str ); for( i=Length-1 ; pos1<=i ; i-- ) Text[i+l_List]=Text[i] ; Length+=l_List ; for( i=0 ; i<l_List ; i++ ) Text[pos1+i]=List[i] ; for( i=0,str_Txt=1 ; i<Length ; i++ ) if( Text[i]=='\n' ) str_Txt++ ; } /***************************************************************************/ // вставить фразу взамен cуществующей /***************************************************************************/ void t_Text :: put_text1p( long Pos1, long Pos2, char *Str ) { long i,L,D ; char f ; L=strlen( Str ); if( Str[L-1]==' ' ) Str[L-1]='.' ; D=L-(Pos2-Pos1)+1 ; if( 0<D ) { // ---------- раздвинуть текст -------------- for( i=Length ; Pos1<=i ; i-- ) Text[i+D]=Text[i] ; for( i=0 ; i<D ; i++ ) Text[Pos1+i]=' ' ; Length+=D ; } if( D<0 ) { // ---------- сдвинуть текст ---------------- for( i=Pos1 ; i<Length ; i++ ) Text[i]=Text[i-D] ; Length+=D ; } // ----------- вставить фразу ---------------- // ---- танцы с f - чтобы сохранить переводы строк ---- for( i=0,f=0 ; i<L ; i++ ) { //if( Text[Pos1+i]=='\n' ) f=1 ; Text[Pos1+i]=Str[i] ; //if( f==1 && Str[i]==' ' ) //{ Text[Pos1+i]='\n' ; f=0 ; } } } /***************************************************************************/ // вставить пустую строку /***************************************************************************/ void t_Text :: insert_str( long PY ) { short i,j ; j=pos_str( PY ); if( max_Length<Length ) { printf("\n t_Text :: insert_str Length>=max_Length !!!" ); exit(-1) ; } for( i=Length ; j<i ; i-- ) Text[i]=Text[i-1] ; Text[j]='\n' ; Length++ ; str_Txt++ ; } /***************************************************************************/ void t_Text :: delete_str( long PY ) { long j,j1 ; j=pos_str( PY ); if( Length<=j ) return ; for( j1=j ; j1<Length ; j1++ ) if( Text[j1]=='\n' ) break ; for( j1++ ; j1<Length ; j1++ ) Text[j++]=Text[j1] ; Length=j ; str_Txt-- ; } /***************************************************************************/ short t_Text :: max_length_str( void ) { short i,j,L=0 ; for( i=j=0 ; i<Length ; i++ ) if( Text[i]=='\n' ) { L=max( L,i-j ); j=i; } L=max( L,i-j ); return L ; } /***************************************************************************/ long t_Text :: length( void ) { return Length ; } /************************************************************************/ long t_Text :: str_txt( ) { return str_Txt ; } /***************************************************************************/ char t_Text :: operator []( long i ) { return Text[i] ; }