File Coverage

blib/lib/Term/Screen/Win32.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Term::Screen::Win32::CursorAndSize;
2 1     1   896 use 5.005;
  1         4  
  1         47  
3 1     1   6 use strict;
  1         3  
  1         40  
4 1     1   24 use warnings;
  1         2  
  1         36  
5            
6 1     1   6 use Carp;
  1         2  
  1         122  
7 1     1     use Win32::Console::ANSI;
  0            
  0            
8            
9             use Tie::Hash;
10             our @ISA = ('Tie::Hash');
11            
12             $|++;
13            
14             sub TIEHASH
15             {
16             my $storage = bless {}, $_[0];
17             return $storage;
18             }
19            
20             sub STORE
21             {
22             my $key = lc($_[1]);
23            
24             if ($key eq 'c')
25             { printf("\e[%d;%dH", (Win32::Console::ANSI::Cursor())[1], $_[2]+1); }
26             elsif ($key eq 'r')
27             { printf("\e[%d;%dH", $_[2]+1, (Win32::Console::ANSI::Cursor())[0]); }
28             elsif ($key eq 'cols')
29             {
30             if (!Win32::Console::ANSI::SetConsoleSize($_[2], (Win32::Console::ANSI::XYMax())[1]))
31             { croak 'Could not set console size: '.$^E; };
32             }
33             elsif ($key eq 'rows')
34             {
35             if (!Win32::Console::ANSI::SetConsoleSize((Win32::Console::ANSI::XYMax())[0], $_[2]))
36             { croak 'Could not set console size: '.$^E; };
37             }
38             else
39             { $_[0]{$_[1]} = $_[2]; };
40             };
41            
42             sub FETCH
43             {
44             my $key = lc($_[1]);
45            
46             if ($key eq 'c')
47             { return ((Win32::Console::ANSI::Cursor())[0] - 1); }
48             elsif ($key eq 'r')
49             { return ((Win32::Console::ANSI::Cursor())[1] - 1); }
50             elsif ($key eq 'cols')
51             { return (Win32::Console::ANSI::XYMax())[0]; }
52             elsif ($key eq 'rows')
53             { return (Win32::Console::ANSI::XYMax())[1]; }
54             else
55             { return $_[0]{$_[1]}; };
56             };
57            
58            
59             package Term::Screen::Win32;
60            
61             use 5.005;
62             use strict;
63             use warnings;
64            
65             use Carp;
66             use Win32::Console::ANSI;
67             use Win32::Console;
68            
69             require Exporter;
70            
71             our @ISA = qw(Exporter);
72            
73             # Items to export into callers namespace by default. Note: do not export
74             # names by default without a very good reason. Use EXPORT_OK instead.
75             # Do not simply export all your public functions/methods/constants.
76            
77             # This allows declaration use Term::Screen::Win32 ':all';
78             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
79             # will save memory.
80             our %EXPORT_TAGS = ( 'all' => [ qw(
81            
82             ) ] );
83            
84             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
85            
86             our @EXPORT = qw(
87            
88             );
89            
90             our $VERSION = '0.03';
91            
92            
93             # Preloaded methods go here.
94            
95             sub term
96             { croak 'This function is not supported on your platform ('.$^O.')'; };
97            
98             sub rows
99             { return $_[0]->{'rows'}; };
100            
101             sub cols
102             { return $_[0]->{'cols'}; };
103            
104             sub at
105             {
106             if (defined($_[1])) { $_[0]->{'r'} = $_[1]; };
107             if (defined($_[2])) { $_[0]->{'c'} = $_[2]; };
108             return $_[0];
109             };
110            
111             sub resize
112             {
113             if (defined($_[1])) { $_[0]->{'rows'} = $_[1]; };
114             if (defined($_[2])) { $_[0]->{'cols'} = $_[2]; };
115            
116             return ($_[0]->{'rows'}, $_[0]->{'cols'});
117             };
118            
119             sub normal { print "\e[0m"; return $_[0]; };
120             sub bold { print "\e[1m"; return $_[0]; };
121             sub reverse { print "\e[7m"; return $_[0]; };
122             sub clrscr { print "\e[2J"; return $_[0]; };
123             sub clreol { print "\e[0K"; return $_[0]; };
124             sub clreos { print "\e[0J"; return $_[0]; };
125             sub il { print "\e[".(defined($_[1]) ? $_[1] : 1).'L'; return $_[0]; };
126             sub dl { print "\e[".(defined($_[1]) ? $_[1] : 1).'M'; return $_[0]; };
127             sub ic_exists { return 1; };
128             sub ic { print "\e[".(defined($_[1]) ? $_[1] : 1).'\@'; return $_[0]; };
129             sub dc_exists { return 1; };
130             sub dc { print "\e[".(defined($_[1]) ? $_[1] : 1).'P'; return $_[0]; };
131             sub puts { my $this = shift; print(@_); return $this; };
132            
133             sub getch
134             {
135             key_pressed($_[0], 0);
136             return shift(@{$_[0]->{'key_pressed'}});
137             };
138            
139             sub def_key
140             { $_[0]->{'def_key'}{$_[1]} = $_[2]; };
141            
142             sub parseKeyEvent
143             {
144             if ($_[1]->[5] != 0)
145             { return chr($_[1]->[5]); };
146            
147             if (exists($_[0]->{'def_key'}{$_[1]->[3]}))
148             { return $_[0]->{'def_key'}{$_[1]->[3]}; };
149            
150             return 'noop';
151             };
152            
153             sub fetchKeyEvent
154             {
155             while($_[0]->{'console'}->GetEvents())
156             {
157             my @key_pressed = $_[0]->{'console'}->Input();
158             if (defined($key_pressed[0]) && ($key_pressed[0] == 1) && $key_pressed[1])
159             { return \@key_pressed; };
160             };
161             return undef;
162             };
163            
164             sub key_pressed
165             {
166             if (scalar(@{$_[0]->{'key_pressed'}}))
167             { return 1; };
168            
169             my $expTime = time() + (defined($_[1]) ? (($_[1] > 0) ? $_[1] : 999999) : -1);
170            
171             while(1)
172             {
173             my $keyEvent = fetchKeyEvent($_[0]);
174            
175             if (defined($keyEvent))
176             {
177             push(@{$_[0]->{'key_pressed'}}, parseKeyEvent($_[0], $keyEvent));
178             return 1;
179             };
180            
181             if (time() > $expTime)
182             { last; };
183            
184             sleep(0.02);
185             };
186             return 0;
187             };
188            
189             sub echo
190             { $_[0]->{'console'}->Mode($_[0]->{'console'}->Mode() | ENABLE_ECHO_INPUT); return $_[0]; };
191            
192             sub noecho
193             { $_[0]->{'console'}->Mode($_[0]->{'console'}->Mode() & (0xFFFF xor ENABLE_ECHO_INPUT)); return $_[0]; };
194            
195             sub flush_input
196             { while(key_pressed($_[0])) { getch($_[0]); }; return $_[0]; };
197            
198             sub stuff_input
199             { push(@{(shift(@_))->{'key_pressed'}}, @_); return $_[0]; };
200            
201             my %def_key = ( 16 => 'shift',
202             17 => 'ctrl',
203             18 => 'alt',
204             19 => 'pause',
205             20 => 'capslock',
206             33 => 'pgup',
207             34 => 'pgdn',
208             35 => 'end',
209             36 => 'home',
210             37 => 'kl',
211             38 => 'ku',
212             39 => 'kr',
213             40 => 'kd',
214             45 => 'ins',
215             46 => 'del',
216             91 => 'lwin',
217             92 => 'rwin',
218             93 => 'winmenu',
219             112 => 'k1',
220             113 => 'k2',
221             114 => 'k3',
222             115 => 'k4',
223             116 => 'k5',
224             117 => 'k6',
225             118 => 'k7',
226             119 => 'k8',
227             120 => 'k9',
228             121 => 'k10',
229             122 => 'k11',
230             123 => 'k12',
231             145 => 'scrlock',
232             144 => 'numlock',
233             );
234            
235            
236             sub new($%)
237             {
238             my ($class) = @_;
239            
240             my $self = undef;
241            
242             tie(%{$self}, 'Term::Screen::Win32::CursorAndSize');
243            
244             $self->{'key_pressed'} = [],
245             $self->{'def_key'} = {},
246             $self->{'console'} = Win32::Console->new(STD_INPUT_HANDLE),
247            
248             $self->{'origMode'} = $self->{'console'}->Mode();
249             $self->{'console'}->Mode(ENABLE_PROCESSED_INPUT);
250             at($self, 0, 0);
251            
252             %{$self->{'def_key'}} = %def_key;
253            
254             return bless $self => $class;
255             };
256            
257             sub cleanup
258             {
259             $_[0]->normal();
260             if (defined($_[0]->{'console'}))
261             { $_[0]->{'console'}->Mode($_[0]->{'origMode'}); };
262             };
263            
264             sub DESTROY
265             { cleanup(@_); };
266            
267            
268             1;
269             __END__