line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Term::Screen; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
866
|
use 5.006; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
41
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
39
|
|
5
|
1
|
|
|
1
|
|
21
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1416
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '1.04'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Term::Screen - A Simple all perl Term::Cap based screen positioning module |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
require Term::Screen; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
$scr = new Term::Screen; |
18
|
|
|
|
|
|
|
unless ($scr) { die " Something's wrong \n"; } |
19
|
|
|
|
|
|
|
$scr->clrscr(); |
20
|
|
|
|
|
|
|
$scr->at(5,3); |
21
|
|
|
|
|
|
|
$scr->puts("this is some stuff"); |
22
|
|
|
|
|
|
|
$scr->at(10,10)->bold()->puts("hi!")->normal(); |
23
|
|
|
|
|
|
|
# you can concatenate many calls (not getch) |
24
|
|
|
|
|
|
|
$c = $scr->getch(); # doesn't need Enter key |
25
|
|
|
|
|
|
|
... |
26
|
|
|
|
|
|
|
if ($scr->key_pressed()) { print "ha you hit a key!"; } |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 DESCRIPTION |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Term::Screen is a very simple screen positioning module that should |
33
|
|
|
|
|
|
|
work wherever C does. It is set up for Unix using stty's but |
34
|
|
|
|
|
|
|
these dependences are isolated by evals in the C constructor. Thus |
35
|
|
|
|
|
|
|
you may create a child module implementing Screen with MS-DOS, ioctl, |
36
|
|
|
|
|
|
|
or other means to get raw and unblocked input. This is not a replacement |
37
|
|
|
|
|
|
|
for Curses -- it has no memory. This was written so that it could be |
38
|
|
|
|
|
|
|
easily changed to fit nasty systems, and to be available first thing. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
The input functions getch, key_pressed, echo, and noecho are implemented |
41
|
|
|
|
|
|
|
so as to work under a fairly standard Unix system. They use 'stty' |
42
|
|
|
|
|
|
|
to set raw and no echo modes and turn on auto flush. All of these are |
43
|
|
|
|
|
|
|
'eval'ed so that this class can be inherited for new definitions easily. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Term::Screen was designed to be "required", then used with object syntax |
46
|
|
|
|
|
|
|
as shown above. One quirk (which the author was used to so he didn't |
47
|
|
|
|
|
|
|
care) is that for function key translation, no delay is set. So for many |
48
|
|
|
|
|
|
|
terminals to get an esc character, you have to hit another char after it, |
49
|
|
|
|
|
|
|
generally another esc. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 PUBLIC INTERFACE |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Term::Screen has a very minimal set of of fixed character terminal position |
54
|
|
|
|
|
|
|
and character reading commands: |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=over 4 |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=cut |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
require Term::Cap; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item new() |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Initialize the screen. Does not clear the screen, but does home the cursor. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=cut |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub new |
69
|
|
|
|
|
|
|
{ |
70
|
0
|
|
|
0
|
1
|
|
my ( $prototype, @args ) = @_; |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
0
|
|
|
|
my $classname = ref($prototype) || $prototype; |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
my ($ospeed); |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# adjust OSPEED below to your system. |
77
|
0
|
0
|
|
|
|
|
if ( $^O ne "solaris" ) |
78
|
|
|
|
|
|
|
{ |
79
|
0
|
|
|
|
|
|
eval { $ospeed = `stty speed 2>/dev/null`; }; # Unixish way to get OSpeed - works |
|
0
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
else |
82
|
|
|
|
|
|
|
{ # on Linux, Gnuish ... |
83
|
|
|
|
|
|
|
# work around Solaris stty |
84
|
|
|
|
|
|
|
eval |
85
|
0
|
|
|
|
|
|
{ |
86
|
0
|
|
|
|
|
|
foreach (`stty 2>/dev/null`) |
87
|
|
|
|
|
|
|
{ |
88
|
0
|
0
|
|
|
|
|
if (/^speed (\d+)/) { $ospeed = $1; last } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
}; |
91
|
|
|
|
|
|
|
} |
92
|
0
|
0
|
0
|
|
|
|
$ospeed = 9600 if ( !$ospeed || $@ ); |
93
|
0
|
|
|
|
|
|
my $term = Tgetent Term::Cap { 'TERM' => '', 'OSPEED' => $ospeed }; |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
|
my $this = {}; # create object |
96
|
0
|
|
|
|
|
|
bless $this, $classname; |
97
|
0
|
|
|
|
|
|
$this->term($term); # keep termcap entry reference |
98
|
0
|
|
|
|
|
|
$this->{IN} = ''; # clear input buffer |
99
|
0
|
|
|
|
|
|
$this->{ROWS} = 0; |
100
|
0
|
|
|
|
|
|
$this->{COLS} = 0; |
101
|
0
|
|
|
|
|
|
$this->resize(); # sets $this->{ROWS} & {COLS} |
102
|
0
|
|
|
|
|
|
$this->{KEYS} = {}; # set up fn key hash of hashes |
103
|
0
|
|
|
|
|
|
$this->get_fn_keys(); # define function key table from defaults |
104
|
0
|
|
|
|
|
|
$this->at( 0, 0 ); # home cursor |
105
|
0
|
|
|
|
|
|
$this->{ECHO} = 1; # start off echoing |
106
|
0
|
|
|
|
|
|
$| = 1; # for output flush on writes |
107
|
|
|
|
|
|
|
# wrapped so inherited versions can call with different input codes |
108
|
0
|
|
|
|
|
|
eval { system('stty raw -echo 2>/dev/null'); }; # turn on raw input |
|
0
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# ignore errors |
110
|
0
|
|
|
|
|
|
return $this; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub DESTROY |
114
|
|
|
|
|
|
|
{ |
115
|
0
|
|
|
0
|
|
|
my $rc = $?; |
116
|
0
|
|
|
|
|
|
system('stty -raw echo 2>/dev/null'); |
117
|
0
|
|
|
|
|
|
$? = $rc; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=item term(term) |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Sets or Gets the Term::Cap object used by this object. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=cut |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub term |
128
|
|
|
|
|
|
|
{ |
129
|
0
|
|
|
0
|
1
|
|
my ( $self, $term ) = @_; |
130
|
|
|
|
|
|
|
|
131
|
0
|
0
|
0
|
|
|
|
if ( defined $term && ref $term and UNIVERSAL::isa( $term, 'Term::Cap' ) ) |
|
|
|
0
|
|
|
|
|
132
|
|
|
|
|
|
|
{ |
133
|
0
|
|
|
|
|
|
$self->{TERM} = $term; |
134
|
|
|
|
|
|
|
} |
135
|
0
|
|
|
|
|
|
return $self->{TERM}; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=item rows(rows) |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Returns and/or sets the number of rows on the terminal. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=cut |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub rows |
145
|
|
|
|
|
|
|
{ |
146
|
0
|
|
|
0
|
1
|
|
my ( $self, $rows ) = @_; |
147
|
|
|
|
|
|
|
|
148
|
0
|
0
|
0
|
|
|
|
if ( defined $rows and $rows =~ /\d+/ ) |
149
|
|
|
|
|
|
|
{ |
150
|
0
|
|
|
|
|
|
$self->{ROWS} = $rows; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
return $self->{ROWS}; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item cols(cols) |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Returns and/or sets the number of cols on the terminal. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=cut |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub cols |
163
|
|
|
|
|
|
|
{ |
164
|
0
|
|
|
0
|
1
|
|
my ( $self, $cols ) = @_; |
165
|
|
|
|
|
|
|
|
166
|
0
|
0
|
0
|
|
|
|
if ( defined $cols and $cols =~ /\d+/ ) |
167
|
|
|
|
|
|
|
{ |
168
|
0
|
|
|
|
|
|
$self->{COLS} = $cols; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
return $self->{COLS}; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item at(row,col) |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Moves cursor to (row,col) where (0,0) is upper left corner, - if the spot is |
177
|
|
|
|
|
|
|
illegal does whatever 'cm' in termcap does, since that is what it uses. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=cut |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub at |
182
|
|
|
|
|
|
|
{ |
183
|
0
|
|
|
0
|
1
|
|
my ( $this, $r, $c ) = @_; |
184
|
0
|
0
|
|
|
|
|
if ( $r < 0 ) { $r = 0; } |
|
0
|
|
|
|
|
|
|
185
|
0
|
0
|
|
|
|
|
if ( $c < 0 ) { $c = 0; } |
|
0
|
|
|
|
|
|
|
186
|
0
|
0
|
|
|
|
|
if ( $r >= $this->{ROWS} ) { $r = $this->{ROWS} - 1; } |
|
0
|
|
|
|
|
|
|
187
|
0
|
0
|
|
|
|
|
if ( $c >= $this->{COLS} ) { $c = $this->{COLS} - 1; } |
|
0
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
$this->term()->Tgoto( 'cm', $c, $r, *STDOUT ); |
189
|
0
|
|
|
|
|
|
return $this; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item resize(r,c) |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Tell screen the new number of rows & cols physically you can skip the r & c |
195
|
|
|
|
|
|
|
and get new checked vals from stty or termcap. Term::Screen does not |
196
|
|
|
|
|
|
|
handle resize signals internally, but you can do it by checking and updating |
197
|
|
|
|
|
|
|
screen size using this function. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=cut |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub resize |
202
|
|
|
|
|
|
|
{ |
203
|
0
|
|
|
0
|
1
|
|
my ( $this, $r, $c ) = @_; |
204
|
0
|
|
|
|
|
|
my $size = ''; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# find screen size -- trying different methods |
207
|
0
|
0
|
0
|
|
|
|
if ( $#_ != 2 || $r <= 0 || $c <= 0 ) |
|
|
|
0
|
|
|
|
|
208
|
|
|
|
|
|
|
{ |
209
|
0
|
|
|
|
|
|
$r = 0; |
210
|
0
|
|
|
|
|
|
$c = 0; |
211
|
|
|
|
|
|
|
|
212
|
0
|
0
|
|
|
|
|
if ( $^O ne "solaris" ) |
213
|
|
|
|
|
|
|
{ |
214
|
0
|
|
|
|
|
|
eval { $size = `stty size`; }; # not portable but most accurate |
|
0
|
|
|
|
|
|
|
215
|
0
|
0
|
|
|
|
|
if ( $size =~ /^\s*(\d+)\s+(\d+)\s*/ ) |
216
|
|
|
|
|
|
|
{ |
217
|
0
|
|
|
|
|
|
( $r, $c ) = ( $1, $2 ); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
else |
221
|
|
|
|
|
|
|
{ |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# work around Solaris stty |
224
|
0
|
|
|
|
|
|
eval { |
225
|
0
|
|
|
|
|
|
foreach (`stty`) |
226
|
|
|
|
|
|
|
{ |
227
|
0
|
0
|
|
|
|
|
if (/^rows = (\d+); columns = (\d+)/) { |
228
|
0
|
|
|
|
|
|
$r = $1; |
229
|
0
|
|
|
|
|
|
$c = $2; |
230
|
0
|
|
|
|
|
|
last; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
}; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
} |
236
|
0
|
0
|
0
|
|
|
|
if ( $r == 0 || $c == 0 ) # try getting rows and cols some other way |
237
|
|
|
|
|
|
|
{ |
238
|
0
|
0
|
|
|
|
|
if ( exists $ENV{'LINES'} ) { $r = $ENV{'LINES'}; } |
|
0
|
|
|
|
|
|
|
239
|
0
|
|
|
|
|
|
else { $r = $this->term()->{'_li'}; } # this is often wrong |
240
|
0
|
0
|
|
|
|
|
if ( exists $ENV{'COLUMNS'} ) { $c = $ENV{'COLUMNS'}; } |
|
0
|
|
|
|
|
|
|
241
|
0
|
|
|
|
|
|
else { $c = $this->term()->{'_co'}; } |
242
|
|
|
|
|
|
|
} |
243
|
0
|
|
|
|
|
|
$this->{ROWS} = $r; |
244
|
0
|
|
|
|
|
|
$this->{COLS} = $c; |
245
|
0
|
|
|
|
|
|
return $this; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=item normal() |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Turn off any highlightling (bold, reverse) |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub normal |
255
|
|
|
|
|
|
|
{ |
256
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
257
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'me', 1, *STDOUT ); |
258
|
0
|
|
|
|
|
|
return $this; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item bold() |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
The md value from termcap - turn on bold usually |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=cut |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub bold |
268
|
|
|
|
|
|
|
{ |
269
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
270
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'md', 1, *STDOUT ); |
271
|
0
|
|
|
|
|
|
return $this; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item reverse() |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
The mr value from termcap - turn on reverse text often. these last |
277
|
|
|
|
|
|
|
two default to whatever is available. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=cut |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub reverse |
282
|
|
|
|
|
|
|
{ |
283
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
284
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'mr', 1, *STDOUT ); |
285
|
0
|
|
|
|
|
|
return $this; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=item clrscr() |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
Clear the screen and home cursor |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=cut |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub clrscr |
295
|
|
|
|
|
|
|
{ |
296
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
297
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'cl', 1, *STDOUT ); |
298
|
0
|
|
|
|
|
|
$this->{'rc'} = [ 0, 0 ]; |
299
|
0
|
|
|
|
|
|
return $this; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item clreol() |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
Clear to the end of the line - cursor doesn't move |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=cut |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub clreol |
309
|
|
|
|
|
|
|
{ |
310
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
311
|
0
|
0
|
|
|
|
|
if ( exists( $this->term()->{'_ce'} ) ) |
312
|
|
|
|
|
|
|
{ |
313
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'ce', 1, *STDOUT ); |
314
|
|
|
|
|
|
|
} |
315
|
0
|
|
|
|
|
|
return $this; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=item clreos() |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Clear to end of screen - right and down, cursor doesn't move. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=cut |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub clreos |
325
|
|
|
|
|
|
|
{ |
326
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
327
|
0
|
0
|
|
|
|
|
if ( exists( $this->term()->{'_cd'} ) ) |
328
|
|
|
|
|
|
|
{ |
329
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'cd', 1, *STDOUT ); |
330
|
|
|
|
|
|
|
} |
331
|
0
|
|
|
|
|
|
return $this; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=item il() |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
Insert blank line before line cursor is on, moving lower lines down. |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=cut |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub il |
341
|
|
|
|
|
|
|
{ |
342
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
343
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'al', 1, *STDOUT ); |
344
|
0
|
|
|
|
|
|
return $this; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=item dl() |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Delete line cursor is on, moving lower lines up. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=cut |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub dl |
354
|
|
|
|
|
|
|
{ |
355
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
356
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'dl', 1, *STDOUT ); |
357
|
0
|
|
|
|
|
|
return $this; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=item ic_exists() |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Insert character option is available. |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=cut |
365
|
|
|
|
|
|
|
|
366
|
0
|
0
|
|
0
|
1
|
|
sub ic_exists { ( exists( $_[0]->term()->{'ic'} ) ? 1 : 0 ); } |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
{ |
369
|
1
|
|
|
1
|
|
7
|
no warnings 'once'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
152
|
|
370
|
|
|
|
|
|
|
*exists_ic = \&ic_exists; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=item ic() |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Insert character at current position move rest to the right. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=cut |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub ic |
380
|
|
|
|
|
|
|
{ |
381
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
382
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'ic', 1, *STDOUT ); |
383
|
0
|
|
|
|
|
|
$this; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=item dc_exists() |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
Delete char option exists and is available. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=cut |
391
|
|
|
|
|
|
|
|
392
|
0
|
0
|
|
0
|
1
|
|
sub dc_exists { ( exists( $_[0]->term()->{'dc'} ) ? 1 : 0 ); } |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
{ |
395
|
1
|
|
|
1
|
|
6
|
no warnings 'once'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1127
|
|
396
|
|
|
|
|
|
|
*exists_dc = \&dc_exists; |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=item dc() |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Delete character at current position moving rest to the left. |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=cut |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub dc |
406
|
|
|
|
|
|
|
{ |
407
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
408
|
0
|
|
|
|
|
|
$this->term()->Tputs( 'dc', 1, *STDOUT ); |
409
|
0
|
|
|
|
|
|
return $this; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=back |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
The following are the I/O functions. They provide standard useful |
415
|
|
|
|
|
|
|
single character reading values. getch returns either a single char or |
416
|
|
|
|
|
|
|
the name of a function key when a key is pressed. The only exception is |
417
|
|
|
|
|
|
|
when you hit a character that is the start of a function key sequence. |
418
|
|
|
|
|
|
|
In this case getch keeps waiting for the next char to see if it is fn key. |
419
|
|
|
|
|
|
|
Generally this is the escape key, and why you need to hit esc twice. |
420
|
|
|
|
|
|
|
To get a stright char, just use the regular 'gets' perl function. You |
421
|
|
|
|
|
|
|
will need to echo it yourself if you want. |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=over 4 |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=item puts(str) |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Prints $s and returns the screen object. Used to do things like |
428
|
|
|
|
|
|
|
C<$scr->at(10,0)->puts("Hi!")->at(0,0);>. You can just use |
429
|
|
|
|
|
|
|
print if you want. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
0
|
|
|
0
|
1
|
|
sub puts { print $_[1]; return $_[0]; } |
|
0
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
=item getch() |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
Returns just a char in raw mode. Function keys are returned as their |
438
|
|
|
|
|
|
|
capability names, e.g. the up key would return "ku". See the |
439
|
|
|
|
|
|
|
C function for what a lot of the names are. This will wait |
440
|
|
|
|
|
|
|
for next char if in a possible fn key string, so you would need to type |
441
|
|
|
|
|
|
|
'esc' 'esc' most likely to get out of getch, since 'esc' is usually the |
442
|
|
|
|
|
|
|
leading char for function keys. You can use perl's getc, to go 'underneath' |
443
|
|
|
|
|
|
|
getch if you want. See the table in Screen::get_fn_keys() for more |
444
|
|
|
|
|
|
|
information. |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=cut |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub getch |
449
|
|
|
|
|
|
|
{ |
450
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
451
|
0
|
|
|
|
|
|
my ( $c, $fn_flag ) = ( '', 0 ); |
452
|
0
|
|
|
|
|
|
my $partial_fn_str = ''; |
453
|
|
|
|
|
|
|
|
454
|
0
|
0
|
|
|
|
|
if ( $this->{IN} ) { $c = chop( $this->{IN} ); } |
|
0
|
|
|
|
|
|
|
455
|
0
|
|
|
|
|
|
else { $c = getc(STDIN); } |
456
|
|
|
|
|
|
|
|
457
|
0
|
|
|
|
|
|
$partial_fn_str = $c; |
458
|
0
|
|
|
|
|
|
while ( exists( $this->{KEYS}{$partial_fn_str} ) ) |
459
|
|
|
|
|
|
|
{ # in a possible function key sequence |
460
|
0
|
|
|
|
|
|
$fn_flag = 1; |
461
|
0
|
0
|
|
|
|
|
if ( $this->{KEYS}{$partial_fn_str} ) # key found |
462
|
|
|
|
|
|
|
{ |
463
|
0
|
|
|
|
|
|
$c = $this->{KEYS}{$partial_fn_str}; |
464
|
0
|
|
|
|
|
|
$partial_fn_str = ''; |
465
|
0
|
|
|
|
|
|
last; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
else # wait for another key to see if were in FN yet |
468
|
|
|
|
|
|
|
{ |
469
|
0
|
0
|
|
|
|
|
if ( $this->{IN} ) { $partial_fn_str .= chop( $this->{IN} ); } |
|
0
|
|
|
|
|
|
|
470
|
0
|
|
|
|
|
|
else { $partial_fn_str .= getc(); } |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
} |
473
|
0
|
0
|
0
|
|
|
|
if ($fn_flag) # seemed like a fn key |
|
|
0
|
|
|
|
|
|
474
|
|
|
|
|
|
|
{ |
475
|
0
|
0
|
|
|
|
|
if ($partial_fn_str) # oops not a fn key |
476
|
|
|
|
|
|
|
{ |
477
|
0
|
0
|
|
|
|
|
if ( $partial_fn_str eq "\e\e" ) # take care of funny ESC case |
478
|
|
|
|
|
|
|
{ |
479
|
0
|
|
|
|
|
|
$c = "\e"; |
480
|
0
|
|
|
|
|
|
$partial_fn_str = ""; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
else # buffer up the received chars |
483
|
|
|
|
|
|
|
{ |
484
|
0
|
|
|
|
|
|
$this->{IN} = CORE::reverse($partial_fn_str) . $this->{IN}; |
485
|
0
|
|
|
|
|
|
$c = chop( $this->{IN} ); |
486
|
0
|
0
|
0
|
|
|
|
$this->puts($c) if ( $this->{ECHO} && ( $c ne "\e" ) ); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# if fn_key then never echo so do nothing here |
491
|
|
|
|
|
|
|
} |
492
|
0
|
|
|
|
|
|
elsif ( $this->{ECHO} && ( $c ne "\e" ) ) { $this->puts($c); } # regular key |
493
|
0
|
|
|
|
|
|
return $c; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item def_key('name','input string') |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Lets you define your own function key sequence. 'name' is what will be |
499
|
|
|
|
|
|
|
returned by getch. 'input string' is what the fn key sends literally. This |
500
|
|
|
|
|
|
|
will override any prev definitions of the input. A whole bunch of defaults |
501
|
|
|
|
|
|
|
are defined for xterms rxvt's, etc. in the get_fn_keys function. |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=cut |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub def_key |
506
|
|
|
|
|
|
|
{ |
507
|
0
|
|
|
0
|
1
|
|
my ( $this, $fn, $str ) = @_; |
508
|
|
|
|
|
|
|
|
509
|
0
|
0
|
|
|
|
|
$this->{KEYS}{$str} = $fn if ( $str ne '' ); |
510
|
0
|
|
|
|
|
|
while ( $str ne '' ) |
511
|
|
|
|
|
|
|
{ |
512
|
0
|
|
|
|
|
|
chop($str); |
513
|
0
|
0
|
|
|
|
|
$this->{KEYS}{$str} = '' if ( $str ne '' ); |
514
|
|
|
|
|
|
|
} |
515
|
0
|
|
|
|
|
|
return $this; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=item key_pressed([sec]) |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
Returns true if there is a character waiting. You can pass an option time in |
521
|
|
|
|
|
|
|
seconds to wait. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=cut |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub key_pressed |
526
|
|
|
|
|
|
|
{ |
527
|
0
|
|
|
0
|
1
|
|
my ( $this, $seconds ) = @_; |
528
|
0
|
|
|
|
|
|
my $readfields = ''; |
529
|
0
|
|
|
|
|
|
my $ready = 0; |
530
|
|
|
|
|
|
|
|
531
|
0
|
0
|
|
|
|
|
$seconds = 0 if ( !defined $seconds ); |
532
|
0
|
|
|
|
|
|
vec( $readfields, fileno(STDIN), 1 ) = 1; # set up to check STDIN |
533
|
0
|
|
|
|
|
|
eval { $ready = select( $readfields, undef, undef, $seconds ); }; |
|
0
|
|
|
|
|
|
|
534
|
0
|
|
|
|
|
|
return $ready; |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=item echo() |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Tells getch to echo the input to the screen. (the default.) |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=cut |
542
|
|
|
|
|
|
|
|
543
|
0
|
|
|
0
|
1
|
|
sub echo { my $this = shift; $this->{ECHO} = 1; return $this; } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=item noecho() |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
Tells getch NOT to echo input to the screen. |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=cut |
550
|
|
|
|
|
|
|
|
551
|
0
|
|
|
0
|
1
|
|
sub noecho { my $this = shift; $this->{ECHO} = 0; return $this; } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=item flush_input() |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
Clears input buffer and removes any incoming chars. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=cut |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
sub flush_input |
560
|
|
|
|
|
|
|
{ |
561
|
0
|
|
|
0
|
1
|
|
my $this = shift; |
562
|
0
|
|
|
|
|
|
$this->{IN} = ''; |
563
|
0
|
|
|
|
|
|
while ( $this->key_pressed() ) { getc(); } |
|
0
|
|
|
|
|
|
|
564
|
0
|
|
|
|
|
|
return $this; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
=item stuff_input(str) |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
Lets you stuff chars into the input buffer to be read like keystrokes. |
570
|
|
|
|
|
|
|
This is only the C method buffer, the underlying getc stuff |
571
|
|
|
|
|
|
|
is not touched. |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=cut |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
sub stuff_input |
576
|
|
|
|
|
|
|
{ |
577
|
0
|
|
|
0
|
1
|
|
my ( $this, $str ) = @_; |
578
|
0
|
|
|
|
|
|
$this->{IN} = CORE::reverse($str) . $this->{IN}; |
579
|
0
|
|
|
|
|
|
return $this; |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
# internal functions |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
# This function sets up the arrow keys from { ku kd kr kl } |
585
|
|
|
|
|
|
|
# and the function keys from {k0 .. k9} with labels from { l0 .. l9} |
586
|
|
|
|
|
|
|
# (if they exist of course.) |
587
|
|
|
|
|
|
|
# This is all encoded in a funny way -- as a hash with the |
588
|
|
|
|
|
|
|
# characters as keys - check the code. It makes checking fn keys easy. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub get_fn_keys |
591
|
|
|
|
|
|
|
{ |
592
|
0
|
|
|
0
|
0
|
|
my $this = shift; |
593
|
0
|
|
|
|
|
|
my $term = $this->term(); |
594
|
0
|
|
|
|
|
|
my @keys = qw/ke kh ku kd kl kr k0 k1 k2 k3 k4 k5 k6 k7 k8 k9/; |
595
|
0
|
|
|
|
|
|
my ( $fn, $ufn, $lfn ); |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# throw in some defaults (xterm & rxvt arrows); |
598
|
0
|
|
|
|
|
|
$this->def_key( "ku", "\e[A" ); |
599
|
0
|
|
|
|
|
|
$this->def_key( "kd", "\e[B" ); |
600
|
0
|
|
|
|
|
|
$this->def_key( "kr", "\e[C" ); |
601
|
0
|
|
|
|
|
|
$this->def_key( "kl", "\e[D" ); |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
# PC keyboard fn keys for xterm (some of them) |
604
|
0
|
|
|
|
|
|
$this->def_key( "k1", "\e[11~" ); |
605
|
0
|
|
|
|
|
|
$this->def_key( "k2", "\e[12~" ); |
606
|
0
|
|
|
|
|
|
$this->def_key( "k3", "\e[13~" ); |
607
|
0
|
|
|
|
|
|
$this->def_key( "k4", "\e[14~" ); |
608
|
0
|
|
|
|
|
|
$this->def_key( "k5", "\e[15~" ); |
609
|
0
|
|
|
|
|
|
$this->def_key( "k6", "\e[17~" ); |
610
|
0
|
|
|
|
|
|
$this->def_key( "k7", "\e[18~" ); |
611
|
0
|
|
|
|
|
|
$this->def_key( "k8", "\e[19~" ); |
612
|
0
|
|
|
|
|
|
$this->def_key( "k9", "\e[20~" ); |
613
|
0
|
|
|
|
|
|
$this->def_key( "k10", "\e[21~" ); |
614
|
0
|
|
|
|
|
|
$this->def_key( "k11", "\e[23~" ); |
615
|
0
|
|
|
|
|
|
$this->def_key( "k12", "\e[24~" ); |
616
|
|
|
|
|
|
|
|
617
|
0
|
|
|
|
|
|
$this->def_key( "ins", "\e[2~" ); |
618
|
0
|
|
|
|
|
|
$this->def_key( "del", "\e[3~" ); |
619
|
|
|
|
|
|
|
|
620
|
0
|
|
|
|
|
|
$this->def_key( "home", "\e[H" ); # mult defs are no problem |
621
|
0
|
|
|
|
|
|
$this->def_key( "home", "\eO" ); # these are some I have found |
622
|
0
|
|
|
|
|
|
$this->def_key( "end", "\eOw" ); |
623
|
0
|
|
|
|
|
|
$this->def_key( "end", "\eOe" ); |
624
|
0
|
|
|
|
|
|
$this->def_key( "pgup", "\e[5~" ); |
625
|
0
|
|
|
|
|
|
$this->def_key( "pgdn", "\e[6~" ); |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# try to get anything useful out of termcap |
628
|
|
|
|
|
|
|
# (not too accurate in many cases |
629
|
|
|
|
|
|
|
|
630
|
0
|
|
|
|
|
|
foreach $fn (@keys) |
631
|
|
|
|
|
|
|
{ |
632
|
0
|
|
|
|
|
|
$ufn = '_' . $fn; |
633
|
0
|
|
|
|
|
|
$lfn = $ufn; |
634
|
0
|
|
|
|
|
|
$lfn =~ s/_k/_l/; |
635
|
|
|
|
|
|
|
|
636
|
0
|
0
|
|
|
|
|
if ( exists $term->{$ufn} ) |
637
|
|
|
|
|
|
|
{ |
638
|
0
|
0
|
0
|
|
|
|
if ( ( exists $term->{$lfn} ) && ( $term->{$lfn} ) ) |
639
|
|
|
|
|
|
|
{ |
640
|
0
|
|
|
|
|
|
$fn = substr( $lfn, 1 ); |
641
|
|
|
|
|
|
|
} |
642
|
0
|
|
|
|
|
|
$this->def_key( $fn, $term->{$ufn} ); |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
} |
645
|
0
|
|
|
|
|
|
return $this; |
646
|
|
|
|
|
|
|
} |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
1; |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
__END__ |