notcurses 0.0.1 → 0.0.2
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 +4 -4
- data/CHANGELOG.md +54 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +9 -1
- data/Rakefile +11 -0
- data/Rakefile.new +28 -0
- data/TODO +19 -0
- data/checksums/notcurses-0.0.1.gem.sha512 +1 -0
- data/data/PurpleDrank.jpg +0 -0
- data/data/Windows10Logo.png +0 -0
- data/data/aidsrobots.jpeg +0 -0
- data/data/atma.png +0 -0
- data/data/changes.jpg +0 -0
- data/data/changes.xcf +0 -0
- data/data/chunli01.png +0 -0
- data/data/chunli02.png +0 -0
- data/data/chunli03.png +0 -0
- data/data/chunli04.png +0 -0
- data/data/chunli05.png +0 -0
- data/data/chunli06.png +0 -0
- data/data/chunli07.png +0 -0
- data/data/chunli08.png +0 -0
- data/data/chunli09.png +0 -0
- data/data/chunli1.bmp +0 -0
- data/data/chunli10.png +0 -0
- data/data/chunli11.png +0 -0
- data/data/chunli12.png +0 -0
- data/data/chunli13.png +0 -0
- data/data/chunli14.png +0 -0
- data/data/chunli15.png +0 -0
- data/data/chunli16.png +0 -0
- data/data/chunli17.png +0 -0
- data/data/chunli18.png +0 -0
- data/data/chunli19.png +0 -0
- data/data/chunli2.bmp +0 -0
- data/data/chunli20.png +0 -0
- data/data/chunli21.png +0 -0
- data/data/chunli22.png +0 -0
- data/data/chunli23.png +0 -0
- data/data/chunli24.png +0 -0
- data/data/chunli25.png +0 -0
- data/data/chunli26.png +0 -0
- data/data/chunli27.png +0 -0
- data/data/chunli28.png +0 -0
- data/data/chunli29.png +0 -0
- data/data/chunli3.bmp +0 -0
- data/data/chunli30.png +0 -0
- data/data/chunli31.png +0 -0
- data/data/chunli32.png +1 -0
- data/data/chunli33.png +1 -0
- data/data/chunli34.png +1 -0
- data/data/chunli35.png +1 -0
- data/data/chunli36.png +1 -0
- data/data/chunli37.png +1 -0
- data/data/chunli38.png +0 -0
- data/data/chunli39.png +1 -0
- data/data/chunli4.bmp +0 -0
- data/data/chunli40.png +0 -0
- data/data/chunli41.png +1 -0
- data/data/chunli42.png +1 -0
- data/data/chunli43.png +1 -0
- data/data/chunli44.png +1 -0
- data/data/chunli45.png +0 -0
- data/data/chunli5.bmp +0 -0
- data/data/chunli6.bmp +0 -0
- data/data/chunli7.bmp +0 -0
- data/data/chunli8.bmp +0 -0
- data/data/covid19.jpg +0 -0
- data/data/dsscaw-purp.png +0 -0
- data/data/eagles.png +0 -0
- data/data/fm6.mov +0 -0
- data/data/fonts.jpg +0 -0
- data/data/freebsd.png +0 -0
- data/data/lamepatents.jpg +0 -0
- data/data/megaman2.bmp +0 -0
- data/data/natasha-blur.png +0 -0
- data/data/natasha-blur.xcf +0 -0
- data/data/normal.png +0 -0
- data/data/normal.xcf +0 -0
- data/data/notcurses.png +0 -0
- data/data/notcursesIII.mov +0 -0
- data/data/onedot.png +0 -0
- data/data/samoa.avi +0 -0
- data/data/samoa.osp +296 -0
- data/data/spaceship.png +0 -0
- data/data/tetris-background.jpg +0 -0
- data/data/tetris-background.xcf +0 -0
- data/data/warmech.bmp +0 -0
- data/data/worldmap.png +0 -0
- data/exe/notcurses-ruby-testscript +57 -0
- data/ext/notcurses/extconf.rb +56 -17
- data/ext/notcurses/{notcurses_wrap.c → src/notcurses_wrap.c} +55459 -18930
- data/ext/notcurses/swig/notcurses.i +552 -0
- data/lib/notcurses/swig_mixins/struct_initializer.rb +25 -0
- data/lib/notcurses/swig_mixins/to_h.rb +22 -0
- data/lib/notcurses/version.rb +1 -1
- data/lib/notcurses.rb +34 -1
- metadata +98 -11
- data/ext/notcurses/Makefile +0 -269
- data/ext/notcurses/notcurses.i +0 -282
- data/ext/notcurses/notcurses_wrapper.h +0 -20
- /data/ext/notcurses/{ncplane_vprintf_aligned.c → src/ruby_ncplane_vprintf_aligned.c} +0 -0
- /data/ext/notcurses/{ncplane_vprintf_stained.c → src/ruby_ncplane_vprintf_stained.c} +0 -0
- /data/ext/notcurses/{ncplane_vprintf_yx.c → src/ruby_ncplane_vprintf_yx.c} +0 -0
- /data/ext/notcurses/{modified_ruby_std_wstring.i → swig/modified_ruby_std_wstring.i} +0 -0
@@ -0,0 +1,552 @@
|
|
1
|
+
%module notcurses
|
2
|
+
|
3
|
+
%feature("autodoc", "2");
|
4
|
+
%feature("kwargs", "1");
|
5
|
+
|
6
|
+
%constant unsigned long NANOSECS_IN_SEC = 1000000000ul;
|
7
|
+
%constant const char* PRIu64 = PRIu64;
|
8
|
+
%constant const char* PRId64 = PRId64;
|
9
|
+
|
10
|
+
// These empty defines are needed because SWIG seems to think compound macros
|
11
|
+
// are syntax errors.
|
12
|
+
%define __attribute__(x)
|
13
|
+
%enddef
|
14
|
+
%define __attribute(x)
|
15
|
+
%enddef
|
16
|
+
%define __declspec(x)
|
17
|
+
%enddef
|
18
|
+
%define __nonnull(x)
|
19
|
+
%enddef
|
20
|
+
|
21
|
+
%include <ruby/rubywstrings.swg>
|
22
|
+
%include <./modified_ruby_std_wstring.i>
|
23
|
+
|
24
|
+
%include <carrays.i>
|
25
|
+
%include <cdata.i>
|
26
|
+
%include <cmalloc.i>
|
27
|
+
%include <constraints.i>
|
28
|
+
%include <cpointer.i>
|
29
|
+
%include <cstring.i>
|
30
|
+
%include <inttypes.i>
|
31
|
+
%include <math.i>
|
32
|
+
%include <stdint.i>
|
33
|
+
%include <wchar.i>
|
34
|
+
|
35
|
+
%include <typemaps/attribute.swg>
|
36
|
+
%include <typemaps/carrays.swg>
|
37
|
+
%include <typemaps/cdata.swg>
|
38
|
+
%include <typemaps/cmalloc.swg>
|
39
|
+
%include <typemaps/cpointer.swg>
|
40
|
+
%include <typemaps/cstrings.swg>
|
41
|
+
%include <typemaps/cstring.swg>
|
42
|
+
%include <typemaps/cwstring.swg>
|
43
|
+
%include <typemaps/enumint.swg>
|
44
|
+
%include <typemaps/exception.swg>
|
45
|
+
%include <typemaps/factory.swg>
|
46
|
+
%include <typemaps/fragments.swg>
|
47
|
+
%include <typemaps/implicit.swg>
|
48
|
+
%include <typemaps/inoutlist.swg>
|
49
|
+
%include <typemaps/misctypes.swg>
|
50
|
+
%include <typemaps/primtypes.swg>
|
51
|
+
%include <typemaps/ptrtypes.swg>
|
52
|
+
%include <typemaps/strings.swg>
|
53
|
+
%include <typemaps/string.swg>
|
54
|
+
%include <typemaps/swigmacros.swg>
|
55
|
+
%include <typemaps/swigobject.swg>
|
56
|
+
%include <typemaps/swigtypemaps.swg>
|
57
|
+
%include <typemaps/swigtype.swg>
|
58
|
+
%include <typemaps/typemaps.swg>
|
59
|
+
%include <typemaps/valtypes.swg>
|
60
|
+
%include <typemaps/void.swg>
|
61
|
+
%include <typemaps/wstring.swg>
|
62
|
+
|
63
|
+
%include <ruby/ruby.swg>
|
64
|
+
%include <ruby/argcargv.i>
|
65
|
+
%include <ruby/rubyautodoc.swg>
|
66
|
+
%include <ruby/file.i>
|
67
|
+
%include <ruby/progargcargv.i>
|
68
|
+
%include <ruby/rubycomplex.swg>
|
69
|
+
%include <ruby/rubyprimtypes.swg>
|
70
|
+
%include <ruby/rubystrings.swg>
|
71
|
+
%include <ruby/timeval.i>
|
72
|
+
%include <ruby/typemaps.i>
|
73
|
+
|
74
|
+
// Put Helper Functions in this block
|
75
|
+
%{
|
76
|
+
#include <fcntl.h>
|
77
|
+
#include <unistd.h>
|
78
|
+
#include <locale.h>
|
79
|
+
|
80
|
+
// Helper function to determine file mode
|
81
|
+
static const char* get_file_mode(int fd) {
|
82
|
+
int flags = fcntl(fd, F_GETFL);
|
83
|
+
if (flags == -1) return "r"; // Default to read mode on error
|
84
|
+
|
85
|
+
int access_mode = flags & O_ACCMODE;
|
86
|
+
int append_flag = flags & O_APPEND;
|
87
|
+
|
88
|
+
if (access_mode == O_RDONLY) return "r";
|
89
|
+
if (access_mode == O_WRONLY) return append_flag ? "a" : "w";
|
90
|
+
if (access_mode == O_RDWR) return append_flag ? "a+" : "r+";
|
91
|
+
|
92
|
+
return "r";
|
93
|
+
}
|
94
|
+
|
95
|
+
// Helper function to call Ruby procs
|
96
|
+
static VALUE call_ruby_proc(VALUE proc, int argc, VALUE* argv) {
|
97
|
+
return rb_funcall2(proc, rb_intern("call"), argc, argv);
|
98
|
+
}
|
99
|
+
%}
|
100
|
+
|
101
|
+
// Package all function results in a hash
|
102
|
+
%typemap(out) SWIGTYPE*, SWIGTYPE& {
|
103
|
+
VALUE hash = rb_hash_new();
|
104
|
+
VALUE obj;
|
105
|
+
|
106
|
+
if (strcmp("$1_type", "void") == 0) {
|
107
|
+
obj = Qnil;
|
108
|
+
} else {
|
109
|
+
obj = SWIG_Ruby_NewPointerObj($1, $1_descriptor, $owner);
|
110
|
+
}
|
111
|
+
|
112
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("return")), obj);
|
113
|
+
$result = hash;
|
114
|
+
}
|
115
|
+
|
116
|
+
%typemap(argout) SWIGTYPE*, SWIGTYPE & {
|
117
|
+
if ($result == Qnil) {
|
118
|
+
$result = rb_hash_new();
|
119
|
+
}
|
120
|
+
if (!RB_TYPE_P($result, T_HASH)) {
|
121
|
+
VALUE temp = rb_hash_new();
|
122
|
+
rb_hash_aset(temp, ID2SYM(rb_intern("return")), $result);
|
123
|
+
$result = temp;
|
124
|
+
}
|
125
|
+
|
126
|
+
swig_type_info *ty = SWIG_TypeQuery("$1_type");
|
127
|
+
if (!ty) ty = $1_descriptor;
|
128
|
+
|
129
|
+
VALUE obj = SWIG_NewPointerObj((void *)$1, ty, 0);
|
130
|
+
rb_hash_aset($result, ID2SYM(rb_intern("$1_name")), obj);
|
131
|
+
}
|
132
|
+
|
133
|
+
%typemap(out) char*, const char* {
|
134
|
+
VALUE hash = rb_hash_new();
|
135
|
+
VALUE obj;
|
136
|
+
|
137
|
+
if ($1 == NULL) {
|
138
|
+
obj = Qnil;
|
139
|
+
} else {
|
140
|
+
// Convert C string to Ruby string
|
141
|
+
obj = rb_str_new2($1);
|
142
|
+
}
|
143
|
+
|
144
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("return")), obj);
|
145
|
+
$result = hash;
|
146
|
+
}
|
147
|
+
|
148
|
+
%typemap(argout) char*, const char* {
|
149
|
+
if ($result == Qnil) {
|
150
|
+
$result = rb_hash_new();
|
151
|
+
}
|
152
|
+
if (!RB_TYPE_P($result, T_HASH)) {
|
153
|
+
VALUE temp = rb_hash_new();
|
154
|
+
rb_hash_aset(temp, ID2SYM(rb_intern("return")), $result);
|
155
|
+
$result = temp;
|
156
|
+
}
|
157
|
+
|
158
|
+
VALUE obj = $1 ? rb_str_new2($1) : Qnil;
|
159
|
+
rb_hash_aset($result, ID2SYM(rb_intern("$1_name")), obj);
|
160
|
+
}
|
161
|
+
|
162
|
+
%typemap(out) wchar_t* {
|
163
|
+
VALUE hash = rb_hash_new();
|
164
|
+
VALUE obj;
|
165
|
+
|
166
|
+
if ($1 == NULL) {
|
167
|
+
obj = Qnil;
|
168
|
+
} else {
|
169
|
+
// Convert wchar_t* to UTF-8 encoded Ruby string
|
170
|
+
setlocale(LC_ALL, "");
|
171
|
+
size_t len = wcslen($1);
|
172
|
+
size_t utf8_len = wcstombs(NULL, $1, 0); // Get required buffer size
|
173
|
+
if (utf8_len != (size_t)-1) {
|
174
|
+
char *utf8_str = (char*)malloc(utf8_len + 1);
|
175
|
+
if (utf8_str) {
|
176
|
+
wcstombs(utf8_str, $1, utf8_len + 1);
|
177
|
+
obj = rb_str_new2(utf8_str);
|
178
|
+
rb_enc_associate(obj, rb_utf8_encoding());
|
179
|
+
free(utf8_str);
|
180
|
+
} else {
|
181
|
+
obj = Qnil; // Handle allocation failure
|
182
|
+
}
|
183
|
+
} else {
|
184
|
+
obj = Qnil; // Handle conversion failure
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("return")), obj);
|
189
|
+
$result = hash;
|
190
|
+
}
|
191
|
+
|
192
|
+
%typemap(argout) wchar_t* {
|
193
|
+
if ($result == Qnil) {
|
194
|
+
$result = rb_hash_new();
|
195
|
+
}
|
196
|
+
if (!RB_TYPE_P($result, T_HASH)) {
|
197
|
+
VALUE temp = rb_hash_new();
|
198
|
+
rb_hash_aset(temp, ID2SYM(rb_intern("return")), $result);
|
199
|
+
$result = temp;
|
200
|
+
}
|
201
|
+
|
202
|
+
VALUE obj;
|
203
|
+
if ($1 == NULL) {
|
204
|
+
obj = Qnil;
|
205
|
+
} else {
|
206
|
+
// Convert wchar_t* to UTF-8 encoded Ruby string
|
207
|
+
setlocale(LC_ALL, "");
|
208
|
+
size_t utf8_len = wcstombs(NULL, $1, 0); // Get required buffer size
|
209
|
+
if (utf8_len != (size_t)-1) {
|
210
|
+
char *utf8_str = (char*)malloc(utf8_len + 1);
|
211
|
+
if (utf8_str) {
|
212
|
+
wcstombs(utf8_str, $1, utf8_len + 1);
|
213
|
+
obj = rb_str_new2(utf8_str);
|
214
|
+
rb_enc_associate(obj, rb_utf8_encoding());
|
215
|
+
free(utf8_str);
|
216
|
+
} else {
|
217
|
+
obj = Qnil; // Handle allocation failure
|
218
|
+
}
|
219
|
+
} else {
|
220
|
+
obj = Qnil; // Handle conversion failure
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
rb_hash_aset($result, ID2SYM(rb_intern("$1_name")), obj);
|
225
|
+
}
|
226
|
+
|
227
|
+
// Time is not on your side
|
228
|
+
%typemap(in) const struct timespec* {
|
229
|
+
if ($input == Qnil) {
|
230
|
+
$1 = NULL;
|
231
|
+
} else if (rb_obj_is_kind_of($input, rb_cTime)) {
|
232
|
+
static struct timespec ts;
|
233
|
+
VALUE seconds = rb_funcall($input, rb_intern("to_f"), 0);
|
234
|
+
ts.tv_sec = NUM2LONG(rb_funcall(seconds, rb_intern("floor"), 0));
|
235
|
+
ts.tv_nsec = NUM2LONG(rb_funcall(rb_funcall(rb_funcall(seconds, rb_intern("-"), 1, seconds), rb_intern("*"), 1, INT2NUM(1000000000)), rb_intern("floor"), 0));
|
236
|
+
$1 = &ts;
|
237
|
+
} else {
|
238
|
+
SWIG_exception(SWIG_TypeError, "Expected Time or nil");
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
// IO
|
243
|
+
%typemap(in) FILE* {
|
244
|
+
if ($input == Qnil) {
|
245
|
+
$1 = NULL;
|
246
|
+
} else if (rb_respond_to($input, rb_intern("fileno"))) {
|
247
|
+
int fd = NUM2INT(rb_funcall($input, rb_intern("fileno"), 0));
|
248
|
+
const char* mode = get_file_mode(fd);
|
249
|
+
$1 = fdopen(dup(fd), mode);
|
250
|
+
if (!$1) {
|
251
|
+
rb_raise(rb_eIOError, "Unable to get FILE* from Ruby IO object");
|
252
|
+
}
|
253
|
+
} else {
|
254
|
+
SWIG_exception(SWIG_TypeError, "Expected IO object or nil");
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
%typemap(out) FILE* {
|
259
|
+
if ($1 == NULL) {
|
260
|
+
$result = Qnil;
|
261
|
+
} else {
|
262
|
+
int fd = fileno($1);
|
263
|
+
if (fd == -1) {
|
264
|
+
rb_raise(rb_eIOError, "Invalid file descriptor");
|
265
|
+
}
|
266
|
+
VALUE io_class = rb_const_get(rb_cObject, rb_intern("IO"));
|
267
|
+
$result = rb_funcall(io_class, rb_intern("for_fd"), 1, INT2NUM(fd));
|
268
|
+
rb_funcall($result, rb_intern("binmode"), 0);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
%typemap(argout) FILE** {
|
273
|
+
if (*$1 != NULL) {
|
274
|
+
int fd = fileno(*$1);
|
275
|
+
if (fd == -1) {
|
276
|
+
rb_raise(rb_eIOError, "Invalid file descriptor");
|
277
|
+
}
|
278
|
+
VALUE io_class = rb_const_get(rb_cObject, rb_intern("IO"));
|
279
|
+
VALUE io_obj = rb_funcall(io_class, rb_intern("for_fd"), 1, INT2NUM(fd));
|
280
|
+
|
281
|
+
// Set the mode of the IO object
|
282
|
+
const char* mode = "r"; // Default to read mode
|
283
|
+
if ((*$1)->_flags & _IO_NO_READS) {
|
284
|
+
if ((*$1)->_flags & _IO_APPEND) {
|
285
|
+
mode = "a";
|
286
|
+
} else {
|
287
|
+
mode = "w";
|
288
|
+
}
|
289
|
+
}
|
290
|
+
if (!((*$1)->_flags & _IO_NO_WRITES)) {
|
291
|
+
mode = (strcmp(mode, "r") == 0) ? "r+" : "w+";
|
292
|
+
}
|
293
|
+
|
294
|
+
// Set the mode
|
295
|
+
rb_funcall(io_obj, rb_intern("set_encoding"), 1, rb_str_new2(mode));
|
296
|
+
|
297
|
+
// Preserve the original encoding if possible
|
298
|
+
VALUE enc = rb_funcall(io_obj, rb_intern("internal_encoding"), 0);
|
299
|
+
if (enc == Qnil) {
|
300
|
+
enc = rb_funcall(io_obj, rb_intern("external_encoding"), 0);
|
301
|
+
}
|
302
|
+
if (enc != Qnil) {
|
303
|
+
rb_funcall(io_obj, rb_intern("set_encoding"), 1, enc);
|
304
|
+
} else {
|
305
|
+
// Fallback to binary mode if no encoding is detected
|
306
|
+
rb_funcall(io_obj, rb_intern("binmode"), 0);
|
307
|
+
}
|
308
|
+
|
309
|
+
rb_io_taint_check(io_obj);
|
310
|
+
|
311
|
+
$result = io_obj;
|
312
|
+
} else {
|
313
|
+
$result = Qnil;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
|
317
|
+
%typemap(in) FILE** (FILE* tempfile = NULL) {
|
318
|
+
if ($input == Qnil) {
|
319
|
+
$1 = &tempfile;
|
320
|
+
} else if (rb_obj_is_kind_of($input, rb_cIO)) {
|
321
|
+
VALUE fileno = rb_funcall($input, rb_intern("fileno"), 0);
|
322
|
+
int fd = NUM2INT(fileno);
|
323
|
+
const char* mode = StringValueCStr(rb_funcall($input, rb_intern("mode"), 0));
|
324
|
+
tempfile = fdopen(dup(fd), mode);
|
325
|
+
if (!tempfile) {
|
326
|
+
rb_raise(rb_eIOError, "Could not create FILE* from Ruby IO object");
|
327
|
+
}
|
328
|
+
$1 = &tempfile;
|
329
|
+
} else {
|
330
|
+
SWIG_exception(SWIG_TypeError, "Expected IO object or nil");
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
%typemap(freearg) FILE** {
|
335
|
+
if (tempfile$argnum != NULL) {
|
336
|
+
fclose(tempfile$argnum);
|
337
|
+
}
|
338
|
+
}
|
339
|
+
|
340
|
+
// Integer Pointers
|
341
|
+
%typemap(in)
|
342
|
+
short*,
|
343
|
+
int*,
|
344
|
+
long*,
|
345
|
+
double*,
|
346
|
+
long long*,
|
347
|
+
int8_t*,
|
348
|
+
int16_t*,
|
349
|
+
int32_t*,
|
350
|
+
int64_t*,
|
351
|
+
unsigned short*,
|
352
|
+
unsigned int*,
|
353
|
+
unsigned long*,
|
354
|
+
unsigned long long*,
|
355
|
+
uint8_t*,
|
356
|
+
uint16_t*,
|
357
|
+
uint32_t*,
|
358
|
+
uint64_t* {
|
359
|
+
|
360
|
+
$1 = ($1_ltype) malloc(sizeof($*1_type));
|
361
|
+
if ($1 == NULL) {
|
362
|
+
SWIG_exception_fail(SWIG_MemoryError, "Failed to allocate memory");
|
363
|
+
}
|
364
|
+
switch(sizeof($*1_type)) {
|
365
|
+
case 1:
|
366
|
+
case 2:
|
367
|
+
case 4:
|
368
|
+
*$1 = ($*1_type) NUM2INT($input);
|
369
|
+
break;
|
370
|
+
case 8:
|
371
|
+
if (strcmp("$*1_type", "double") == 0) {
|
372
|
+
*$1 = ($*1_type) NUM2DBL($input);
|
373
|
+
} else {
|
374
|
+
*$1 = ($*1_type) NUM2LL($input);
|
375
|
+
}
|
376
|
+
break;
|
377
|
+
default:
|
378
|
+
SWIG_exception_fail(SWIG_TypeError, "Unsupported integer size");
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
%typemap(argout)
|
383
|
+
short*,
|
384
|
+
int*,
|
385
|
+
long*,
|
386
|
+
double*,
|
387
|
+
long long*,
|
388
|
+
int8_t*,
|
389
|
+
int16_t*,
|
390
|
+
int32_t*,
|
391
|
+
int64_t*,
|
392
|
+
size_t*,
|
393
|
+
unsigned short*,
|
394
|
+
unsigned int*,
|
395
|
+
unsigned long*,
|
396
|
+
unsigned long long*,
|
397
|
+
uint8_t*,
|
398
|
+
uint16_t*,
|
399
|
+
uint32_t*,
|
400
|
+
uint64_t* {
|
401
|
+
|
402
|
+
if ($1 != NULL) {
|
403
|
+
if ($result == Qnil) {
|
404
|
+
$result = rb_hash_new();
|
405
|
+
} else if (!RB_TYPE_P($result, T_HASH)) {
|
406
|
+
VALUE temp = rb_hash_new();
|
407
|
+
rb_hash_aset(temp, ID2SYM(rb_intern("return")), $result);
|
408
|
+
$result = temp;
|
409
|
+
}
|
410
|
+
VALUE converted_value;
|
411
|
+
switch(sizeof($*1_type)) {
|
412
|
+
case 1:
|
413
|
+
case 2:
|
414
|
+
case 4:
|
415
|
+
converted_value = INT2NUM(*$1);
|
416
|
+
break;
|
417
|
+
case 8:
|
418
|
+
if (strcmp("$*1_type", "double") == 0) {
|
419
|
+
converted_value = DBL2NUM(*$1);
|
420
|
+
} else {
|
421
|
+
converted_value = LL2NUM(*$1);
|
422
|
+
}
|
423
|
+
break;
|
424
|
+
default:
|
425
|
+
rb_raise(rb_eTypeError, "Unsupported integer size");
|
426
|
+
}
|
427
|
+
rb_hash_aset($result, ID2SYM(rb_intern("$1_name")), converted_value);
|
428
|
+
free($1);
|
429
|
+
}
|
430
|
+
}
|
431
|
+
|
432
|
+
// Callbacks
|
433
|
+
%typemap(in) fadecb, ncstreamcb, tabletcb, tabcb, ncfdplane_done_cb {
|
434
|
+
if (!NIL_P($input)) {
|
435
|
+
$1 = ($1_ltype)rb_proc_new((VALUE (*)(ANYARGS))call_ruby_proc, $input);
|
436
|
+
} else {
|
437
|
+
$1 = NULL;
|
438
|
+
}
|
439
|
+
}
|
440
|
+
|
441
|
+
// Stuff in the inline block is both written to the generated C code AND has
|
442
|
+
// swig wrappers generated for the functions.
|
443
|
+
%inline %{
|
444
|
+
#include <notcurses/ncport.h>
|
445
|
+
#include <notcurses/version.h>
|
446
|
+
#include <notcurses/nckeys.h>
|
447
|
+
#include <notcurses/ncseqs.h>
|
448
|
+
#include <notcurses/notcurses.h>
|
449
|
+
#include <notcurses/direct.h>
|
450
|
+
|
451
|
+
|
452
|
+
// Put fake function macros here.
|
453
|
+
// NCCHANNEL_INITIALIZER
|
454
|
+
uint32_t ncchannel_initializer(
|
455
|
+
uint32_t r,
|
456
|
+
uint32_t g,
|
457
|
+
uint32_t b
|
458
|
+
) {
|
459
|
+
return ((r << 16u) + (g << 8u) + b + NC_BGDEFAULT_MASK);
|
460
|
+
}
|
461
|
+
|
462
|
+
// NCCHANNELS_INITIALIZER
|
463
|
+
uint64_t ncchannels_initializer(
|
464
|
+
uint32_t fr,
|
465
|
+
uint32_t fg,
|
466
|
+
uint32_t fb,
|
467
|
+
uint32_t br,
|
468
|
+
uint32_t bg,
|
469
|
+
uint32_t bb
|
470
|
+
) {
|
471
|
+
|
472
|
+
uint64_t tmp_fg_chan = ((uint64_t)ncchannel_initializer(fr, fg, fb) << 32ull);
|
473
|
+
uint64_t tmp_bg_chan = ncchannel_initializer(br, bg, bb);
|
474
|
+
|
475
|
+
return tmp_fg_chan + tmp_bg_chan;
|
476
|
+
}
|
477
|
+
|
478
|
+
|
479
|
+
// NCMETRICFWIDTH
|
480
|
+
int ncmetricfwidth(const char* x, int cols) {
|
481
|
+
return (int)(strlen(x) - ncstrwidth(x, NULL, NULL) + cols);
|
482
|
+
}
|
483
|
+
|
484
|
+
// NCPREFIXFMT (note this macro expands to this as well as ", x")
|
485
|
+
int ncprefixfmt(const char* x) {
|
486
|
+
return (int)ncmetricfwidth(x, NCPREFIXCOLUMNS);
|
487
|
+
}
|
488
|
+
|
489
|
+
// NCIPREFIXFMT (note this macro expands to this as well as ", x")
|
490
|
+
int nciprefixfmt(const char* x) {
|
491
|
+
return (int)ncmetricfwidth(x, NCIPREFIXCOLUMNS);
|
492
|
+
}
|
493
|
+
|
494
|
+
// NCBPREFIXFMT (note this macro expands to this as well as ", x")
|
495
|
+
int ncbprefixfmt(const char* x) {
|
496
|
+
return (int)ncmetricfwidth(x, NCBPREFIXCOLUMNS);
|
497
|
+
}
|
498
|
+
|
499
|
+
// NCCELL_INITIALIZER
|
500
|
+
void nccell_initializer(nccell* cell, uint32_t c, uint16_t s, uint64_t chan) {
|
501
|
+
if (cell == NULL) return;
|
502
|
+
cell->gcluster = htole(c);
|
503
|
+
cell->gcluster_backstop = 0;
|
504
|
+
cell->width = (uint8_t)((wcwidth(c) < 0 || !c) ? 1 : wcwidth(c));
|
505
|
+
cell->stylemask = s;
|
506
|
+
cell->channels = chan;
|
507
|
+
}
|
508
|
+
|
509
|
+
// NCCELL_CHAR_INITIALIZER
|
510
|
+
void nccell_char_initializer(nccell* cell, uint32_t c) {
|
511
|
+
if (cell == NULL) return;
|
512
|
+
cell->gcluster = htole(c);
|
513
|
+
cell->gcluster_backstop = 0;
|
514
|
+
cell->width = (uint8_t)((wcwidth(c) < 0 || !c) ? 1 : wcwidth(c));
|
515
|
+
cell->stylemask = 0;
|
516
|
+
cell->channels = 0;
|
517
|
+
}
|
518
|
+
|
519
|
+
// NCCELL_TRIVIAL_INITIALIZER
|
520
|
+
void nccell_trivial_initializer(nccell* cell) {
|
521
|
+
if (cell == NULL) return;
|
522
|
+
cell->gcluster = 0;
|
523
|
+
cell->gcluster_backstop = 0;
|
524
|
+
cell->width = 1;
|
525
|
+
cell->stylemask = 0;
|
526
|
+
cell->channels = 0;
|
527
|
+
}
|
528
|
+
|
529
|
+
// Prototypes for functions that replace va_list arg functions, actual
|
530
|
+
// definitions are in .c files in ../src
|
531
|
+
int ruby_ncplane_vprintf_yx(struct ncplane* n, int y, int x, const char* format, VALUE rb_args);
|
532
|
+
int ruby_ncplane_vprintf_aligned(struct ncplane* n, int y, ncalign_e align, const char* format, VALUE rb_args);
|
533
|
+
int ruby_ncplane_vprintf_stained(struct ncplane* n, const char* format, VALUE rb_args);
|
534
|
+
|
535
|
+
int ruby_ncplane_vprintf(struct ncplane* n, const char* format, VALUE rb_args) {
|
536
|
+
return ruby_ncplane_vprintf_yx(n, -1, -1, format, rb_args);
|
537
|
+
}
|
538
|
+
%}
|
539
|
+
|
540
|
+
// Ignore problematic functions (va_list stuff)
|
541
|
+
%ignore ncplane_vprintf_yx;
|
542
|
+
%ignore ncplane_vprintf;
|
543
|
+
%ignore ncplane_vprintf_aligned;
|
544
|
+
%ignore ncplane_vprintf_stained;
|
545
|
+
|
546
|
+
%include <notcurses/ncport.h>
|
547
|
+
%include <notcurses/version.h>
|
548
|
+
%include <notcurses/nckeys.h>
|
549
|
+
%include <notcurses/ncseqs.h>
|
550
|
+
%include <notcurses/notcurses.h>
|
551
|
+
%include <notcurses/direct.h>
|
552
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Notcurses
|
2
|
+
module SwigMixins
|
3
|
+
module StructInitializer
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
alias_method :swig_initialize, :initialize
|
7
|
+
|
8
|
+
def initialize(**options)
|
9
|
+
swig_initialize
|
10
|
+
|
11
|
+
options.each do |k, v|
|
12
|
+
setter = "#{k}="
|
13
|
+
|
14
|
+
unless respond_to?(setter)
|
15
|
+
raise ArgumentError, "Unknown attribute: #{k}"
|
16
|
+
end
|
17
|
+
|
18
|
+
send(setter, v)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# There might be a better way, but this works.
|
2
|
+
module Notcurses
|
3
|
+
module SwigMixins
|
4
|
+
module ToH
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
def to_h
|
8
|
+
hash = {}
|
9
|
+
meffids = self.class.instance_methods(false).select{|m| m !~ /=$/}
|
10
|
+
|
11
|
+
meffids.each do |m|
|
12
|
+
next if (m == :to_h || m =~ /=$/)
|
13
|
+
hash[m] = send(m)[:return] if method(m).arity < 1
|
14
|
+
end
|
15
|
+
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/notcurses/version.rb
CHANGED
data/lib/notcurses.rb
CHANGED
@@ -1,4 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Temporarily suppress warnings to kill allocator warnings, should be fixed
|
4
|
+
# in SWIG 4.2
|
5
|
+
$VERBOSE = nil
|
6
|
+
require 'notcurses.so'
|
2
7
|
|
3
8
|
require_relative 'notcurses/version'
|
4
|
-
require_relative 'notcurses
|
9
|
+
require_relative 'notcurses/swig_mixins/struct_initializer'
|
10
|
+
require_relative 'notcurses/swig_mixins/to_h'
|
11
|
+
|
12
|
+
module Notcurses
|
13
|
+
# No matter how hard I tried I could not get SWIG to do this for me.
|
14
|
+
class << self
|
15
|
+
alias_method :ncplane_vprintf_yx, :ruby_ncplane_vprintf_yx
|
16
|
+
alias_method :ncplane_vprintf, :ruby_ncplane_vprintf
|
17
|
+
alias_method :ncplane_vprintf_aligned, :ruby_ncplane_vprintf_aligned
|
18
|
+
alias_method :ncplane_vprintf_stained, :ruby_ncplane_vprintf_stained
|
19
|
+
end
|
20
|
+
|
21
|
+
# This is a stub, couldn't find an easy way to figure this out looking at
|
22
|
+
# constants and methods etc. There is an instance variable but I'd have to
|
23
|
+
# instantiate it to get it...
|
24
|
+
def self.swig_generated_class?(klass)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
# "Mixin' the Swiiiggssss" -- Pauly Shore
|
29
|
+
constants.each do |const_name|
|
30
|
+
const = const_get(const_name)
|
31
|
+
if const.is_a?(Class) && swig_generated_class?(const)
|
32
|
+
const.include(SwigMixins::StructInitializer)
|
33
|
+
const.include(SwigMixins::ToH)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|