File Coverage

blib/lib/BBS/Perm/Term.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package BBS::Perm::Term;
2              
3 1     1   21728 use warnings;
  1         3  
  1         32  
4 1     1   6 use strict;
  1         2  
  1         36  
5 1     1   5 use Carp;
  1         2  
  1         114  
6 1     1   463 use Glib qw/TRUE FALSE/;
  0            
  0            
7             use Gnome2::Vte;
8             use File::Spec::Functions 'file_name_is_absolute';
9              
10             sub new {
11             my ( $class, %opt ) = @_;
12             my $self = {%opt};
13             $self->{widget} = Gtk2::HBox->new unless $self->{widget};
14             $self->{terms} = [];
15             $self->{titles} = [];
16             $self->{encoding} = [];
17             bless $self, ref $class || $class;
18             }
19              
20             sub init { # initiate a new term
21             my ( $self, $conf ) = @_;
22             my $term = Gnome2::Vte::Terminal->new;
23             push @{ $self->{terms} }, $term;
24             push @{ $self->{titles} }, $conf->{title}
25             || $conf->{username} . '@' . $conf->{site};
26             push @{ $self->{encoding} }, $conf->{encoding};
27              
28             if ( defined $self->{current} ) { # has term already?
29             $self->term->hide;
30             }
31              
32             $self->{current} = $#{ $self->{terms} };
33             $self->widget->pack_start( $self->term, TRUE, TRUE, 0 );
34             $self->term->show;
35             $self->term->grab_focus;
36              
37             if ( $conf->{encoding} ) {
38             $term->set_encoding( $conf->{encoding} );
39             }
40              
41             if ( $conf->{font} ) {
42             my $font = Pango::FontDescription->from_string( $conf->{font} );
43             $term->set_font($font);
44             }
45              
46             if ( $conf->{color} ) {
47             my @elements = qw/foreground background dim bold cursor highlight/;
48             for (@elements) {
49             if ( $conf->{color}{$_} ) {
50             no strict 'refs';
51             "Gnome2::Vte::Terminal::set_color_$_"->(
52             $term, Gtk2::Gdk::Color->parse( $conf->{color}{$_} )
53             );
54             }
55             }
56             }
57              
58             if ( $conf->{background_file} && -e $conf->{background_file} ) {
59             $term->set_background_image_file( $conf->{background_file} );
60             }
61              
62             if ( $conf->{background_transparent} ) {
63             $term->set_background_transparent(1);
64             }
65              
66             if ( defined $conf->{opacity} ) {
67             $conf->{opacity} *= 65535 if $conf->{opacity} <= 1;
68             $term->set_opacity($conf->{opacity});
69             }
70              
71             if ( defined $conf->{mouse_autohide} ) {
72             $term->set_mouse_autohide( $conf->{mouse_autohide} );
73             }
74              
75             my $timeout = defined $conf->{timeout} ? $conf->{timeout} : 60;
76             if ($timeout) {
77             $term->{timer} = Glib::Timeout->add( 1000 * $timeout,
78             sub { $term->feed_child( chr 0 ); return TRUE; }, $term );
79             }
80             }
81              
82             sub clean { # called when child exited
83             my $self = shift;
84             my ( $current, $new_pos );
85             $new_pos = $current = $self->{current};
86             if ( @{ $self->{terms} } > 1 ) {
87             if ( $current == @{ $self->{terms} } - 1 ) {
88             $new_pos = 0;
89             }
90             else {
91             $new_pos++;
92             }
93             $self->term->hide;
94             $self->{terms}->[$new_pos]->show;
95             $self->{terms}->[$new_pos]->grab_focus;
96             }
97             else {
98             undef $new_pos;
99             }
100             $self->widget->remove( $self->term );
101             $self->term->destroy;
102             splice @{ $self->{terms} }, $current, 1;
103             $self->{current} = $new_pos == 0 ? 0 : $new_pos - 1
104             if defined $new_pos;
105             }
106              
107             sub term { # get current terminal
108             my $self = shift;
109             return $self->{terms}->[ $self->{current} ]
110             if defined $self->{current};
111             }
112              
113             sub switch { # switch terms, -1 for left, 1 for right
114             my ( $self, $offset ) = @_;
115             return unless $offset;
116             return unless @{ $self->{terms} } > 1;
117              
118             my ( $current, $new_pos );
119             $new_pos = $current = $self->{current};
120              
121             if ( $offset == 1 ) {
122             if ( $current >= @{ $self->{terms} } - 1 ) {
123             $new_pos = 0;
124             }
125             else {
126             $new_pos++;
127             }
128             }
129             elsif ( $offset == -1 ) {
130             if ( $current == 0 ) {
131             $new_pos = @{ $self->{terms} } - 1;
132             }
133             else {
134             $new_pos--;
135             }
136             }
137             $self->term->hide if defined $self->term;
138             $self->{current} = $new_pos;
139             if ( $self->term ) {
140             $self->term->show;
141             $self->term->grab_focus;
142             }
143             }
144              
145             sub connect {
146             my ( $self, $conf, $file, $site ) = @_;
147             my $agent = $conf->{agent} || $self->{agent};
148              
149             # check if it's a perl script
150             my $use_current_perl;
151              
152             unless ( file_name_is_absolute( $agent ) ) {
153             require File::Which;
154             my $path = File::Which::which( $agent );
155             if ( $path ) {
156             $agent = $path;
157             }
158             else {
159             die "can't find $agent";
160             }
161             }
162              
163             if ( -T $agent ) {
164             open my $fh, '<', $agent or die "can't open $agent: $!";
165             my $shebang = <$fh>;
166             if ( $shebang =~ m{#!/usr/bin/(?:perl|env\s+perl)} ) {
167             $use_current_perl = 1;
168             }
169             }
170             elsif ( !-e $agent ) {
171             die "$agent doesn't exist";
172             }
173              
174             if ($agent) {
175             $self->term->fork_command(
176             ( $use_current_perl ? $^X : $agent ),
177             (
178             [
179             ( $use_current_perl ? ($^X) : () ),
180             $agent,
181             $conf->{protocol} =~ /ssh|telnet/ ? ( $file, $site ) : ()
182             ]
183             ),
184             undef, q{}, FALSE, FALSE, FALSE
185             );
186             }
187             else {
188             croak 'seems something wrong with your agent script';
189             }
190             }
191              
192             sub title {
193             my $self = shift;
194             return $self->{titles}[ $self->{current} ];
195             }
196              
197             sub encoding {
198             my $self = shift;
199             return $self->{encoding}[ $self->{current} ];
200             }
201              
202             sub text { # get current terminal's text
203             # list context is needed.
204             my $self = shift;
205             if ( $self->term ) {
206             my ($text) = $self->term->get_text( sub { return TRUE } );
207             return $text;
208             }
209             }
210              
211             sub widget {
212             return shift->{widget};
213             }
214              
215             1;
216              
217             __END__