rbcurse-core 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/README.md +69 -0
  2. data/VERSION +1 -0
  3. data/examples/abasiclist.rb +151 -0
  4. data/examples/alpmenu.rb +46 -0
  5. data/examples/app.sample +17 -0
  6. data/examples/atree.rb +100 -0
  7. data/examples/common/file.rb +45 -0
  8. data/examples/data/README.markdown +9 -0
  9. data/examples/data/brew.txt +38 -0
  10. data/examples/data/color.2 +37 -0
  11. data/examples/data/gemlist.txt +60 -0
  12. data/examples/data/lotr.txt +12 -0
  13. data/examples/data/ports.txt +136 -0
  14. data/examples/data/table.txt +37 -0
  15. data/examples/data/tasks.csv +88 -0
  16. data/examples/data/tasks.txt +27 -0
  17. data/examples/data/todo.txt +10 -0
  18. data/examples/data/todocsv.csv +28 -0
  19. data/examples/data/unix1.txt +21 -0
  20. data/examples/data/unix2.txt +11 -0
  21. data/examples/dbdemo.rb +487 -0
  22. data/examples/dirtree.rb +90 -0
  23. data/examples/newtabbedwindow.rb +100 -0
  24. data/examples/newtesttabp.rb +92 -0
  25. data/examples/tabular.rb +132 -0
  26. data/examples/tasks.rb +167 -0
  27. data/examples/term2.rb +83 -0
  28. data/examples/testkeypress.rb +72 -0
  29. data/examples/testlistbox.rb +158 -0
  30. data/examples/testmessagebox.rb +140 -0
  31. data/examples/testree.rb +106 -0
  32. data/examples/testwsshortcuts.rb +66 -0
  33. data/examples/testwsshortcuts2.rb +127 -0
  34. data/lib/rbcurse.rb +8 -0
  35. data/lib/rbcurse/core/docs/index.txt +73 -0
  36. data/lib/rbcurse/core/include/action.rb +40 -0
  37. data/lib/rbcurse/core/include/appmethods.rb +112 -0
  38. data/lib/rbcurse/core/include/bordertitle.rb +41 -0
  39. data/lib/rbcurse/core/include/chunk.rb +182 -0
  40. data/lib/rbcurse/core/include/io.rb +953 -0
  41. data/lib/rbcurse/core/include/listcellrenderer.rb +140 -0
  42. data/lib/rbcurse/core/include/listeditable.rb +317 -0
  43. data/lib/rbcurse/core/include/listscrollable.rb +590 -0
  44. data/lib/rbcurse/core/include/listselectable.rb +264 -0
  45. data/lib/rbcurse/core/include/multibuffer.rb +83 -0
  46. data/lib/rbcurse/core/include/orderedhash.rb +77 -0
  47. data/lib/rbcurse/core/include/ractionevent.rb +67 -0
  48. data/lib/rbcurse/core/include/rchangeevent.rb +27 -0
  49. data/lib/rbcurse/core/include/rhistory.rb +62 -0
  50. data/lib/rbcurse/core/include/rinputdataevent.rb +47 -0
  51. data/lib/rbcurse/core/include/vieditable.rb +170 -0
  52. data/lib/rbcurse/core/system/colormap.rb +163 -0
  53. data/lib/rbcurse/core/system/keyboard.rb +150 -0
  54. data/lib/rbcurse/core/system/keydefs.rb +30 -0
  55. data/lib/rbcurse/core/system/ncurses.rb +218 -0
  56. data/lib/rbcurse/core/system/panel.rb +162 -0
  57. data/lib/rbcurse/core/system/window.rb +901 -0
  58. data/lib/rbcurse/core/util/ansiparser.rb +117 -0
  59. data/lib/rbcurse/core/util/app.rb +1235 -0
  60. data/lib/rbcurse/core/util/basestack.rb +407 -0
  61. data/lib/rbcurse/core/util/bottomline.rb +1850 -0
  62. data/lib/rbcurse/core/util/colorparser.rb +71 -0
  63. data/lib/rbcurse/core/util/focusmanager.rb +31 -0
  64. data/lib/rbcurse/core/util/padreader.rb +189 -0
  65. data/lib/rbcurse/core/util/rcommandwindow.rb +587 -0
  66. data/lib/rbcurse/core/util/rdialogs.rb +619 -0
  67. data/lib/rbcurse/core/util/viewer.rb +149 -0
  68. data/lib/rbcurse/core/util/widgetshortcuts.rb +505 -0
  69. data/lib/rbcurse/core/widgets/applicationheader.rb +102 -0
  70. data/lib/rbcurse/core/widgets/box.rb +58 -0
  71. data/lib/rbcurse/core/widgets/divider.rb +310 -0
  72. data/lib/rbcurse/core/widgets/keylabelprinter.rb +178 -0
  73. data/lib/rbcurse/core/widgets/rcombo.rb +238 -0
  74. data/lib/rbcurse/core/widgets/rcontainer.rb +415 -0
  75. data/lib/rbcurse/core/widgets/rlink.rb +30 -0
  76. data/lib/rbcurse/core/widgets/rlist.rb +723 -0
  77. data/lib/rbcurse/core/widgets/rmenu.rb +939 -0
  78. data/lib/rbcurse/core/widgets/rmenulink.rb +22 -0
  79. data/lib/rbcurse/core/widgets/rmessagebox.rb +373 -0
  80. data/lib/rbcurse/core/widgets/rprogress.rb +118 -0
  81. data/lib/rbcurse/core/widgets/rtabbedpane.rb +615 -0
  82. data/lib/rbcurse/core/widgets/rtabbedwindow.rb +68 -0
  83. data/lib/rbcurse/core/widgets/rtextarea.rb +920 -0
  84. data/lib/rbcurse/core/widgets/rtextview.rb +780 -0
  85. data/lib/rbcurse/core/widgets/rtree.rb +787 -0
  86. data/lib/rbcurse/core/widgets/rwidget.rb +3040 -0
  87. data/lib/rbcurse/core/widgets/scrollbar.rb +143 -0
  88. data/lib/rbcurse/core/widgets/statusline.rb +94 -0
  89. data/lib/rbcurse/core/widgets/tabular.rb +264 -0
  90. data/lib/rbcurse/core/widgets/tabularwidget.rb +1211 -0
  91. data/lib/rbcurse/core/widgets/textpad.rb +516 -0
  92. data/lib/rbcurse/core/widgets/tree/treecellrenderer.rb +150 -0
  93. data/lib/rbcurse/core/widgets/tree/treemodel.rb +428 -0
  94. metadata +156 -0
