package Text::Editor::Easy::Abstract::Key;

use warnings;
use strict;

=head1 NAME

Text::Editor::Easy::Abstract::Key - Key functions using subs of "Text::Editor::Easy::Abstract" module.
Faster than using the object-oriented interface (that is, faster than "Text::Editor::Easy::Key") but not very clear.

=head1 VERSION

Version 0.31

=cut

use constant {
    PARENT    => 13,
	SELECTION => 18,
};

our $VERSION = '0.31';
use Data::Dump qw(dump);

sub left {
    my ( $self, $shift ) = @_;
	
	delete_start_selection_point( $self ) if ( ! $shift );

    if ( my $position = Text::Editor::Easy::Abstract::cursor_get($self) ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, $position - 1 );
    }

    # Curseur en début de ligne
    #my $line = $cursor->line->previous;
	my ( $ref_line, $text ) = $self->[PARENT]->previous_line( scalar(Text::Editor::Easy::Abstract::cursor_line($self)) );
    if ( $ref_line ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, length( $text ), $ref_line );
    }

    # Curseur en début de fichier (utilisé par la touche 'backspace')
    return;
}

sub right {
    my ( $self, $shift ) = @_;
	
	delete_start_selection_point( $self ) if ( ! $shift );
    my ( $text, $ref_cursor_line ) = Text::Editor::Easy::Abstract::cursor_line($self);
    my $position = Text::Editor::Easy::Abstract::cursor_get($self);
	
    if ( $position < length( $text ) ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, $position + 1, $ref_cursor_line );
    }

    # Curseur en début de ligne
    #my $line = $cursor->line->previous;
	( $ref_cursor_line, $text ) = $self->[PARENT]->next_line( $ref_cursor_line );
    if ( $ref_cursor_line ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, 0, $ref_cursor_line );
    }

    # Curseur en début de fichier (utilisé par la touche 'backspace')
    return;
}

sub home {
    my ($self, $shift) = @_;

	delete_start_selection_point( $self ) if ( ! $shift );

    my $display = Text::Editor::Easy::Abstract::cursor_display($self);
    if ( Text::Editor::Easy::Abstract::cursor_position_in_display( $self ) ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, 0, $display );
    }
    elsif ( Text::Editor::Easy::Abstract::display_previous_is_same( $self, $display ) ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self, 0, Text::Editor::Easy::Abstract::display_previous( $self, $display ) );
    }
    return;
}

sub end {
    my ($self, $shift) = @_;

	delete_start_selection_point( $self ) if ( ! $shift );

    my $display = Text::Editor::Easy::Abstract::cursor_display($self);
    if ( Text::Editor::Easy::Abstract::cursor_position_in_display( $self )
	== length( Text::Editor::Easy::Abstract::display_text( $self, $display ) ) ) {
        if ( Text::Editor::Easy::Abstract::display_next_is_same ($self, $display ) ) {
            my $next = Text::Editor::Easy::Abstract::display_next ($self, $display );
            return Text::Editor::Easy::Abstract::cursor_set( 
			    $self, 
			    length( Text::Editor::Easy::Abstract::display_text( $self, $next ) ), 
			    $next
		    );
        }
    }
    else {
        return Text::Editor::Easy::Abstract::cursor_set(
		    $self,
    		length( Text::Editor::Easy::Abstract::display_text( $self, $display ) ),
			$display
		);
    }
    return;
}

sub delete_start_selection_point {
	my ( $self, $mode ) = @_;
		
	$self->[SELECTION] = undef;
	Text::Editor::Easy::Abstract::deselect( $self );
}

