ffi-ncurses 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/COPYING +22 -0
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +13 -0
  4. data/History.txt +32 -3
  5. data/README.rdoc +118 -58
  6. data/Rakefile +30 -0
  7. data/examples/acs_chars.rb +53 -0
  8. data/examples/acs_chars.rbc +1502 -0
  9. data/examples/{example-attributes.rb → attributes.rb} +0 -0
  10. data/examples/color.rb +63 -0
  11. data/examples/cursor.rb +27 -0
  12. data/examples/example.rb +17 -17
  13. data/examples/getkey.rb +212 -0
  14. data/examples/{example-getsetsyx.rb → getsetsyx.rb} +2 -2
  15. data/examples/globals.rb +38 -0
  16. data/examples/hello.rb +34 -0
  17. data/examples/hello.rbc +638 -0
  18. data/examples/hellowide.rb +59 -0
  19. data/examples/keys.rb +27 -0
  20. data/examples/{example-mouse.rb → mouse.rb} +2 -2
  21. data/examples/multiterm.rb +120 -0
  22. data/examples/ncurses/LICENSES_for_examples +26 -0
  23. data/examples/{ncurses-example.rb → ncurses/example.rb} +13 -80
  24. data/examples/ncurses/hello_ncurses.rb +57 -0
  25. data/examples/ncurses/rain.rb +220 -0
  26. data/examples/ncurses/read_line.rb +67 -0
  27. data/examples/ncurses/subwin.rb +71 -0
  28. data/examples/ncurses/tclock.rb +227 -0
  29. data/examples/newterm.rb +65 -0
  30. data/examples/panel_simple.rb +82 -0
  31. data/examples/{example-printw-variadic.rb → printw-variadic.rb} +1 -1
  32. data/examples/ripoffline.rb +86 -0
  33. data/examples/run-all.sh +14 -0
  34. data/examples/{example-softkeys.rb → softkeys.rb} +0 -0
  35. data/examples/{example-stdscr.rb → stdscr.rb} +2 -1
  36. data/examples/temp_leave.rb +99 -0
  37. data/examples/viewer.rb +350 -0
  38. data/examples/wacs_chars.rb +64 -0
  39. data/examples/windows.rb +73 -0
  40. data/ffi-ncurses.gemspec +39 -52
  41. data/lib/ffi-ncurses.rb +214 -474
  42. data/lib/ffi-ncurses/acs.rb +150 -0
  43. data/lib/ffi-ncurses/bool_wrappers.rb +66 -0
  44. data/lib/ffi-ncurses/functions.rb +450 -0
  45. data/lib/ffi-ncurses/keydefs.rb +136 -99
  46. data/lib/ffi-ncurses/mouse.rb +106 -106
  47. data/lib/ffi-ncurses/ncurses.rb +176 -0
  48. data/lib/ffi-ncurses/{ord-shim.rb → ord_shim.rb} +0 -0
  49. data/lib/ffi-ncurses/panel.rb +21 -0
  50. data/lib/ffi-ncurses/typedefs.rb +35 -0
  51. data/lib/ffi-ncurses/version.rb +7 -0
  52. data/lib/ffi-ncurses/widechars.rb +137 -0
  53. data/lib/ffi-ncurses/winstruct.rb +55 -33
  54. data/spec/attached_functions_spec.rb +42 -0
  55. metadata +95 -85
  56. data/examples/example-colour.rb +0 -63
  57. data/examples/example-cursor.rb +0 -22
  58. data/examples/example-hello.rb +0 -24
  59. data/examples/example-jruby.rb +0 -14
  60. data/examples/example-keys.rb +0 -25
  61. data/examples/example-windows.rb +0 -24
