rbhex-core 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- metadata +172 -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,236 @@
|
|
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
|
+
# in case we want a blocking getch, you may want to first
|
11
|
+
# set wtimeout to -1, and then reset it to this value.
|
12
|
+
# Please first check that we are using this.
|
13
|
+
$ncurses_wtimeout = 500 # used by windows for timeout of wgetch
|
14
|
+
|
15
|
+
# The initscr code determines the terminal type and initializes all curses
|
16
|
+
# data structures.
|
17
|
+
# initscr also causes the first call to refresh to clear the screen.
|
18
|
+
# If errors occur, initscr writes an appropriate error message to standard
|
19
|
+
# error and exits; otherwise, a pointer is returned to stdscr.
|
20
|
+
stdscr = Ncurses.initscr ## FFI
|
21
|
+
|
22
|
+
# Color.start if Ncurses.has_colors?
|
23
|
+
Ncurses.start_color();
|
24
|
+
ColorMap.setup # added by RK 2008-11-30 00:48
|
25
|
+
# The keypad option enables the keypad of the user's terminal.
|
26
|
+
# If enabled (bf is TRUE), the user can press a function key (such as an
|
27
|
+
# arrow key) and wgetch returns a single value representing the function
|
28
|
+
# key, as in KEY_LEFT.
|
29
|
+
# If disabled (bf is FALSE), curses does not treat function keys specially
|
30
|
+
# and the program has to interpret the escape sequences itself.
|
31
|
+
# If the keypad in the terminal can be turned on (made to transmit) and off
|
32
|
+
# (made to work locally), turning on this option causes the terminal keypad
|
33
|
+
# to be turned on when wgetch is called.
|
34
|
+
# The default value for keypad is false.
|
35
|
+
Ncurses.keypad(stdscr.pointer, bf = true) # FFIWINDOW
|
36
|
+
#Ncurses.keypad(stdscr, bf = true)
|
37
|
+
#Ncurses.stdscr.keypad(true) # turn on keypad mode FFI
|
38
|
+
#Ncurses.keypad(stdscr, bf = 1)
|
39
|
+
|
40
|
+
# The nl and nonl routines control whether the underlying display device
|
41
|
+
# translates the return key into newline on input, and whether it
|
42
|
+
# translates newline into return and line-feed on output (in either case,
|
43
|
+
# the call addch('\n') does the equivalent of return and line feed on the
|
44
|
+
# virtual screen).
|
45
|
+
# Initially, these translations do occur.
|
46
|
+
# If you disable them using nonl, curses will be able to make better use of
|
47
|
+
# the line-feed capability, resulting in faster cursor motion.
|
48
|
+
# Also, curses will then be able to detect the return key.
|
49
|
+
Ncurses.nonl
|
50
|
+
|
51
|
+
# The raw and noraw routines place the terminal into or out of raw mode.
|
52
|
+
# Raw mode is similar to cbreak mode, in that characters typed are
|
53
|
+
# immediately passed through to the user program.
|
54
|
+
# The differences are that in raw mode, the interrupt, quit, suspend, and
|
55
|
+
# flow control characters are all passed through uninterpreted, instead of
|
56
|
+
# generating a signal.
|
57
|
+
# The behavior of the BREAK key depends on other bits in the tty driver
|
58
|
+
# that are not set by curses.
|
59
|
+
Ncurses.raw
|
60
|
+
|
61
|
+
# Normally, the tty driver buffers typed characters until a newline or
|
62
|
+
# carriage return is typed.
|
63
|
+
# The cbreak routine disables line buffering and
|
64
|
+
# erase/kill character-processing (interrupt and flow control characters
|
65
|
+
# are unaffected), making characters typed by the user immediately
|
66
|
+
# available to the program.
|
67
|
+
#Ncurses.cbreak
|
68
|
+
# I have removed cbreak and halfdelay since they were causing C-c
|
69
|
+
# to crash if i pressed it in succession
|
70
|
+
|
71
|
+
# The echo and noecho routines control whether characters typed by the user
|
72
|
+
# are echoed by getch as they are typed.
|
73
|
+
# Echoing by the tty driver is always disabled, but initially getch is in
|
74
|
+
# echo mode, so characters typed are echoed.
|
75
|
+
Ncurses.noecho
|
76
|
+
|
77
|
+
# The curs_set routine sets the cursor state is set to invisible, normal,
|
78
|
+
# or very visible for visibility equal to 0, 1, or 2 respectively.
|
79
|
+
# If the terminal supports the visibility requested, the previous cursor
|
80
|
+
# state is returned; otherwise, ERR is returned.
|
81
|
+
Ncurses.curs_set(1)
|
82
|
+
|
83
|
+
# The halfdelay routine is used for half-delay mode, which is similar to
|
84
|
+
# cbreak mode in that characters typed by the user are immediately
|
85
|
+
# available to the program.
|
86
|
+
# However, after blocking for tenths tenths of seconds, ERR is returned if
|
87
|
+
# nothing has been typed.
|
88
|
+
# The value of tenths must be a number between 1 and 255.
|
89
|
+
# Use nocbreak to leave half-delay mode.
|
90
|
+
#Ncurses::halfdelay(tenths = 10)
|
91
|
+
# See above why switched off
|
92
|
+
|
93
|
+
# The nodelay option causes getch to be a non-blocking call. If no input is
|
94
|
+
# ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a
|
95
|
+
# key is pressed.
|
96
|
+
# I am using the next line for the window when creating, this does not
|
97
|
+
# have any impact on window.
|
98
|
+
# For this to have any effect your getch should be Ncurses.getch and not
|
99
|
+
# wgetch(@window), For that do this with window.
|
100
|
+
# I am disableing this 2011-12-20 since it does not work with combinations
|
101
|
+
# such as gg. Any routine that does a getch will just immediatelt return an ERR.
|
102
|
+
#Ncurses::nodelay(stdscr.pointer, bf = true)
|
103
|
+
|
104
|
+
# added these 2 so we can do resizing based on original and current size when terminal resized
|
105
|
+
# 2012-01-8
|
106
|
+
$orig_cols = FFI::NCurses.COLS
|
107
|
+
$orig_rows = FFI::NCurses.LINES
|
108
|
+
end
|
109
|
+
|
110
|
+
# this should happen only in outermost program that started ncurses
|
111
|
+
# if a called program does this, the calling program can have a display freeze
|
112
|
+
def stop_ncurses
|
113
|
+
Ncurses.echo
|
114
|
+
Ncurses.nocbreak
|
115
|
+
Ncurses.nl
|
116
|
+
Ncurses.endwin
|
117
|
+
$ncurses_started = false
|
118
|
+
#puts "curses over"
|
119
|
+
ensure
|
120
|
+
return unless error = @last_error
|
121
|
+
#log = RbConfig[:logfile].value
|
122
|
+
#Kernel.warn "There may have been fatal errors logged to: #{log}."
|
123
|
+
#Kernel.warn "The most recent was:"
|
124
|
+
|
125
|
+
$stderr.puts ''
|
126
|
+
$stderr.puts @last_error_message if @last_error_message
|
127
|
+
$stderr.puts @last_error, *@last_error.backtrace
|
128
|
+
end
|
129
|
+
require 'rbhex/core/system/colormap'
|
130
|
+
include RubyCurses::ColorMap
|
131
|
+
end
|
132
|
+
module Ncurses
|
133
|
+
extend self
|
134
|
+
FALSE = 0
|
135
|
+
TRUE = 1
|
136
|
+
module NCX
|
137
|
+
def COLS
|
138
|
+
FFI::NCurses.getmaxx(FFI::NCurses.stdscr)
|
139
|
+
end
|
140
|
+
def LINES
|
141
|
+
# #FFI::NCurses.getmaxy(FFI::NCurses.stdscr)
|
142
|
+
FFI::NCurses.LINES
|
143
|
+
end
|
144
|
+
# # supposed to be picked up at runtime
|
145
|
+
def COLORS
|
146
|
+
FFI::NCurses.COLORS
|
147
|
+
end
|
148
|
+
|
149
|
+
# jsut trying this so i can do Ncurses.stdscr.getmax
|
150
|
+
def _stdscr
|
151
|
+
FFI::NCurses.stdscr
|
152
|
+
end
|
153
|
+
# this allows me to refer to them as Ncurses::A_REVERSE as is the case everywhere
|
154
|
+
A_REVERSE = FFI::NCurses::A_REVERSE
|
155
|
+
A_STANDOUT = FFI::NCurses::A_STANDOUT
|
156
|
+
A_BOLD = FFI::NCurses::A_BOLD
|
157
|
+
A_UNDERLINE = FFI::NCurses::A_UNDERLINE
|
158
|
+
A_BLINK = FFI::NCurses::A_BLINK
|
159
|
+
A_NORMAL = FFI::NCurses::A_NORMAL
|
160
|
+
KEY_F1 = FFI::NCurses::KEY_F1
|
161
|
+
end
|
162
|
+
include NCX
|
163
|
+
extend NCX
|
164
|
+
# i think we can knock this off
|
165
|
+
def method_missing meth, *args
|
166
|
+
if (FFI::NCurses.respond_to?(meth))
|
167
|
+
FFI::NCurses.send meth, *args
|
168
|
+
end
|
169
|
+
end
|
170
|
+
# FFINC.constants.each { |e| Ncurses.const_set(e, FFINC.const_get(e) ) }
|
171
|
+
def const_missing name
|
172
|
+
val = FFI::NCurses.const_get(name)
|
173
|
+
const_set(name, val)
|
174
|
+
return val
|
175
|
+
end
|
176
|
+
|
177
|
+
# This is a window pointer wrapper, to be used for stdscr and others.
|
178
|
+
# Ideally ffi-ncurses should do this, if it returns a pointer, I'll do this.
|
179
|
+
class FFIWINDOW
|
180
|
+
attr_accessor :pointer
|
181
|
+
def initialize(*args, &block)
|
182
|
+
if block_given?
|
183
|
+
@pointer = args.first
|
184
|
+
else
|
185
|
+
@pointer = FFI::NCurses.newwin(*args)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
def method_missing(name, *args)
|
189
|
+
name = name.to_s
|
190
|
+
if (name[0,2] == "mv")
|
191
|
+
test_name = name.dup
|
192
|
+
test_name[2,0] = "w" # insert "w" after"mv"
|
193
|
+
if (FFI::NCurses.respond_to?(test_name))
|
194
|
+
return FFI::NCurses.send(test_name, @pointer, *args)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
test_name = "w" + name
|
198
|
+
if (FFI::NCurses.respond_to?(test_name))
|
199
|
+
return FFI::NCurses.send(test_name, @pointer, *args)
|
200
|
+
end
|
201
|
+
FFI::NCurses.send(name, @pointer, *args)
|
202
|
+
end
|
203
|
+
def respond_to?(name)
|
204
|
+
name = name.to_s
|
205
|
+
if (name[0,2] == "mv" && FFI::NCurses.respond_to?("mvw" + name[2..-1]))
|
206
|
+
return true
|
207
|
+
end
|
208
|
+
FFI::NCurses.respond_to?("w" + name) || FFI::NCurses.respond_to?(name)
|
209
|
+
end
|
210
|
+
def del
|
211
|
+
FFI::NCurses.delwin(@pointer)
|
212
|
+
end
|
213
|
+
alias delete del
|
214
|
+
end
|
215
|
+
# if ffi-ncurses returns a pointer wrap it.
|
216
|
+
# or we can check for whether it responds_to? refresh and getch
|
217
|
+
def self.initscr
|
218
|
+
#@stdscr = Ncurses::FFIWINDOW.new(FFI::NCurses.initscr) { }
|
219
|
+
stdscr = FFI::NCurses.initscr
|
220
|
+
if stdscr.is_a? FFI::Pointer
|
221
|
+
@stdscr = Ncurses::FFIWINDOW.new(stdscr) { }
|
222
|
+
else
|
223
|
+
@stdscr = stdscr
|
224
|
+
end
|
225
|
+
end
|
226
|
+
def self.stdscr
|
227
|
+
@stdscr
|
228
|
+
end
|
229
|
+
# commented off on 2011-09-15 FFIWINDOW results in errors
|
230
|
+
# class << self
|
231
|
+
# def method_missing(method, *args, &block)
|
232
|
+
# FFI::NCurses.send(method, *args, &block)
|
233
|
+
# end
|
234
|
+
# end
|
235
|
+
# ---
|
236
|
+
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
|