sub shift_left {
		my ( $self ) = @_;
		
		#print "Dans shift_left de Key\n";
		my $select_ref = set_start_selection_point($self, '-');
		
		my ( $ref_line, $pos ) = left( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect($self, $ref_line);
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);				    
					$select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
					$select_ref->{'mode'} = '+';
			    }
		}
		else {
		    if ( $ref_line == $select_ref->{'stop_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect($self, $ref_line);
		    }
			if ( $select_ref->{'mode'} eq '+' ) {
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub shift_right {
		my ( $self ) = @_;
		
		#print "Dans shift_left de Key\n";
		my $select_ref = set_start_selection_point($self, '+');
		
		my ( $ref_line, $pos ) = right( $self, 'shift' );
		return if ( ! $ref_line );
		
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
				    $select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);
					$select_ref->{'mode'} = '+';
			    }
		}
		else {
		    if ( $ref_line == $select_ref->{'stop_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
		    }
			#print "Dans shift_right, mode = ", $select_ref->{'mode'} , "\n";
			if ( $select_ref->{'mode'} eq '+' ) {
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub down {
    my ($self, $shift ) = @_;

	delete_start_selection_point( $self ) if ( ! $shift );
	
    Text::Editor::Easy::Abstract::cursor_make_visible( $self );
    my $display  = Text::Editor::Easy::Abstract::cursor_display( $self );
    my $next = Text::Editor::Easy::Abstract::display_next( $self, $display );
    if ( defined $next ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self,
            {
                'x'            => Text::Editor::Easy::Abstract::cursor_virtual_abs ($self ),
                'display'      => $next,
                'keep_virtual' => 1,
            }
        );
    }
	return;
}

sub up {
    my ($self, $shift ) = @_;
	
	delete_start_selection_point( $self ) if ( ! $shift );

    Text::Editor::Easy::Abstract::cursor_make_visible( $self );
    my $display  = Text::Editor::Easy::Abstract::cursor_display( $self );
    my $previous = Text::Editor::Easy::Abstract::display_previous( $self, $display );
    if ( defined $previous ) {
        return Text::Editor::Easy::Abstract::cursor_set( $self,
            {
                'x'            => Text::Editor::Easy::Abstract::cursor_virtual_abs ($self ),
                'display'      => $previous,
                'keep_virtual' => 1,
            }
        );
    }
    return;
}

sub shift_down {
		my ( $self ) = @_;
		
		#print "Dans shift_left de Key\n";
		my $select_ref = set_start_selection_point($self, '+');
		
		my ( $ref_line, $pos ) = down( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
				    $select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);
					$select_ref->{'mode'} = '+';
			    }
				my $ref_stop_line = $select_ref->{'stop_line'};
				if ( defined $ref_stop_line and $ref_line != $ref_stop_line ) {
						Text::Editor::Easy::Abstract::line_deselect( $self, $ref_stop_line);
				}
		}
		else {
		    my $ref_stop_line = $select_ref->{'stop_line'};
			if ( ! defined $ref_stop_line or $ref_stop_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $select_ref->{'start_line'} );
				Text::Editor::Easy::Abstract::line_select( $self, $select_ref->{'start_line'}, $select_ref->{'start_pos'} );
				$select_ref->{'mode'} = '+';
		    }
		    if ( defined $ref_stop_line ) {
				if ( $ref_line == $ref_stop_line ) {
				    Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
		        }
			    elsif ( $ref_stop_line != $select_ref->{'start_line'} ) {
					Text::Editor::Easy::Abstract::line_deselect( $self, $ref_stop_line);
					if ( $select_ref->{'mode'} eq '+' ) {
					    Text::Editor::Easy::Abstract::line_select( $self, $ref_stop_line);
				    }
			    }
		    }
					
			#print "Dans shift_right, mode = ", $select_ref->{'mode'} , "\n";
			if ( $select_ref->{'mode'} eq '+' ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub shift_up {
		my ( $self ) = @_;
		
		#print "Dans shift_left de Key\n";
		my $select_ref = set_start_selection_point($self, '-');
		
		my ( $ref_line, $pos ) = up( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line);
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
				    $select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line,  $pos, $start_pos);
					$select_ref->{'mode'} = '+';
			    }
				my $ref_stop_line = $select_ref->{'stop_line'};
				if ( defined $ref_stop_line and $ref_line != $ref_stop_line ) {
						Text::Editor::Easy::Abstract::line_deselect( $self, $ref_stop_line );
				}
		}
		else {
		    #print "shift_up intermédiaire mode = ", $select_ref->{'mode'}, "\n";
		    my $ref_stop_line = $select_ref->{'stop_line'};
			if ( ! defined $ref_stop_line or $ref_stop_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $select_ref->{'start_line'} );
				Text::Editor::Easy::Abstract::line_select( $self, $select_ref->{'start_line'}, 0, $select_ref->{'start_pos'} );
				$select_ref->{'mode'} = '-';
		    }
			if ( defined $ref_stop_line ) {
		        if ( $ref_line == $ref_stop_line ) {
				    Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
		        }
			    elsif ( $ref_stop_line != $select_ref->{'start_line'} ) {
					Text::Editor::Easy::Abstract::line_deselect( $self, $ref_stop_line );
					if ( $select_ref->{'mode'} eq '-' ) {
					    Text::Editor::Easy::Abstract::line_select( $self, $ref_stop_line );
				    }
			    }
		    }
					
			#print "Dans shift_right, mode = ", $select_ref->{'mode'} , "\n";
			if ( $select_ref->{'mode'} eq '+' ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub shift_home {
		my ( $self ) = @_;
		
		my $select_ref = set_start_selection_point($self, '-');
		
		my ( $ref_line, $pos ) = home ( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
				    $select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);
					$select_ref->{'mode'} = '+';
			    }
		}
		else {
			#print "Dans shift_right, mode = ", $select_ref->{'mode'} , "\n";
			if ( $select_ref->{'mode'} eq '+' ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub shift_end {
		my ( $self ) = @_;
		
		my $select_ref = set_start_selection_point($self, '+');
		
		my ( $ref_line, $pos ) = end( $self, 'shift' );
		return if ( ! $ref_line );
		
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
				    $select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);
					$select_ref->{'mode'} = '+';
			    }
		}
		else {
			#print "Dans shift_right, mode = ", $select_ref->{'mode'} , "\n";
			if ( $select_ref->{'mode'} eq '+' ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub set_start_selection_point {
		my ( $self, $mode ) = @_;
		
		my $select_ref = $self->[SELECTION];
		if ( ! defined $select_ref ) {
		    my ( $ref_line, $pos ) = Text::Editor::Easy::Abstract::cursor_get($self);
			$select_ref = {
					'start_line' => $ref_line,
					'start_pos' => $pos, 
					'mode' => $mode,
			};
			#$self->save_info($select_ref, 'select');
	    }
		#print "Départ : mode = ", $select_ref->{'mode'}, "\n";
		return $select_ref;
}

sub page_down {
    my ($self, $shift) = @_;

	delete_start_selection_point( $self ) if ( ! $shift );

    my $ref_display = Text::Editor::Easy::Abstract::cursor_display( $self );
	my $y = Text::Editor::Easy::Abstract::display_middle_ord( $self, $ref_display );

    my $ref_last   = Text::Editor::Easy::Abstract::screen_number( $self, Text::Editor::Easy::Abstract::screen_number( $self ) );
    #print "LAST text :", $last->text, "\n";
    Text::Editor::Easy::Abstract::display( $self, $ref_last, {
			'at' => 'top',
		    'no_check' => '1',
		} );
    my ( @pos ) = Text::Editor::Easy::Abstract::cursor_set( $self, 
            {
                'x'            => Text::Editor::Easy::Abstract::cursor_virtual_abs( $self ),
                'y'      	     => $y,
                'keep_virtual' => 1,
	        }
        );
    Text::Editor::Easy::Abstract::screen_check_borders ( $self );
	return @pos;
}

sub page_up {
    my ($self, $shift) = @_;

	delete_start_selection_point( $self ) if ( ! $shift );

    my $ref_display = Text::Editor::Easy::Abstract::cursor_display( $self );
	my $y = Text::Editor::Easy::Abstract::display_middle_ord( $self, $ref_display );
    my $ref_first   = Text::Editor::Easy::Abstract::screen_number( $self, 1 );

    #print "FIRST text :", $first->text, "\n";
    Text::Editor::Easy::Abstract::display( $self, $ref_first, {
			'at' => 'bottom',
			'from' => 'bottom',
			'no_check' => '1',
	    } );
    my ( @pos ) = Text::Editor::Easy::Abstract::cursor_set( $self,
            {
                'x'            => Text::Editor::Easy::Abstract::cursor_virtual_abs( $self ),
                'y'      	     => $y,
                'keep_virtual' => 1,
            }
        );
    Text::Editor::Easy::Abstract::screen_check_borders ( $self );
	return @pos;
}

sub shift_page_down {
		my ( $self ) = @_;
		
		my $select_ref = set_start_selection_point($self, '+');
		
		my ( $ref_line, $pos ) = page_down( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				#$line->deselect;
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);				    
					$select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
					$select_ref->{'mode'} = '+';
			    }
				$select_ref->{'stop_line'} = $ref_line;
		        $select_ref->{'stop_pos'} = $pos;
		        $self->[SELECTION] = $select_ref;
				return;
		}
		if ( $select_ref->{'mode'} eq '+' ) {
		    my $ref_line_to_select = $select_ref->{'stop_line'};
			$ref_line_to_select = $select_ref->{'start_line'} if ( ! defined $ref_line_to_select );
			print "1 Dans shift_page_down : ref = $ref_line_to_select\n";
			while ( defined $ref_line_to_select and $ref_line_to_select != $ref_line ) {
					Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line_to_select );
					Text::Editor::Easy::Abstract::line_select( $self, $ref_line_to_select );
					( $ref_line_to_select ) = $self->[PARENT]->next_line( $ref_line_to_select );
					print "2 Dans shift_page_down : ref = $ref_line_to_select\n";
			}
			return if ( ! $ref_line_to_select ); # MEssage d'erreur ...
			Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos );
			
			$ref_line_to_select = $select_ref->{'stop_line'};
		    $select_ref->{'stop_line'} = $ref_line;
		    $select_ref->{'stop_pos'} = $pos;
		    $self->[SELECTION] = $select_ref;
			return if ( ! defined $ref_line_to_select );
			#Sélection par l'arrière
			TOP: while ( $ref_line_to_select != $select_ref->{'start_line'} ) {
		        ( $ref_line_to_select ) = $self->[PARENT]->previous_line( $ref_line_to_select );
				my $string = Text::Editor::Easy::Abstract::line_select( $self, $ref_line_to_select ) if ( $ref_line_to_select );
				last TOP if ( ! defined $string );
		    }
	    }
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub shift_page_up {
		my ( $self ) = @_;
		
		#print "Dans shift_left de Key\n";
		my $select_ref = set_start_selection_point($self, '-');
		
		my ( $ref_line, $pos ) = page_up( $self, 'shift' );
		return if ( ! $ref_line );
		#print "Line récupérée de left $line, ", $line->text, " |", $line->ref, "\n";
		#print "Start Line ", $select_ref->{'start_line'}, $select_ref->{'start_line'}->text, " |", $select_ref->{'start_line'}->ref, "\n";
		if ( $ref_line == $select_ref->{'start_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
				my $start_pos = $select_ref->{'start_pos'};
				if ( $start_pos > $pos ) {
				    #$line->select( $pos, $start_pos);		    
					Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos, $start_pos);
					$select_ref->{'mode'} = '-';
			    }
				else {
				    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $start_pos, $pos );
					$select_ref->{'mode'} = '+';
			    }
		}
		else {
		    if ( $ref_line == $select_ref->{'stop_line'} ) {
				Text::Editor::Easy::Abstract::line_deselect( $self, $ref_line );
		    }
			if ( $select_ref->{'mode'} eq '+' ) {
				# Changement possible de sens
				#my $search_line = $line->next;
				my ( $ref_search_line ) = $self->[PARENT]->next_line( $ref_line );
				my $ref_start_line = $select_ref->{'start_line'};
				my $ref_stop_line = $select_ref->{'stop_line'};
				while ( $ref_search_line 
				    and $ref_search_line ne  $ref_start_line
					and $ref_search_line ne  $ref_stop_line ) {
							#
							#
						( $ref_search_line ) = $self->[PARENT]->next_line( $ref_search_line );
				}
				if ( $ref_search_line == $ref_start_line ) {
						# Inversion
						$select_ref->{'mode'} = '-';
				}
			    Text::Editor::Easy::Abstract::line_select( $self, $ref_line, 0, $pos);
		    }
			else {
				Text::Editor::Easy::Abstract::line_select( $self, $ref_line, $pos);
		    }
	    }
		
		$select_ref->{'stop_line'} = $ref_line;
		$select_ref->{'stop_pos'} = $pos;
		$self->[SELECTION] = $select_ref;
}

