ffi-ncurses 0.3.3 → 0.4.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.
- data/COPYING +22 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +13 -0
- data/History.txt +32 -3
- data/README.rdoc +118 -58
- data/Rakefile +30 -0
- data/examples/acs_chars.rb +53 -0
- data/examples/acs_chars.rbc +1502 -0
- data/examples/{example-attributes.rb → attributes.rb} +0 -0
- data/examples/color.rb +63 -0
- data/examples/cursor.rb +27 -0
- data/examples/example.rb +17 -17
- data/examples/getkey.rb +212 -0
- data/examples/{example-getsetsyx.rb → getsetsyx.rb} +2 -2
- data/examples/globals.rb +38 -0
- data/examples/hello.rb +34 -0
- data/examples/hello.rbc +638 -0
- data/examples/hellowide.rb +59 -0
- data/examples/keys.rb +27 -0
- data/examples/{example-mouse.rb → mouse.rb} +2 -2
- data/examples/multiterm.rb +120 -0
- data/examples/ncurses/LICENSES_for_examples +26 -0
- data/examples/{ncurses-example.rb → ncurses/example.rb} +13 -80
- data/examples/ncurses/hello_ncurses.rb +57 -0
- data/examples/ncurses/rain.rb +220 -0
- data/examples/ncurses/read_line.rb +67 -0
- data/examples/ncurses/subwin.rb +71 -0
- data/examples/ncurses/tclock.rb +227 -0
- data/examples/newterm.rb +65 -0
- data/examples/panel_simple.rb +82 -0
- data/examples/{example-printw-variadic.rb → printw-variadic.rb} +1 -1
- data/examples/ripoffline.rb +86 -0
- data/examples/run-all.sh +14 -0
- data/examples/{example-softkeys.rb → softkeys.rb} +0 -0
- data/examples/{example-stdscr.rb → stdscr.rb} +2 -1
- data/examples/temp_leave.rb +99 -0
- data/examples/viewer.rb +350 -0
- data/examples/wacs_chars.rb +64 -0
- data/examples/windows.rb +73 -0
- data/ffi-ncurses.gemspec +39 -52
- data/lib/ffi-ncurses.rb +214 -474
- data/lib/ffi-ncurses/acs.rb +150 -0
- data/lib/ffi-ncurses/bool_wrappers.rb +66 -0
- data/lib/ffi-ncurses/functions.rb +450 -0
- data/lib/ffi-ncurses/keydefs.rb +136 -99
- data/lib/ffi-ncurses/mouse.rb +106 -106
- data/lib/ffi-ncurses/ncurses.rb +176 -0
- data/lib/ffi-ncurses/{ord-shim.rb → ord_shim.rb} +0 -0
- data/lib/ffi-ncurses/panel.rb +21 -0
- data/lib/ffi-ncurses/typedefs.rb +35 -0
- data/lib/ffi-ncurses/version.rb +7 -0
- data/lib/ffi-ncurses/widechars.rb +137 -0
- data/lib/ffi-ncurses/winstruct.rb +55 -33
- data/spec/attached_functions_spec.rb +42 -0
- metadata +95 -85
- data/examples/example-colour.rb +0 -63
- data/examples/example-cursor.rb +0 -22
- data/examples/example-hello.rb +0 -24
- data/examples/example-jruby.rb +0 -14
- data/examples/example-keys.rb +0 -25
- data/examples/example-windows.rb +0 -24
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
#
|
4
|
+
# Sean O'Halpin, 2009-02-15
|
5
|
+
#
|
6
|
+
require 'ffi-ncurses'
|
7
|
+
require 'ffi-ncurses/widechars'
|
8
|
+
|
9
|
+
def centre(text)
|
10
|
+
col = (COLS() - WideChars.display_width(text.strip))/2
|
11
|
+
y, x = getyx(stdscr)
|
12
|
+
mvaddstr y, col, text
|
13
|
+
end
|
14
|
+
|
15
|
+
if RUBY_VERSION >= '1.9.0'
|
16
|
+
def fullwidth(txt)
|
17
|
+
txt.encode("UTF-32BE").codepoints.map{ |x|
|
18
|
+
case x
|
19
|
+
when 0x30..0x7F
|
20
|
+
x + 0xFEE0
|
21
|
+
else
|
22
|
+
x
|
23
|
+
end
|
24
|
+
}.pack("U*")
|
25
|
+
end
|
26
|
+
else
|
27
|
+
def fullwidth(txt)
|
28
|
+
txt.unpack("U*").map { |x|
|
29
|
+
case x
|
30
|
+
when 0x30..0x7F
|
31
|
+
x + 0xFEE0
|
32
|
+
else
|
33
|
+
x
|
34
|
+
end
|
35
|
+
}.pack("U*")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
include FFI::NCurses
|
40
|
+
begin
|
41
|
+
greeting = ARGV.shift || "World"
|
42
|
+
stdscr = initscr
|
43
|
+
raw
|
44
|
+
keypad stdscr, true
|
45
|
+
noecho
|
46
|
+
curs_set 0
|
47
|
+
clear
|
48
|
+
move (LINES() - 3)/3, 0
|
49
|
+
centre "Hello " + greeting + "\n"
|
50
|
+
centre "你好\n"
|
51
|
+
centre "HELLO WORLD\n"
|
52
|
+
centre fullwidth("[Testing 1234]\n\n")
|
53
|
+
centre "Press any key to continue"
|
54
|
+
refresh
|
55
|
+
ch = getch
|
56
|
+
ensure
|
57
|
+
flushinp
|
58
|
+
endwin
|
59
|
+
end
|
data/examples/keys.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
include FFI::NCurses
|
7
|
+
begin
|
8
|
+
initscr
|
9
|
+
raw
|
10
|
+
keypad stdscr, true
|
11
|
+
noecho
|
12
|
+
curs_set 0
|
13
|
+
ch = 0
|
14
|
+
name = "none"
|
15
|
+
# while ch != 27 # Escape
|
16
|
+
while ch != KEY_CTRL_Q
|
17
|
+
clear
|
18
|
+
addstr "Press any key (Ctrl-Q to exit): "
|
19
|
+
#printw "name: %s dec: %d char: [%c]", :string, name, :int, ch, :int, ch
|
20
|
+
addstr sprintf("name: %s dec: %d char: [%s]", name, ch, (1..127).include?(ch) ? ch.chr : " ")
|
21
|
+
refresh
|
22
|
+
ch = getch
|
23
|
+
name = keyname(ch)
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
endwin
|
27
|
+
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
require 'ffi-ncurses'
|
6
6
|
require 'ffi-ncurses/mouse'
|
7
|
-
require 'ffi-ncurses/
|
7
|
+
require 'ffi-ncurses/ord_shim' # for 1.8.6 compatibility
|
8
8
|
|
9
9
|
include FFI::NCurses
|
10
10
|
|
@@ -13,7 +13,7 @@ begin
|
|
13
13
|
clear
|
14
14
|
noecho
|
15
15
|
cbreak
|
16
|
-
keypad stdscr,
|
16
|
+
keypad stdscr, true
|
17
17
|
|
18
18
|
# Get all the mouse events
|
19
19
|
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nil)
|
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'ffi-ncurses'
|
3
|
+
|
4
|
+
# newterm2 - how to use more than one terminal at a time
|
5
|
+
#
|
6
|
+
# Note: ncurses knows nothing about your window manager so cannot
|
7
|
+
# switch window focus for you.
|
8
|
+
#
|
9
|
+
# This is how programmers used to do multi-screen - with more than one
|
10
|
+
# physical terminal. Typically, one would be used for input, the other
|
11
|
+
# for output.
|
12
|
+
#
|
13
|
+
# It might be useful for outputting debug info during a program for
|
14
|
+
# instance.
|
15
|
+
|
16
|
+
def log(*a)
|
17
|
+
File.open("ncurses.log", "a") do |file|
|
18
|
+
file.puts(a.inspect)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module CLib
|
23
|
+
extend FFI::Library
|
24
|
+
ffi_lib FFI::Library::LIBC
|
25
|
+
# FILE* open and close
|
26
|
+
typedef :pointer, :FILEP
|
27
|
+
attach_function :fdopen, [:int, :string], :FILEP
|
28
|
+
attach_function :fopen, [:string, :string], :FILEP
|
29
|
+
attach_function :fclose, [:FILEP], :int
|
30
|
+
attach_function :feof, [:FILEP], :int
|
31
|
+
|
32
|
+
module FileExt
|
33
|
+
def closed?
|
34
|
+
CLib.feof(self) ? true : false
|
35
|
+
end
|
36
|
+
|
37
|
+
def close
|
38
|
+
if closed?
|
39
|
+
raise IOError, "closed stream"
|
40
|
+
else
|
41
|
+
CLib.fclose(self)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def usage
|
49
|
+
abort "usage: #{$0} term1 term2\ne.g. #{$0} /dev/pts/0 /dev/pts/1"
|
50
|
+
end
|
51
|
+
|
52
|
+
if ARGV.size != 2
|
53
|
+
usage
|
54
|
+
end
|
55
|
+
term1 = ARGV[0]
|
56
|
+
term2 = ARGV[1]
|
57
|
+
|
58
|
+
if File.exist?(term1)
|
59
|
+
term1_file = File.open(term1, "rb+")
|
60
|
+
if !term1_file.tty?
|
61
|
+
term1_file.close
|
62
|
+
usage
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if File.exist?(term1)
|
67
|
+
term2_file = File.open(term2, "rb+")
|
68
|
+
if !term2_file.tty?
|
69
|
+
term2_file.close
|
70
|
+
term1_file.close
|
71
|
+
usage
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
begin
|
76
|
+
tty1 = CLib.fdopen(term1_file.fileno, "rb+")
|
77
|
+
tty1.extend(CLib::FileExt)
|
78
|
+
tty2 = CLib.fdopen(term2_file.fileno, "rb+")
|
79
|
+
tty2.extend(CLib::FileExt)
|
80
|
+
screen1 = FFI::NCurses.newterm(nil, tty1, tty1)
|
81
|
+
screen2 = FFI::NCurses.newterm(nil, tty2, tty2)
|
82
|
+
FFI::NCurses.noecho
|
83
|
+
[[screen1, "Hello"], [screen2, "World"]].each do |screen, text|
|
84
|
+
old_screen = FFI::NCurses.set_term(screen)
|
85
|
+
FFI::NCurses.curs_set(0)
|
86
|
+
FFI::NCurses.border(*([0]*8))
|
87
|
+
FFI::NCurses.move(4, 4)
|
88
|
+
FFI::NCurses.addstr(text)
|
89
|
+
FFI::NCurses.refresh
|
90
|
+
FFI::NCurses.flushinp
|
91
|
+
end
|
92
|
+
FFI::NCurses.set_term(screen1)
|
93
|
+
FFI::NCurses.curs_set(1)
|
94
|
+
FFI::NCurses.getch
|
95
|
+
rescue => e
|
96
|
+
log :e1, e
|
97
|
+
ensure
|
98
|
+
begin
|
99
|
+
# Watch the ordering of these calls, i.e. do not call delscreen
|
100
|
+
# before endwin
|
101
|
+
FFI::NCurses.flushinp
|
102
|
+
FFI::NCurses.echo
|
103
|
+
|
104
|
+
# close each terminal
|
105
|
+
[screen2, screen1].each do |screen|
|
106
|
+
FFI::NCurses.set_term(screen)
|
107
|
+
FFI::NCurses.endwin
|
108
|
+
FFI::NCurses.delscreen(screen)
|
109
|
+
end
|
110
|
+
rescue => e
|
111
|
+
log :e2, e
|
112
|
+
ensure
|
113
|
+
# [tty2, tty1] do |fd|
|
114
|
+
# CLib.fclose(fd)
|
115
|
+
# end
|
116
|
+
[tty2, tty1, term2_file, term1_file].each do |fd|
|
117
|
+
fd.close if !fd.closed? # handle case where tty1 == tty2
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$Id: LICENSES_for_examples,v 1.6 2004/05/13 21:55:17 t-peters Exp $
|
2
|
+
|
3
|
+
Ideally, an example program on how to use a library should be in the public
|
4
|
+
domain.
|
5
|
+
|
6
|
+
Some of the example programs contained in this dircectory have not been put in
|
7
|
+
the public domain, however.
|
8
|
+
|
9
|
+
The reason is because I did not write all programs completely myself -- I've
|
10
|
+
adapted the following example programs from ncurses programs in other
|
11
|
+
programming languages, or I have included example programs contributed by
|
12
|
+
other authors, and I have to respect their original licenses:
|
13
|
+
- rain.rb is adapted from rain.c from the ncurses library distribution.
|
14
|
+
- example.rb is adapted from an example program for the python ncurses binding.
|
15
|
+
- tclock.rb is adapted from tclock.c from the ncurses library distribution.
|
16
|
+
- form.rb anf form2.rb have been written by Simon Kaczor, who has adapted them
|
17
|
+
from sample code from the NCurses Programming HOWTO.
|
18
|
+
|
19
|
+
See the comments in the source files for restrictions imposed on copying and
|
20
|
+
modifying these.
|
21
|
+
|
22
|
+
That said, I suppose you may still look at their source code and learn how
|
23
|
+
ncurses programs generally work, as long as you dont start your own programs
|
24
|
+
by loading the example program into your editor and modify it to your needs.
|
25
|
+
|
26
|
+
Tobias Peters <t-peters@users.berlios.de>
|
@@ -6,8 +6,8 @@
|
|
6
6
|
# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
|
7
7
|
#
|
8
8
|
# The following license applys only to this file. It is less restrictive
|
9
|
-
# than the license for the rest of the ncurses-ruby distribution.
|
10
|
-
# I've adapted this file from someone else, see below.
|
9
|
+
# than the license for the rest of the ncurses-ruby distribution.
|
10
|
+
# I've adapted this file from someone else, see below.
|
11
11
|
#
|
12
12
|
# Permission is hereby granted, free of charge, to any person
|
13
13
|
# obtaining a copy of this file
|
@@ -16,10 +16,10 @@
|
|
16
16
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
17
17
|
# and to permit persons to whom the Software is furnished to do so,
|
18
18
|
# subject to the following conditions:
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# The above copyright notice and this permission notice shall be
|
21
21
|
# included in all copies or substantial portions of the Software.
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
24
24
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
25
25
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -36,7 +36,7 @@
|
|
36
36
|
# statement:
|
37
37
|
|
38
38
|
# Copyright (c) 2000 by Harry Henry Gebel
|
39
|
-
#
|
39
|
+
#
|
40
40
|
# Permission is hereby granted, free of charge, to any person
|
41
41
|
# obtaining a copy of this software and associated documentation files
|
42
42
|
# (the "Software"), to deal in the Software without restriction,
|
@@ -44,10 +44,10 @@
|
|
44
44
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
45
45
|
# and to permit persons to whom the Software is furnished to do so,
|
46
46
|
# subject to the following conditions:
|
47
|
-
#
|
47
|
+
#
|
48
48
|
# The above copyright notice and this permission notice shall be
|
49
49
|
# included in all copies or substantial portions of the Software.
|
50
|
-
#
|
50
|
+
#
|
51
51
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
52
52
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
53
53
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -57,73 +57,9 @@
|
|
57
57
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
58
58
|
# SOFTWARE.
|
59
59
|
|
60
|
-
require "ffi-ncurses"
|
61
|
-
require 'ffi-ncurses/ord-shim' # for 1.8.6 compatibility
|
62
60
|
|
63
|
-
module NcursesExtension
|
64
|
-
def method_missing(method, *args, &block)
|
65
|
-
FFI::NCurses.send(method, self.win, *args, &block)
|
66
|
-
end
|
67
|
-
end
|
68
61
|
|
69
|
-
|
70
|
-
FALSE = 0
|
71
|
-
TRUE = 1
|
72
|
-
module NCX
|
73
|
-
def COLS
|
74
|
-
FFI::NCurses.getmaxx(FFI::NCurses.stdscr)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
include NCX
|
78
|
-
extend NCX
|
79
|
-
class WINDOW
|
80
|
-
attr_accessor :win
|
81
|
-
def initialize(*args, &block)
|
82
|
-
if block_given?
|
83
|
-
@win = args.first
|
84
|
-
else
|
85
|
-
@win = FFI::NCurses.newwin(*args)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
def method_missing(name, *args)
|
89
|
-
name = name.to_s
|
90
|
-
if (name[0,2] == "mv")
|
91
|
-
test_name = name.dup
|
92
|
-
test_name[2,0] = "w" # insert "w" after"mv"
|
93
|
-
if (FFI::NCurses.respond_to?(test_name))
|
94
|
-
return FFI::NCurses.send(test_name, @win, *args)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
test_name = "w" + name
|
98
|
-
if (FFI::NCurses.respond_to?(test_name))
|
99
|
-
return FFI::NCurses.send(test_name, @win, *args)
|
100
|
-
end
|
101
|
-
FFI::NCurses.send(name, @win, *args)
|
102
|
-
end
|
103
|
-
def respond_to?(name)
|
104
|
-
name = name.to_s
|
105
|
-
if (name[0,2] == "mv" && FFI::NCurses.respond_to?("mvw" + name[2..-1]))
|
106
|
-
return true
|
107
|
-
end
|
108
|
-
FFI::NCurses.respond_to?("w" + name) || FFI::NCurses.respond_to?(name)
|
109
|
-
end
|
110
|
-
def del
|
111
|
-
FFI::NCurses.delwin(@win)
|
112
|
-
end
|
113
|
-
alias delete del
|
114
|
-
end
|
115
|
-
def self.initscr
|
116
|
-
@stdscr = Ncurses::WINDOW.new(FFI::NCurses.initscr) { }
|
117
|
-
end
|
118
|
-
def self.stdscr
|
119
|
-
@stdscr
|
120
|
-
end
|
121
|
-
class << self
|
122
|
-
def method_missing(method, *args, &block)
|
123
|
-
FFI::NCurses.send(method, *args, &block)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
62
|
+
require "ncurses"
|
127
63
|
|
128
64
|
def moving(scr)
|
129
65
|
scr.clear() # clear screen
|
@@ -175,14 +111,11 @@ begin
|
|
175
111
|
Ncurses.cbreak # provide unbuffered input
|
176
112
|
Ncurses.noecho # turn off input echoing
|
177
113
|
Ncurses.nonl # turn off newline translation
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
Ncurses.stdscr.
|
183
|
-
Ncurses.stdscr.keypad(Ncurses::TRUE) # turn on keypad mode
|
184
|
-
Ncurses.addstr("Press a key to continue") # output string
|
185
|
-
Ncurses.getch() # get a charachter
|
114
|
+
Ncurses.stdscr.intrflush(false) # turn off flush-on-interrupt
|
115
|
+
Ncurses.stdscr.keypad(true) # turn on keypad mode
|
116
|
+
|
117
|
+
Ncurses.stdscr.addstr("Press a key to continue") # output string
|
118
|
+
Ncurses.stdscr.getch # get a charachter
|
186
119
|
|
187
120
|
moving(Ncurses.stdscr) # demo of moving cursor
|
188
121
|
border(Ncurses.stdscr) # demo of borders
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# $Id: hello_ncurses.rb,v 1.3 2002/02/28 13:50:03 t-peters Exp $
|
4
|
+
|
5
|
+
# this ncurses-ruby program follows an ancient tradition of example
|
6
|
+
# computer programs: When invoked, it prints a friendly greeting on the
|
7
|
+
# screen and exits.
|
8
|
+
#
|
9
|
+
# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
|
10
|
+
#
|
11
|
+
# You may use, modify, and redistribute this file without restriction.
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
# First, we have to tell Ruby to use the Ncurses extension module:
|
16
|
+
|
17
|
+
require "ncurses"
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# Second, every program using ncurses must initialize the ncurses library
|
22
|
+
# before the first call to any ncurses function:
|
23
|
+
|
24
|
+
Ncurses.initscr
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
# Now the program can use ncurses facilities for screen output. It will print
|
29
|
+
# a greeting to the 5th line on the screen, starting at column 20
|
30
|
+
|
31
|
+
Ncurses.mvaddstr(4, 19, "Hello, world!");
|
32
|
+
|
33
|
+
# Note that ncurses counts lines and columns starting from 0, and that it
|
34
|
+
# expects the line number first and the column number second every time it
|
35
|
+
# expects a coordinate pair.
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
# The previous function call did not alter the screen at all. Ncurses makes
|
40
|
+
# all changes first to an internal buffer. The contents of this buffer is
|
41
|
+
# copied to the screen with the following function call:
|
42
|
+
|
43
|
+
Ncurses.refresh
|
44
|
+
|
45
|
+
|
46
|
+
# Now pause for a short while, enough time for the program user to read the
|
47
|
+
# greeting and greet back.
|
48
|
+
|
49
|
+
sleep(2.5)
|
50
|
+
|
51
|
+
|
52
|
+
# The program has almost finished its task. It only needs to put the screen
|
53
|
+
# back to its normal state:
|
54
|
+
|
55
|
+
Ncurses.endwin
|
56
|
+
|
57
|
+
|