package Text::Editor::Easy::Graphic; use warnings; use strict; =head1 NAME Text::Editor::Easy::Graphic::Console_glue - Link between "Text::Editor::Easy::Abstract" and a terminal. Does not actually work. =head1 VERSION Version 0.1 =cut our $VERSION = '0.1'; #require Term::Screen; require Term::Screen::Win32; use Scalar::Util qw(refaddr); use IO::File; use threads; use threads::shared; my %editor ; # A un canevas, on fait correspondre un éditeur, l'éditeur qui a le focus #share ( %editor); #my %canva; # A un éditeur, on fait correspondre un canevas : inutile, car contenu # dans l'objet Graphic et accessible par ->[CANVA] use constant { TERM => 0, RESIZE => 1, KEY_PRESS => 2, TEXT => 3, # Hachage artificiel des bouts de texte demandés pour l'affichage MARKED => 4 , # Hachage articificiel des bouts de textes marqués (pour éventuel déplacement) ID => 5, # Dernier identifiant attribué pour un bout de texte FIC => 6, # Descripteur de fichier pour debug EXAMINE => 7, # Descripteur de fichier pour debug # Pour garder le positionnement du curseur CURSOR => 8, META_KEYS => 9, # Sauvegarder l'appui sur ALT, SHIFT et CTRL ABS => 0, ORD => 1, }; sub new { my ( $class, $hash_ref ) = @_; my $self = []; bless $self, $class; $self->initialize($hash_ref); return $self; } sub initialize { my ( $self, $hash_ref ) = @_; my $mw; if ( $hash_ref->{main_window} ) { #print "La fenêtre principale a déjà été créée\n"; $mw = $hash_ref->{main_window}; } else { $mw = create_main_window( $hash_ref->{width}, $hash_ref->{height}, $hash_ref->{x_offset}, $hash_ref->{y_offset}, $hash_ref->{title}, ); } $self->[TERM] = $mw; #open ( $self->[FIC], ">console_debug.txt") or die "Impossible d'ouvrir console_debug.txt : $!\n"; #$| = 1; #print {$self->[FIC]} "SELF : $self\n"; # my $canva; # if ( $hash_ref->{canvas} ) { # $canva = $hash_ref->{canvas}; # } # else { # $canva = create_canva ( # $mw, # $hash_ref->{background}, # -xscrollincrement => 0, # -yscrollincrement => 0, # ); # } if ( $hash_ref->{editor_ref} ) { $editor{ refaddr $mw} = $hash_ref->{editor_ref}; } # Pour l'instant on ne gère pas la fonction manage_event, on #$canva->CanvasBind( '', [ \&resize, $hash_ref->{resize}, Ev('w'), Ev('h') ] ); $self->[RESIZE] = $hash_ref->{resize}; #$canva->CanvasBind( '' => [ \&key_press, $hash_ref->{key_press}, Ev('K'), Ev('A') ] ); #$canva->CanvasBind('' => [ \&redirect, $hash_ref->{key_release}, Ev('K')]); $self->[KEY_PRESS] = $hash_ref->{key_press}; $self->[EXAMINE] = $hash_ref->{repeat}; #$mw->repeat(80, [ $hash_ref->{repeat}, $editor{refaddr $canva} ] ); # Gestion des évènements externes : dans manage_event } sub redirect { my ( $mw, $sub_ref, @data ) = @_; my $editor_ref = $editor{ refaddr $mw}; $sub_ref->( $editor_ref, @data ); } sub create_main_window { my ( $width, $height, $x, $y, $title ) = @_; #my $mw =new Term::Screen; my $mw = new Term::Screen::Win32; $mw->noecho(); #$mw->resize( $width, $height ); #my $mw = {}; return $mw; } my %key = ( 'ku' => 'Up', 'kd' => 'Down', 'kr' => 'Right', 'kl' => 'Left', 'end' => 'End', 'home' => 'Home', 'ins' => 'Insert', 'del' => 'Delete', 'ctrl' => 'Control_L', 'alt' => 'Alt_L', 'pgup' => 'Prior', 'pgdn' => 'Next', ); my %ascii = ( 1 => 'ctrl_A', 2 => 'ctrl_B', 3 => 'ctrl_C', 4 => 'ctrl_D', 5 => 'ctrl_E', 6 => 'ctrl_F', 7 => 'ctrl_G', 9 => 'ctrl_I', 10 => 'ctrl_J', 11 => 'ctrl_K', 12 => 'ctrl_L', 14 => 'ctrl_N', 15 => 'ctrl_O', 16 => 'ctrl_P', 17 => 'ctrl_Q', 18 => 'ctrl_R', 19 => 'ctrl_S', 20 => 'ctrl_T', 21 => 'ctrl_U', 22 => 'ctrl_V', 23 => 'ctrl_W', 24 => 'ctrl_X', 25 => 'ctrl_Y', 26 => 'ctrl_Z', 13 => "Return", 8 => "BackSpace", 127 => "Delete", 4294967289 => '¨', 4294967170 => 'é', 4294967178 => 'è', 4294967175 => 'ç', 4294967173 => 'à', 4294967288 => '°', 4294967196 => '£', 4294967270 => 'µ', 4294967191 => 'ù', 4294967285 => '§', 4294967293 => '²', 4294967247 => '¤', ); sub clear_screen { my ($self) = @_; $self->[TERM]->clrscr(); } sub manage_event { my ($self) = @_; # Génération du premier resize $self->[TERM]->clrscr(); #my $hash_ref = $self->[TERM]->resize( ); #$self->[RESIZE]->( $editor{refaddr $self->[TERM]}, $hash_ref->{COLS}, $hash_ref->{ROWS}); #my $console = Term::ANSIScreen->new; #$console->Cls; #my $term =new Term::Screen; $self->[RESIZE]->( $editor{ refaddr $self->[TERM] }, 120, 35 ); #threads->new( \&manage_keyboard, refaddr $self->[TERM], $self->[KEY_PRESS] );# # Pour l'instant pas de gestion des changements de la taille d'écran #EVENT: while ( my $char = $self->[TERM]->getch() ){ use Time::HiRes qw (sleep ); while (1) { #use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; #print colored ("TAPER $char", "bold blue"); #$self->[KEY_PRESS]->( $editor{refaddr $self->[TERM]}, $char, $char); #last EVENT if ($char eq "&"); $self->[EXAMINE]->( $editor{ refaddr $self->[TERM] } ); KEY: while ( $self->[TERM]->key_pressed ) { my $char = $self->[TERM]->getch(); $char = $ascii{ ord($char) } if ( $ascii{ ord($char) } ); $char = $key{$char} if ( $key{$char} ); if ( $char eq 'Control_L' ) { $self->[META_KEYS]{'ctrl'} = 5; next KEY; } if ( $char eq 'Alt_L' ) { $self->[META_KEYS]{'alt'} = 5; next KEY; } if ( $char eq 'shift' ) { $self->[META_KEYS]{'shift'} = 5; next KEY; } if ( $char =~ /ctrl_(\w)/ ) { $self->[META_KEYS]{'ctrl'} = 5; $char = $1; } my @options; if ( $self->[META_KEYS]{'ctrl'} ) { push @options, 'ctrl', 1; } if ( $self->[META_KEYS]{'alt'} ) { push @options, 'alt', 1; } if ( $self->[META_KEYS]{'shift'} ) { push @options, 'shift', 1; } $self->[KEY_PRESS] ->( $editor{ refaddr $self->[TERM] }, $char, $char, {@options} ); } sleep(0.1); for ( keys %{ $self->[META_KEYS] } ) { if ( $self->[META_KEYS]{$_} ) { $self->[META_KEYS]{$_} -= 1; } } } } # After initialisation sub length_text { my ( $self, $text, $font ) = @_; return length $text; } my %color = ( "black" => "white", "dark blue" => "bold blue", "dark red" => "bold red", ); sub create_text_and_mark_it { my ( $self, $hash_ref ) = @_; use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; $self->[ID] += 1; my $id = $self->[ID]; $self->[TEXT]{$id} = $hash_ref; $self->[MARKED]{$id} = 1; my $color = $color{ $hash_ref->{color} } || "bold green"; # $self->[TERM]->at($hash_ref->{ord}, $hash_ref->{abs}); locate( $hash_ref->{ord}, $hash_ref->{abs} ); print colored ( $hash_ref->{text}, $color ); # $self->[TERM]->puts($hash_ref->{text}); replace_cursor($self); return $id; } sub delete_mark_from_text { my ($self) = @_; for ( keys %{ $self->[MARKED] } ) { delete $self->[MARKED]{$_}; } } sub move_marked_text_one_line_up { my ($self) = @_; #$self->[CANVA]->move( 'just_created', 0, -17 ); } sub change_text_item_property { my ( $self, $text_id, $text ) = @_; #$self->[CANVA]->itemconfigure($text_id, -text, $text); } sub delete_text_item { my ( $self, $text_id ) = @_; my $hash_ref = $self->[TEXT]{$text_id}; my $abs = $hash_ref->{abs}; my $ord = $hash_ref->{ord}; my $text = $hash_ref->{text}; locate( $hash_ref->{ord}, $hash_ref->{abs} ); print " " x length( $hash_ref->{text} ); #print locate($abs,$ord), " " x length($text); #print "delete ($abs,$ord)", length($text), "\n"; delete $self->[TEXT]{ID}; replace_cursor($self); } sub position_cursor_in_text_item { my ( $self, $text_id, $position ) = @_; #print {$self->[FIC]} "Dans position cursor : $text_id|$position|\n"; my $hash_ref = $self->[TEXT]{$text_id}; my $abs = $hash_ref->{abs}; my $ord = $hash_ref->{ord}; $self->[CURSOR][ORD] = $hash_ref->{ord} - 1; $self->[CURSOR][ABS] = $hash_ref->{abs} - 1 + $position; $self->[TERM]->at( $self->[CURSOR][ORD], $self->[CURSOR][ABS] ); #print "Dans position cursor : $abs + $position,$ord)\n"; } sub replace_cursor { my ($self) = @_; $self->[TERM]->at( $self->[CURSOR][ORD], $self->[CURSOR][ABS] ); } sub resize { my ( $canva, $sub_ref, $height, $width ) = @_; } sub move { my ( $self, $x, $y ) = @_; # $self->[CANVA]->move( 'text', $x, $y ); } sub get_regexp { my ( $self, $sub_ref, $title ) = @_; } sub look_for { my ( undef, $self, $sub_ref ) = @_; } sub destroy_find { my ( $find, $self ) = @_; } sub change_reference { # Avant d'appeler cette fonction, faire le ménage sur le canevas my ( $self, $edit_ref, $file_name ) = @_; # $editor{refaddr $self->[CANVA]} = $edit_ref; # $self->[TERM]->configure( -title => $file_name ); } sub get_displayed_editor { my ($editor) = @_; # my $canva = $editor->[CANVA]; # return $editor{ refaddr $canva }; } sub set_font_size { my ( $self, $font, $size ) = @_; } sub create_font { return 1; } sub line_height { return 1; } sub margin { return 1; } =head1 COPYRIGHT & LICENSE Copyright 2008 Sebastien Grommier, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;