line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- perl -*- |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (c) 2004 by Jeff Weisberg |
4
|
|
|
|
|
|
|
# Author: Jeff Weisberg |
5
|
|
|
|
|
|
|
# Created: 2004-Jun-03 10:24 (EDT) |
6
|
|
|
|
|
|
|
# Function: pager like more/less |
7
|
|
|
|
|
|
|
# |
8
|
|
|
|
|
|
|
# $Id: Pager.pm,v 1.4 2012/12/02 18:06:46 jaw Exp $ |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Term::Pager - Page through text, a screenful at a time, like more or less |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 SYNOPSIS |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
use Term::Pager; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my $t = Term::Pager->new( rows => 25, cols => 80 ); |
19
|
|
|
|
|
|
|
$t->add_text( $text ); |
20
|
|
|
|
|
|
|
$t->more(); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 DESCRIPTION |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
This is a module for paging through text one screenful at a time. |
25
|
|
|
|
|
|
|
It supports the features you expect, including backwards |
26
|
|
|
|
|
|
|
movement and searching. It uses the keys you expect. |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 USAGE |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head2 Create the Pager |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$t = Term::Pager->new( option => value, ... ); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
If no options are specified, sensible default values will be used. |
35
|
|
|
|
|
|
|
The following options are recognized: |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=over 4 |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=item C |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
The number of rows on your terminal. |
42
|
|
|
|
|
|
|
This defaults to 25. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=item C |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
The number of columns on your terminal. |
47
|
|
|
|
|
|
|
This defaults to 80. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item C |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
The speed (baud rate) of your terminal. Will default |
52
|
|
|
|
|
|
|
to a sensible value. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=back |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head2 Adding Text |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
You will need some text to page through. You can specify text as |
59
|
|
|
|
|
|
|
as a parameter to the constructor: |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
text => $text |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Or add text later: |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
$t->add_text( $text ); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=cut |
68
|
|
|
|
|
|
|
; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
package Term::Pager; |
71
|
|
|
|
|
|
|
$VERSION = '1.02'; |
72
|
|
|
|
|
|
|
|
73
|
1
|
|
|
1
|
|
1407
|
use Term::Cap; |
|
1
|
|
|
|
|
2804
|
|
|
1
|
|
|
|
|
26
|
|
74
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
2313
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub new { |
77
|
0
|
|
|
0
|
0
|
|
my $class = shift; |
78
|
0
|
|
|
|
|
|
my %param = @_; |
79
|
|
|
|
|
|
|
|
80
|
0
|
|
0
|
|
|
|
my $t = Term::Cap->Tgetent({ OSPEED => ($param{speed} || 38400) }); |
81
|
0
|
|
|
|
|
|
my $dumbp; |
82
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
eval{ |
84
|
0
|
|
|
|
|
|
$t->Trequire(qw/cm ce cl sf sr/); |
85
|
|
|
|
|
|
|
}; |
86
|
0
|
0
|
|
|
|
|
$dumbp = 1 if $@; |
87
|
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
my $me = bless { |
89
|
|
|
|
|
|
|
# default values |
90
|
|
|
|
|
|
|
term => $t, |
91
|
|
|
|
|
|
|
cols => 80, |
92
|
|
|
|
|
|
|
rows => 25, |
93
|
|
|
|
|
|
|
dumbp => $dumbp, |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# if the termcap entries don't exist, nothing bad will happen |
96
|
|
|
|
|
|
|
HI => $t->Tputs('md') . $t->Tputs('us'), # search hilight |
97
|
|
|
|
|
|
|
SE => $t->Tputs('md') . $t->Tputs('us'), # search entry |
98
|
|
|
|
|
|
|
MN => $t->Tputs('md') . $t->Tputs('mr'), # popup menus |
99
|
|
|
|
|
|
|
ML => $t->Tputs('mr'), # mode line |
100
|
|
|
|
|
|
|
NO => $t->Tputs('me'), # normal |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# user supplied values override |
103
|
|
|
|
|
|
|
%param, |
104
|
|
|
|
|
|
|
}, $class; |
105
|
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
$me->{fnc} = { |
107
|
|
|
|
|
|
|
"\n"=> \&downline, |
108
|
|
|
|
|
|
|
' ' => \&downpage, |
109
|
|
|
|
|
|
|
'd' => \&downhalf, |
110
|
|
|
|
|
|
|
'q' => \&done, |
111
|
|
|
|
|
|
|
'b' => \&uppage, |
112
|
|
|
|
|
|
|
'y' => \&upline, |
113
|
|
|
|
|
|
|
'u' => \&uphalf, |
114
|
|
|
|
|
|
|
'r' => \&refresh, |
115
|
|
|
|
|
|
|
'h' => \&help, |
116
|
|
|
|
|
|
|
'?' => \&help, |
117
|
|
|
|
|
|
|
'0' => \&to_top, |
118
|
|
|
|
|
|
|
'g' => \&to_bott, |
119
|
|
|
|
|
|
|
'$' => \&to_bott, # ' |
120
|
|
|
|
|
|
|
'/' => \&search, |
121
|
|
|
|
|
|
|
'<' => \&move_left, |
122
|
|
|
|
|
|
|
'>' => \&move_right, |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
$me; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub add_text { |
129
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
130
|
0
|
|
|
|
|
|
my $tx = shift; |
131
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
|
$me->{text} .= $tx; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub add_func { |
136
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
137
|
0
|
|
|
|
|
|
my $fn = shift; |
138
|
0
|
|
|
|
|
|
my $fc = shift; |
139
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
$me->{fnc}{$fn} = $fc; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub more { |
144
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
145
|
0
|
|
|
|
|
|
my $sp = $|; |
146
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
$me->{L} = $me->{rows} - 1; |
149
|
0
|
|
|
|
|
|
$me->{l} = [ split /\n/, $me->{text} ]; |
150
|
0
|
|
|
|
|
|
$me->{nl}= @{ $me->{l} }; |
|
0
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
|
152
|
0
|
|
|
|
|
|
$me->{start} = 0; |
153
|
0
|
|
|
|
|
|
$me->{end} = $me->{L} - 1; |
154
|
|
|
|
|
|
|
|
155
|
0
|
|
|
|
|
|
$SIG{INT} = $SIG{QUIT} = \&done; |
156
|
0
|
|
|
|
|
|
system('stty -icanon -echo min 1'); |
157
|
0
|
|
|
|
|
|
$| = 1; |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
eval { |
160
|
0
|
0
|
|
|
|
|
if( $me->{dumbp} ){ |
161
|
0
|
|
|
|
|
|
$me->dumb_mode(); |
162
|
|
|
|
|
|
|
}else{ |
163
|
0
|
|
|
|
|
|
print $me->{NO}; |
164
|
0
|
|
|
|
|
|
$me->refresh(); |
165
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
while(1){ |
167
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L}); # bottom left |
168
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
169
|
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
print $me->{ML}; # reverse video |
171
|
0
|
|
|
|
|
|
$me->prompt(); |
172
|
0
|
|
|
|
|
|
print $me->{NO}; # normal video |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
my $q = getc(); |
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L}); # bottom left |
177
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
178
|
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
|
$me->{msg} = ''; |
180
|
0
|
|
0
|
|
|
|
my $f = $me->{fnc}->{lc($q)} || \&beep; |
181
|
0
|
|
|
|
|
|
$f->($me); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
}; |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
system('stty icanon echo'); |
187
|
0
|
|
|
|
|
|
$| = $sp; |
188
|
|
|
|
|
|
|
|
189
|
0
|
0
|
0
|
|
|
|
if( $@ && !ref $@ ){ |
190
|
0
|
|
|
|
|
|
die $@; |
191
|
|
|
|
|
|
|
} |
192
|
0
|
|
|
|
|
|
return; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
*less = \&more; |
196
|
|
|
|
|
|
|
*page = \&more; |
197
|
|
|
|
|
|
|
|
198
|
0
|
|
|
0
|
0
|
|
sub beep { print "\a" } |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# display a prompt, etc |
201
|
|
|
|
|
|
|
sub prompt { |
202
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
203
|
|
|
|
|
|
|
|
204
|
0
|
0
|
|
|
|
|
my $pct = ($me->{nl} > 1) ? 100*$me->{end}/($me->{nl}-1) : 100; |
205
|
0
|
0
|
|
|
|
|
my $p = sprintf "[more] %d%% %s %s", $pct, |
|
|
0
|
|
|
|
|
|
206
|
|
|
|
|
|
|
($me->{start} ? ($me->{end}==$me->{nl}-1) ? 'Bottom' : '' : 'Top'), $me->{msg}; |
207
|
|
|
|
|
|
|
|
208
|
0
|
|
|
|
|
|
my $p2 = " =down =back =help =quit"; |
209
|
|
|
|
|
|
|
|
210
|
0
|
|
|
|
|
|
$p .= ' ' x ($me->{cols} - 2 - length($p) - length($p2)); |
211
|
|
|
|
|
|
|
|
212
|
0
|
|
|
|
|
|
print $p,$p2; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub done { |
216
|
0
|
|
|
0
|
0
|
|
die \ 'foo'; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# put a box around some text |
220
|
|
|
|
|
|
|
sub box_text { |
221
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
222
|
0
|
|
|
|
|
|
my $txt = shift; |
223
|
0
|
|
|
|
|
|
my $l; |
224
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
my @l = split /\n/, $txt; |
226
|
0
|
0
|
|
|
|
|
foreach (@l){ $l = length($_) if length($_) > $l }; |
|
0
|
|
|
|
|
|
|
227
|
0
|
|
|
|
|
|
my $b = '+' . '=' x ($l + 2) . '+'; |
228
|
0
|
|
|
|
|
|
my $o = join('', map { "| $_" . (' 'x($l-length($_))) ." |\n" } @l); |
|
0
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
"$b\n$o$b\n"; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# provide help to user |
234
|
|
|
|
|
|
|
sub help { |
235
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
236
|
|
|
|
|
|
|
|
237
|
0
|
|
|
|
|
|
my $help = $me->box_text(<
|
238
|
|
|
|
|
|
|
q quit h help |
239
|
|
|
|
|
|
|
/ search |
240
|
|
|
|
|
|
|
space page down b page up |
241
|
|
|
|
|
|
|
enter line down y line up |
242
|
|
|
|
|
|
|
d half page down u half page up |
243
|
|
|
|
|
|
|
0 goto top g goto bottom |
244
|
|
|
|
|
|
|
< scroll left > scroll right |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
press any key to continue |
247
|
|
|
|
|
|
|
EOH |
248
|
|
|
|
|
|
|
; |
249
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
|
$me->disp_menu( $help ); |
251
|
0
|
|
|
|
|
|
getc(); |
252
|
0
|
|
|
|
|
|
$me->remove_menu(); |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# display a popup menu (or other text) |
257
|
|
|
|
|
|
|
sub disp_menu { |
258
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
259
|
0
|
|
|
|
|
|
my $menu = shift; |
260
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
261
|
|
|
|
|
|
|
|
262
|
0
|
|
|
|
|
|
my $nl = @{[split /\n/, $menu]}; |
|
0
|
|
|
|
|
|
|
263
|
0
|
|
|
|
|
|
$me->{menu_nl} = $nl; |
264
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L} - $nl); # move |
266
|
0
|
|
|
|
|
|
print $me->{MN}; # set color |
267
|
|
|
|
|
|
|
|
268
|
0
|
|
|
|
|
|
my $x = $t->Tgoto('RI', 0,4); # 4 transparent spaces |
269
|
0
|
|
|
|
|
|
$menu =~ s/^\s*/$x/gm; |
270
|
0
|
|
|
|
|
|
print $menu; |
271
|
0
|
|
|
|
|
|
print $me->{NO}; # normal color |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# remove popup and repaint |
276
|
|
|
|
|
|
|
sub remove_menu { |
277
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
278
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
279
|
|
|
|
|
|
|
|
280
|
0
|
|
|
|
|
|
my $s = $me->{end} - $me->{menu_nl} + 1; |
281
|
0
|
|
|
|
|
|
foreach my $n ($s .. $me->{end}){ |
282
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $n - $me->{start}); # move |
283
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear |
284
|
0
|
|
|
|
|
|
$me->line($n); |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# refresh screen |
289
|
|
|
|
|
|
|
sub refresh { |
290
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
291
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
print $t->Tputs('cl'); # home, clear |
294
|
0
|
|
|
|
|
|
for my $n ($me->{start} .. $me->{end}){ |
295
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $n - $me->{start}); # move |
296
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
297
|
0
|
|
|
|
|
|
$me->line($n); |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub prline { |
302
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
303
|
0
|
|
|
|
|
|
my $line = shift; |
304
|
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
my $len = length($line); |
306
|
0
|
|
|
|
|
|
$line = substr($line, $me->{left}, $me->{cols}); |
307
|
0
|
0
|
|
|
|
|
if( $len - $me->{left} > $me->{cols} ){ |
308
|
0
|
|
|
|
|
|
substr($line, -1, 1, "\$"); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
0
|
0
|
|
|
|
|
if( $me->{search} ne '' ){ |
312
|
0
|
|
|
|
|
|
my $s = $me->{HI}; |
313
|
0
|
|
|
|
|
|
my $e = $me->{NO}; |
314
|
0
|
|
|
|
|
|
$line =~ s/($me->{search})/$s$1$e/g; |
315
|
|
|
|
|
|
|
} |
316
|
0
|
|
|
|
|
|
print $line; |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub line { |
321
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
322
|
0
|
|
|
|
|
|
my $n = shift; |
323
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
$me->prline( $me->{l}[$n] ); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub down_lines { |
328
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
329
|
0
|
|
|
|
|
|
my $n = shift; |
330
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
for (1 .. $n){ |
333
|
0
|
0
|
|
|
|
|
if( $me->{end} >= $me->{nl}-1 ){ |
334
|
0
|
|
|
|
|
|
print "\a"; |
335
|
0
|
|
|
|
|
|
last; |
336
|
|
|
|
|
|
|
}else{ |
337
|
|
|
|
|
|
|
# why? because some terminals have bugs... |
338
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L} ); # move |
339
|
0
|
|
|
|
|
|
print $t->Tputs('sf'); # scroll |
340
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L} - 1); # move |
341
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
342
|
|
|
|
|
|
|
|
343
|
0
|
|
|
|
|
|
$me->line( ++$me->{end} ); |
344
|
0
|
|
|
|
|
|
$me->{start} ++; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub downhalf { |
350
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
351
|
0
|
|
|
|
|
|
$me->down_lines( $me->{L} / 2 ); |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub downpage { |
355
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
356
|
0
|
|
|
|
|
|
$me->down_lines( $me->{L} ); |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub downline { |
360
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
361
|
0
|
|
|
|
|
|
$me->down_lines( 1 ); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub up_lines { |
365
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
366
|
0
|
|
|
|
|
|
my $n = shift; |
367
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
for (1 .. $n){ |
370
|
0
|
0
|
|
|
|
|
if( $me->{start} <= 0 ){ |
371
|
0
|
|
|
|
|
|
print "\a"; |
372
|
0
|
|
|
|
|
|
last; |
373
|
|
|
|
|
|
|
}else{ |
374
|
0
|
|
|
|
|
|
print $t->Tgoto('cm',0,0); # move |
375
|
0
|
|
|
|
|
|
print $t->Tputs('sr'); # scroll back |
376
|
0
|
|
|
|
|
|
$me->line( --$me->{start} ); |
377
|
0
|
|
|
|
|
|
$me->{end} --; |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
0
|
|
|
|
|
|
print $t->Tgoto('cm',0,$me->{L}); # goto bottom |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub uppage { |
385
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
386
|
0
|
|
|
|
|
|
$me->up_lines( $me->{L} ); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub upline { |
390
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
391
|
0
|
|
|
|
|
|
$me->up_lines( 1 ); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub uphalf { |
395
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
396
|
0
|
|
|
|
|
|
$me->up_lines( $me->{L} / 2 ); |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
sub to_top { |
400
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
401
|
|
|
|
|
|
|
|
402
|
0
|
|
|
|
|
|
$me->{start} = 0; |
403
|
0
|
|
|
|
|
|
$me->{end} = $me->{L} - 1; |
404
|
0
|
|
|
|
|
|
$me->refresh(); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub to_bott { |
408
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
409
|
|
|
|
|
|
|
|
410
|
0
|
|
|
|
|
|
$me->{start} = $me->{nl} - $me->{L}; |
411
|
0
|
0
|
|
|
|
|
$me->{start} = 0 if $me->{start} < 0; |
412
|
0
|
|
|
|
|
|
$me->{end} = $me->{start} + $me->{L} - 1; |
413
|
0
|
|
|
|
|
|
$me->refresh(); |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub move_right { |
417
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
418
|
|
|
|
|
|
|
|
419
|
0
|
|
|
|
|
|
$me->{left} += 8; |
420
|
0
|
|
|
|
|
|
$me->refresh(); |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub move_left { |
424
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
$me->{left} -= 8; |
427
|
0
|
0
|
|
|
|
|
$me->{left} = 0 if $me->{left} < 0; |
428
|
0
|
|
|
|
|
|
$me->refresh(); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub search { |
432
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
433
|
0
|
|
|
|
|
|
my $t = $me->{term}; |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# get pattern |
436
|
0
|
|
|
|
|
|
my $prev = $me->{search}; |
437
|
0
|
|
|
|
|
|
$me->{search} = ''; |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L}); # move bottom |
440
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
441
|
0
|
|
|
|
|
|
print $me->{SE}; # set color |
442
|
0
|
|
|
|
|
|
print "/"; |
443
|
|
|
|
|
|
|
|
444
|
0
|
|
|
|
|
|
while(1){ |
445
|
0
|
|
|
|
|
|
my $l = getc(); |
446
|
0
|
0
|
0
|
|
|
|
last if $l eq "\n" || $l eq "\r"; |
447
|
0
|
0
|
0
|
|
|
|
if( $l eq "\e" || !defined($l) ){ |
448
|
0
|
|
|
|
|
|
$me->{search} = ''; |
449
|
0
|
|
|
|
|
|
last; |
450
|
|
|
|
|
|
|
} |
451
|
0
|
0
|
0
|
|
|
|
if( $l eq "\b" || $l eq "\177" || $l eq '#' ){ |
|
|
|
0
|
|
|
|
|
452
|
0
|
0
|
|
|
|
|
print "\b \b" if $me->{search} ne ''; |
453
|
0
|
|
|
|
|
|
substr($me->{search}, -1, 1, ''); |
454
|
0
|
|
|
|
|
|
next; |
455
|
|
|
|
|
|
|
} |
456
|
0
|
|
|
|
|
|
print $l; |
457
|
0
|
|
|
|
|
|
$me->{search} .= $l; |
458
|
|
|
|
|
|
|
} |
459
|
0
|
|
|
|
|
|
print $me->{NO}; # normal color |
460
|
0
|
|
|
|
|
|
print $t->Tgoto('cm', 0, $me->{L}); # move bottom |
461
|
0
|
|
|
|
|
|
print $t->Tputs('ce'); # clear line |
462
|
0
|
0
|
|
|
|
|
return if $me->{search} eq ''; |
463
|
|
|
|
|
|
|
|
464
|
0
|
0
|
0
|
|
|
|
$me->{search} = $prev if $me->{search} eq '/' && $prev; |
465
|
|
|
|
|
|
|
|
466
|
0
|
|
|
|
|
|
for my $n ( $me->{start} .. $me->{nl}-1 ){ |
467
|
0
|
0
|
|
|
|
|
next unless $me->{l}[$n] =~ /$me->{search}/; |
468
|
|
|
|
|
|
|
|
469
|
0
|
|
|
|
|
|
$me->{start} = $n; |
470
|
0
|
0
|
|
|
|
|
$me->{start} = 0 if $me->{nl} < $me->{L} - 1; |
471
|
0
|
|
|
|
|
|
$me->{end} = $me->{start} + $me->{L} - 1; |
472
|
|
|
|
|
|
|
|
473
|
0
|
0
|
0
|
|
|
|
if( $me->{end} > $me->{nl} - 1 && $me->{start} ){ |
474
|
0
|
|
|
|
|
|
my $x = $me->{end} - $me->{nl} + 1; |
475
|
0
|
0
|
|
|
|
|
$x = $me->{start} if $x > $me->{start}; |
476
|
0
|
|
|
|
|
|
$me->{start} -= $x; |
477
|
0
|
|
|
|
|
|
$me->{end} -= $x; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
0
|
|
|
|
|
|
$me->refresh(); |
481
|
0
|
|
|
|
|
|
return; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
# not found |
484
|
0
|
|
|
|
|
|
print "\a"; |
485
|
0
|
|
|
|
|
|
my $m = $me->box_text( 'Not Found' ); |
486
|
0
|
|
|
|
|
|
$me->disp_menu($m); |
487
|
0
|
|
|
|
|
|
sleep 1; |
488
|
0
|
|
|
|
|
|
$me->remove_menu(); |
489
|
0
|
|
|
|
|
|
return; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub dumb_mode { |
495
|
0
|
|
|
0
|
0
|
|
my $me = shift; |
496
|
0
|
|
|
|
|
|
my $end = 0; |
497
|
|
|
|
|
|
|
|
498
|
0
|
|
|
|
|
|
while(1){ |
499
|
0
|
|
|
|
|
|
for my $i (1 .. $me->{rows} - 1){ |
500
|
0
|
0
|
|
|
|
|
last if $end >= $me->{nl}; |
501
|
0
|
|
|
|
|
|
print $me->{l}[$end++], "\n"; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
|
print "--more [dumb]--"; |
505
|
0
|
|
|
|
|
|
my $a = getc(); |
506
|
0
|
|
|
|
|
|
print "\b \b"x15; |
507
|
|
|
|
|
|
|
|
508
|
0
|
0
|
|
|
|
|
return if $a eq 'q'; |
509
|
0
|
0
|
|
|
|
|
return if $end >= $me->{nl}; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head1 FEATURES |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
This code uses termcap. If the termcap entry for your ancient esoteric |
518
|
|
|
|
|
|
|
terminal is wrong or incomplete, this module may either fill your screen |
519
|
|
|
|
|
|
|
with unintelligible gibberish, or drop back to a feature-free mode. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=head1 SEE ALSO |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
Term::Cap, termcap(5), more(1), less(1) |
524
|
|
|
|
|
|
|
Yellowstone National Park |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=head1 AUTHOR |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
Jeff Weisberg - http://www.tcp4me.com |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=cut |
531
|
|
|
|
|
|
|
; |