| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Term::Cap; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | # Since the debugger uses Term::ReadLine which uses Term::Cap, we want | 
| 4 |  |  |  |  |  |  | # to load as few modules as possible.  This includes Carp.pm. | 
| 5 |  |  |  |  |  |  | sub carp | 
| 6 |  |  |  |  |  |  | { | 
| 7 | 1 |  |  | 1 | 0 | 5 | require Carp; | 
| 8 | 1 |  |  |  |  | 83 | goto &Carp::carp; | 
| 9 |  |  |  |  |  |  | } | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | sub croak | 
| 12 |  |  |  |  |  |  | { | 
| 13 | 7 |  |  | 7 | 0 | 55 | require Carp; | 
| 14 | 7 |  |  |  |  | 1202 | goto &Carp::croak; | 
| 15 |  |  |  |  |  |  | } | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 1 |  |  | 1 |  | 169392 | use strict; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 51 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 1 |  |  | 1 |  | 7 | use vars qw($VERSION $VMS_TERMCAP); | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 86 |  | 
| 20 | 1 |  |  | 1 |  | 31 | use vars qw($termpat $state $first $entry); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3203 |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | $VERSION = '1.17'; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | # TODO: | 
| 25 |  |  |  |  |  |  | # support Berkeley DB termcaps | 
| 26 |  |  |  |  |  |  | # force $FH into callers package? | 
| 27 |  |  |  |  |  |  | # keep $FH in object at Tgetent time? | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | =head1 NAME | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | Term::Cap - Perl termcap interface | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | require Term::Cap; | 
| 36 |  |  |  |  |  |  | $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed }; | 
| 37 |  |  |  |  |  |  | $terminal->Trequire(qw/ce ku kd/); | 
| 38 |  |  |  |  |  |  | $terminal->Tgoto('cm', $col, $row, $FH); | 
| 39 |  |  |  |  |  |  | $terminal->Tputs('dl', $count, $FH); | 
| 40 |  |  |  |  |  |  | $terminal->Tpad($string, $count, $FH); | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | These are low-level functions to extract and use capabilities from | 
| 45 |  |  |  |  |  |  | a terminal capability (termcap) database. | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | More information on the terminal capabilities will be found in the | 
| 48 |  |  |  |  |  |  | termcap manpage on most Unix-like systems. | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | =head2 METHODS | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | The output strings for B are cached for counts of 1 for performance. | 
| 53 |  |  |  |  |  |  | B and B do not cache.  C<$self-E{_xx}> is the raw termcap | 
| 54 |  |  |  |  |  |  | data and C<$self-E{xx}> is the cached version. | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | print $terminal->Tpad($self->{_xx}, 1); | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | B, B, and B return the string and will also | 
| 59 |  |  |  |  |  |  | output the string to $FH if specified. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | =cut | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | # Preload the default VMS termcap. | 
| 65 |  |  |  |  |  |  | # If a different termcap is required then the text of one can be supplied | 
| 66 |  |  |  |  |  |  | # in $Term::Cap::VMS_TERMCAP before Tgetent is called. | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | if ( $^O eq 'VMS' ) | 
| 69 |  |  |  |  |  |  | { | 
| 70 |  |  |  |  |  |  | chomp( my @entry =  ); | 
| 71 |  |  |  |  |  |  | $VMS_TERMCAP = join '', @entry; | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | # Returns a list of termcap files to check. | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | sub termcap_path | 
| 77 |  |  |  |  |  |  | {    ## private | 
| 78 | 8 |  |  | 8 | 0 | 1106 | my @termcap_path; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | # $TERMCAP, if it's a filespec | 
| 81 |  |  |  |  |  |  | push( @termcap_path, $ENV{TERMCAP} ) | 
| 82 |  |  |  |  |  |  | if ( | 
| 83 |  |  |  |  |  |  | ( exists $ENV{TERMCAP} ) | 
| 84 |  |  |  |  |  |  | && ( | 
| 85 |  |  |  |  |  |  | ( $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'dos' ) | 
| 86 |  |  |  |  |  |  | ? $ENV{TERMCAP} =~ /^[a-z]:[\\\/]/is | 
| 87 | 8 | 50 | 33 |  |  | 117 | : $ENV{TERMCAP} =~ /^\//s | 
|  |  | 100 | 66 |  |  |  |  | 
| 88 |  |  |  |  |  |  | ) | 
| 89 |  |  |  |  |  |  | ); | 
| 90 | 8 | 100 | 66 |  |  | 33 | if ( ( exists $ENV{TERMPATH} ) && ( $ENV{TERMPATH} ) ) | 
| 91 |  |  |  |  |  |  | { | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | # Add the users $TERMPATH | 
| 94 | 6 |  |  |  |  | 118 | push( @termcap_path, split( /(:|\s+)/, $ENV{TERMPATH} ) ); | 
| 95 |  |  |  |  |  |  | } | 
| 96 |  |  |  |  |  |  | else | 
| 97 |  |  |  |  |  |  | { | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | # Defaults | 
| 100 |  |  |  |  |  |  | push( @termcap_path, | 
| 101 | 2 | 100 |  |  |  | 9 | exists $ENV{'HOME'} ? $ENV{'HOME'} . '/.termcap' : undef, | 
| 102 |  |  |  |  |  |  | '/etc/termcap', '/usr/share/misc/termcap', ); | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | # return the list of those termcaps that exist | 
| 106 | 8 | 100 |  |  |  | 18 | return grep { defined $_ && -f $_ } @termcap_path; | 
|  | 77 |  |  |  |  | 719 |  | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | =over 4 | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | =item B | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | Returns a blessed object reference which the user can | 
| 114 |  |  |  |  |  |  | then use to send the control strings to the terminal using B | 
| 115 |  |  |  |  |  |  | and B. | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | The function extracts the entry of the specified terminal | 
| 118 |  |  |  |  |  |  | type I (defaults to the environment variable I) from the | 
| 119 |  |  |  |  |  |  | database. | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | It will look in the environment for a I variable.  If | 
| 122 |  |  |  |  |  |  | found, and the value does not begin with a slash, and the terminal | 
| 123 |  |  |  |  |  |  | type name is the same as the environment string I, the | 
| 124 |  |  |  |  |  |  | I string is used instead of reading a termcap file.  If | 
| 125 |  |  |  |  |  |  | it does begin with a slash, the string is used as a path name of | 
| 126 |  |  |  |  |  |  | the termcap file to search.  If I does not begin with a | 
| 127 |  |  |  |  |  |  | slash and name is different from I, B searches the | 
| 128 |  |  |  |  |  |  | files F<$HOME/.termcap>, F, and F, | 
| 129 |  |  |  |  |  |  | in that order, unless the environment variable I exists, | 
| 130 |  |  |  |  |  |  | in which case it specifies a list of file pathnames (separated by | 
| 131 |  |  |  |  |  |  | spaces or colons) to be searched B.  Whenever multiple | 
| 132 |  |  |  |  |  |  | files are searched and a tc field occurs in the requested entry, | 
| 133 |  |  |  |  |  |  | the entry it names must be found in the same file or one of the | 
| 134 |  |  |  |  |  |  | succeeding files.  If there is a C<:tc=...:> in the I | 
| 135 |  |  |  |  |  |  | environment variable string it will continue the search in the | 
| 136 |  |  |  |  |  |  | files as above. | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | The extracted termcap entry is available in the object | 
| 139 |  |  |  |  |  |  | as C<$self-E{TERMCAP}>. | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | It takes a hash reference as an argument with two optional keys: | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | =over 2 | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | =item OSPEED | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | The terminal output bit rate (often mistakenly called the baud rate) | 
| 148 |  |  |  |  |  |  | for this terminal - if not set a warning will be generated | 
| 149 |  |  |  |  |  |  | and it will be defaulted to 9600.  I can be specified as | 
| 150 |  |  |  |  |  |  | either a POSIX termios/SYSV termio speeds (where 9600 equals 9600) or | 
| 151 |  |  |  |  |  |  | an old DSD-style speed ( where 13 equals 9600). | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | =item TERM | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | The terminal type whose termcap entry will be used - if not supplied it will | 
| 157 |  |  |  |  |  |  | default to $ENV{TERM}: if that is not set then B will croak. | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | =back | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | It calls C on failure. | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | =cut | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | sub Tgetent | 
| 166 |  |  |  |  |  |  | {    ## public -- static method | 
| 167 | 8 |  |  | 8 | 1 | 7495 | my $class = shift; | 
| 168 | 8 |  |  |  |  | 17 | my ($self) = @_; | 
| 169 |  |  |  |  |  |  |  | 
| 170 | 8 | 100 |  |  |  | 24 | $self = {} unless defined $self; | 
| 171 | 8 |  |  |  |  | 11 | bless $self, $class; | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 8 |  |  |  |  | 24 | my ( $term, $cap, $search, $field, $max, $tmp_term, $TERMCAP ); | 
| 174 | 8 |  |  |  |  | 15 | local ( $termpat, $state, $first, $entry );    # used inside eval | 
| 175 | 8 |  |  |  |  | 7 | local $_; | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | # Compute PADDING factor from OSPEED (to be used by Tpad) | 
| 178 | 8 | 100 |  |  |  | 21 | if ( !$self->{OSPEED} ) | 
| 179 |  |  |  |  |  |  | { | 
| 180 | 2 | 100 |  |  |  | 8 | if ($^W) | 
| 181 |  |  |  |  |  |  | { | 
| 182 | 1 |  |  |  |  | 3 | carp "OSPEED was not set, defaulting to 9600"; | 
| 183 |  |  |  |  |  |  | } | 
| 184 | 2 |  |  |  |  | 39 | $self->{OSPEED} = 9600; | 
| 185 |  |  |  |  |  |  | } | 
| 186 | 8 | 100 |  |  |  | 23 | if ( $self->{OSPEED} < 16 ) | 
| 187 |  |  |  |  |  |  | { | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | # delays for old style speeds | 
| 190 | 5 |  |  |  |  | 25 | my @pad = ( | 
| 191 |  |  |  |  |  |  | 0,    200, 133.3, 90.9, 74.3, 66.7, 50, 33.3, | 
| 192 |  |  |  |  |  |  | 16.7, 8.3, 5.5,   4.1,  2,    1,    .5, .2 | 
| 193 |  |  |  |  |  |  | ); | 
| 194 | 5 |  |  |  |  | 18 | $self->{PADDING} = $pad[ $self->{OSPEED} ]; | 
| 195 |  |  |  |  |  |  | } | 
| 196 |  |  |  |  |  |  | else | 
| 197 |  |  |  |  |  |  | { | 
| 198 | 3 |  |  |  |  | 8 | $self->{PADDING} = 10000 / $self->{OSPEED}; | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 8 | 100 |  |  |  | 22 | unless ( $self->{TERM} ) | 
| 202 |  |  |  |  |  |  | { | 
| 203 | 5 | 100 |  |  |  | 10 | if ( $ENV{TERM} ) | 
| 204 |  |  |  |  |  |  | { | 
| 205 | 1 |  |  |  |  | 5 | $self->{TERM} =  $ENV{TERM} ; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | else | 
| 208 |  |  |  |  |  |  | { | 
| 209 | 4 | 100 |  |  |  | 12 | if ( $^O eq 'MSWin32' ) | 
| 210 |  |  |  |  |  |  | { | 
| 211 | 1 |  |  |  |  | 3 | $self->{TERM} =  'dumb'; | 
| 212 |  |  |  |  |  |  | } | 
| 213 |  |  |  |  |  |  | else | 
| 214 |  |  |  |  |  |  | { | 
| 215 | 3 |  |  |  |  | 5 | croak "TERM not set"; | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 | 5 |  |  |  |  | 13 | $term = $self->{TERM};    # $term is the term type we are looking for | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | # $tmp_term is always the next term (possibly :tc=...:) we are looking for | 
| 223 | 5 |  |  |  |  | 11 | $tmp_term = $self->{TERM}; | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | # protect any pattern metacharacters in $tmp_term | 
| 226 | 5 |  |  |  |  | 8 | $termpat = $tmp_term; | 
| 227 | 5 |  |  |  |  | 15 | $termpat =~ s/(\W)/\\$1/g; | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 5 | 100 |  |  |  | 17 | my $foo = ( exists $ENV{TERMCAP} ? $ENV{TERMCAP} : '' ); | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | # $entry is the extracted termcap entry | 
| 232 | 5 | 50 | 33 |  |  | 183 | if ( ( $foo !~ m:^/:s ) && ( $foo =~ m/(^|\|)${termpat}[:|]/s ) ) | 
| 233 |  |  |  |  |  |  | { | 
| 234 | 0 |  |  |  |  | 0 | $entry = $foo; | 
| 235 |  |  |  |  |  |  | } | 
| 236 |  |  |  |  |  |  |  | 
| 237 | 5 |  |  |  |  | 22 | my @termcap_path = termcap_path(); | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 5 | 50 | 66 |  |  | 42 | if ( !@termcap_path && !$entry ) | 
| 240 |  |  |  |  |  |  | { | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | # last resort--fake up a termcap from terminfo | 
| 243 | 2 |  |  |  |  | 12 | local $ENV{TERM} = $term; | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 2 | 50 |  |  |  | 9 | if ( $^O eq 'VMS' ) | 
| 246 |  |  |  |  |  |  | { | 
| 247 | 0 |  |  |  |  | 0 | $entry = $VMS_TERMCAP; | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  | else | 
| 250 |  |  |  |  |  |  | { | 
| 251 | 2 | 100 |  |  |  | 13 | if ( grep { -x "$_/infocmp" } split /:/, $ENV{PATH} ) | 
|  | 7 |  |  |  |  | 27153 |  | 
| 252 |  |  |  |  |  |  | { | 
| 253 | 1 |  |  |  |  | 5 | eval { | 
| 254 | 1 |  |  |  |  | 4227 | my $tmp = `infocmp -C 2>/dev/null`; | 
| 255 | 1 |  |  |  |  | 8 | $tmp =~ s/^#.*\n//gm;    # remove comments | 
| 256 | 1 | 50 | 33 |  |  | 70 | if (   ( $tmp !~ m%^/%s ) | 
| 257 |  |  |  |  |  |  | && ( $tmp =~ /(^|\|)${termpat}[:|]/s ) ) | 
| 258 |  |  |  |  |  |  | { | 
| 259 | 0 |  |  |  |  | 0 | $entry = $tmp; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  | }; | 
| 262 | 1 | 50 |  |  |  | 19 | warn "Can't run infocmp to get a termcap entry: $@" if $@; | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  | else | 
| 265 |  |  |  |  |  |  | { | 
| 266 |  |  |  |  |  |  | # this is getting desperate now | 
| 267 | 1 | 50 |  |  |  | 7 | if ( $self->{TERM} eq 'dumb' ) | 
| 268 |  |  |  |  |  |  | { | 
| 269 | 1 |  |  |  |  | 3 | $entry = 'dumb|80-column dumb tty::am::co#80::bl=^G:cr=^M:do=^J:sf=^J:'; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  |  | 
| 275 | 5 | 100 | 66 |  |  | 35 | croak "Can't find a valid termcap file" unless @termcap_path || $entry; | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 4 |  |  |  |  | 6 | $state = 1;    # 0 == finished | 
| 278 |  |  |  |  |  |  | # 1 == next file | 
| 279 |  |  |  |  |  |  | # 2 == search again | 
| 280 |  |  |  |  |  |  |  | 
| 281 | 4 |  |  |  |  | 8 | $first = 0;    # first entry (keeps term name) | 
| 282 |  |  |  |  |  |  |  | 
| 283 | 4 |  |  |  |  | 7 | $max = 32;     # max :tc=...:'s | 
| 284 |  |  |  |  |  |  |  | 
| 285 | 4 | 100 |  |  |  | 13 | if ($entry) | 
| 286 |  |  |  |  |  |  | { | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | # ok, we're starting with $TERMCAP | 
| 289 | 1 |  |  |  |  | 2 | $first++;    # we're the first entry | 
| 290 |  |  |  |  |  |  | # do we need to continue? | 
| 291 | 1 | 50 |  |  |  | 6 | if ( $entry =~ s/:tc=([^:]+):/:/ ) | 
| 292 |  |  |  |  |  |  | { | 
| 293 | 0 |  |  |  |  | 0 | $tmp_term = $1; | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | # protect any pattern metacharacters in $tmp_term | 
| 296 | 0 |  |  |  |  | 0 | $termpat = $tmp_term; | 
| 297 | 0 |  |  |  |  | 0 | $termpat =~ s/(\W)/\\$1/g; | 
| 298 |  |  |  |  |  |  | } | 
| 299 |  |  |  |  |  |  | else | 
| 300 |  |  |  |  |  |  | { | 
| 301 | 1 |  |  |  |  | 2 | $state = 0;    # we're already finished | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  | } | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | # This is eval'ed inside the while loop for each file | 
| 306 | 4 |  |  |  |  | 8 | $search = q{ | 
| 307 |  |  |  |  |  |  | while () { | 
| 308 |  |  |  |  |  |  | next if /^\\t/ || /^#/; | 
| 309 |  |  |  |  |  |  | if ($_ =~ m/(^|\\|)${termpat}[:|]/o) { | 
| 310 |  |  |  |  |  |  | chomp; | 
| 311 |  |  |  |  |  |  | s/^[^:]*:// if $first++; | 
| 312 |  |  |  |  |  |  | $state = 0; | 
| 313 |  |  |  |  |  |  | while ($_ =~ s/\\\\$//) { | 
| 314 |  |  |  |  |  |  | defined(my $x = ) or last; | 
| 315 |  |  |  |  |  |  | $_ .= $x; chomp; | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  | last; | 
| 318 |  |  |  |  |  |  | } | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | defined $entry or $entry = ''; | 
| 321 |  |  |  |  |  |  | $entry .= $_ if $_; | 
| 322 |  |  |  |  |  |  | }; | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 4 |  |  |  |  | 12 | while ( $state != 0 ) | 
| 325 |  |  |  |  |  |  | { | 
| 326 | 37 | 100 |  |  |  | 77 | if ( $state == 1 ) | 
| 327 |  |  |  |  |  |  | { | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | # get the next TERMCAP | 
| 330 | 4 |  | 66 |  |  | 21 | $TERMCAP = shift @termcap_path | 
| 331 |  |  |  |  |  |  | || croak "failed termcap lookup on $tmp_term"; | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | else | 
| 334 |  |  |  |  |  |  | { | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | # do the same file again | 
| 337 |  |  |  |  |  |  | # prevent endless recursion | 
| 338 | 33 | 100 |  |  |  | 77 | $max-- || croak "failed termcap loop at $tmp_term"; | 
| 339 | 32 |  |  |  |  | 40 | $state = 1;    # ok, maybe do a new file next time | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 | 35 | 50 |  |  |  | 891 | open( TERMCAP, "< $TERMCAP\0" ) || croak "open $TERMCAP: $!"; | 
| 343 | 35 |  |  |  |  | 8935 | eval $search; | 
| 344 | 35 | 50 |  |  |  | 127 | die $@ if $@; | 
| 345 | 35 |  |  |  |  | 306 | close TERMCAP; | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | # If :tc=...: found then search this file again | 
| 348 | 35 | 100 |  |  |  | 385 | $entry =~ s/:tc=([^:]+):/:/ && ( $tmp_term = $1, $state = 2 ); | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | # protect any pattern metacharacters in $tmp_term | 
| 351 | 35 |  |  |  |  | 43 | $termpat = $tmp_term; | 
| 352 | 35 |  |  |  |  | 120 | $termpat =~ s/(\W)/\\$1/g; | 
| 353 |  |  |  |  |  |  | } | 
| 354 |  |  |  |  |  |  |  | 
| 355 | 2 | 50 |  |  |  | 7 | croak "Can't find $term" if $entry eq ''; | 
| 356 | 2 |  |  |  |  | 21 | $entry =~ s/:+\s*:+/:/g;    # cleanup $entry | 
| 357 | 2 |  |  |  |  | 14 | $entry =~ s/:+/:/g;         # cleanup $entry | 
| 358 | 2 |  |  |  |  | 8 | $self->{TERMCAP} = $entry;  # save it | 
| 359 |  |  |  |  |  |  | # print STDERR "DEBUG: $entry = ", $entry, "\n"; | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | # Precompile $entry into the object | 
| 362 | 2 |  |  |  |  | 8 | $entry =~ s/^[^:]*://; | 
| 363 | 2 |  |  |  |  | 15 | foreach $field ( split( /:[\s:\\]*/, $entry ) ) | 
| 364 |  |  |  |  |  |  | { | 
| 365 | 11 | 100 | 66 |  |  | 137 | if ( defined $field && $field =~ /^(\w{2,})$/ ) | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  | 50 | 33 |  |  |  |  | 
| 366 |  |  |  |  |  |  | { | 
| 367 | 3 | 50 |  |  |  | 22 | $self->{ '_' . $field } = 1 unless defined $self->{ '_' . $1 }; | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  | # print STDERR "DEBUG: flag $1\n"; | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  | elsif ( defined $field && $field =~ /^(\w{2,})\@/ ) | 
| 372 |  |  |  |  |  |  | { | 
| 373 | 1 |  |  |  |  | 5 | $self->{ '_' . $1 } = ""; | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | # print STDERR "DEBUG: unset $1\n"; | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  | elsif ( defined $field && $field =~ /^(\w{2,})#(.*)/ ) | 
| 378 |  |  |  |  |  |  | { | 
| 379 | 2 | 50 |  |  |  | 16 | $self->{ '_' . $1 } = $2 unless defined $self->{ '_' . $1 }; | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | # print STDERR "DEBUG: numeric $1 = $2\n"; | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  | elsif ( defined $field && $field =~ /^(\w{2,})=(.*)/ ) | 
| 384 |  |  |  |  |  |  | { | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | # print STDERR "DEBUG: string $1 = $2\n"; | 
| 387 | 5 | 50 |  |  |  | 14 | next if defined $self->{ '_' . ( $cap = $1 ) }; | 
| 388 | 5 |  |  |  |  | 11 | $_ = $2; | 
| 389 | 5 |  |  |  |  | 6 | if ( ord('A') == 193 ) | 
| 390 |  |  |  |  |  |  | { | 
| 391 |  |  |  |  |  |  | s/\\E/\047/g; | 
| 392 |  |  |  |  |  |  | s/\\(\d\d\d)/pack('c',oct($1) & 0177)/eg; | 
| 393 |  |  |  |  |  |  | s/\\n/\n/g; | 
| 394 |  |  |  |  |  |  | s/\\r/\r/g; | 
| 395 |  |  |  |  |  |  | s/\\t/\t/g; | 
| 396 |  |  |  |  |  |  | s/\\b/\b/g; | 
| 397 |  |  |  |  |  |  | s/\\f/\f/g; | 
| 398 |  |  |  |  |  |  | s/\\\^/\337/g; | 
| 399 |  |  |  |  |  |  | s/\^\?/\007/g; | 
| 400 |  |  |  |  |  |  | s/\^(.)/pack('c',ord($1) & 31)/eg; | 
| 401 |  |  |  |  |  |  | s/\\(.)/$1/g; | 
| 402 |  |  |  |  |  |  | s/\337/^/g; | 
| 403 |  |  |  |  |  |  | } | 
| 404 |  |  |  |  |  |  | else | 
| 405 |  |  |  |  |  |  | { | 
| 406 | 5 |  |  |  |  | 7 | s/\\E/\033/g; | 
| 407 | 5 |  |  |  |  | 7 | s/\\(\d\d\d)/pack('c',oct($1) & 0177)/eg; | 
|  | 0 |  |  |  |  | 0 |  | 
| 408 | 5 |  |  |  |  | 10 | s/\\n/\n/g; | 
| 409 | 5 |  |  |  |  | 8 | s/\\r/\r/g; | 
| 410 | 5 |  |  |  |  | 5 | s/\\t/\t/g; | 
| 411 | 5 |  |  |  |  | 7 | s/\\b/\b/g; | 
| 412 | 5 |  |  |  |  | 5 | s/\\f/\f/g; | 
| 413 | 5 |  |  |  |  | 4 | s/\\\^/\377/g; | 
| 414 | 5 |  |  |  |  | 7 | s/\^\?/\177/g; | 
| 415 | 5 |  |  |  |  | 18 | s/\^(.)/pack('c',ord($1) & 31)/eg; | 
|  | 4 |  |  |  |  | 18 |  | 
| 416 | 5 |  |  |  |  | 8 | s/\\(.)/$1/g; | 
| 417 | 5 |  |  |  |  | 8 | s/\377/^/g; | 
| 418 |  |  |  |  |  |  | } | 
| 419 | 5 |  |  |  |  | 18 | $self->{ '_' . $cap } = $_; | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | # else { carp "junk in $term ignored: $field"; } | 
| 423 |  |  |  |  |  |  | } | 
| 424 | 2 | 50 |  |  |  | 12 | $self->{'_pc'} = "\0" unless defined $self->{'_pc'}; | 
| 425 | 2 | 50 |  |  |  | 7 | $self->{'_bc'} = "\b" unless defined $self->{'_bc'}; | 
| 426 | 2 |  |  |  |  | 14 | $self; | 
| 427 |  |  |  |  |  |  | } | 
| 428 |  |  |  |  |  |  |  | 
| 429 |  |  |  |  |  |  | # $terminal->Tpad($string, $cnt, $FH); | 
| 430 |  |  |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | =item B | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | Outputs a literal string with appropriate padding for the current terminal. | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | It takes three arguments: | 
| 436 |  |  |  |  |  |  |  | 
| 437 |  |  |  |  |  |  | =over 2 | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | =item B<$string> | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | The literal string to be output.  If it starts with a number and an optional | 
| 442 |  |  |  |  |  |  | '*' then the padding will be increased by an amount relative to this number, | 
| 443 |  |  |  |  |  |  | if the '*' is present then this amount will be multiplied by $cnt.  This part | 
| 444 |  |  |  |  |  |  | of $string is removed before output/ | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | =item B<$cnt> | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | Will be used to modify the padding applied to string as described above. | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =item B<$FH> | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | An optional filehandle (or IO::Handle ) that output will be printed to. | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | =back | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | The padded $string is returned. | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | =cut | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | sub Tpad | 
| 461 |  |  |  |  |  |  | {    ## public | 
| 462 | 17 |  |  | 17 | 1 | 232 | my $self = shift; | 
| 463 | 17 |  |  |  |  | 30 | my ( $string, $cnt, $FH ) = @_; | 
| 464 | 17 |  |  |  |  | 17 | my ( $decr, $ms ); | 
| 465 |  |  |  |  |  |  |  | 
| 466 | 17 | 100 | 100 |  |  | 107 | if ( defined $string && $string =~ /(^[\d.]+)(\*?)(.*)$/ ) | 
| 467 |  |  |  |  |  |  | { | 
| 468 | 2 |  |  |  |  | 4 | $ms = $1; | 
| 469 | 2 | 50 |  |  |  | 7 | $ms *= $cnt if $2; | 
| 470 | 2 |  |  |  |  | 3 | $string = $3; | 
| 471 | 2 |  |  |  |  | 7 | $decr   = $self->{PADDING}; | 
| 472 | 2 | 50 |  |  |  | 4 | if ( $decr > .1 ) | 
| 473 |  |  |  |  |  |  | { | 
| 474 | 2 |  |  |  |  | 3 | $ms += $decr / 2; | 
| 475 | 2 |  |  |  |  | 6 | $string .= $self->{'_pc'} x ( $ms / $decr ); | 
| 476 |  |  |  |  |  |  | } | 
| 477 |  |  |  |  |  |  | } | 
| 478 | 17 | 100 |  |  |  | 39 | print $FH $string if $FH; | 
| 479 | 17 |  |  |  |  | 50 | $string; | 
| 480 |  |  |  |  |  |  | } | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | # $terminal->Tputs($cap, $cnt, $FH); | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | =item B | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | Output the string for the given capability padded as appropriate without | 
| 487 |  |  |  |  |  |  | any parameter substitution. | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | It takes three arguments: | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | =over 2 | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | =item B<$cap> | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | The capability whose string is to be output. | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | =item B<$cnt> | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | A count passed to Tpad to modify the padding applied to the output string. | 
| 500 |  |  |  |  |  |  | If $cnt is zero or one then the resulting string will be cached. | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | =item B<$FH> | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | An optional filehandle (or IO::Handle ) that output will be printed to. | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | =back | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | The appropriate string for the capability will be returned. | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | =cut | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | sub Tputs | 
| 513 |  |  |  |  |  |  | {    ## public | 
| 514 | 3 |  |  | 3 | 1 | 5 | my $self = shift; | 
| 515 | 3 |  |  |  |  | 13 | my ( $cap, $cnt, $FH ) = @_; | 
| 516 | 3 |  |  |  |  | 3 | my $string; | 
| 517 |  |  |  |  |  |  |  | 
| 518 | 3 | 100 |  |  |  | 8 | $cnt = 0 unless $cnt; | 
| 519 |  |  |  |  |  |  |  | 
| 520 | 3 | 100 |  |  |  | 32 | if ( $cnt > 1 ) | 
| 521 |  |  |  |  |  |  | { | 
| 522 | 1 |  |  |  |  | 11 | $string = Tpad( $self, $self->{ '_' . $cap }, $cnt ); | 
| 523 |  |  |  |  |  |  | } | 
| 524 |  |  |  |  |  |  | else | 
| 525 |  |  |  |  |  |  | { | 
| 526 |  |  |  |  |  |  |  | 
| 527 |  |  |  |  |  |  | # cache result because Tpad can be slow | 
| 528 | 2 | 100 |  |  |  | 6 | unless ( exists $self->{$cap} ) | 
| 529 |  |  |  |  |  |  | { | 
| 530 |  |  |  |  |  |  | $self->{$cap} = | 
| 531 |  |  |  |  |  |  | exists $self->{"_$cap"} | 
| 532 | 1 | 50 |  |  |  | 7 | ? Tpad( $self, $self->{"_$cap"}, 1 ) | 
| 533 |  |  |  |  |  |  | : undef; | 
| 534 |  |  |  |  |  |  | } | 
| 535 | 2 |  |  |  |  | 3 | $string = $self->{$cap}; | 
| 536 |  |  |  |  |  |  | } | 
| 537 | 3 | 100 |  |  |  | 10 | print $FH $string if $FH; | 
| 538 | 3 |  |  |  |  | 11 | $string; | 
| 539 |  |  |  |  |  |  | } | 
| 540 |  |  |  |  |  |  |  | 
| 541 |  |  |  |  |  |  | # $terminal->Tgoto($cap, $col, $row, $FH); | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | =item B | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | B decodes a cursor addressing string with the given parameters. | 
| 546 |  |  |  |  |  |  |  | 
| 547 |  |  |  |  |  |  | There are four arguments: | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | =over 2 | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | =item B<$cap> | 
| 552 |  |  |  |  |  |  |  | 
| 553 |  |  |  |  |  |  | The name of the capability to be output. | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | =item B<$col> | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | The first value to be substituted in the output string ( usually the column | 
| 558 |  |  |  |  |  |  | in a cursor addressing capability ) | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | =item B<$row> | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | The second value to be substituted in the output string (usually the row | 
| 563 |  |  |  |  |  |  | in cursor addressing capabilities) | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | =item B<$FH> | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | An optional filehandle (or IO::Handle ) to which the output string will be | 
| 568 |  |  |  |  |  |  | printed. | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | =back | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | Substitutions are made with $col and $row in the output string with the | 
| 573 |  |  |  |  |  |  | following sprintf() line formats: | 
| 574 |  |  |  |  |  |  |  | 
| 575 |  |  |  |  |  |  | %%   output `%' | 
| 576 |  |  |  |  |  |  | %d   output value as in printf %d | 
| 577 |  |  |  |  |  |  | %2   output value as in printf %2d | 
| 578 |  |  |  |  |  |  | %3   output value as in printf %3d | 
| 579 |  |  |  |  |  |  | %.   output value as in printf %c | 
| 580 |  |  |  |  |  |  | %+x  add x to value, then do %. | 
| 581 |  |  |  |  |  |  |  | 
| 582 |  |  |  |  |  |  | %>xy if value > x then add y, no output | 
| 583 |  |  |  |  |  |  | %r   reverse order of two parameters, no output | 
| 584 |  |  |  |  |  |  | %i   increment by one, no output | 
| 585 |  |  |  |  |  |  | %B   BCD (16*(value/10)) + (value%10), no output | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | %n   exclusive-or all parameters with 0140 (Datamedia 2500) | 
| 588 |  |  |  |  |  |  | %D   Reverse coding (value - 2*(value%16)), no output (Delta Data) | 
| 589 |  |  |  |  |  |  |  | 
| 590 |  |  |  |  |  |  | The output string will be returned. | 
| 591 |  |  |  |  |  |  |  | 
| 592 |  |  |  |  |  |  | =cut | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | sub Tgoto | 
| 595 |  |  |  |  |  |  | {    ## public | 
| 596 | 12 |  |  | 12 | 1 | 913 | my $self = shift; | 
| 597 | 12 |  |  |  |  | 31 | my ( $cap, $code, $tmp, $FH ) = @_; | 
| 598 | 12 |  |  |  |  | 27 | my $string = $self->{ '_' . $cap }; | 
| 599 | 12 |  |  |  |  | 14 | my $result = ''; | 
| 600 | 12 |  |  |  |  | 15 | my $after  = ''; | 
| 601 | 12 |  |  |  |  | 13 | my $online = 0; | 
| 602 | 12 |  |  |  |  | 27 | my @tmp    = ( $tmp, $code ); | 
| 603 | 12 |  |  |  |  | 13 | my $cnt    = $code; | 
| 604 |  |  |  |  |  |  |  | 
| 605 | 12 |  |  |  |  | 73 | while ( $string =~ /^([^%]*)%(.)(.*)/ ) | 
| 606 |  |  |  |  |  |  | { | 
| 607 | 14 |  |  |  |  | 36 | $result .= $1; | 
| 608 | 14 |  |  |  |  | 22 | $code   = $2; | 
| 609 | 14 |  |  |  |  | 23 | $string = $3; | 
| 610 | 14 | 100 |  |  |  | 73 | if ( $code eq 'd' ) | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | { | 
| 612 | 2 |  |  |  |  | 13 | $result .= sprintf( "%d", shift(@tmp) ); | 
| 613 |  |  |  |  |  |  | } | 
| 614 |  |  |  |  |  |  | elsif ( $code eq '.' ) | 
| 615 |  |  |  |  |  |  | { | 
| 616 | 2 |  |  |  |  | 4 | $tmp = shift(@tmp); | 
| 617 | 2 | 50 | 66 |  |  | 19 | if ( $tmp == 0 || $tmp == 4 || $tmp == 10 ) | 
|  |  |  | 66 |  |  |  |  | 
| 618 |  |  |  |  |  |  | { | 
| 619 | 1 | 50 |  |  |  | 6 | if ($online) | 
| 620 |  |  |  |  |  |  | { | 
| 621 | 0 | 0 |  |  |  | 0 | ++$tmp, $after .= $self->{'_up'} if $self->{'_up'}; | 
| 622 |  |  |  |  |  |  | } | 
| 623 |  |  |  |  |  |  | else | 
| 624 |  |  |  |  |  |  | { | 
| 625 | 1 |  |  |  |  | 4 | ++$tmp, $after .= $self->{'_bc'}; | 
| 626 |  |  |  |  |  |  | } | 
| 627 |  |  |  |  |  |  | } | 
| 628 | 2 |  |  |  |  | 8 | $result .= sprintf( "%c", $tmp ); | 
| 629 | 2 |  |  |  |  | 7 | $online = !$online; | 
| 630 |  |  |  |  |  |  | } | 
| 631 |  |  |  |  |  |  | elsif ( $code eq '+' ) | 
| 632 |  |  |  |  |  |  | { | 
| 633 | 3 |  |  |  |  | 13 | $result .= sprintf( "%c", shift(@tmp) + ord($string) ); | 
| 634 | 3 |  |  |  |  | 8 | $string = substr( $string, 1, 99 ); | 
| 635 | 3 |  |  |  |  | 9 | $online = !$online; | 
| 636 |  |  |  |  |  |  | } | 
| 637 |  |  |  |  |  |  | elsif ( $code eq 'r' ) | 
| 638 |  |  |  |  |  |  | { | 
| 639 | 1 |  |  |  |  | 4 | ( $code, $tmp ) = @tmp; | 
| 640 | 1 |  |  |  |  | 3 | @tmp = ( $tmp, $code ); | 
| 641 | 1 |  |  |  |  | 7 | $online = !$online; | 
| 642 |  |  |  |  |  |  | } | 
| 643 |  |  |  |  |  |  | elsif ( $code eq '>' ) | 
| 644 |  |  |  |  |  |  | { | 
| 645 | 1 |  |  |  |  | 9 | ( $code, $tmp, $string ) = unpack( "CCa99", $string ); | 
| 646 | 1 | 50 |  |  |  | 6 | if ( $tmp[0] > $code ) | 
| 647 |  |  |  |  |  |  | { | 
| 648 | 0 |  |  |  |  | 0 | $tmp[0] += $tmp; | 
| 649 |  |  |  |  |  |  | } | 
| 650 |  |  |  |  |  |  | } | 
| 651 |  |  |  |  |  |  | elsif ( $code eq '2' ) | 
| 652 |  |  |  |  |  |  | { | 
| 653 | 2 |  |  |  |  | 8 | $result .= sprintf( "%02d", shift(@tmp) ); | 
| 654 | 2 |  |  |  |  | 8 | $online = !$online; | 
| 655 |  |  |  |  |  |  | } | 
| 656 |  |  |  |  |  |  | elsif ( $code eq '3' ) | 
| 657 |  |  |  |  |  |  | { | 
| 658 | 1 |  |  |  |  | 5 | $result .= sprintf( "%03d", shift(@tmp) ); | 
| 659 | 1 |  |  |  |  | 5 | $online = !$online; | 
| 660 |  |  |  |  |  |  | } | 
| 661 |  |  |  |  |  |  | elsif ( $code eq 'i' ) | 
| 662 |  |  |  |  |  |  | { | 
| 663 | 1 |  |  |  |  | 3 | ( $code, $tmp ) = @tmp; | 
| 664 | 1 |  |  |  |  | 10 | @tmp = ( $code + 1, $tmp + 1 ); | 
| 665 |  |  |  |  |  |  | } | 
| 666 |  |  |  |  |  |  | else | 
| 667 |  |  |  |  |  |  | { | 
| 668 | 1 |  |  |  |  | 5 | return "OOPS"; | 
| 669 |  |  |  |  |  |  | } | 
| 670 |  |  |  |  |  |  | } | 
| 671 | 11 |  |  |  |  | 34 | $string = Tpad( $self, $result . $string . $after, $cnt ); | 
| 672 | 11 | 100 |  |  |  | 36 | print $FH $string if $FH; | 
| 673 | 11 |  |  |  |  | 63 | $string; | 
| 674 |  |  |  |  |  |  | } | 
| 675 |  |  |  |  |  |  |  | 
| 676 |  |  |  |  |  |  | # $terminal->Trequire(qw/ce ku kd/); | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | =item B | 
| 679 |  |  |  |  |  |  |  | 
| 680 |  |  |  |  |  |  | Takes a list of capabilities as an argument and will croak if one is not | 
| 681 |  |  |  |  |  |  | found. | 
| 682 |  |  |  |  |  |  |  | 
| 683 |  |  |  |  |  |  | =cut | 
| 684 |  |  |  |  |  |  |  | 
| 685 |  |  |  |  |  |  | sub Trequire | 
| 686 |  |  |  |  |  |  | {    ## public | 
| 687 | 2 |  |  | 2 | 1 | 304 | my $self = shift; | 
| 688 | 2 |  |  |  |  | 3 | my ( $cap, @undefined ); | 
| 689 | 2 |  |  |  |  | 4 | foreach $cap (@_) | 
| 690 |  |  |  |  |  |  | { | 
| 691 |  |  |  |  |  |  | push( @undefined, $cap ) | 
| 692 | 2 | 100 | 66 |  |  | 19 | unless defined $self->{ '_' . $cap } && $self->{ '_' . $cap }; | 
| 693 |  |  |  |  |  |  | } | 
| 694 | 2 | 100 |  |  |  | 12 | croak "Terminal does not support: (@undefined)" if @undefined; | 
| 695 |  |  |  |  |  |  | } | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | =back | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | =head1 EXAMPLES | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | use Term::Cap; | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | # Get terminal output speed | 
| 704 |  |  |  |  |  |  | require POSIX; | 
| 705 |  |  |  |  |  |  | my $termios = new POSIX::Termios; | 
| 706 |  |  |  |  |  |  | $termios->getattr; | 
| 707 |  |  |  |  |  |  | my $ospeed = $termios->getospeed; | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | # Old-style ioctl code to get ospeed: | 
| 710 |  |  |  |  |  |  | #     require 'ioctl.pl'; | 
| 711 |  |  |  |  |  |  | #     ioctl(TTY,$TIOCGETP,$sgtty); | 
| 712 |  |  |  |  |  |  | #     ($ispeed,$ospeed) = unpack('cc',$sgtty); | 
| 713 |  |  |  |  |  |  |  | 
| 714 |  |  |  |  |  |  | # allocate and initialize a terminal structure | 
| 715 |  |  |  |  |  |  | $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed }; | 
| 716 |  |  |  |  |  |  |  | 
| 717 |  |  |  |  |  |  | # require certain capabilities to be available | 
| 718 |  |  |  |  |  |  | $terminal->Trequire(qw/ce ku kd/); | 
| 719 |  |  |  |  |  |  |  | 
| 720 |  |  |  |  |  |  | # Output Routines, if $FH is undefined these just return the string | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | # Tgoto does the % expansion stuff with the given args | 
| 723 |  |  |  |  |  |  | $terminal->Tgoto('cm', $col, $row, $FH); | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | # Tputs doesn't do any % expansion. | 
| 726 |  |  |  |  |  |  | $terminal->Tputs('dl', $count = 1, $FH); | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | Copyright 1995-2015 (c) perl5 porters. | 
| 731 |  |  |  |  |  |  |  | 
| 732 |  |  |  |  |  |  | This software is free software and can be modified and distributed under | 
| 733 |  |  |  |  |  |  | the same terms as Perl itself. | 
| 734 |  |  |  |  |  |  |  | 
| 735 |  |  |  |  |  |  | Please see the file README in the Perl source distribution for details of | 
| 736 |  |  |  |  |  |  | the Perl license. | 
| 737 |  |  |  |  |  |  |  | 
| 738 |  |  |  |  |  |  | =head1 AUTHOR | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | This module is part of the core Perl distribution and is also maintained | 
| 741 |  |  |  |  |  |  | for CPAN by Jonathan Stowe . | 
| 742 |  |  |  |  |  |  |  | 
| 743 |  |  |  |  |  |  | The code is hosted on Github: https://github.com/jonathanstowe/Term-Cap | 
| 744 |  |  |  |  |  |  | please feel free to fork, submit patches etc, etc there. | 
| 745 |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  | termcap(5) | 
| 749 |  |  |  |  |  |  |  | 
| 750 |  |  |  |  |  |  | =cut | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | # Below is a default entry for systems where there are terminals but no | 
| 753 |  |  |  |  |  |  | # termcap | 
| 754 |  |  |  |  |  |  | 1; | 
| 755 |  |  |  |  |  |  | __DATA__ |