sub copy {
    my ($self) = @_;

    #Appel au thread manager à faire. Pour l'instant, méthode provisoire et très longue
	my $select_ref = set_start_selection_point($self, '+');
	return if ( ! defined $select_ref->{'stop_line'} );
	my ( $ref_start_line, $start_pos, $ref_stop_line, $stop_pos );
	if ( $select_ref->{'mode'} eq '+' ) {
		$ref_start_line = $select_ref->{'start_line'};
		$start_pos = $select_ref->{'start_pos'};
		$ref_stop_line = $select_ref->{'stop_line'};
		$stop_pos = $select_ref->{'stop_pos'};
    }
	else {
		$ref_start_line = $select_ref->{'stop_line'};
		$start_pos = $select_ref->{'stop_pos'};
		$ref_stop_line = $select_ref->{'start_line'};
		$stop_pos = $select_ref->{'start_pos'};
    }
	my $buffer;
    if ( $ref_stop_line != $ref_start_line ) {
		$buffer = substr ( $self->[PARENT]->get_text_from_ref( $ref_start_line) , $start_pos );
		$buffer .= "\n";
    }
    else {
		$buffer = substr ( $self->[PARENT]->get_text_from_ref( $ref_start_line ), $start_pos, $stop_pos - $start_pos );
		print "========Debut buffer\n$buffer\n==========Fin buffer\n";
		Text::Editor::Easy->clipboard_set($buffer);
		return;
    }
    my ( $ref_line ) = $self->[PARENT]->next_line( $ref_start_line );
    while ( defined $ref_line and $ref_line != $ref_stop_line ) {
		$buffer .= $self->[PARENT]->get_text_from_ref( $ref_line ) . "\n";
		( $ref_line ) = $self->[PARENT]->next_line( $ref_line );
    }
    return if ( ! defined $ref_line ); # stop line suppressed
    $buffer .= substr ( $self->[PARENT]->get_text_from_ref( $ref_line ), 0, $stop_pos );
    print "========Debut buffer\n$buffer\n==========Fin buffer\n";
	Text::Editor::Easy->clipboard_set($buffer);
    #$buffer = $self->cursor->line->text . "\n";
}