data/COPYING ADDED
@@ -0,0 +1,22 @@
1
+ ffi-ncurses
2
+
3
+ Copyright (c) 2008-2011 Sean O'Halpin sean.ohalpin at gmail.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ source :rubygems
3
+
4
+ gem "ffi"
5
+ gem "ffi-locale"
@@ -0,0 +1,13 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ffi (1.0.9)
5
+ ffi-locale (1.0.0)
6
+ ffi (>= 1.0.9)
7
+
8
+ PLATFORMS
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ ffi
13
+ ffi-locale
@@ -1,3 +1,31 @@
1
+ = Changelog for ffi-ncurses
2
+
3
+ == 0.4.0 / 2011-09-25
4
+
5
+ * Supports all functions in ncursesw except the =vwprintw/vwscanw=
6
+ family.
7
+ * Added =ACS= constants (box characters). See =examples/acs.rb= and
8
+ =examples/wacs.rb=.
9
+ * Added support for =libpanelw=. See =examples/panel_simple.rb=.
10
+ * Better examples. See =examples/viewer.rb= for a simple but complete
11
+ file viewing application.
12
+ * Methods with boolean arguments now =true= or =false= as well as 1 or
13
+ 0.
14
+ * Start of a compatibility layer for the existing C extension-based
15
+ Ncurses Ruby libraries - require 'ffi-ncurses/ncurses'. Runs all
16
+ the examples from ncurses-ruby without changes (except those relying
17
+ on menus and forms). See =examples/ncurses/*.rb=.
18
+ * Sets the locale (using FFI::Locale.setlocale(LC_ALL, "")) in ruby
19
+ 1.8.x to enable UTF-8 input. See =examples/getkey.rb= to see how to
20
+ distinguish between function keys and Unicode characters.
21
+
22
+ == 0.3.4 / 2010-08-28
23
+
24
+ * Added MIT licence (License.txt, COPYING)
25
+ * Bumped version
26
+ * Added nested PDat struct to WinStruct
27
+ * Reformatted comments for rocco
28
+
1
29
  == 0.3.3 / 2010-08-24
2
30
 
3
31
  * Depends on ffi again (>= 0.6.3)
@@ -7,16 +35,17 @@
7
35
  * Included keydefs.rb by default
8
36
  * Examples have been tested with:
9
37
  - jruby-1.5.1
10
- - rbx-1.0.0-20100514
11
38
  - ree-1.8.7-2010.02
12
39
  - ruby-1.8.6-p399
13
40
  Note: the examples require "ffi-ncurses/ord-shim" to add
14
41
  Integer#ord
15
- - ruby-1.8.7-p299
42
+ - ruby-1.8.7-p302
16
43
  - ruby-1.9.2-p0
44
+ * Sadly not compatible with Rubinius (rbx-1.0.0-20100514)
17
45
  * Removed attempt to load XCurses (PDCurses)
18
46
  * Removed dependency on bones
19
- - no Rakefile any more - just use gem build ffi-ncurses.gemspec
47
+ - no Rakefile any more - just use
48
+ gem build ffi-ncurses.gemspec
20
49
 
21
50
  == 0.3.2 / 2009-02-16
22
51
 
@@ -2,34 +2,67 @@
2
2
 
3
3
  Author: Sean O'Halpin
4
4
 
5
- A wrapper for ncurses 5.x. Tested on Ubuntu 8.04 to 10.04 and Mac OS X
6
- 10.4 (Tiger) with ruby 1.8.6, 1.8.7 and 1.9.x using ffi (>= 0.6.3) and
7
- JRuby 1.5.1.
5
+ A pure-ruby wrapper for {http://invisible-island.net/ncurses/ ncursesw
6
+ 5.x} using the {https://github.com/ffi/ffi ffi} library.
7
+
8
+ All of the core ncursesw functions are supported along with the Panel
9
+ library. The main things left to do are support for the Menu and Form
10
+ libraries.
8
11
 
9
12
  The API is a transliteration of the C API rather than an attempt to
10
13
  provide an idiomatic Ruby object-oriented API. The intent is to
11
14
  provide a 'close to the metal' wrapper around the ncurses library upon
12
15
  which you can build your own abstractions.
13
16
 
14
- This is still very much a work-in-progress, so expect some rough
15
- edges. Having said that, you can do quite a lot with it as it is. The
16
- main things left to be done are tests, access to global variables and
17
- various macros.
17
+ Please note that this documentation does not cover individual
18
+ ncursesw methods. For that you'll need to refer to existing
19
+ ncursesw documentation. For example, to find out about +addstr+,
20
+ use:
21
+
22
+ $ man addstr
23
+
24
+ One benefit of using a minimal wrapper approach is that you can use
25
+ existing examples and man pages to find out how to use the library. To
26
+ get an overview of ncurses, use:
27
+
28
+ $ man ncurses
29
+
30
+ Having said that, this release also includes a wrapper that emulates
31
+ the existing Ncurses library API. To use it, substitute
32
+
33
+ require 'ffi-ncurses/ncurses'
34
+
35
+ for
36
+
37
+ require 'ncurses'
18
38
 
19
- Below are some very preliminary notes on usage. See the examples
20
- directory for real working examples.
39
+ or create a file called 'ncurses.rb' on your +$LOAD_PATH+ ($:) that
40
+ requires +ffi-ncurses/ncurses.rb+.
21
41
 
22
- == Install
42
+ Below you'll find some very preliminary notes on usage. See the
43
+ examples directory for real working examples, which among other things
44
+ show how to input and output UTF-8, deal with pointers and handle wide
45
+ characters.
23
46
 
24
- ruby 1.8.x:
47
+ This version of ffi-ncurses defaults to loading ncursesw, the 'wide
48
+ character' version which supports UTF-8 and double width characters.
25
49
 
26
- $ sudo gem install ffi-ncurses
50
+ Tested on Ubuntu 10.04 with ruby1.8.7 and 1.9.2 using ffi (>= 0.6.3)
51
+ and JRuby 1.6.4 (head). A previous version of the library was tested
52
+ on Mac OS X 10.04. Please let me know if anything has stopped working.
27
53
 
28
- jruby 1.5.1:
54
+ Rubinius is not supported as its FFI does not provide the required
55
+ API, especially for dealing with buffers and pointers.
29
56
 
30
- $ jruby -S gem install ffi-ncurses
57
+ This is still very much a work-in-progress, so expect some rough edges
58
+ (and please {https://github.com/seanohalpin/ffi-ncurses/issues report
59
+ them}). Having said that, you can do quite a lot with it as it is.
31
60
 
32
- == Usage
61
+ = Install
62
+
63
+ $ [sudo] gem install ffi-ncurses
64
+
65
+ = Usage
33
66
 
34
67
  Load the library with:
35
68
 
@@ -38,7 +71,7 @@ Load the library with:
38
71
  FFI::NCurses methods can be called as module methods:
39
72
 
40
73
  begin
41
- stdscr = FFI::NCurses.initscr
74
+ FFI::NCurses.initscr
42
75
  FFI::NCurses.clear
43
76
  FFI::NCurses.addstr("Hello world!")
44
77
  FFI::NCurses.refresh
@@ -49,15 +82,13 @@ FFI::NCurses methods can be called as module methods:
49
82
 
50
83
  or as included methods:
51
84
 
52
- require 'ffi-ncurses'
53
85
  include FFI::NCurses
86
+
54
87
  begin
55
- stdscr = initscr
56
- start_color
57
- curs_set 0
58
- raw
88
+ initscr
59
89
  cbreak
60
90
  noecho
91
+ curs_set 0
61
92
  clear
62
93
  move 10, 10
63
94
  standout
@@ -82,22 +113,23 @@ or as included methods:
82
113
 
83
114
  == Typical initialization
84
115
 
85
- stdscr = FFI::NCurses.initscr
116
+ FFI::NCurses.initscr
86
117
  FFI::NCurses.start_color
87
118
  FFI::NCurses.curs_set 0
88
119
  FFI::NCurses.raw
89
- FFI::NCurses.cbreak
90
120
  FFI::NCurses.noecho
91
- FFI::NCurses.keypad(stdscr, true)
121
+ FFI::NCurses.keypad(FFI::NCurses.stdscr, true)
92
122
 
93
123
  == Colours
94
124
 
95
125
  start_color
96
126
  init_pair(1, FFI::NCurses::COLOR_BLACK, FFI::NCurses::COLOR_RED)
97
127
  attr_set FFI::NCurses::A_NORMAL, 1, nil
98
- addch("A"[0].ord) # works in both 1.8.x and 1.9.x
128
+ addch("A"[0].ord) # works in both 1.8.7 and 1.9.x
99
129
  addch("Z"[0].ord | COLOR_PAIR(1))
100
130
 
131
+ See +examples/color.rb+ for an example of use.
132
+
101
133
  == Cursor
102
134
 
103
135
  === Turn cursor off
@@ -123,25 +155,30 @@ or as included methods:
123
155
  ch = wgetch(inner_win)
124
156
  delwin(win)
125
157
 
126
- rescue Object => e
158
+ rescue => e
127
159
  FFI::NCurses.endwin
128
- puts e
160
+ raise
129
161
  ensure
130
162
  FFI::NCurses.endwin
131
163
  end
132
164
 
133
- == Mouse handling
165
+ == Panels
134
166
 
135
- The ncurses mouse API is defined in a separate file. To include it use:
167
+ See +examples/panel_simple.rb+ for how to use panels.
168
+
169
+ == Mouse handling
136
170
 
137
- require 'ffi-ncurses/mouse'
171
+ NOTE: In previous versions of ffi-ncurses, the ncurses mouse API was
172
+ included separately. You now no longer need to <tt>require
173
+ 'ffi-ncurses/mouse'</tt> to get mouse support.
138
174
 
139
- You need to specify that you want keypad translation with:
175
+ To use the mouse with ffi-ncurses, you first need to specify that you
176
+ want keypad translation with:
140
177
 
141
- keypad stdscr, FFI::NCurses::TRUE
178
+ keypad stdscr, true
142
179
 
143
180
  otherwise your program will receive the raw mouse escape codes,
144
- instead of KEY_MOUSE mouse event codes.
181
+ instead of +KEY_MOUSE+ mouse event codes.
145
182
 
146
183
  Specify which events you want to handle with:
147
184
 
@@ -169,31 +206,63 @@ or
169
206
 
170
207
  if FFI::NCurses.BUTTON_PRESS(mouse_event[:bstate], 1)
171
208
 
172
- The possible button states are: PRESS, RELEASE, CLICK, DOUBLE_CLICK
173
- and TRIPLE_CLICK.
209
+ The possible button states are: +PRESS+, +RELEASE+, +CLICK+,
210
+ +DOUBLE_CLICK+ and +TRIPLE_CLICK+.
174
211
 
175
- = Experimental stuff
212
+ See +examples/mouse.rb+ for a complete example.
176
213
 
177
214
  == Specifying which curses library to use
178
215
 
179
216
  You can specify which variant of curses you want to use by setting the
180
217
  environment variable +RUBY_FFI_NCURSES_LIB+ to the one you want. For
181
- example, to use PDCurses X11 curses lib, use:
218
+ example, to use the PDCurses X11 curses lib, use:
219
+
220
+ RUBY_FFI_NCURSES_LIB=XCurses ruby examples/example.rb
221
+
222
+ You could also use this to specify ncursesw-dbg for example to get
223
+ access to the +trace+ functions.
224
+
225
+ = Examples
226
+
227
+ +examples/acs_chars.rb+ :: How to display box drawing characters
228
+ +examples/attributes.rb+ :: How to set attributes
229
+ +examples/color.rb+ :: How to initialize and use colour
230
+ +examples/cursor.rb+ :: How to turn the cursor on and off
231
+ +examples/doc-eg1.rb+ :: Example 1 from the documentation
232
+ +examples/doc-eg2.rb+ :: Example 2 from the documentation
233
+ +examples/doc-eg3.rb+ :: Example 3 from the documentation
234
+ +examples/example.rb+ :: An example showing off the main features of ncurses
235
+ +examples/getkey.rb+ :: How to get Unicode input
236
+ +examples/getsetsyx.rb+ :: Shows how to use the getsetyx function
237
+ +examples/globals.rb+ :: Display ncurses global variables
238
+ +examples/hello.rb+ :: Hello world
239
+ +examples/hellowide.rb+ :: Hello world using wide characters
240
+ +examples/keys.rb+ :: How to use the getch function. See getkey for a more general solution
241
+ +examples/mouse.rb+ :: How to use the mouse
242
+ +examples/multiterm.rb+ :: How to display on more than one tty
243
+ +examples/newterm.rb+ :: How to use +newterm+ so you can pipe stdin into an ncurses program
244
+ +examples/panel_simple.rb+ :: How to use panels
245
+ +examples/printw-variadic.rb+:: How to call the +printw+ method
246
+ +examples/ripoffline.rb+ :: An example of the +ripoffline+ method
247
+ +examples/softkeys.rb+ :: How to set up soft keys (function key labels)
248
+ +examples/stdscr.rb+ :: Shows that +initscr+ returns same value as +stdscr+
249
+ +examples/temp_leave.rb+ :: How to temporarily shell out from an ncurses program
250
+ +examples/viewer.rb+ :: A simple file viewer (lesser than less) that shows how to use pads and pop up windows
251
+ +examples/wacs_chars.rb+ :: How to display wide (Unicode) box drawing characters
252
+ +examples/windows.rb+ :: Move a window about the screen
253
+
254
+ = Issues
255
+
256
+ Please report any issues on the {https://github.com/seanohalpin/ffi-ncurses/issues github issues} page.
182
257
 
183
- RUBY_FFI_NCURSES_LIB=XCurses ruby examples/hello.rb
258
+ = Trivia
184
259
 
185
- You can use this to specify +ncursesw+ for example. Please note that
186
- only the bog standard ncurses lib has been in any way tested as of
187
- yet.
260
+ While researching ncurses on Google, I innocently entered "curses
261
+ getsx" as a search term. NSFW and definitely not one for "I'm Feeling
262
+ Lucky".
188
263
 
189
264
  = TO DO
190
265
 
191
- == Complete translation of core functions to Darwin (Mac OS X)
192
-
193
- There are some macros in darwin ncurses.h which I haven't
194
- implemented yet. I'm working on it but if there are any you
195
- desperately need let me know.
196
-
197
266
  == Tests
198
267
 
199
268
  This is tricky - I'm not sure exactly how to properly test a wrapper
@@ -209,17 +278,8 @@ the output. However, this is not really ready for prime time yet.
209
278
  Things got a bit messy as I switched between the Linux and Mac
210
279
  versions. The examples should be more focussed.
211
280
 
212
- == Scope implementation of Menu and Form interface wrappers
281
+ = Credits
213
282
 
214
- I'm not particularly interested in the ncurses extension libraries for
215
- forms and menus. I would rather spend time implementing similar
216
- functionality on top of a portable text console library (or porting
217
- rbcurses). However, in the interests of completeness, I suppose I
218
- ought to at least scope it out.
219
-
220
- = Trivia
283
+ Thanks to rahul and manveru for their support!
221
284
 
222
- While researching ncurses on Google, I innocently entered "curses
223
- getsx" as a search term. NSFW and definitely not one for "I'm Feeling
224
- Lucky".
225
285
 
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
+
4
+ require 'ffi-ncurses/version'
5
+ project = FFI::NCurses
6
+
7
+ require 'rake/testtask'
8
+ require 'yard'
9
+
10
+ Rake::TestTask.new(:spec) do |spec|
11
+ spec.pattern = 'spec/**/*_spec.rb'
12
+ end
13
+
14
+ task :default => %w(spec)
15
+
16
+ YARD::Rake::YardocTask.new do |t|
17
+ t.files = ['lib/**/*.rb']
18
+ t.options = %w[--readme README.rdoc]
19
+ end
20
+
21
+ desc "Build #{project::NAME}-#{project::VERSION} gem"
22
+ task :gem do
23
+ system "gem build #{project::NAME}.gemspec"
24
+ end
25
+
26
+ desc "Push #{project::NAME}-#{project::VERSION} gem to rubygems.org"
27
+ task :release => :gem do
28
+ system "gem push #{project::NAME}-#{project::VERSION}.gem"
29
+ end
30
+
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8; -*-
3
+ require 'ffi-ncurses'
4
+
5
+ include FFI::NCurses
6
+
7
+ def main
8
+ begin
9
+ initscr
10
+
11
+ addstr("Upper left corner "); addch(ACS_ULCORNER); addstr("\n");
12
+ addstr("Lower left corner "); addch(ACS_LLCORNER); addstr("\n");
13
+ addstr("Lower right corner "); addch(ACS_LRCORNER); addstr("\n");
14
+ addstr("Tee pointing right "); addch(ACS_LTEE); addstr("\n");
15
+ addstr("Tee pointing left "); addch(ACS_RTEE); addstr("\n");
16
+ addstr("Tee pointing up "); addch(ACS_BTEE); addstr("\n");
17
+ addstr("Tee pointing down "); addch(ACS_TTEE); addstr("\n");
18
+ addstr("Horizontal line "); addch(ACS_HLINE); addstr("\n");
19
+ addstr("Vertical line "); addch(ACS_VLINE); addstr("\n");
20
+ addstr("Large Plus or cross over "); addch(ACS_PLUS); addstr("\n");
21
+ addstr("Scan Line 1 "); addch(ACS_S1); addstr("\n");
22
+ addstr("Scan Line 3 "); addch(ACS_S3); addstr("\n");
23
+ addstr("Scan Line 7 "); addch(ACS_S7); addstr("\n");
24
+ addstr("Scan Line 9 "); addch(ACS_S9); addstr("\n");
25
+ addstr("Diamond "); addch(ACS_DIAMOND); addstr("\n");
26
+ addstr("Checker board (stipple) "); addch(ACS_CKBOARD); addstr("\n");
27
+ addstr("Degree Symbol "); addch(ACS_DEGREE); addstr("\n");
28
+ addstr("Plus/Minus Symbol "); addch(ACS_PLMINUS); addstr("\n");
29
+ addstr("Bullet "); addch(ACS_BULLET); addstr("\n");
30
+ addstr("Arrow Pointing Left "); addch(ACS_LARROW); addstr("\n");
31
+ addstr("Arrow Pointing Right "); addch(ACS_RARROW); addstr("\n");
32
+ addstr("Arrow Pointing Down "); addch(ACS_DARROW); addstr("\n");
33
+ addstr("Arrow Pointing Up "); addch(ACS_UARROW); addstr("\n");
34
+ addstr("Board of squares "); addch(ACS_BOARD); addstr("\n");
35
+ addstr("Lantern Symbol "); addch(ACS_LANTERN); addstr("\n");
36
+ addstr("Solid Square Block "); addch(ACS_BLOCK); addstr("\n");
37
+ addstr("Less/Equal sign "); addch(ACS_LEQUAL); addstr("\n");
38
+ addstr("Greater/Equal sign "); addch(ACS_GEQUAL); addstr("\n");
39
+ addstr("Pi "); addch(ACS_PI); addstr("\n");
40
+ addstr("Not equal "); addch(ACS_NEQUAL); addstr("\n");
41
+ addstr("UK pound sign "); addch(ACS_STERLING); addstr("\n");
42
+
43
+ refresh
44
+ getch
45
+ rescue => e
46
+ endwin
47
+ raise
48
+ ensure
49
+ endwin
50
+ end
51
+ end
52
+
53
+ main