/*******************************************************************/
// "Меркурий"-"Правда" - 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] ; }