sub delete_selection {
    my ( $self ) = @_;
	
	my $select_ref = $self->[SELECTION];
	my ( $ref_start_line, $start_pos, $ref_stop_line, $stop_pos );
	if ( $select_ref->{'mode'} eq '+' ) {
		$ref_start_line = $select_ref->{'start_line'};
		$start_pos = $select_ref->{'start_pos'};
		$ref_stop_line = $select_ref->{'stop_line'};
		$stop_pos = $select_ref->{'stop_pos'};
    }
	else {
		$ref_start_line = $select_ref->{'stop_line'};
		$start_pos = $select_ref->{'stop_pos'};
		$ref_stop_line = $select_ref->{'start_line'};
		$stop_pos = $select_ref->{'start_pos'};
    }
	
	#print "Dans delete_selection : $start_pos|$stop_pos\n";
	if ( $ref_start_line ==  $ref_stop_line ) {
        my ( $text, $ref_cursor_line ) = Text::Editor::Easy::Abstract::cursor_line($self);
		if ( $ref_cursor_line != $ref_stop_line ) {
		    # Bizarre !
			print STDERR "Cursor not on start or end of selection : the text won't be suppressed\n";
			Text::Editor::Easy::Abstract::deselect( $self );
		    undef $self->[SELECTION];
			return;
	    }
		my $new_text = substr ( $text, 0, $start_pos) . substr( $text, $stop_pos);
		#print "Nouveau text de $ref_stop_line : |$new_text| START POS : $start_pos\n";
		Text::Editor::Easy::Abstract::cursor_set( $self, $start_pos, $ref_stop_line );
		Text::Editor::Easy::Abstract::line_set($self, $ref_stop_line, $new_text);
		Text::Editor::Easy::Abstract::line_deselect( $self, $ref_stop_line );
		undef $self->[SELECTION];
		return;
	}
	
    my ( $text, $ref_cursor_line ) = Text::Editor::Easy::Abstract::cursor_line($self);
    if ( $ref_cursor_line != $ref_start_line and $ref_cursor_line != $ref_stop_line ) {
	    print STDERR "Cursor not on start or end of selection : the text won't be suppressed\n";
		Text::Editor::Easy::Abstract::deselect( $self );
		undef $self->[SELECTION];
		return;
    }

	my ( $at, $from );
	if ( Text::Editor::Easy::Abstract::line_displayed( $self, $ref_start_line ) ) {
		$at = 'ord_' . Text::Editor::Easy::Abstract::line_top_ord ( $self, $ref_start_line );
		$from = 'top';		
	}
	elsif ( Text::Editor::Easy::Abstract::line_displayed( $self, $ref_stop_line ) ) {
		$at = 'ord_' . Text::Editor::Easy::Abstract::line_bottom_ord ( $self, $ref_stop_line );
        $from = 'bottom';
	}
    else { # Affichage au milieu des 2 lignes jointes
        $from = 'middle';
        $at = 'middle';		
	}
	Text::Editor::Easy::Abstract::cursor_set( $self, $start_pos, $ref_start_line );
    my $start_text = substr ( $self->[PARENT]->get_text_from_ref( $ref_start_line) , 0, $start_pos );
    my $end_text = substr ( $self->[PARENT]->get_text_from_ref( $ref_stop_line) , $stop_pos );
		
		#print "Nouveau texte première ligne : $start_text$end_text\n";
	Text::Editor::Easy::Abstract::line_set($self, $ref_start_line, $start_text . $end_text );
	Text::Editor::Easy::Abstract::deselect( $self );
	#Suppression des lignes jusqu'à $ref_stop_line incluse
	my @refs_to_suppress;
	my $ref_to_suppress = $ref_start_line;
	do {
	    ( $ref_to_suppress ) = $self->[PARENT]->next_line( $ref_to_suppress );
		push @refs_to_suppress, $ref_to_suppress;
    }
	while ( $ref_to_suppress != $ref_stop_line );
	for my $ref_line ( @refs_to_suppress ) {
	    $self->[PARENT]->delete_line( $ref_line );
    }
	
	Text::Editor::Easy::Abstract::display ( $self, $ref_start_line, { 
			'from' => $from,
			'at' => $at
		} );

	undef $self->[SELECTION];
	return;
}

sub backspace {
    my ($self) = @_;
	
	if ( defined $self->[SELECTION] ) {
		Text::Editor::Easy::Abstract::Key::delete_selection($self);
		return; # pour comportement le plus "standard"
	}
    # left_key renvoie undef si on est au début du fichier
    return if ( !defined left($self) );
	
    # Améliorer l'interface de erase en autorisant les nombres négatifs ==>
    #    $self->erase(-1)
    $self->[PARENT]->erase(1);
}

sub delete {
    my ($self) = @_;
	
	if ( defined $self->[SELECTION] ) {
		Text::Editor::Easy::Abstract::Key::delete_selection($self);
		return; # pour comportement le plus "standard"
	}
    $self->[PARENT]->erase(1);
}

sub enter {
    my ($self) = @_;
	
	if ( defined $self->[SELECTION] ) {
		Text::Editor::Easy::Abstract::Key::delete_selection($self);
	}

    Text::Editor::Easy::Abstract::enter( $self, { 'indent' => 'auto' } );
}

sub cut {
    my ( $self ) = @_;
	
    copy ( $self );

    delete_selection ( $self );
}