@@ -0,0 +1,150 @@
1
+ module VER
2
+ module Keyboard # avoid initialize
3
+ ESC = 27 # keycode
4
+ @polling = false
5
+
6
+ module_function
7
+
8
+ def focus=(receiver)
9
+ @stack = []
10
+ @focus = receiver
11
+ poll unless @polling
12
+ end
13
+
14
+ def poll
15
+ @polling = true
16
+
17
+ while char = @focus.window.getch
18
+ break if @focus.stopping? # XXX
19
+ #break if VER.stopping?
20
+ $log.debug("char: #{char} stakc: #{@stack.inspect}") if char != Ncurses::ERR
21
+ if char == Ncurses::ERR # timeout or signal
22
+ @focus.press('esc') if @stack == [ESC]
23
+ @stack.clear
24
+ elsif ready = resolve(char)
25
+ $log.debug("char: #{char} ready: #{ready}")
26
+ @stack.clear
27
+ @focus.press(ready)
28
+ end
29
+ end
30
+
31
+ ensure
32
+ @polling = false
33
+ end
34
+
35
+ def resolve(char)
36
+ @stack << char
37
+
38
+ if @stack.first == ESC
39
+ MOD_KEYS[@stack] || SPECIAL_KEYS[@stack]
40
+ else
41
+ NCURSES_KEYS[char] || CONTROL_KEYS[char] || PRINTABLE_KEYS[char]
42
+ end
43
+ end
44
+
45
+ # TODO: make this section sane
46
+
47
+ ASCII = (0..255).map{|c| c.chr }
48
+ CONTROL = ASCII.grep(/[[:cntrl:]]/)
49
+ PRINTABLE = ASCII.grep(/[[:print:]]/)
50
+
51
+ SPECIAL_KEYS = {
52
+ [27, 79, 50, 81] => 'F14',
53
+ [27, 79, 50, 82] => 'F15',
54
+ [27, 79, 70] => 'end',
55
+ [27, 79, 70] => 'end',
56
+ [27, 79, 72] => 'home',
57
+ [27, 79, 80] => 'F1',
58
+ [27, 79, 81] => 'F2',
59
+ [27, 79, 82] => 'F3',
60
+ [27, 79, 83] => 'F4',
61
+ [27, 91, 49, 126] => 'end',
62
+ [27, 91, 49, 126] => 'home',
63
+ [27, 91, 49, 49, 126] => 'F1',
64
+ [27, 91, 49, 50, 126] => 'F2',
65
+ [27, 91, 49, 51, 126] => 'F3',
66
+ [27, 91, 49, 52, 126] => 'F4',
67
+ [27, 91, 49, 52, 126] => 'F4',
68
+ [27, 91, 49, 53, 126] => 'F5',
69
+ [27, 91, 49, 55, 126] => 'F6',
70
+ [27, 91, 49, 56, 59, 50, 126] => 'F19',
71
+ [27, 91, 49, 56, 59, 51, 126] => 'F7',
72
+ [27, 91, 49, 59, 51, 65] => 'ppage',
73
+ [27, 91, 49, 59, 51, 66] => 'npage',
74
+ [27, 91, 49, 59, 53, 65] => 'ppage',
75
+ [27, 91, 49, 59, 53, 66] => 'npage',
76
+ [27, 91, 49, 59, 53, 70] => 'M-<',
77
+ [27, 91, 49, 59, 53, 72] => 'M->',
78
+ [27, 91, 50, 54, 126] => 'F14',
79
+ [27, 91, 50, 56, 126] => 'F15',
80
+ [27, 91, 51, 59, 51, 126] => 'del',
81
+ [27, 91, 52, 126] => 'end',
82
+ [27, 91, 55, 126] => 'home',
83
+ [27, 91, 55, 126] => 'home',
84
+ [27, 91, 56, 126] => 'end',
85
+ [27, 91, 56, 126] => 'end',
86
+ [27, 91, 65] => 'up',
87
+ [27, 91, 66] => 'down',
88
+ [27, 91, 67] => 'right',
89
+ [27, 91, 68] => 'left',
90
+ [27, 91, 70] => 'end',
91
+ [27, 91, 72] => 'end',
92
+ [27, 91, 72] => 'home',
93
+ [27, 91, 91, 65] => 'F1',
94
+ [27, 91, 91, 66] => 'F2',
95
+ [27, 91, 91, 67] => 'F3',
96
+ [27, 91, 91, 68] => 'F4',
97
+ [27, 91, 91, 69] => 'F5',
98
+ }
99
+
100
+ CONTROL_KEYS = {
101
+ 0 => 'C-space',
102
+ 1 => 'C-a',
103
+ 2 => 'C-b',
104
+ 3 => 'C-c',
105
+ 4 => 'C-d',
106
+ 5 => 'C-e',
107
+ 6 => 'C-f',
108
+ 7 => 'C-g',
109
+ 8 => 'C-h',
110
+ 9 => 'tab',
111
+ 10 => 'return', # C-j
112
+ 11 => 'C-k',
113
+ 12 => 'C-l',
114
+ 13 => 'return', # C-m
115
+ 14 => 'C-n',
116
+ 15 => 'C-o',
117
+ 16 => 'C-p',
118
+ 17 => 'C-q',
119
+ 18 => 'C-r',
120
+ 19 => 'C-s',
121
+ 20 => 'C-t',
122
+ 21 => 'C-u',
123
+ 22 => 'C-v',
124
+ 23 => 'C-w',
125
+ 24 => 'C-x',
126
+ 25 => 'C-y',
127
+ 26 => 'C-z', # FIXME: is usually suspend in shell job control
128
+ # 27 => 'esc',
129
+ 32 => 'space',
130
+ 127 => 'backspace',
131
+ }
132
+
133
+ PRINTABLE_KEYS = {}
134
+ MOD_KEYS = {}
135
+
136
+ PRINTABLE.each do |key|
137
+ code = key.unpack('c')[0] # using unpack to be compatible with 1.9
138
+ PRINTABLE_KEYS[code] = key
139
+ MOD_KEYS[[ESC, code]] = "M-#{key}" unless key == '[' # don't map esc
140
+ end
141
+
142
+ NCURSES_KEYS = {}
143
+ Ncurses.constants.grep(/^KEY_/).each do |const|
144
+ value = Ncurses.const_get(const)
145
+ key = const[/^KEY_(.*)/, 1]
146
+ key = key =~ /^F/ ? key : key.downcase # function keys
147
+ NCURSES_KEYS[value] = key
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,30 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: keydefs.rb
3
+ # Description: Some common keys used in app. Earlier part of rwidget.rb
4
+ # Author: rkumar http://github.com/rkumar/rbcurse/
5
+ # Date: 08.11.11 - 14:57
6
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
7
+ # Last update: 08.11.11 - 14:57
8
+ # ----------------------------------------------------------------------------- #
9
+ #
10
+
11
+ # some common definition that we use throughout app. Do not add more, only what is common.
12
+ # I should not have added Sh-F9 and C-left since they are rare, but only to show they exist.
13
+ #
14
+ KEY_TAB = 9
15
+ KEY_F1 = FFI::NCurses::KEY_F1
16
+ KEY_F10 = FFI::NCurses::KEY_F10
17
+ KEY_ENTER = 13 # FFI::NCurses::KEY_ENTER gives 343
18
+ KEY_RETURN = 10 # FFI gives 10 too
19
+ KEY_BTAB = 353 # nc gives same
20
+ KEY_DELETE = 330
21
+ KEY_BACKSPACE = KEY_BSPACE = 127 # Nc gives 263 for BACKSPACE
22
+ KEY_CC = 3 # C-c
23
+ KEY_LEFT = FFI::NCurses::KEY_LEFT
24
+ KEY_RIGHT = FFI::NCurses::KEY_RIGHT
25
+ KEY_UP = FFI::NCurses::KEY_UP
26
+ KEY_DOWN = FFI::NCurses::KEY_DOWN
27
+ C_LEFT = 18168
28
+ C_RIGHT = 18167
29
+ S_F9 = 17949126
30
+ META_KEY = 128
@@ -0,0 +1,218 @@
1
+ require 'ffi-ncurses'
2
+ #include FFI::NCurses # this pollutes many objects and invalidates method_missing
3
+ module VER
4
+ module_function
5
+
6
+ # Setup ncurses, nicely documented by the curses manpages
7
+ def start_ncurses
8
+ return if $ncurses_started
9
+ $ncurses_started = true
10
+ # The initscr code determines the terminal type and initializes all curses
11
+ # data structures.
12
+ # initscr also causes the first call to refresh to clear the screen.
13
+ # If errors occur, initscr writes an appropriate error message to standard
14
+ # error and exits; otherwise, a pointer is returned to stdscr.
15
+ stdscr = Ncurses.initscr ## FFI
16
+
17
+ # Color.start if Ncurses.has_colors?
18
+ Ncurses.start_color();
19
+ ColorMap.setup # added by RK 2008-11-30 00:48
20
+ # The keypad option enables the keypad of the user's terminal.
21
+ # If enabled (bf is TRUE), the user can press a function key (such as an
22
+ # arrow key) and wgetch returns a single value representing the function
23
+ # key, as in KEY_LEFT.
24
+ # If disabled (bf is FALSE), curses does not treat function keys specially
25
+ # and the program has to interpret the escape sequences itself.
26
+ # If the keypad in the terminal can be turned on (made to transmit) and off
27
+ # (made to work locally), turning on this option causes the terminal keypad
28
+ # to be turned on when wgetch is called.
29
+ # The default value for keypad is false.
30
+ Ncurses.keypad(stdscr.pointer, bf = true) # FFIWINDOW
31
+ #Ncurses.keypad(stdscr, bf = true)
32
+ #Ncurses.stdscr.keypad(true) # turn on keypad mode FFI
33
+ #Ncurses.keypad(stdscr, bf = 1)
34
+
35
+ # The nl and nonl routines control whether the underlying display device
36
+ # translates the return key into newline on input, and whether it
37
+ # translates newline into return and line-feed on output (in either case,
38
+ # the call addch('\n') does the equivalent of return and line feed on the
39
+ # virtual screen).
40
+ # Initially, these translations do occur.
41
+ # If you disable them using nonl, curses will be able to make better use of
42
+ # the line-feed capability, resulting in faster cursor motion.
43
+ # Also, curses will then be able to detect the return key.
44
+ Ncurses.nonl
45
+
46
+ # The raw and noraw routines place the terminal into or out of raw mode.
47
+ # Raw mode is similar to cbreak mode, in that characters typed are
48
+ # immediately passed through to the user program.
49
+ # The differences are that in raw mode, the interrupt, quit, suspend, and
50
+ # flow control characters are all passed through uninterpreted, instead of
51
+ # generating a signal.
52
+ # The behavior of the BREAK key depends on other bits in the tty driver
53
+ # that are not set by curses.
54
+ Ncurses.raw
55
+
56
+ # Normally, the tty driver buffers typed characters until a newline or
57
+ # carriage return is typed.
58
+ # The cbreak routine disables line buffering and
59
+ # erase/kill character-processing (interrupt and flow control characters
60
+ # are unaffected), making characters typed by the user immediately
61
+ # available to the program.
62
+ Ncurses.cbreak
63
+
64
+ # The echo and noecho routines control whether characters typed by the user
65
+ # are echoed by getch as they are typed.
66
+ # Echoing by the tty driver is always disabled, but initially getch is in
67
+ # echo mode, so characters typed are echoed.
68
+ Ncurses.noecho
69
+
70
+ # The curs_set routine sets the cursor state is set to invisible, normal,
71
+ # or very visible for visibility equal to 0, 1, or 2 respectively.
72
+ # If the terminal supports the visibility requested, the previous cursor
73
+ # state is returned; otherwise, ERR is returned.
74
+ Ncurses.curs_set(1)
75
+
76
+ # The halfdelay routine is used for half-delay mode, which is similar to
77
+ # cbreak mode in that characters typed by the user are immediately
78
+ # available to the program.
79
+ # However, after blocking for tenths tenths of seconds, ERR is returned if
80
+ # nothing has been typed.
81
+ # The value of tenths must be a number between 1 and 255.
82
+ # Use nocbreak to leave half-delay mode.
83
+ Ncurses::halfdelay(tenths = 10)
84
+
85
+ # The nodelay option causes getch to be a non-blocking call. If no input is
86
+ # ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a
87
+ # key is pressed.
88
+ # Ncurses::nodelay(Ncurses::stdscr, bf = true)
89
+ end
90
+
91
+ # this should happen only in outermost program that started ncurses
92
+ # if a called program does this, the calling program can have a display freeze
93
+ def stop_ncurses
94
+ Ncurses.echo
95
+ Ncurses.nocbreak
96
+ Ncurses.nl
97
+ Ncurses.endwin
98
+ $ncurses_started = false
99
+ #puts "curses over"
100
+ ensure
101
+ return unless error = @last_error
102
+ log = Config[:logfile].value
103
+
104
+ Kernel.warn "There may have been fatal errors logged to: #{log}."
105
+ Kernel.warn "The most recent was:"
106
+
107
+ $stderr.puts ''
108
+ $stderr.puts @last_error_message if @last_error_message
109
+ $stderr.puts @last_error, *@last_error.backtrace
110
+ end
111
+ require 'rbcurse/core/system/colormap'
112
+ include ColorMap
113
+ end
114
+ module Ncurses
115
+ extend self
116
+ FALSE = 0
117
+ TRUE = 1
118
+ module NCX
119
+ def COLS
120
+ FFI::NCurses.getmaxx(FFI::NCurses.stdscr)
121
+ end
122
+ def LINES
123
+ # #FFI::NCurses.getmaxy(FFI::NCurses.stdscr)
124
+ FFI::NCurses.LINES
125
+ end
126
+ # # supposed to be picked up at runtime
127
+ def COLORS
128
+ FFI::NCurses.COLORS
129
+ end
130
+
131
+ # jsut trying this so i can do Ncurses.stdscr.getmax
132
+ def _stdscr
133
+ FFI::NCurses.stdscr
134
+ end
135
+ # this allows me to refer to them as Ncurses::A_REVERSE as is the case everywhere
136
+ A_REVERSE = FFI::NCurses::A_REVERSE
137
+ A_STANDOUT = FFI::NCurses::A_STANDOUT
138
+ A_BOLD = FFI::NCurses::A_BOLD
139
+ A_UNDERLINE = FFI::NCurses::A_UNDERLINE
140
+ A_BLINK = FFI::NCurses::A_BLINK
141
+ A_NORMAL = FFI::NCurses::A_NORMAL
142
+ KEY_F1 = FFI::NCurses::KEY_F1
143
+ end
144
+ include NCX
145
+ extend NCX
146
+ # i think we can knock this off
147
+ def method_missing meth, *args
148
+ if (FFI::NCurses.respond_to?(meth))
149
+ FFI::NCurses.send meth, *args
150
+ end
151
+ end
152
+ # FFINC.constants.each { |e| Ncurses.const_set(e, FFINC.const_get(e) ) }
153
+ def const_missing name
154
+ val = FFI::NCurses.const_get(name)
155
+ const_set(name, val)
156
+ return val
157
+ end
158
+
159
+ # This is a window pointer wrapper, to be used for stdscr and others.
160
+ # Ideally ffi-ncurses should do this, if it returns a pointer, I'll do this.
161
+ class FFIWINDOW
162
+ attr_accessor :pointer
163
+ def initialize(*args, &block)
164
+ if block_given?
165
+ @pointer = args.first
166
+ else
167
+ @pointer = FFI::NCurses.newwin(*args)
168
+ end
169
+ end
170
+ def method_missing(name, *args)
171
+ name = name.to_s
172
+ if (name[0,2] == "mv")
173
+ test_name = name.dup
174
+ test_name[2,0] = "w" # insert "w" after"mv"
175
+ if (FFI::NCurses.respond_to?(test_name))
176
+ return FFI::NCurses.send(test_name, @pointer, *args)
177
+ end
178
+ end
179
+ test_name = "w" + name
180
+ if (FFI::NCurses.respond_to?(test_name))
181
+ return FFI::NCurses.send(test_name, @pointer, *args)
182
+ end
183
+ FFI::NCurses.send(name, @pointer, *args)
184
+ end
185
+ def respond_to?(name)
186
+ name = name.to_s
187
+ if (name[0,2] == "mv" && FFI::NCurses.respond_to?("mvw" + name[2..-1]))
188
+ return true
189
+ end
190
+ FFI::NCurses.respond_to?("w" + name) || FFI::NCurses.respond_to?(name)
191
+ end
192
+ def del
193
+ FFI::NCurses.delwin(@pointer)
194
+ end
195
+ alias delete del
196
+ end
197
+ # if ffi-ncurses returns a pointer wrap it.
198
+ # or we can check for whether it responds_to? refresh and getch
199
+ def self.initscr
200
+ #@stdscr = Ncurses::FFIWINDOW.new(FFI::NCurses.initscr) { }
201
+ stdscr = FFI::NCurses.initscr
202
+ if stdscr.is_a? FFI::Pointer
203
+ @stdscr = Ncurses::FFIWINDOW.new(stdscr) { }
204
+ else
205
+ @stdscr = stdscr
206
+ end
207
+ end
208
+ def self.stdscr
209
+ @stdscr
210
+ end
211
+ # commented off on 2011-09-15 FFIWINDOW results in errors
212
+ # class << self
213
+ # def method_missing(method, *args, &block)
214
+ # FFI::NCurses.send(method, *args, &block)
215
+ # end
216
+ # end
217
+ # ---
218
+ end
@@ -0,0 +1,162 @@
1
+ require "ffi-ncurses"
2
+ module Ncurses # changed on 2011-09-8
3
+ # making minimal changes as per ffi-ncurses 0.4.0 which implements panels
4
+ #module VER # too many places call Ncurses::Panel
5
+ class Panel #< Struct.new(:pointer)
6
+ # extend FFI::Library
7
+ #
8
+ # # use RUBY_FFI_NCURSES_LIB to specify exactly which lib you want, e.g.
9
+ # # ncursesw, XCurses (from PDCurses)
10
+ # if ENV["RUBY_FFI_PANEL_LIB"].to_s != ""
11
+ # LIB_HANDLE = ffi_lib( ENV["RUBY_FFI_PANEL_LIB"] ).first
12
+ # else
13
+ # # next works but not when ENV, maybe since 'panel' not in code above
14
+ # LIB_HANDLE = ffi_lib( 'panel', '/opt/local/lib/libpanelw.5.dylib' ).first
15
+ # #LIB_HANDLE = ffi_lib( 'panel', 'libpanel' ).first # this also works
16
+ # end
17
+ #
18
+ # functions = [
19
+ # [:new_panel, [:pointer], :pointer],
20
+ # [:bottom_panel, [:pointer], :int],
21
+ # [:top_panel, [:pointer], :int],
22
+ # [:show_panel, [:pointer], :int],
23
+ # [:update_panels, [], :void],
24
+ # [:hide_panel, [:pointer], :int],
25
+ # [:panel_window, [:pointer], :pointer],
26
+ # [:replace_panel, [:pointer, :pointer], :int],
27
+ # [:move_panel, [:pointer, :int, :int], :int],
28
+ # [:panel_hidden, [:pointer], :int],
29
+ # [:panel_above, [:pointer], :pointer],
30
+ # [:panel_below, [:pointer], :pointer],
31
+ # [:set_panel_userptr, [:pointer, :pointer], :int],
32
+ # [:panel_userptr, [:pointer], :pointer],
33
+ # [:del_panel, [:pointer], :int],
34
+ # ]
35
+ #
36
+ # functions.each do |function|
37
+ # attach_function(*function)
38
+ # end
39
+
40
+ def initialize(window)
41
+ if window.respond_to?(:pointer)
42
+ @pointer = FFI::NCurses.new_panel(window.pointer)
43
+ else
44
+ @pointer = FFI::NCurses.new_panel(window)
45
+ end
46
+ end
47
+ def pointer
48
+ @pointer
49
+ end
50
+
51
+ # Puts panel below all other panels.
52
+ def bottom_panel
53
+ FFI::NCurses.bottom_panel(@pointer)
54
+ end
55
+ alias bottom bottom_panel
56
+
57
+ # Put the visible panel on top of all other panels in the stack.
58
+ #
59
+ # To ensure compatibility across platforms, use this method instead of
60
+ # {show_panel} when the panel is shown.
61
+ def top_panel
62
+ FFI::NCurses.top_panel(@pointer)
63
+ end
64
+ alias top top_panel
65
+
66
+ # Makes hidden panel visible by placing it on the top of the stack.
67
+ #
68
+ # To ensure compatibility across platforms, use this method instead of
69
+ # {top_panel} when the panel is hidden.
70
+ def show_panel
71
+ FFI::NCurses.show_panel(@pointer)
72
+ end
73
+ alias show show_panel
74
+
75
+ # Removes the given panel from the panel stack and thus hides it from
76
+ # view.
77
+ # The PANEL structure is not lost, merely removed from the stack.
78
+ def hide_panel
79
+ FFI::NCurses.hide_panel(@pointer)
80
+ end
81
+ alias hide hide_panel
82
+
83
+ # Returns a pointer to the window of the given panel.
84
+ def panel_window
85
+ FFI::NCurses.panel_window(@pointer)
86
+ end
87
+ alias window panel_window
88
+
89
+ # Replace the window of the panel with the given window.
90
+ # Useful, for example, if you want to resize a panel.
91
+ # You can call {replace_panel} on the output of {wresize}.
92
+ # It does not change the position of the panel in the stack.
93
+ def replace_panel(window)
94
+ FFI::NCurses.replace_panel(@pointer, window)
95
+ end
96
+ alias replace replace_panel
97
+
98
+ # Move the panel window so that its upper-left corner is at
99
+ # (+starty+,+startx+).
100
+ # It does not change the position of the panel in the stack.
101
+ # Be sure to use this method instead of {mvwin}, to move a panel window.
102
+ def move_panel(starty = 0, startx = 0)
103
+ FFI::NCurses.move_panel(@pointer, starty, startx)
104
+ end
105
+ alias move move_panel
106
+
107
+ # Returns true if the panel is in the panel stack, false if not.
108
+ # Returns ERR if the panel pointer is a null pointer.
109
+ def panel_hidden
110
+ FFI::NCurses.panel_hidden(@pointer) == 0
111
+ end
112
+ alias hidden? panel_hidden
113
+
114
+ # Returns pointer to the panel above.
115
+ def panel_above
116
+ FFI::NCurses.panel_above(@pointer)
117
+ end
118
+ alias above panel_above
119
+
120
+ # Return a pointer to the panel just below panel.
121
+ # If the panel argument is a pointer to 0, it returns a pointer to the
122
+ # top panel in the stack.
123
+ def panel_below
124
+ FFI::NCurses.panel_below(@pointer)
125
+ end
126
+ alias below panel_below
127
+
128
+ # Returns the user pointer for a given panel.
129
+ def panel_userptr
130
+ FFI::NCurses.panel_userptr(@pointer)
131
+ end
132
+ alias userptr panel_userptr
133
+
134
+ # sets the panel's user pointer.
135
+ def set_panel_userptr(user_pointer)
136
+ FFI::NCurses.set_panel_userptr(@pointer, user_pointer)
137
+ end
138
+ alias userptr= set_panel_userptr
139
+
140
+ # Remove the panel from the stack and deallocate the PANEL structure.
141
+ # Doesn't remove the associated window.
142
+ def del_panel
143
+ FFI::NCurses.del_panel(@pointer)
144
+ end
145
+ alias del del_panel
146
+ alias delete del_panel
147
+
148
+ class << self
149
+ # these will be used when you say Ncurses::Panel.del_panel(@panel.pointer)
150
+ # You could directly say FFI:NCurses or even @panel.del_panel.
151
+ def update_panels
152
+ FFI::NCurses.update_panels
153
+ end
154
+ def method_missing(name, *args)
155
+ if (FFI::NCurses.respond_to?(name))
156
+ return FFI::NCurses.send(name, *args)
157
+ end
158
+ raise "Panel did not respond_to #{name} "
159
+ end
160
+ end
161
+ end
162
+ end