ruby-terminfo-r3 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/ChangeLog +44 -0
  2. data/README +92 -0
  3. data/extconf.rb +80 -0
  4. data/lib/terminfo.rb +140 -0
  5. data/make_gem +24 -0
  6. data/terminfo.c +427 -0
  7. metadata +73 -0
data/ChangeLog ADDED
@@ -0,0 +1,44 @@
1
+ 2009-03-06 Tanaka Akira <akr@fsij.org>
2
+
3
+ * version 0.2 released.
4
+
5
+ 2008-12-30 Tanaka Akira <akr@fsij.org>
6
+
7
+ * terminfo.c (rt_wcswidth): check the return value of wcwidth.
8
+
9
+ 2008-12-30 Tanaka Akira <akr@fsij.org>
10
+
11
+ * terminfo.c: prefer ruby/io.h over rubyio.h.
12
+ include wchar.h.
13
+ (FILENO): condition refined.
14
+ (rt_wcswidth): new method TermInfo.wcswidth.
15
+
16
+ * extconf.rb: check ruby/io.h and ruby/encoding.h.
17
+
18
+ 2007-05-30 Tanaka Akira <akr@fsij.org>
19
+
20
+ * terminfo.c (TermInfo.ctermid): defined.
21
+
22
+ * lib/terminfo.rb, sample/resize: use TermInfo.ctermid instead of
23
+ "/dev/tty".
24
+
25
+ 2007-05-29 Tanaka Akira <akr@fsij.org>
26
+
27
+ * sample/resize: new sample program.
28
+
29
+ 2007-04-29 Tanaka Akira <akr@fsij.org>
30
+
31
+ * lib/terminfo.rb (TermInfo.default_object): Use File::NOCTTY for
32
+ opening /dev/tty to avoid acquire a controlling terminal.
33
+
34
+ 2007-04-19 Tanaka Akira <akr@fsij.org>
35
+
36
+ * extconf.rb, terminfo.c: try ncurses.h when ncurses is used.
37
+ NetBSD has curses.h which is incompatible with ncurses.
38
+
39
+ * terminfo.c: define del_curterm empty on FreeBSD and OpenBSD to
40
+ avoid warning and core dump.
41
+
42
+ 2007-04-10 Tanaka Akira <akr@fsij.org>
43
+
44
+ * version 0.1 released.
data/README ADDED
@@ -0,0 +1,92 @@
1
+ = ruby-terminfo-r3 - terminfo binding for Ruby-3
2
+
3
+ ruby-terminfo-r3 is a terminfo binding for Ruby-3. It is a repackaged version
4
+ of the Ruby-2 package ruby-terminfo.
5
+
6
+ Use './make_gem' to build the GEM.
7
+
8
+ The home page for this package is https://github.com/clrgit/ruby-terminfo-r3,
9
+ the original README follows below:
10
+
11
+ = ruby-terminfo - terminfo binding for Ruby
12
+
13
+ ruby-terminfo is a terminfo binding for Ruby
14
+
15
+ == Author
16
+
17
+ Tanaka Akira <akr@fsij.org>
18
+
19
+ == Home Page
20
+
21
+ http://www.a-k-r.org/ruby-terminfo/
22
+
23
+ == Feature
24
+
25
+ * easy to use method, control, for combination of tigetstr/tparm/tputs
26
+ * low-level terminfo binding (setupterm, tigetflag, tigetnum, tigetstr, tparm, tputs)
27
+ * TIOCGWINSZ/TIOCSWINSZ ioctl for screen size
28
+ * ctermid to avoid hardcoding /dev/tty
29
+ * wcswidth to measure a string width in number of columns
30
+
31
+ == Usage
32
+
33
+ === easy to use methods
34
+
35
+ require 'terminfo'
36
+ TermInfo.control("cuf", 7) # cursor forward 7 columns
37
+ p TermInfo.screen_size # use TIOCGWINSZ, LINES/COLUMNS env. or terminfo lines#/cols#
38
+
39
+ === low level methods
40
+
41
+ require 'terminfo'
42
+ t = TermInfo.new(ENV["TERM"], File.open(TermInfo.ctermid, "r+"))
43
+ print t.tputs(t.tparm(t.tigetstr("cuf"), 7), 1) # cursor forward 7 columns
44
+ p TermInfo.tiocgwinsz(STDOUT) # use TIOCGWINSZ
45
+
46
+ == Requirements
47
+
48
+ * ruby : http://www.ruby-lang.org/
49
+
50
+ == Download
51
+
52
+ * latest release: http://www.a-k-r.org/ruby-terminfo/ruby-terminfo-0.2.tar.gz
53
+
54
+ * development version: http://github.com/akr/ruby-terminfo
55
+
56
+ == Install
57
+
58
+ % ruby extconf.rb
59
+ % make
60
+ % make install
61
+
62
+ == Reference Manual
63
+
64
+ See rdoc/TermInfo.html or
65
+ http://www.a-k-r.org/ruby-terminfo/rdoc/TermInfo.html
66
+
67
+ == License
68
+
69
+
70
+ Redistribution and use in source and binary forms, with or without
71
+ modification, are permitted provided that the following conditions are met:
72
+
73
+ (1) Redistributions of source code must retain the above copyright notice, this
74
+ list of conditions and the following disclaimer.
75
+ (2) Redistributions in binary form must reproduce the above copyright notice,
76
+ this list of conditions and the following disclaimer in the documentation
77
+ and/or other materials provided with the distribution.
78
+ (3) The name of the author may not be used to endorse or promote products
79
+ derived from this software without specific prior written permission.
80
+
81
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
82
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
83
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
84
+ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
85
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
86
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
87
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
88
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
89
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
90
+ OF SUCH DAMAGE.
91
+
92
+ (The modified BSD licence)
data/extconf.rb ADDED
@@ -0,0 +1,80 @@
1
+ # extconf.rb - a part of a Ruby binding for terminfo library.
2
+ #
3
+ # Copyright (C) 2007 Tanaka Akira. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following
13
+ # disclaimer in the documentation and/or other materials provided
14
+ # with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote
16
+ # products derived from this software without specific prior
17
+ # written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'mkmf'
32
+
33
+ # Debian GNU/Linux 4.0 (etch) curses.h, term.h, -lncurses (ncurses.h is linked to curses.h)
34
+ # FreeBSD 6.2 curses.h, term.h, -lncurses (ncurses.h is linked to curses.h)
35
+ # OpenBSD 4.0 curses.h, term.h, -lncurses (curses.h includes ncurses.h by default)
36
+ # HP-UX 11i v3 term.h, -lcurses
37
+ # SunOS 5.10 curses.h, term.h, -lcurses
38
+
39
+ # NetBSD 3.1 with ncurses ncurses.h, -lncurses (curses.h is incompatible for ncurses)
40
+
41
+ have_header("curses.h")
42
+ have_header("term.h")
43
+
44
+ have_func("ctermid", "stdio.h")
45
+
46
+ has_setupterm = true
47
+ if have_library("ncurses", "setupterm")
48
+ have_header("ncurses.h")
49
+ elsif have_library("curses", "setupterm")
50
+ else
51
+ has_setupterm = false
52
+ end
53
+
54
+ have_header("wchar.h")
55
+
56
+ rubyio_h = nil
57
+ rubyio_h = "ruby/io.h" if have_header("ruby/io.h")
58
+ rubyio_h = "rubyio.h" unless rubyio_h
59
+
60
+ if have_type("rb_io_t", ["ruby.h", rubyio_h])
61
+ have_struct_member("rb_io_t", "fd", ["ruby.h", rubyio_h])
62
+ else
63
+ have_struct_member("OpenFile", "fd", ["ruby.h", rubyio_h])
64
+ end
65
+
66
+ have_header("ruby/encoding.h")
67
+
68
+ if has_setupterm
69
+ create_header
70
+ create_makefile('terminfo')
71
+
72
+ open("Makefile", "a") {|mfile|
73
+ mfile.puts <<'End'
74
+ rdoc:
75
+ rdoc --op rdoc terminfo.c lib/terminfo.rb
76
+ End
77
+ }
78
+ else
79
+ puts "terminfo library not found"
80
+ end
data/lib/terminfo.rb ADDED
@@ -0,0 +1,140 @@
1
+ # terminfo.rb - a part of a Ruby binding for terminfo library.
2
+ #
3
+ # Copyright (C) 2007 Tanaka Akira. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following
13
+ # disclaimer in the documentation and/or other materials provided
14
+ # with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote
16
+ # products derived from this software without specific prior
17
+ # written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'terminfo.so'
32
+
33
+ class TermInfo
34
+ def TermInfo.default_object
35
+ unless defined? @default_terminfo
36
+ io = File.open(TermInfo.ctermid, File::RDWR|File::NOCTTY)
37
+ io.sync = true
38
+ @default_terminfo = TermInfo.new(ENV['TERM'], io)
39
+ end
40
+ @default_terminfo
41
+ end
42
+
43
+ def TermInfo.control_string(*args) default_object.control_string(*args) end
44
+ def TermInfo.control(*args) default_object.control(*args) end
45
+ def TermInfo.write(str) default_object.write(str) end
46
+ def TermInfo.flush(&block) default_object.flush(&block) end
47
+ def TermInfo.screen_size() default_object.screen_size() end
48
+ def TermInfo.screen_lines() default_object.screen_lines() end
49
+ def TermInfo.screen_height() default_object.screen_height() end
50
+ def TermInfo.screen_columns() default_object.screen_columns() end
51
+ def TermInfo.screen_width() default_object.screen_width() end
52
+ def TermInfo.io() default_object.io() end
53
+
54
+ def initialize(term=ENV['TERM'], io=STDERR)
55
+ setupterm(term, io.fileno)
56
+ @term = term
57
+ @io = io
58
+ end
59
+ attr_reader :io
60
+
61
+ def inspect
62
+ "\#<#{self.class}:#{@term}>"
63
+ end
64
+
65
+ # TermInfo#control_string return a string to control terminal.
66
+ #
67
+ # TermInfo#control_string([afflines,] capname, p1, p2, ...)
68
+ #
69
+ # capname is a terminfo string capability such as "cuu", "el".
70
+ #
71
+ # p1, p2, ... are parameters for the capability.
72
+ #
73
+ # afflines is a number of lines affected. (used for determining padding length)
74
+ def control_string(*args)
75
+ afflines = 1
76
+ raise ArgumentError, "capname requried" if args.empty?
77
+ afflines = args.shift.to_i if args.first.respond_to?(:to_int)
78
+ raise ArgumentError, "capname not given" if !args.first.respond_to?(:to_str)
79
+ capname = args.shift.to_str
80
+ self.tputs(self.tparm(self.tigetstr(capname), *args), afflines)
81
+ end
82
+
83
+ # TermInfo#control controls a terminal.
84
+ #
85
+ # It prints the result of control_string to io specified at initialization.
86
+ def control(*args)
87
+ @io.write(self.control_string(*args))
88
+ nil
89
+ end
90
+
91
+ def write(str)
92
+ @io.write(str)
93
+ end
94
+
95
+ def flush
96
+ oldlevel = nil
97
+ if block_given?
98
+ oldlevel = Thread.current[:TermInfo_Flush_level]
99
+ oldsync = @io.sync
100
+ begin
101
+ Thread.current[:TermInfo_Flush_level] = (oldlevel || 0) + 1
102
+ @io.sync = false
103
+ yield
104
+ ensure
105
+ Thread.current[:TermInfo_Flush_level] = oldlevel
106
+ @io.sync = oldsync
107
+ end
108
+ end
109
+ @io.flush if oldlevel == nil
110
+ nil
111
+ end
112
+
113
+ # returns terminal screen size in a two element array: [lines, columns].
114
+ def screen_size
115
+ begin
116
+ size = TermInfo.tiocgwinsz(@io)
117
+ rescue NotImplementedError
118
+ size = [0,0]
119
+ end
120
+ if size[0] == 0
121
+ size[0] = ENV.include?('LINES') ? ENV['LINES'].to_i : self.tigetnum("lines")
122
+ end
123
+ if size[1] == 0
124
+ size[1] = ENV.include?('COLUMNS') ? ENV['COLUMNS'].to_i : self.tigetnum("cols")
125
+ end
126
+ size
127
+ end
128
+
129
+ # returns terminal screen height.
130
+ def screen_lines
131
+ self.screen_size[0]
132
+ end
133
+ alias screen_height screen_lines
134
+
135
+ # returns terminal screen width.
136
+ def screen_columns
137
+ self.screen_size[1]
138
+ end
139
+ alias screen_width screen_columns
140
+ end
data/make_gem ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/bash
2
+
3
+ set -eo pipefail
4
+
5
+ # Create the GEM package. The gem command is not used to create the package
6
+ # because it doesn't contain a Gemspec file. Instead it is create using tar and
7
+ # gzip
8
+
9
+ NAME="ruby-terminfo-r3"
10
+ VERSION="0.1.1"
11
+ PCK=$NAME-$VERSION
12
+ FILES="README ChangeLog lib/terminfo.rb terminfo.c extconf.rb make_gem"
13
+
14
+ tar cf - $FILES | gzip --best --stdout >data.tar.gz
15
+ gzip --best --stdout metadata >metadata.gz
16
+ tar cf $PCK.gem data.tar.gz metadata.gz
17
+ rm data.tar.gz metadata.gz
18
+
19
+
20
+ #tar zcf - $FILES | gzip --best --stdout >data.tar.gz
21
+ #gzip --best --stdout metadata >metadata.gz
22
+ #tar cf $PCK.gem data.tar.gz metadata.gz
23
+ #rm data.tar.gz metadata.gz
24
+
data/terminfo.c ADDED
@@ -0,0 +1,427 @@
1
+ /* terminfo.c - Ruby binding for terminfo library.
2
+
3
+ Copyright (C) 2007, 2008 Tanaka Akira. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+ 3. The name of the author may not be used to endorse or promote
16
+ products derived from this software without specific prior
17
+ written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ #include "ruby.h"
33
+ #ifdef HAVE_RUBY_IO_H
34
+ # include "ruby/io.h"
35
+ #else
36
+ # include "rubyio.h"
37
+ #endif
38
+ #include "extconf.h"
39
+
40
+ #if defined(HAVE_NCURSES_H)
41
+ #include <ncurses.h>
42
+ #elif defined(HAVE_CURSES_H)
43
+ #include <curses.h>
44
+ #endif
45
+
46
+ #ifdef HAVE_TERM_H
47
+ #include <term.h>
48
+ #endif
49
+
50
+ #include <termios.h>
51
+ #include <sys/ioctl.h>
52
+ #include <unistd.h>
53
+
54
+ #ifdef HAVE_WCHAR_H
55
+ #include <wchar.h>
56
+ #endif
57
+
58
+ static VALUE cTermInfo;
59
+ static VALUE eTermInfoError;
60
+
61
+ #ifndef HAVE_TYPE_RB_IO_T
62
+ typedef OpenFile rb_io_t;
63
+ #endif
64
+
65
+ #if defined(HAVE_RB_IO_T_FD) || defined(HAVE_ST_FD)
66
+ # define FILENO(fptr) (fptr->fd)
67
+ #else
68
+ # define FILENO(fptr) fileno(fptr->f)
69
+ #endif
70
+
71
+ #if (defined(__FreeBSD__) && __FreeBSD_cc_version <= 602001) || \
72
+ defined(__OpenBSD__)
73
+ /*
74
+ * warning on FreeBSD
75
+ http://www.FreeBSD.org/cgi/query-pr.cgi?pr=108117&cat=
76
+ * core dump on OpenBSD
77
+ http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&textonly=yes&numbers=5447
78
+ */
79
+ #define del_curterm(oterm) do {} while(0)
80
+ #endif
81
+
82
+ static void
83
+ rt_free(void *ptr)
84
+ {
85
+ if(ptr != NULL)
86
+ del_curterm(ptr);
87
+ }
88
+
89
+ static VALUE
90
+ rt_alloc(VALUE klass)
91
+ {
92
+ return Data_Wrap_Struct(klass, NULL, rt_free, 0);
93
+ }
94
+
95
+ static TERMINAL *
96
+ check_rt(VALUE self)
97
+ {
98
+ Check_Type(self, T_DATA);
99
+ if (RDATA(self)->dfree != rt_free) {
100
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected TermInfo)",
101
+ rb_class2name(CLASS_OF(self)));
102
+ }
103
+ return DATA_PTR(self);
104
+ }
105
+
106
+ static void
107
+ setup(VALUE self)
108
+ {
109
+ TERMINAL *old;
110
+ TERMINAL *term = check_rt(self);
111
+ if (term == NULL) { rb_raise(eTermInfoError, "terminfo object not initialized"); }
112
+ if (cur_term == term)
113
+ return;
114
+ old = set_curterm(term);
115
+ }
116
+
117
+ /*
118
+ * TermInfo#setupterm(term, fd) => int
119
+ *
120
+ * TermInfo#setupterm initializes TermInfo object.
121
+ *
122
+ * term is a string of nil.
123
+ * If nil is given, the environment variable $TERM is used.
124
+ *
125
+ * fd is a file descriptor for target terminal.
126
+ */
127
+ static VALUE
128
+ rt_setupterm(VALUE self, VALUE v_term, VALUE v_fd)
129
+ {
130
+ char *term;
131
+ int fd;
132
+ int err;
133
+ int ret;
134
+ if (check_rt(self) != NULL) { rb_raise(eTermInfoError, "terminfo object already initialized"); }
135
+
136
+ if (v_term == Qnil)
137
+ term = NULL;
138
+ else
139
+ term = StringValueCStr(v_term);
140
+ fd = NUM2INT(v_fd);
141
+
142
+ ret = setupterm(term, fd, &err);
143
+ if (ret == ERR) {
144
+ if (err == 1) rb_raise(eTermInfoError, "hardcopy terminal");
145
+ else if (err == 0) rb_raise(eTermInfoError, "terminal could not be found");
146
+ else if (err == -1) rb_raise(eTermInfoError, "terminfo database could not be found");
147
+ else rb_raise(eTermInfoError, "unexpected setupterm error");
148
+ }
149
+
150
+ DATA_PTR(self) = cur_term;
151
+
152
+ return INT2NUM(err);
153
+ }
154
+
155
+ /*
156
+ * TermInfo#tigetflag(capname) => int
157
+ *
158
+ * TermInfo#tigetflag returns a boolean capability specified by capname.
159
+ */
160
+ static VALUE
161
+ rt_tigetflag(VALUE self, VALUE v_capname)
162
+ {
163
+ int ret;
164
+ setup(self);
165
+ ret = tigetflag(StringValueCStr(v_capname));
166
+ if (ret == -1) { rb_raise(eTermInfoError, "not a boolean capability"); }
167
+ return RTEST(ret) ? Qtrue : Qfalse;
168
+ }
169
+
170
+ /*
171
+ * TermInfo#tigetnum(capname) => int
172
+ *
173
+ * TermInfo#tigetnum returns a numeric capability specified by capname.
174
+ */
175
+ static VALUE
176
+ rt_tigetnum(VALUE self, VALUE v_capname)
177
+ {
178
+ int ret;
179
+ setup(self);
180
+ ret = tigetnum(StringValueCStr(v_capname));
181
+ if (ret == -2) { rb_raise(eTermInfoError, "not a numeric capability"); }
182
+ if (ret == -1) { rb_raise(eTermInfoError, "canceled or absent numeric capability"); }
183
+ return INT2NUM(ret);
184
+ }
185
+
186
+ /*
187
+ * TermInfo#tigetstr(capname) => str
188
+ *
189
+ * TermInfo#tigetstr returns a string capability specified by capname.
190
+ *
191
+ * The return value should be printed after tputs is applied.
192
+ * Also tparm should be applied if it has parameters.
193
+ *
194
+ * io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2))
195
+ *
196
+ * Note that "cuf" means "cursor forward".
197
+ */
198
+ static VALUE
199
+ rt_tigetstr(VALUE self, VALUE v_capname)
200
+ {
201
+ char *ret;
202
+ setup(self);
203
+ ret = tigetstr(StringValueCStr(v_capname));
204
+ if (ret == (char*)-1) {
205
+ rb_raise(eTermInfoError, "not a string capability");
206
+ }
207
+ if (ret == 0) {
208
+ rb_raise(eTermInfoError, "canceled or absent string capability");
209
+ }
210
+ return rb_str_new2(ret);
211
+ }
212
+
213
+ /*
214
+ * TermInfo#tparm(str, ...) => str
215
+ *
216
+ * TermInfo#tparm expands parameters in str returned by tigetstr.
217
+ */
218
+ static VALUE
219
+ rt_tparm(int argc, VALUE *argv, VALUE self)
220
+ {
221
+ char *capname, *ret;
222
+ setup(self);
223
+ VALUE v_capname, v1, v2, v3, v4, v5, v6, v7, v8, v9;
224
+ long p1, p2, p3, p4, p5, p6, p7, p8, p9;
225
+ setup(self);
226
+
227
+ if (rb_scan_args(argc, argv, "19", &v_capname, &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9) == 0) {
228
+ rb_raise(rb_eArgError, "capname required");
229
+ }
230
+
231
+ capname = StringValueCStr(v_capname);
232
+ #define conv(p, v) do { if (v == Qnil) p = 0; else p = NUM2LONG(v); } while(0)
233
+ conv(p1, v1);
234
+ conv(p2, v2);
235
+ conv(p3, v3);
236
+ conv(p4, v4);
237
+ conv(p5, v5);
238
+ conv(p6, v6);
239
+ conv(p7, v7);
240
+ conv(p8, v8);
241
+ conv(p9, v9);
242
+
243
+ ret = tparm(capname, p1, p2, p3, p4, p5, p6, p7, p8, p9);
244
+
245
+ if (ret == NULL) { rb_raise(eTermInfoError, "tparm failed"); }
246
+
247
+ return rb_str_new2(ret);
248
+ }
249
+
250
+ static VALUE putfunc_output; /* xxx: not thread safe */
251
+
252
+ static int
253
+ putfunc(int arg)
254
+ {
255
+ char ch = arg;
256
+ rb_str_cat(putfunc_output, &ch, 1);
257
+ return arg;
258
+ }
259
+
260
+ /*
261
+ * TermInfo#tputs(str, affcnt) => str
262
+ *
263
+ * TermInfo#tputs expands padding informaiton using padding characters.
264
+ * affcnt is a number of lines affected by the str.
265
+ */
266
+ static VALUE
267
+ rt_tputs(VALUE self, VALUE v_str, VALUE v_affcnt)
268
+ {
269
+ int ret;
270
+ char *str;
271
+ int affcnt;
272
+ VALUE output;
273
+
274
+ setup(self);
275
+ str = StringValueCStr(v_str);
276
+ affcnt = NUM2INT(v_affcnt);
277
+
278
+ putfunc_output = output = rb_str_new2("");
279
+ ret = tputs(str, affcnt, putfunc);
280
+ putfunc_output = Qnil;
281
+
282
+ if (ret == ERR) { rb_raise(eTermInfoError, "tputs failed"); }
283
+
284
+ return output;
285
+ }
286
+
287
+ /*
288
+ * TermInfo.tiocgwinsz(io) => [row, col]
289
+ *
290
+ * TermInfo.tiocgwinsz returns the screen size of the terminal refered by io,
291
+ * using TIOCGWINSZ ioctl.
292
+ */
293
+ static VALUE
294
+ rt_tiocgwinsz(VALUE self, VALUE io)
295
+ {
296
+ #ifdef TIOCGWINSZ
297
+ rb_io_t *fptr;
298
+ struct winsize sz;
299
+ int ret;
300
+
301
+ GetOpenFile(io, fptr);
302
+
303
+ ret = ioctl(FILENO(fptr), TIOCGWINSZ, &sz);
304
+ if (ret == -1) rb_raise(rb_eIOError, "TIOCGWINSZ failed");
305
+
306
+ return rb_ary_new3(2, INT2NUM(sz.ws_row), INT2NUM(sz.ws_col));
307
+ #else
308
+ rb_notimplement();
309
+ #endif
310
+ }
311
+
312
+ /*
313
+ * TermInfo.tiocswinsz(io, row, col)
314
+ *
315
+ * TermInfo.tiocgwinsz update the screen size information of the terminal refered by io,
316
+ * using TIOCSWINSZ ioctl.
317
+ *
318
+ * It returns nil.
319
+ */
320
+ static VALUE
321
+ rt_tiocswinsz(VALUE self, VALUE io, VALUE row, VALUE col)
322
+ {
323
+ #ifdef TIOCSWINSZ
324
+ rb_io_t *fptr;
325
+ struct winsize sz;
326
+ int ret;
327
+
328
+ GetOpenFile(io, fptr);
329
+
330
+ sz.ws_row = NUM2INT(row);
331
+ sz.ws_col = NUM2INT(col);
332
+
333
+ ret = ioctl(FILENO(fptr), TIOCSWINSZ, &sz);
334
+ if (ret == -1) rb_raise(rb_eIOError, "TIOCSWINSZ failed");
335
+
336
+ return Qnil;
337
+ #else
338
+ rb_notimplement();
339
+ #endif
340
+ }
341
+
342
+ /*
343
+ * TermInfo.ctermid
344
+ *
345
+ * TermInfo.ctermid returns a pathname for the current controling terminal,
346
+ * such as "/dev/tty".
347
+ */
348
+ static VALUE
349
+ rt_ctermid(VALUE self)
350
+ {
351
+ #ifdef HAVE_CTERMID
352
+ char buf[L_ctermid];
353
+ return rb_str_new2(ctermid(buf));
354
+ #else
355
+ return rb_str_new2("/dev/tty");
356
+ #endif
357
+ }
358
+
359
+ /*
360
+ * TermInfo.wcswidth(str)
361
+ *
362
+ * TermInfo.wcswidth returns a the number of columns of str,
363
+ * according to current locale.
364
+ */
365
+ static VALUE
366
+ rt_wcswidth(VALUE self, VALUE str)
367
+ {
368
+ char *s;
369
+ size_t l, r;
370
+ mbstate_t mbs;
371
+ wchar_t wc;
372
+ long cols;
373
+ int width;
374
+
375
+ #ifdef HAVE_RUBY_ENCODING_H
376
+ /* The encoding of str is assumed to be the locale encoding on Ruby 1.8. */
377
+ str = rb_str_encode(str, rb_enc_from_encoding(rb_locale_encoding()), 0, Qnil);
378
+ #endif
379
+
380
+ memset(&mbs,0,sizeof(mbstate_t));
381
+
382
+ s = StringValueCStr(str);
383
+ l = RSTRING_LEN(str);
384
+
385
+ cols = 0;
386
+ while (0 < l) {
387
+ r = mbrtowc(&wc, s, l, &mbs);
388
+ if (r == 0)
389
+ rb_raise(rb_eArgError, "NUL found");
390
+
391
+ width = wcwidth(wc);
392
+ if (width == -1)
393
+ rb_raise(rb_eArgError, "non-printable charactor found");
394
+ cols += width;
395
+
396
+ l -= r;
397
+ s += r;
398
+ }
399
+
400
+ return LONG2NUM(cols);
401
+ }
402
+
403
+ void
404
+ Init_terminfo()
405
+ {
406
+ putfunc_output = Qnil;
407
+ rb_global_variable(&putfunc_output);
408
+
409
+ cTermInfo = rb_define_class("TermInfo", rb_cData);
410
+ eTermInfoError = rb_define_class_under(cTermInfo, "TermInfoError", rb_eRuntimeError);
411
+
412
+ rb_define_alloc_func(cTermInfo, rt_alloc);
413
+
414
+ rb_define_method(cTermInfo, "setupterm", rt_setupterm, 2);
415
+ rb_define_method(cTermInfo, "tigetflag", rt_tigetflag, 1);
416
+ rb_define_method(cTermInfo, "tigetnum", rt_tigetnum, 1);
417
+ rb_define_method(cTermInfo, "tigetstr", rt_tigetstr, 1);
418
+ rb_define_method(cTermInfo, "tparm", rt_tparm, -1);
419
+ rb_define_method(cTermInfo, "tputs", rt_tputs, 2);
420
+
421
+ rb_define_module_function(cTermInfo, "tiocgwinsz", rt_tiocgwinsz, 1);
422
+ rb_define_module_function(cTermInfo, "tiocswinsz", rt_tiocswinsz, 3);
423
+
424
+ rb_define_module_function(cTermInfo, "ctermid", rt_ctermid, 0);
425
+
426
+ rb_define_module_function(cTermInfo, "wcswidth", rt_wcswidth, 1);
427
+ }
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-terminfo-r3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tanaka Akira
8
+ - Claus Rasmussen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2022-07-20 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: terminfo binding for Ruby-3. Derives from the ruby-terminfo package
18
+ email: akr@fsij.org
19
+ executables: []
20
+
21
+ extensions:
22
+ - extconf.rb
23
+ extra_rdoc_files:
24
+ - README
25
+ - ChangeLog
26
+ files:
27
+ - README
28
+ - ChangeLog
29
+ - lib/terminfo.rb
30
+ - terminfo.c
31
+ - extconf.rb
32
+ - make_gem
33
+ has_rdoc: true
34
+ homepage: http://ruby-terminfo.rubyforge.org
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --title
40
+ - ruby-terminfo documentation
41
+ - --charset
42
+ - utf-8
43
+ - --opname
44
+ - index.html
45
+ - --line-numbers
46
+ - --main
47
+ - README
48
+ - --inline-source
49
+ - --exclude
50
+ - ^(examples|extras)/
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: ruby-terminfo
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: terminfo binding for Ruby-3
72
+ test_files: []
73
+