curses 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +1 -0
- data/BSDL +22 -0
- data/COPYING +56 -0
- data/History.md +5 -0
- data/Manifest.txt +16 -0
- data/README.md +28 -0
- data/Rakefile +43 -0
- data/curses.gemspec +14 -0
- data/ext/curses/curses.c +4330 -0
- data/ext/curses/depend +5 -0
- data/ext/curses/extconf.rb +133 -0
- data/lib/curses.rb +1 -0
- data/sample/hello.rb +30 -0
- data/sample/mouse.rb +53 -0
- data/sample/rain.rb +76 -0
- data/sample/view.rb +91 -0
- data/sample/view2.rb +149 -0
- metadata +151 -0
- metadata.gz.sig +0 -0
data/ext/curses/depend
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
def have_all(*args)
|
4
|
+
old_libs = $libs.dup
|
5
|
+
old_defs = $defs.dup
|
6
|
+
result = []
|
7
|
+
begin
|
8
|
+
args.each {|arg|
|
9
|
+
r = arg.call(*result)
|
10
|
+
if !r
|
11
|
+
return nil
|
12
|
+
end
|
13
|
+
result << r
|
14
|
+
}
|
15
|
+
result
|
16
|
+
ensure
|
17
|
+
if result.length != args.length
|
18
|
+
$libs = old_libs
|
19
|
+
$defs = old_defs
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
dir_config('curses')
|
25
|
+
dir_config('ncurses')
|
26
|
+
dir_config('termcap')
|
27
|
+
|
28
|
+
have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
|
29
|
+
have_library("tinfo", "tgetent") or have_library("termcap", "tgetent")
|
30
|
+
|
31
|
+
header_library = nil
|
32
|
+
[
|
33
|
+
["ncurses.h", ["ncursesw", "ncurses"]],
|
34
|
+
["ncurses/curses.h", ["ncurses"]],
|
35
|
+
["curses_colr/curses.h", ["cur_colr"]],
|
36
|
+
["curses.h", ["curses", "pdcurses"]],
|
37
|
+
# ["xcurses.h", ["XCurses"]], # XCurses (PDCurses for X11)
|
38
|
+
].each {|hdr, libs|
|
39
|
+
header_library = have_all(
|
40
|
+
lambda { have_header(hdr) && hdr },
|
41
|
+
lambda {|h| libs.find {|lib| have_library(lib, "initscr", h) } })
|
42
|
+
if header_library
|
43
|
+
break;
|
44
|
+
end
|
45
|
+
}
|
46
|
+
|
47
|
+
if header_library
|
48
|
+
header, library = header_library
|
49
|
+
puts "header: #{header}"
|
50
|
+
puts "library: #{library}"
|
51
|
+
|
52
|
+
curses = [header]
|
53
|
+
if header == 'curses_colr/curses.h'
|
54
|
+
curses.unshift("varargs.h")
|
55
|
+
end
|
56
|
+
|
57
|
+
for f in %w(beep bkgd bkgdset curs_set deleteln doupdate flash
|
58
|
+
getbkgd getnstr init isendwin keyname keypad resizeterm
|
59
|
+
scrl set setscrreg ungetch
|
60
|
+
wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr
|
61
|
+
wresize wscrl wsetscrreg
|
62
|
+
def_prog_mode reset_prog_mode timeout wtimeout nodelay
|
63
|
+
init_color wcolor_set use_default_colors newpad)
|
64
|
+
have_func(f) || (have_macro(f, curses) && $defs.push(format("-DHAVE_%s", f.upcase)))
|
65
|
+
end
|
66
|
+
flag = "-D_XOPEN_SOURCE_EXTENDED"
|
67
|
+
if try_static_assert("sizeof(char*)>sizeof(int)",
|
68
|
+
%w[stdio.h stdlib.h]+curses,
|
69
|
+
flag)
|
70
|
+
$defs << flag
|
71
|
+
end
|
72
|
+
have_var("ESCDELAY", curses)
|
73
|
+
have_var("TABSIZE", curses)
|
74
|
+
have_var("COLORS", curses)
|
75
|
+
have_var("COLOR_PAIRS", curses)
|
76
|
+
|
77
|
+
# SVR4 curses has a (undocumented) variable char *curses_version.
|
78
|
+
# ncurses and PDcurses has a function char *curses_version().
|
79
|
+
# Note that the original BSD curses doesn't provide version information.
|
80
|
+
#
|
81
|
+
# configure option:
|
82
|
+
# --with-curses-version=function for SVR4
|
83
|
+
# --with-curses-version=variable for ncurses and PDcurses
|
84
|
+
# (not given) automatically determined
|
85
|
+
|
86
|
+
case with_curses_version = with_config("curses-version")
|
87
|
+
when "function"
|
88
|
+
$defs << '-DHAVE_FUNC_CURSES_VERSION'
|
89
|
+
when "variable"
|
90
|
+
$defs << '-DHAVE_VAR_CURSES_VERSION'
|
91
|
+
when nil
|
92
|
+
func_test_program = cpp_include(curses) + <<-"End"
|
93
|
+
int main(int argc, char *argv[])
|
94
|
+
{
|
95
|
+
curses_version();
|
96
|
+
return EXIT_SUCCESS;
|
97
|
+
}
|
98
|
+
End
|
99
|
+
var_test_program = cpp_include(curses) + <<-"End"
|
100
|
+
extern char *curses_version;
|
101
|
+
int main(int argc, char *argv[])
|
102
|
+
{
|
103
|
+
int i = 0;
|
104
|
+
for (i = 0; i < 100; i++) {
|
105
|
+
if (curses_version[i] == 0)
|
106
|
+
return 0 < i ? EXIT_SUCCESS : EXIT_FAILURE;
|
107
|
+
if (curses_version[i] & 0x80)
|
108
|
+
return EXIT_FAILURE;
|
109
|
+
}
|
110
|
+
return EXIT_FAILURE;
|
111
|
+
}
|
112
|
+
End
|
113
|
+
try = method(CROSS_COMPILING ? :try_link : :try_run)
|
114
|
+
function_p = checking_for(checking_message('function curses_version', curses)) { try[func_test_program] }
|
115
|
+
variable_p = checking_for(checking_message('variable curses_version', curses)) { try[var_test_program] }
|
116
|
+
if function_p and variable_p
|
117
|
+
if [header, library].grep(/ncurses|pdcurses|xcurses/i)
|
118
|
+
variable_p = false
|
119
|
+
else
|
120
|
+
warn "found curses_version but cannot determin whether it is a"
|
121
|
+
warn "function or a variable, so assume a variable in old SVR4"
|
122
|
+
warn "ncurses."
|
123
|
+
function_p = false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
$defs << '-DHAVE_FUNC_CURSES_VERSION' if function_p
|
127
|
+
$defs << '-DHAVE_VAR_CURSES_VERSION' if variable_p
|
128
|
+
else
|
129
|
+
warn "unexpeted value for --with-curses-version: #{with_curses_version}"
|
130
|
+
end
|
131
|
+
|
132
|
+
create_makefile("curses")
|
133
|
+
end
|
data/lib/curses.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "curses.so"
|
data/sample/hello.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require "curses"
|
4
|
+
include Curses
|
5
|
+
|
6
|
+
def show_message(message)
|
7
|
+
width = message.length + 6
|
8
|
+
win = Window.new(5, width,
|
9
|
+
(lines - 5) / 2, (cols - width) / 2)
|
10
|
+
win.box('|', '-')
|
11
|
+
win.setpos(2, 3)
|
12
|
+
win.addstr(message)
|
13
|
+
win.refresh
|
14
|
+
win.getch
|
15
|
+
win.close
|
16
|
+
end
|
17
|
+
|
18
|
+
init_screen
|
19
|
+
begin
|
20
|
+
crmode
|
21
|
+
# show_message("Hit any key")
|
22
|
+
setpos((lines - 5) / 2, (cols - 10) / 2)
|
23
|
+
addstr("Hit any key")
|
24
|
+
refresh
|
25
|
+
getch
|
26
|
+
show_message("Hello, World!")
|
27
|
+
refresh
|
28
|
+
ensure
|
29
|
+
close_screen
|
30
|
+
end
|
data/sample/mouse.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require "curses"
|
4
|
+
include Curses
|
5
|
+
|
6
|
+
def show_message(*msgs)
|
7
|
+
message = msgs.join
|
8
|
+
width = message.length + 6
|
9
|
+
win = Window.new(5, width,
|
10
|
+
(lines - 5) / 2, (cols - width) / 2)
|
11
|
+
win.keypad = true
|
12
|
+
win.attron(color_pair(COLOR_RED)){
|
13
|
+
win.box(?|, ?-, ?+)
|
14
|
+
}
|
15
|
+
win.setpos(2, 3)
|
16
|
+
win.addstr(message)
|
17
|
+
win.refresh
|
18
|
+
win.getch
|
19
|
+
win.close
|
20
|
+
end
|
21
|
+
|
22
|
+
init_screen
|
23
|
+
start_color
|
24
|
+
init_pair(COLOR_BLUE,COLOR_BLUE,COLOR_WHITE)
|
25
|
+
init_pair(COLOR_RED,COLOR_RED,COLOR_WHITE)
|
26
|
+
crmode
|
27
|
+
noecho
|
28
|
+
stdscr.keypad(true)
|
29
|
+
|
30
|
+
begin
|
31
|
+
mousemask(BUTTON1_CLICKED|BUTTON2_CLICKED|BUTTON3_CLICKED|BUTTON4_CLICKED)
|
32
|
+
setpos((lines - 5) / 2, (cols - 10) / 2)
|
33
|
+
attron(color_pair(COLOR_BLUE)|A_BOLD){
|
34
|
+
addstr("click")
|
35
|
+
}
|
36
|
+
refresh
|
37
|
+
while( true )
|
38
|
+
c = getch
|
39
|
+
case c
|
40
|
+
when KEY_MOUSE
|
41
|
+
m = getmouse
|
42
|
+
if( m )
|
43
|
+
show_message("getch = #{c.inspect}, ",
|
44
|
+
"mouse event = #{'0x%x' % m.bstate}, ",
|
45
|
+
"axis = (#{m.x},#{m.y},#{m.z})")
|
46
|
+
end
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
refresh
|
51
|
+
ensure
|
52
|
+
close_screen
|
53
|
+
end
|
data/sample/rain.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
# rain for a curses test
|
3
|
+
|
4
|
+
require "curses"
|
5
|
+
include Curses
|
6
|
+
|
7
|
+
def onsig(sig)
|
8
|
+
close_screen
|
9
|
+
exit sig
|
10
|
+
end
|
11
|
+
|
12
|
+
def ranf
|
13
|
+
rand(32767).to_f / 32767
|
14
|
+
end
|
15
|
+
|
16
|
+
# main #
|
17
|
+
for i in %w[HUP INT QUIT TERM]
|
18
|
+
if trap(i, "SIG_IGN") != 0 then # 0 for SIG_IGN
|
19
|
+
trap(i) {|sig| onsig(sig) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
init_screen
|
24
|
+
nl
|
25
|
+
noecho
|
26
|
+
srand
|
27
|
+
|
28
|
+
xpos = {}
|
29
|
+
ypos = {}
|
30
|
+
r = lines - 4
|
31
|
+
c = cols - 4
|
32
|
+
for i in 0 .. 4
|
33
|
+
xpos[i] = (c * ranf).to_i + 2
|
34
|
+
ypos[i] = (r * ranf).to_i + 2
|
35
|
+
end
|
36
|
+
|
37
|
+
i = 0
|
38
|
+
while TRUE
|
39
|
+
x = (c * ranf).to_i + 2
|
40
|
+
y = (r * ranf).to_i + 2
|
41
|
+
|
42
|
+
|
43
|
+
setpos(y, x); addstr(".")
|
44
|
+
|
45
|
+
setpos(ypos[i], xpos[i]); addstr("o")
|
46
|
+
|
47
|
+
i = if i == 0 then 4 else i - 1 end
|
48
|
+
setpos(ypos[i], xpos[i]); addstr("O")
|
49
|
+
|
50
|
+
i = if i == 0 then 4 else i - 1 end
|
51
|
+
setpos(ypos[i] - 1, xpos[i]); addstr("-")
|
52
|
+
setpos(ypos[i], xpos[i] - 1); addstr("|.|")
|
53
|
+
setpos(ypos[i] + 1, xpos[i]); addstr("-")
|
54
|
+
|
55
|
+
i = if i == 0 then 4 else i - 1 end
|
56
|
+
setpos(ypos[i] - 2, xpos[i]); addstr("-")
|
57
|
+
setpos(ypos[i] - 1, xpos[i] - 1); addstr("/ \\")
|
58
|
+
setpos(ypos[i], xpos[i] - 2); addstr("| O |")
|
59
|
+
setpos(ypos[i] + 1, xpos[i] - 1); addstr("\\ /")
|
60
|
+
setpos(ypos[i] + 2, xpos[i]); addstr("-")
|
61
|
+
|
62
|
+
i = if i == 0 then 4 else i - 1 end
|
63
|
+
setpos(ypos[i] - 2, xpos[i]); addstr(" ")
|
64
|
+
setpos(ypos[i] - 1, xpos[i] - 1); addstr(" ")
|
65
|
+
setpos(ypos[i], xpos[i] - 2); addstr(" ")
|
66
|
+
setpos(ypos[i] + 1, xpos[i] - 1); addstr(" ")
|
67
|
+
setpos(ypos[i] + 2, xpos[i]); addstr(" ")
|
68
|
+
|
69
|
+
|
70
|
+
xpos[i] = x
|
71
|
+
ypos[i] = y
|
72
|
+
refresh
|
73
|
+
sleep(0.5)
|
74
|
+
end
|
75
|
+
|
76
|
+
# end of main
|
data/sample/view.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require "curses"
|
4
|
+
include Curses
|
5
|
+
|
6
|
+
#
|
7
|
+
# main
|
8
|
+
#
|
9
|
+
|
10
|
+
if ARGV.size != 1 then
|
11
|
+
printf("usage: view file\n");
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
begin
|
15
|
+
fp = open(ARGV[0], "r")
|
16
|
+
rescue
|
17
|
+
raise "cannot open file: #{ARGV[1]}"
|
18
|
+
end
|
19
|
+
|
20
|
+
# signal(SIGINT, finish)
|
21
|
+
|
22
|
+
init_screen
|
23
|
+
#keypad(stdscr, TRUE)
|
24
|
+
nonl
|
25
|
+
cbreak
|
26
|
+
noecho
|
27
|
+
#scrollok(stdscr, TRUE)
|
28
|
+
|
29
|
+
# slurp the file
|
30
|
+
data_lines = []
|
31
|
+
fp.each_line { |l|
|
32
|
+
data_lines.push(l)
|
33
|
+
}
|
34
|
+
fp.close
|
35
|
+
|
36
|
+
|
37
|
+
lptr = 0
|
38
|
+
while TRUE
|
39
|
+
i = 0
|
40
|
+
while i < lines
|
41
|
+
setpos(i, 0)
|
42
|
+
#clrtoeol
|
43
|
+
addstr(data_lines[lptr + i] || '')
|
44
|
+
i += 1
|
45
|
+
end
|
46
|
+
refresh
|
47
|
+
|
48
|
+
explicit = FALSE
|
49
|
+
n = 0
|
50
|
+
while TRUE
|
51
|
+
c = getch
|
52
|
+
if c =~ /[0-9]/
|
53
|
+
n = 10 * n + c.to_i
|
54
|
+
else
|
55
|
+
break
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
n = 1 if !explicit && n == 0
|
60
|
+
|
61
|
+
case c
|
62
|
+
when "n" #when KEY_DOWN
|
63
|
+
i = 0
|
64
|
+
while i < n
|
65
|
+
if lptr + lines < data_lines.size then
|
66
|
+
lptr += 1
|
67
|
+
else
|
68
|
+
break
|
69
|
+
end
|
70
|
+
i += 1
|
71
|
+
end
|
72
|
+
#wscrl(i)
|
73
|
+
|
74
|
+
when "p" #when KEY_UP
|
75
|
+
i = 0
|
76
|
+
while i < n
|
77
|
+
if lptr > 0 then
|
78
|
+
lptr -= 1
|
79
|
+
else
|
80
|
+
break
|
81
|
+
end
|
82
|
+
i += 1
|
83
|
+
end
|
84
|
+
#wscrl(-i)
|
85
|
+
|
86
|
+
when "q"
|
87
|
+
break
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
close_screen
|
data/sample/view2.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require "curses"
|
4
|
+
|
5
|
+
|
6
|
+
# A curses based file viewer
|
7
|
+
class FileViewer
|
8
|
+
|
9
|
+
# Create a new fileviewer, and view the file.
|
10
|
+
def initialize(filename)
|
11
|
+
@data_lines = []
|
12
|
+
@screen = nil
|
13
|
+
@top = nil
|
14
|
+
init_curses
|
15
|
+
load_file(filename)
|
16
|
+
interact
|
17
|
+
end
|
18
|
+
|
19
|
+
# Perform the curses setup
|
20
|
+
def init_curses
|
21
|
+
# signal(SIGINT, finish)
|
22
|
+
|
23
|
+
Curses.init_screen
|
24
|
+
Curses.nonl
|
25
|
+
Curses.cbreak
|
26
|
+
Curses.noecho
|
27
|
+
|
28
|
+
@screen = Curses.stdscr
|
29
|
+
|
30
|
+
@screen.scrollok(true)
|
31
|
+
#$screen.keypad(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Load the file into memory, and put
|
35
|
+
# the first part on the curses display.
|
36
|
+
def load_file(filename)
|
37
|
+
fp = open(filename, "r") do |fp|
|
38
|
+
# slurp the file
|
39
|
+
fp.each_line { |l|
|
40
|
+
@data_lines.push(l.chop)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
@top = 0
|
44
|
+
@data_lines[0..@screen.maxy-1].each_with_index{|line, idx|
|
45
|
+
@screen.setpos(idx, 0)
|
46
|
+
@screen.addstr(line)
|
47
|
+
}
|
48
|
+
@screen.setpos(0,0)
|
49
|
+
@screen.refresh
|
50
|
+
rescue
|
51
|
+
raise "cannot open file '#{filename}' for reading"
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Scroll the display up by one line
|
56
|
+
def scroll_up
|
57
|
+
if( @top > 0 )
|
58
|
+
@screen.scrl(-1)
|
59
|
+
@top -= 1
|
60
|
+
str = @data_lines[@top]
|
61
|
+
if( str )
|
62
|
+
@screen.setpos(0, 0)
|
63
|
+
@screen.addstr(str)
|
64
|
+
end
|
65
|
+
return true
|
66
|
+
else
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Scroll the display down by one line
|
72
|
+
def scroll_down
|
73
|
+
if( @top + @screen.maxy < @data_lines.length )
|
74
|
+
@screen.scrl(1)
|
75
|
+
@top += 1
|
76
|
+
str = @data_lines[@top + @screen.maxy - 1]
|
77
|
+
if( str )
|
78
|
+
@screen.setpos(@screen.maxy - 1, 0)
|
79
|
+
@screen.addstr(str)
|
80
|
+
end
|
81
|
+
return true
|
82
|
+
else
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Allow the user to interact with the display.
|
88
|
+
# This uses EMACS-like keybindings, and also
|
89
|
+
# vi-like keybindings as well, except that left
|
90
|
+
# and right move to the beginning and end of the
|
91
|
+
# file, respectively.
|
92
|
+
def interact
|
93
|
+
while true
|
94
|
+
result = true
|
95
|
+
c = Curses.getch
|
96
|
+
case c
|
97
|
+
when Curses::KEY_DOWN, Curses::KEY_CTRL_N, ?j
|
98
|
+
result = scroll_down
|
99
|
+
when Curses::KEY_UP, Curses::KEY_CTRL_P, ?k
|
100
|
+
result = scroll_up
|
101
|
+
when Curses::KEY_NPAGE, ?\s # white space
|
102
|
+
for i in 0..(@screen.maxy - 2)
|
103
|
+
if( ! scroll_down )
|
104
|
+
if( i == 0 )
|
105
|
+
result = false
|
106
|
+
end
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
when Curses::KEY_PPAGE
|
111
|
+
for i in 0..(@screen.maxy - 2)
|
112
|
+
if( ! scroll_up )
|
113
|
+
if( i == 0 )
|
114
|
+
result = false
|
115
|
+
end
|
116
|
+
break
|
117
|
+
end
|
118
|
+
end
|
119
|
+
when Curses::KEY_LEFT, Curses::KEY_CTRL_T, ?h
|
120
|
+
while( scroll_up )
|
121
|
+
end
|
122
|
+
when Curses::KEY_RIGHT, Curses::KEY_CTRL_B, ?l
|
123
|
+
while( scroll_down )
|
124
|
+
end
|
125
|
+
when ?q
|
126
|
+
break
|
127
|
+
else
|
128
|
+
@screen.setpos(0,0)
|
129
|
+
@screen.addstr("[unknown key `#{Curses.keyname(c)}'=#{c}] ")
|
130
|
+
end
|
131
|
+
if( !result )
|
132
|
+
Curses.beep
|
133
|
+
end
|
134
|
+
@screen.setpos(0,0)
|
135
|
+
end
|
136
|
+
Curses.close_screen
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
# If we are being run as a main program...
|
142
|
+
if __FILE__ == $0
|
143
|
+
if ARGV.size != 1 then
|
144
|
+
printf("usage: #{$0} file\n");
|
145
|
+
exit
|
146
|
+
end
|
147
|
+
|
148
|
+
viewer = FileViewer.new(ARGV[0])
|
149
|
+
end
|