summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-08-13 05:37:52 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-08-13 05:37:52 +0000
commit0a64817fb80016030c03518fb9459f63c11605ea (patch)
tree3ea2e607f9ea08c56830ef7b803cd259e3d67c7f
parent210367ec889f5910e270d6ea2c7ddb8a8d939e61 (diff)
remove marshal/gtk/kconv
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ext/Setup2
-rw-r--r--ext/Setup.dj4
-rw-r--r--ext/Setup.emx16
-rw-r--r--ext/Setup.nt15
-rw-r--r--ext/Win32API/MANIFEST7
-rw-r--r--ext/Win32API/Win32API.c231
-rw-r--r--ext/Win32API/depend2
-rw-r--r--ext/Win32API/extconf.rb7
-rw-r--r--ext/Win32API/getch.rb5
-rw-r--r--ext/Win32API/point.rb18
-rw-r--r--ext/aix_ld.rb73
-rw-r--r--ext/aix_mksym.rb33
-rw-r--r--ext/curses/curses.c24
-rw-r--r--ext/curses/extconf.rb15
-rw-r--r--ext/dbm/dbm.c7
-rw-r--r--ext/dbm/depend2
-rw-r--r--ext/dbm/extconf.rb5
-rw-r--r--ext/etc/MANIFEST3
-rw-r--r--ext/etc/depend2
-rw-r--r--ext/etc/etc.c18
-rw-r--r--ext/etc/etc.txt72
-rw-r--r--ext/etc/etc.txt.jp (renamed from ext/etc/etc.doc)3
-rw-r--r--ext/extmk.rb.in604
-rw-r--r--ext/extmk.rb.nt501
-rw-r--r--ext/fcntl/depend2
-rw-r--r--ext/fcntl/fcntl.c1
-rw-r--r--ext/gdbm/MANIFEST (renamed from ext/marshal/MANIFEST)4
-rw-r--r--ext/gdbm/README1
-rw-r--r--ext/gdbm/depend1
-rw-r--r--ext/gdbm/extconf.rb7
-rw-r--r--ext/gdbm/gdbm.c604
-rw-r--r--ext/gtk/MANIFEST18
-rw-r--r--ext/gtk/extconf.rb6
-rw-r--r--ext/gtk/gtk.c5904
-rw-r--r--ext/gtk/test.rb96
-rw-r--r--ext/gtk/test.xpm92
-rw-r--r--ext/gtk/test0.rb13
-rw-r--r--ext/gtk/test1.rb41
-rw-r--r--ext/gtk/test2.rb89
-rw-r--r--ext/gtk/test3.rb16
-rw-r--r--ext/gtk/test4.rb77
-rw-r--r--ext/gtk/test5.rb63
-rw-r--r--ext/gtk/test6.rb49
-rw-r--r--ext/gtk/test7.rb49
-rw-r--r--ext/gtk/test8.rb49
-rw-r--r--ext/gtk/test9.rb98
-rw-r--r--ext/gtk/testa.rb78
-rw-r--r--ext/gtk/testb.rb78
-rw-r--r--ext/gtk/testc.rb64
-rw-r--r--ext/kconv/MANIFEST3
-rw-r--r--ext/kconv/depend1
-rw-r--r--ext/mandel/MANIFEST3
-rw-r--r--ext/mandel/mandel.c59
-rw-r--r--ext/mandel/tkmandel.rb172
-rw-r--r--ext/marshal/depend2
-rw-r--r--ext/marshal/extconf.rb1
-rw-r--r--ext/marshal/marshal.c850
-rw-r--r--ext/marshal/marshal.doc48
-rw-r--r--ext/md5/MANIFEST3
-rw-r--r--ext/md5/depend2
-rw-r--r--ext/md5/md5.txt38
-rw-r--r--ext/md5/md5.txt.jp (renamed from ext/md5/md5.doc)3
-rw-r--r--ext/md5/md5init.c28
-rw-r--r--ext/nkf/MANIFEST7
-rw-r--r--ext/nkf/depend1
-rw-r--r--ext/nkf/extconf.rb2
-rw-r--r--ext/nkf/lib/kconv.rb58
-rw-r--r--ext/nkf/nkf.c206
-rw-r--r--ext/nkf/nkf1.7/nkf.c (renamed from ext/kconv/kconv.c)1285
-rw-r--r--ext/nkf/test.rb318
-rw-r--r--ext/pty/MANIFEST11
-rw-r--r--ext/pty/README93
-rw-r--r--ext/pty/README.expect22
-rw-r--r--ext/pty/README.expect.jp21
-rw-r--r--ext/pty/README.jp89
-rw-r--r--ext/pty/expect_sample.rb56
-rw-r--r--ext/pty/extconf.rb10
-rw-r--r--ext/pty/lib/expect.rb36
-rw-r--r--ext/pty/pty.c497
-rw-r--r--ext/pty/script.rb38
-rw-r--r--ext/pty/shl.rb96
-rw-r--r--ext/readline/extconf.rb3
-rw-r--r--ext/readline/readline.c91
-rw-r--r--ext/sdbm/MANIFEST5
-rw-r--r--ext/sdbm/_sdbm.c977
-rw-r--r--ext/sdbm/extconf.rb3
-rw-r--r--ext/sdbm/init.c584
-rw-r--r--ext/sdbm/sdbm.h84
-rw-r--r--ext/socket/MANIFEST4
-rw-r--r--ext/socket/addrinfo.h172
-rw-r--r--ext/socket/depend4
-rw-r--r--ext/socket/extconf.rb257
-rw-r--r--ext/socket/getaddrinfo.c676
-rw-r--r--ext/socket/getnameinfo.c250
-rw-r--r--ext/socket/socket.c1289
-rw-r--r--ext/socket/sockport.h43
-rw-r--r--ext/tcltklib/depend2
-rw-r--r--ext/tcltklib/extconf.rb96
-rw-r--r--ext/tcltklib/tcltklib.c362
-rw-r--r--ext/tk/MANIFEST25
-rw-r--r--ext/tk/depend1
-rw-r--r--ext/tk/extconf.rb2
-rw-r--r--ext/tk/lib/tk.rb2495
-rw-r--r--ext/tk/lib/tkafter.rb296
-rw-r--r--ext/tk/lib/tkbgerror.rb17
-rw-r--r--ext/tk/lib/tkcanvas.rb829
-rw-r--r--ext/tk/lib/tkclass.rb38
-rw-r--r--ext/tk/lib/tkdialog.rb141
-rw-r--r--ext/tk/lib/tkentry.rb73
-rw-r--r--ext/tk/lib/tkfont.rb953
-rw-r--r--ext/tk/lib/tkmenubar.rb137
-rw-r--r--ext/tk/lib/tkmngfocus.rb27
-rw-r--r--ext/tk/lib/tkpalette.rb48
-rw-r--r--ext/tk/lib/tkscrollbox.rb29
-rw-r--r--ext/tk/lib/tktext.rb946
-rw-r--r--ext/tk/lib/tkvirtevent.rb66
-rw-r--r--ext/tk/sample/tkbiff.rb149
-rw-r--r--ext/tk/sample/tkbrowse.rb79
-rw-r--r--ext/tk/sample/tkdialog.rb62
-rw-r--r--ext/tk/sample/tkfrom.rb132
-rw-r--r--ext/tk/sample/tkhello.rb10
-rw-r--r--ext/tk/sample/tkline.rb45
-rw-r--r--ext/tk/sample/tktimer.rb50
-rw-r--r--ext/tk/tkutil.c45
124 files changed, 14605 insertions, 10220 deletions
diff --git a/ext/Setup b/ext/Setup
index 9e3a2474c3..830a5095ca 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -7,6 +7,8 @@
#fcntl
#kconv
#md5
+#pty
+#sdbm
#socket
#tkutil
#tcltklib
diff --git a/ext/Setup.dj b/ext/Setup.dj
index 25adea2035..cf25c07e6b 100644
--- a/ext/Setup.dj
+++ b/ext/Setup.dj
@@ -3,10 +3,12 @@ option nodynamic
#GD
#curses
dbm
+gdbm
#etc
fcntl
-kconv
+nkf
marshal
md5
+sdbm
#socket
#tkutil
diff --git a/ext/Setup.emx b/ext/Setup.emx
new file mode 100644
index 0000000000..dbb4b7a61c
--- /dev/null
+++ b/ext/Setup.emx
@@ -0,0 +1,16 @@
+option nodynamic
+
+#Win32API
+curses
+#dbm
+etc
+fcntl
+#gdbm
+md5
+nkf
+#pty
+#readline
+#sdbm
+socket
+#tcltklib
+#tk
diff --git a/ext/Setup.nt b/ext/Setup.nt
index b469709585..cd7969bb73 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -1,12 +1,19 @@
-option nodynamic
+#option nodynamic
#GD
+Win32API
#curses
#dbm
#etc
fcntl
-kconv
-#marshal
+#gdbm
+#gtk
+marshal
md5
+nkf
+#pty
+#readline
+sdbm
socket
-#tkutil
+#tcltklib
+#tk
diff --git a/ext/Win32API/MANIFEST b/ext/Win32API/MANIFEST
new file mode 100644
index 0000000000..7cc9ac445e
--- /dev/null
+++ b/ext/Win32API/MANIFEST
@@ -0,0 +1,7 @@
+MANIFEST
+depend
+MANIFEST
+Win32API.c
+extconf.rb
+getch.rb
+point.rb
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
new file mode 100644
index 0000000000..9f75653132
--- /dev/null
+++ b/ext/Win32API/Win32API.c
@@ -0,0 +1,231 @@
+/*
+ Win32API - Ruby Win32 API Import Facility
+*/
+
+#ifndef _MSC_VER
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#endif
+
+#define _T_VOID 0
+#define _T_NUMBER 1
+#define _T_POINTER 2
+#define _T_INTEGER 3
+
+typedef char *ApiPointer(void);
+typedef long ApiNumber(void);
+typedef void ApiVoid(void);
+typedef int ApiInteger(void);
+
+#include "ruby.h"
+
+typedef struct {
+ HANDLE dll;
+ HANDLE proc;
+ VALUE dllname;
+ VALUE import;
+ VALUE export;
+} Win32API;
+
+static void
+Win32API_FreeLibrary(hdll)
+ HINSTANCE hdll;
+{
+ FreeLibrary(hdll);
+}
+
+static VALUE
+Win32API_initialize(self, dllname, proc, import, export)
+ VALUE self;
+ VALUE dllname;
+ VALUE proc;
+ VALUE import;
+ VALUE export;
+{
+ HANDLE hproc;
+ HINSTANCE hdll;
+ VALUE str;
+ VALUE a_import;
+ VALUE *ptr;
+ int i;
+ int len;
+ int ex;
+
+ hdll = GetModuleHandle(RSTRING(dllname)->ptr);
+ if (!hdll) {
+ hdll = LoadLibrary(RSTRING(dllname)->ptr);
+ if (!hdll)
+ rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
+ Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll);
+ }
+ hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
+ if (!hproc) {
+ str = rb_str_new3(proc);
+ str = rb_str_cat(str, "A", 1);
+ hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
+ if (!hproc)
+ rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n",
+ RSTRING(proc)->ptr, RSTRING(str)->ptr);
+ }
+ rb_iv_set(self, "__dll__", INT2NUM((int)hdll));
+ rb_iv_set(self, "__dllname__", dllname);
+ rb_iv_set(self, "__proc__", INT2NUM((int)hproc));
+
+ a_import = rb_ary_new();
+ ptr = RARRAY(import)->ptr;
+ for (i = 0, len = RARRAY(import)->len; i < len; i++) {
+ int c = *(char *)RSTRING(ptr[i])->ptr;
+ switch (c) {
+ case 'N': case 'n': case 'L': case 'l':
+ rb_ary_push(a_import, INT2FIX(_T_NUMBER));
+ break;
+ case 'P': case 'p':
+ rb_ary_push(a_import, INT2FIX(_T_POINTER));
+ break;
+ case 'I': case 'i':
+ rb_ary_push(a_import, INT2FIX(_T_INTEGER));
+ break;
+ }
+ }
+ rb_iv_set(self, "__import__", a_import);
+
+ switch (*RSTRING(export)->ptr) {
+ case 'V': case 'v':
+ ex = _T_VOID;
+ break;
+ case 'N': case 'n': case 'L': case 'l':
+ ex = _T_NUMBER;
+ break;
+ case 'P': case 'p':
+ ex = _T_POINTER;
+ break;
+ case 'I': case 'i':
+ ex = _T_INTEGER;
+ break;
+ }
+ rb_iv_set(self, "__export__", INT2FIX(ex));
+
+ return Qnil;
+}
+
+static VALUE
+Win32API_Call(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE args;
+
+ FARPROC ApiFunction;
+
+ ApiPointer *ApiFunctionPointer;
+ ApiNumber *ApiFunctionNumber;
+ ApiVoid *ApiFunctionVoid;
+ ApiInteger *ApiFunctionInteger;
+
+ long lParam;
+ char *pParam;
+
+ VALUE Return;
+
+ VALUE obj_proc;
+ VALUE obj_import;
+ VALUE obj_export;
+ VALUE import_type;
+ int nimport, timport, texport, i;
+ int items;
+
+ items = rb_scan_args(argc, argv, "0*", &args);
+
+ obj_proc = rb_iv_get(obj, "__proc__");
+
+ ApiFunction = (FARPROC)NUM2INT(obj_proc);
+
+ obj_import = rb_iv_get(obj, "__import__");
+ obj_export = rb_iv_get(obj, "__export__");
+ nimport = RARRAY(obj_import)->len;
+ texport = FIX2INT(obj_export);
+
+ if (items != nimport)
+ rb_raise(rb_eRuntimeError, "Wrong number of parameters: expected %d, got %d.\n",
+ nimport, items);
+
+ if (0 < nimport) {
+ for (i = nimport - 1; 0 <= i; i--) {
+ VALUE str;
+ import_type = rb_ary_entry(obj_import, i);
+ timport = FIX2INT(import_type);
+ switch (timport) {
+ case _T_NUMBER:
+ case _T_INTEGER:
+ lParam = NUM2INT(rb_ary_entry(args, i));
+#if defined(_MSC_VER) || defined(__LCC__)
+ _asm {
+ mov eax, lParam
+ push eax
+ }
+#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+ asm volatile ("pushl %0" :: "g" (lParam));
+#else
+#error
+#endif
+ break;
+ case _T_POINTER:
+ str = rb_ary_entry(args, i);
+ Check_Type(str, T_STRING);
+ rb_str_modify(str);
+ pParam = RSTRING(str)->ptr;
+#if defined(_MSC_VER) || defined(__LCC__)
+ _asm {
+ mov eax, dword ptr pParam
+ push eax
+ }
+#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+ asm volatile ("pushl %0" :: "g" (pParam));
+#else
+#error
+#endif
+ break;
+ }
+ }
+
+ }
+
+ switch (texport) {
+ case _T_NUMBER:
+ ApiFunctionNumber = (ApiNumber *) ApiFunction;
+ Return = INT2NUM(ApiFunctionNumber());
+ break;
+ case _T_POINTER:
+ ApiFunctionPointer = (ApiPointer *) ApiFunction;
+ Return = rb_str_new2((char *)ApiFunctionPointer());
+ break;
+ case _T_INTEGER:
+ ApiFunctionInteger = (ApiInteger *) ApiFunction;
+ Return = INT2NUM(ApiFunctionInteger());
+ break;
+ case _T_VOID:
+ default:
+ ApiFunctionVoid = (ApiVoid *) ApiFunction;
+ ApiFunctionVoid();
+ Return = INT2NUM(0);
+ break;
+ }
+ return Return;
+}
+
+void
+Init_Win32API()
+{
+ VALUE cWin32API = rb_define_class("Win32API", rb_cObject);
+ rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
+ rb_define_method(cWin32API, "call", Win32API_Call, -1);
+ rb_define_alias(cWin32API, "Call", "call");
+}
+
+void
+Init_win32api()
+{
+ Init_Win32API();
+}
diff --git a/ext/Win32API/depend b/ext/Win32API/depend
index 517b546de3..b224bb66c9 100644
--- a/ext/Win32API/depend
+++ b/ext/Win32API/depend
@@ -1 +1 @@
-Win32API.o : Win32API.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+Win32API.o : Win32API.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
new file mode 100644
index 0000000000..5af3243d96
--- /dev/null
+++ b/ext/Win32API/extconf.rb
@@ -0,0 +1,7 @@
+case PLATFORM
+when /cygwin/,/mingw/
+ $CFLAGS = "-fno-defer-pop"
+ create_makefile("Win32API")
+when /win32/
+ create_makefile("Win32API")
+end
diff --git a/ext/Win32API/getch.rb b/ext/Win32API/getch.rb
new file mode 100644
index 0000000000..c015bbe9bc
--- /dev/null
+++ b/ext/Win32API/getch.rb
@@ -0,0 +1,5 @@
+require 'Win32API'
+
+getch = Win32API.new("crtdll", "_getch", [], 'L')
+
+puts getch.Call.chr
diff --git a/ext/Win32API/point.rb b/ext/Win32API/point.rb
new file mode 100644
index 0000000000..60e265f3ee
--- /dev/null
+++ b/ext/Win32API/point.rb
@@ -0,0 +1,18 @@
+require 'Win32API'
+
+getCursorPos = Win32API.new("user32", "GetCursorPos", ['P'], 'V')
+
+lpPoint = " " * 8 # store two LONGs
+getCursorPos.Call(lpPoint)
+x, y = lpPoint.unpack("LL") # get the actual values
+
+print "x: ", x, "\n"
+print "y: ", y, "\n"
+
+ods = Win32API.new("kernel32", "OutputDebugString", ['P'], 'V')
+ods.Call("Hello, World\n");
+
+GetDesktopWindow = Win32API.new("user32", "GetDesktopWindow", [], 'L')
+GetActiveWindow = Win32API.new("user32", "GetActiveWindow", [], 'L')
+SendMessage = Win32API.new("user32", "SendMessage", ['L'] * 4, 'L')
+SendMessage.Call GetDesktopWindow.Call, 274, 0xf140, 0
diff --git a/ext/aix_ld.rb b/ext/aix_ld.rb
deleted file mode 100644
index 42b2087a46..0000000000
--- a/ext/aix_ld.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#! /usr/local/bin/ruby
-
-def older(file1, file2)
- if !File.exist?(file1) then
- return TRUE
- end
- if !File.exist?(file2) then
- return FALSE
- end
- if File.mtime(file1) < File.mtime(file2)
- return TRUE
- end
- return FALSE
-end
-
-target = ARGV.shift
-unless target =~ /\.so/
- STDERR.printf "wrong suffix specified\n"
- exit 1
-end
-base = File.basename(target, ".so")
-entry="Init_#{base}"
-ldargs = "-e#{entry} -bI:../ruby.imp -bM:SRE -T512 -H512 -lc"
-
-def uniq(data)
- last=nil
- data.delete_if do |name|
- if last == name
- TRUE
- else
- last = name
- FALSE
- end
- end
-end
-
-def extract(nm, out)
- data = nm.readlines.collect{|line|
- line = line.split
- case line[1]
- when "B", "D", "T"
- line[2]
- else
- next
- end
- }.compact!.sort!
- uniq(data)
- exp = open(out, "w")
- for line in data
- exp.printf "%s\n", line
- end
- exp.close
- nm.close
-end
-if older("../ruby.imp", "../../miniruby")
-# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
-# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
- nm = open("|nm ../../*.o")
- extract(nm, "../ruby.imp")
-end
-
-objs = Dir["*.o"].join(" ")
-#nm = open("|/usr/ccs/bin/nm -Bex #{objs}")
-nm = open("|nm #{objs}")
-extract(nm, "#{base}.exp")
-
-#system format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
-#system "/bin/rm -f #{base}.exp"
-#system "chmod o-rwx ${base}.so"
-
-p format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
-p "/bin/rm -f #{base}.exp"
-p "chmod o-rwx ${base}.so"
diff --git a/ext/aix_mksym.rb b/ext/aix_mksym.rb
new file mode 100644
index 0000000000..7e1af283dc
--- /dev/null
+++ b/ext/aix_mksym.rb
@@ -0,0 +1,33 @@
+
+def uniq(data)
+ last=nil
+ data.delete_if do |name|
+ if last == name
+ TRUE
+ else
+ last = name
+ FALSE
+ end
+ end
+end
+
+def extract(nm, out)
+ data = nm.readlines.collect{|line|
+ line = line.split
+ case line[1]
+ when "B", "D"
+ line[0]
+ else
+ next
+ end
+ }.compact!.sort!
+ uniq(data)
+ exp = open(out, "w")
+ exp.printf "#!\n"
+ for line in data
+ exp.printf "%s\n", line
+ end
+ exp.close
+ nm.close
+end
+extract(open("|/usr/ccs/bin/nm -p ../libruby.a"), "../ruby.imp")
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index f3d1bc0970..202a0f9244 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -10,6 +10,10 @@
#else
# ifdef HAVE_NCURSES_CURSES_H
# include <ncurses/curses.h>
+#else
+# ifdef HAVE_CURSES_COLR_CURSES_H
+# include <varargs.h>
+# include <curses_colr/curses.h>
# else
# include <curses.h>
# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxx)
@@ -26,8 +30,11 @@
# endif
# endif
#endif
+#endif
+#include "stdio.h"
#include "ruby.h"
+#include "rubyio.h"
static VALUE mCurses;
static VALUE cWindow;
@@ -350,6 +357,7 @@ static VALUE
curses_getch(obj)
VALUE obj;
{
+ rb_read_check(stdin);
return CHR2FIX(getch());
}
@@ -359,6 +367,8 @@ curses_getstr(obj)
VALUE obj;
{
char rtn[1024]; /* This should be big enough.. I hope */
+
+ rb_read_check(stdin);
getstr(rtn);
return rb_tainted_str_new2(rtn);
}
@@ -408,11 +418,13 @@ window_s_new(class, lines, cols, top, left)
{
VALUE w;
WINDOW *window;
+ VALUE args[4];
window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left));
wclear(window);
w = prep_window(class, window);
- rb_obj_call_init(w);
+ args[0] = lines; args[1] = cols; args[2] = top; args[3] = left;
+ rb_obj_call_init(w, 4, args);
return w;
}
@@ -428,11 +440,17 @@ window_subwin(obj, lines, cols, top, left)
{
struct windata *winp;
WINDOW *window;
+ VALUE w;
+ VALUE args[4];
GetWINDOW(obj, winp);
window = subwin(winp->window, NUM2INT(lines), NUM2INT(cols),
NUM2INT(top), NUM2INT(left));
- return prep_window(cWindow, window);
+ w = prep_window(cWindow, window);
+ args[0] = lines; args[1] = cols; args[2] = top; args[3] = left;
+ rb_obj_call_init(w, 4, args);
+
+ return w;
}
/* def close */
@@ -717,6 +735,7 @@ window_getch(obj)
{
struct windata *winp;
+ rb_read_check(stdin);
GetWINDOW(obj, winp);
return CHR2FIX(wgetch(winp->window));
}
@@ -730,6 +749,7 @@ window_getstr(obj)
char rtn[1024]; /* This should be big enough.. I hope */
GetWINDOW(obj, winp);
+ rb_read_check(stdin);
wgetstr(winp->window, rtn);
return rb_tainted_str_new2(rtn);
}
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 442a9424a2..e1bf24c435 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -1,22 +1,21 @@
require 'mkmf'
-$CFLAGS="-I/usr/include/ncurses -I/usr/local/include/ncurses"
-$LDFLAGS="-L/usr/local/lib"
-make=FALSE
+make=false
have_library("mytinfo", "tgetent") if /bow/ =~ PLATFORM
if have_header("ncurses.h") and have_library("ncurses", "initscr")
- make=TRUE
+ make=true
elsif have_header("ncurses/curses.h") and have_library("ncurses", "initscr")
- make=TRUE
+ make=true
+elsif have_header("curses_colr/curses.h") and have_library("cur_colr", "initscr")
+ make=true
else
- $CFLAGS=nil
have_library("termcap", "tgetent")
if have_library("curses", "initscr")
- make=TRUE
+ make=true
end
end
-if make then
+if make
for f in %w(isendwin ungetch beep doupdate flash deleteln wdeleteln)
have_func(f)
end
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 2764a325e1..4d83cec1b1 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -12,6 +12,9 @@
#include "ruby.h"
+#ifdef HAVE_CDEFS_H
+# include <cdefs.h>
+#endif
#include <ndbm.h>
#include <fcntl.h>
#include <errno.h>
@@ -84,7 +87,7 @@ fdbm_s_open(argc, argv, klass)
obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
- rb_obj_call_init(obj);
+ rb_obj_call_init(obj, argc, argv);
return obj;
}
@@ -329,7 +332,7 @@ fdbm_store(obj, keystr, valstr)
dbmp->di_size = -1;
dbm = dbmp->di_dbm;
if (dbm_store(dbm, key, val, DBM_REPLACE)) {
-#ifdef HAVE_DBM_CLAERERR
+#ifdef HAVE_DBM_CLEARERR
dbm_clearerr(dbm);
#endif
if (errno == EPERM) rb_sys_fail(0);
diff --git a/ext/dbm/depend b/ext/dbm/depend
index d7f1f419d4..5fae80b096 100644
--- a/ext/dbm/depend
+++ b/ext/dbm/depend
@@ -1 +1 @@
-dbm.o: dbm.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+dbm.o: dbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
index 3a96cee12f..22198910cc 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -1,9 +1,10 @@
require 'mkmf'
-$LDFLAGS = "-L/usr/local/lib"
+dir_config("dbm")
have_library("gdbm", "dbm_open") or
have_library("db", "dbm_open") or
have_library("dbm", "dbm_open")
-if have_func("dbm_open")
+have_header("cdefs.h")
+if have_header("ndbm.h") and have_func("dbm_open")
have_func("dbm_clearerr")
create_makefile("dbm")
end
diff --git a/ext/etc/MANIFEST b/ext/etc/MANIFEST
index a0f521b386..79fb1ff34c 100644
--- a/ext/etc/MANIFEST
+++ b/ext/etc/MANIFEST
@@ -1,5 +1,6 @@
MANIFEST
etc.c
-etc.doc
+etc.txt
+etc.txt.jp
depend
extconf.rb
diff --git a/ext/etc/depend b/ext/etc/depend
index fb3318a0c6..ac706477b0 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -1 +1 @@
-etc.o : etc.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+etc.o : etc.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index c10680c7d3..e5f69f9285 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -125,7 +125,7 @@ static VALUE
etc_passwd(obj)
VALUE obj;
{
-#if defined(HAVE_GETPWENT)
+#ifdef HAVE_GETPWENT
struct passwd *pw;
if (rb_iterator_p()) {
@@ -136,12 +136,11 @@ etc_passwd(obj)
endpwent();
return obj;
}
- pw = getpwent();
- if (pw == 0) rb_raise(rb_eRuntimeError, "can't fetch next -- /etc/passwd");
- return setup_passwd(pw);
-#else
- return Qnil;
+ if (pw = getpwent()) {
+ return setup_passwd(pw);
+ }
#endif
+ return Qnil;
}
#ifdef HAVE_GETGRENT
@@ -214,10 +213,11 @@ etc_group(obj)
endgrent();
return obj;
}
- return setup_group(getgrent());
-#else
- return Qnil;
+ if (grp = getgrent()) {
+ return setup_group(grp);
+ }
#endif
+ return Qnil;
}
static VALUE mEtc;
diff --git a/ext/etc/etc.txt b/ext/etc/etc.txt
new file mode 100644
index 0000000000..9801dc0e02
--- /dev/null
+++ b/ext/etc/etc.txt
@@ -0,0 +1,72 @@
+.\" etc.doc - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995
+
+** Etc(Module)
+
+The module to retrieve information under /etc directory. Available
+only on UNIX platforms. All operations defined in this module are
+module functions, so that you can include Etc module into your class.
+
+Module Function:
+
+ getlogin
+
+ returns login name of the user. It this fails, try getpwuid().
+
+ getpwnam(name)
+
+ searches in /etc/passwd file (or equivalent database), and
+ returns password entry for the user. The return value is an
+ passwd structure, which has members described below.
+
+ struct passwd
+ name # user name(string)
+ passwd # encrypted password(string)
+ uid # user ID(integer)
+ gid # group ID(integer)
+ gecos # gecos field(string)
+ dir # home directory(string)
+ shell # login shell(string)
+ # members below are optional
+ change # password change time(integer)
+ quota # quota value(integer)
+ age # password age(integer)
+ class # user access class(string)
+ comment # comment(string)
+ expire # account expiration time(integer)
+ end
+
+ See getpwnam(3) for detail.
+
+ getpwuid([uid])
+
+ returns passwd entry for the specified user id. If uid is
+ ommitted, use the value from getuid(). See getpwuid(3) for
+ detail.
+
+ getgrgid(gid)
+
+ searches in /etc/group file (or equivalent database), and
+ returns group entry for the group id. The return value is an
+ group structure, which has members described below.
+
+ struct group
+ name # group name(string)
+ passwd # group password(string)
+ gid # group ID(integer)
+ mem # array of the group member names
+ end
+
+ See getgrgid(3) for detail.
+
+ getgrnam(name)
+
+ returns the group entry for the specified name. The return
+ value is the group structure. See getgrnam(3) for detail.
+
+ group
+
+ iterates over all group entries.
+
+ passwd
+
+ iterates over all passwd entries.
diff --git a/ext/etc/etc.doc b/ext/etc/etc.txt.jp
index 2af895c9de..8191f4886b 100644
--- a/ext/etc/etc.doc
+++ b/ext/etc/etc.txt.jp
@@ -5,8 +5,7 @@
/etc¥Ç¥£¥ì¥¯¥È¥ê°Ê²¼¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤Î¥â¥¸¥å¡¼¥ë¡¥¥¯¥é¥¹¤Ë¥¤¥ó¥¯¥ë¡¼¥É
¤·¤Æ»È¤¦¤³¤È¤â¤Ç¤­¤ë¡¥
-Methods:
-Single Methods:
+Module Function:
getlogin
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index 058c144f94..66f5e9267c 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -1,43 +1,40 @@
#! /usr/local/bin/ruby
-$".push 'mkmf.rb' #"
-load '@top_srcdir@/lib/find.rb'
+$".push 'mkmf.rb'
if ARGV[0] == 'static'
- $force_static = TRUE
+ $force_static = true
ARGV.shift
elsif ARGV[0] == 'install'
- $install = TRUE
+ $install = true
$destdir = ARGV[1] || ''
ARGV.shift
elsif ARGV[0] == 'clean'
- $clean = TRUE
+ $clean = true
ARGV.shift
end
+SRC_EXT = ["c", "cc", "m", "cxx", "cpp", "C"]
$extlist = []
-$cache_mod = FALSE;
+$includedir = "@includedir@".gsub(/\$\{prefix\}|\$\(prefix\)/,'@prefix@')
+
+$cache_mod = false
$lib_cache = {}
$func_cache = {}
$hdr_cache = {}
$top_srcdir = "@top_srcdir@"
if $top_srcdir !~ "^/"
# get absolute path
- save = Dir.pwd
- Dir.chdir $top_srcdir
- $top_srcdir = Dir.pwd
- Dir.chdir save
-end
-$topdir = ".."
-if $topdir !~ "^/"
- # get absolute path
- save = Dir.pwd
- Dir.chdir $topdir
- $topdir = Dir.pwd
- Dir.chdir save
+ $top_srcdir = File.expand_path($top_srcdir)
end
-$dots = if "@INSTALL@" =~ /^\// then "" else "#{$topdir}/ext/" end
+# get absolute path
+$topdir = File.expand_path("..")
+
+$:.push $top_srcdir
+$:.push $top_srcdir+"/lib"
+
+require 'find'
if File.exist?("config.cache") then
f = open("config.cache", "r")
@@ -56,26 +53,26 @@ end
def older(file1, file2)
if !File.exist?(file1) then
- return TRUE
+ return true
end
if !File.exist?(file2) then
- return FALSE
+ return false
end
if File.mtime(file1) < File.mtime(file2)
- return TRUE
+ return true
end
- return FALSE
+ return false
end
-if PLATFORM == "m68k-human"
-CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
+if RUBY_PLATFORM == "m68k-human"
+ CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
else
-CFLAGS = "@CFLAGS@"
+ CFLAGS = "@CFLAGS@"
end
-LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s @LDFLAGS@ %s conftest.c @LIBS@ %s"
-CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s conftest.c"
+LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir @LDFLAGS@ %s %s conftest.c %s %s @LIBS@"
+CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir %s %s conftest.c"
-if /cygwin|mswin32|djgpp|mingw32|m68k-human/i =~ PLATFORM
+if /cygwin|mswin32|djgpp|mingw32|m68k-human|i386-os2_emx/i =~ RUBY_PLATFORM
$null = open("nul", "w")
else
$null = open("/dev/null", "w")
@@ -85,6 +82,7 @@ $orgerr = $stderr.dup
$orgout = $stdout.dup
def xsystem command
if $DEBUG
+ puts command
return system(command)
end
$stderr.reopen($null)
@@ -95,116 +93,194 @@ def xsystem command
return r
end
-def try_link(libs)
- xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs))
+def try_link0(src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ xsystem(format(LINK, $CFLAGS, $LDFLAGS, opt, $LOCAL_LIBS))
+end
+
+def try_link(src, opt="")
+ begin
+ try_link0(src, opt)
+ ensure
+ system "rm -f conftest*"
+ end
+end
+
+def try_cpp(src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ begin
+ xsystem(format(CPP, $CFLAGS, opt))
+ ensure
+ system "rm -f conftest*"
+ end
end
-def try_cpp
- xsystem(format(CPP, $CFLAGS))
+def egrep_cpp(pat, src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ begin
+ xsystem(format(CPP+"|egrep #{pat}", $CFLAGS, opt))
+ ensure
+ system "rm -f conftest*"
+ end
end
-def install_rb(mfile)
+def try_run(src, opt="")
+ begin
+ if try_link0(src, opt)
+ if xsystem("./conftest")
+ true
+ else
+ false
+ end
+ else
+ nil
+ end
+ ensure
+ system "rm -f conftest*"
+ end
+end
+
+def install_rb(mfile, srcdir = nil)
+ libdir = "lib"
+ libdir = srcdir + "/" + libdir if srcdir
path = []
dir = []
- Find.find("lib") do |f|
+ Find.find(libdir) do |f|
next unless /\.rb$/ =~ f
- f = f[4..-1]
+ f = f[libdir.length+1..-1]
path.push f
dir |= File.dirname(f)
end
for f in dir
next if f == "."
- mfile.printf "\t@test -d $(DESTDIR)$(pkglibdir)/%s || mkdir $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(pkglibdir)/%s\n", f
end
for f in path
- mfile.printf "\t$(INSTALL_DATA) lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' $(srcdir)/lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ end
+end
+
+def append_library(libs, lib)
+ if /mswin32/ =~ RUBY_PLATFORM
+ lib + ".lib " + libs
+ else
+ "-l" + lib + " " + libs
end
end
def have_library(lib, func="main")
if $lib_cache[lib]
if $lib_cache[lib] == "yes"
- if $libs
- $libs = "-l" + lib + " " + $libs
- else
- $libs = "-l" + lib
- end
- return TRUE
+ $libs = append_library($libs, lib)
+ return true
else
- return FALSE
+ return false
end
end
if func && func != ""
- cfile = open("conftest.c", "w")
- cfile.printf "\
+ libs = append_library($libs, lib)
+ if /mswin32/ =~ RUBY_PLATFORM
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
int main() { return 0; }
-int t() { %s(); return 0; }
-", func
- cfile.close
-
- begin
- if $libs
- libs = "-l" + lib + " " + $libs
- else
- libs = "-l" + lib
- end
- unless try_link(libs)
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- return FALSE
+int t() { #{func}(); return 0; }
+SRC
+ unless r
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
+int main() { return 0; }
+int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
end
- ensure
- system "rm -f conftest*"
- end
- else
- if $libs
- libs = "-l" + lib + " " + $libs
else
- libs = "-l" + lib
+ r = try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ end
+ unless r
+ $lib_cache[lib] = 'no'
+ $cache_mod = true
+ return false
end
+ else
+ libs = append_library($libs, lib)
end
$libs = libs
$lib_cache[lib] = 'yes'
- $cache_mod = TRUE
- return TRUE
+ $cache_mod = true
+ return true
+end
+
+def find_library(lib, func, *paths)
+ ldflags = $LDFLAGS
+ libs = append_library($libs, lib)
+ until try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ if paths.size == 0
+ $LDFLAGS = ldflags
+ return false
+ end
+ $LDFLAGS = ldflags + " -L"+paths.shift
+ end
+ $libs = libs
+ return true
end
def have_func(func)
if $func_cache[func]
if $func_cache[func] == "yes"
$defs.push(format("-DHAVE_%s", func.upcase))
- return TRUE
+ return true
else
- return FALSE
+ return false
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-char %s();
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func, func
- cfile.close
-
libs = $libs
- libs = "" if libs == nil
- begin
- unless try_link(libs)
- $func_cache[func] = 'no'
- $cache_mod = TRUE
- return FALSE
+ if /mswin32/ =~ RUBY_PLATFORM
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ unless r
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
+int main() { return 0; }
+int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
end
- ensure
- system "rm -f conftest*"
+ else
+ r = try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ end
+ unless r
+ $func_cache[func] = 'no'
+ $cache_mod = true
+ return false
end
$defs.push(format("-DHAVE_%s", func.upcase))
$func_cache[func] = 'yes'
- $cache_mod = TRUE
- return TRUE
+ $cache_mod = true
+ return true
end
def have_header(header)
@@ -212,32 +288,60 @@ def have_header(header)
if $hdr_cache[header] == "yes"
header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header))
- return TRUE
+ return true
else
- return FALSE
+ return false
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <%s>
-", header
- cfile.close
-
- begin
- unless try_cpp
- $hdr_cache[header] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
+ unless try_cpp(<<"SRC")
+#include <#{header}>
+SRC
+ $hdr_cache[header] = 'no'
+ $cache_mod = true
+ return false
end
$hdr_cache[header] = 'yes'
header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header))
- $cache_mod = TRUE
- return TRUE
+ $cache_mod = true
+ return true
+end
+
+def arg_config(config, default=nil)
+ unless defined? $configure_args
+ $configure_args = {}
+ args = "@configure_args@"
+ if /mswin32/ =~ RUBY_PLATFORM and ENV["CONFIGURE_ARGS"]
+ args = args + " " + ENV["CONFIGURE_ARGS"]
+ end
+ for arg in args.split
+ next unless /^--/ =~ arg
+ if /=/ =~ arg
+ $configure_args[$`] = $'
+ else
+ $configure_args[arg] = true
+ end
+ end
+ end
+ $configure_args.fetch(config, default)
+end
+
+def with_config(config, default=nil)
+ unless /^--with-/ =~ config
+ config = '--with-' + config
+ end
+ arg_config(config, default)
+end
+
+def enable_config(config, default=nil)
+ if arg_config("--enable-"+config, default)
+ true
+ elsif arg_config("--disable-"+config, false)
+ false
+ else
+ default
+ end
end
def create_header()
@@ -251,28 +355,54 @@ def create_header()
end
end
+def dir_config(target)
+ dir = with_config("%s-dir"%target)
+ if dir
+ idir = " -I"+dir+"/include"
+ ldir = " -L"+dir+"/lib"
+ end
+ unless idir
+ dir = with_config("%s-include"%target)
+ idir = " -I"+dir if dir
+ end
+ unless ldir
+ dir = with_config("%s-lib"%target)
+ ldir = " -L"+dir if dir
+ end
+
+ $CFLAGS += idir if idir
+ $LDFLAGS += ldir if ldir
+end
+
def create_makefile(target)
+ $target = target
- if $libs and "@DLEXT@" == "o"
+ system "rm -f conftest*"
+ if "@DLEXT@" == $OBJEXT
libs = $libs.split
for lib in libs
- lib.sub!(/-l(.*)/, '"lib\1.a"')
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
end
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end
$DLDFLAGS = '@DLDFLAGS@'
- if PLATFORM =~ /beos/
- if $libs
- $libs = $libs + " -lruby"
- else
- $libs = "-lruby"
+ if RUBY_PLATFORM =~ /beos/
+ $libs = $libs + " -lruby"
+ $DLDFLAGS = $DLDFLAGS + " -L" + $topdir
+ end
+
+ defflag = ''
+ if RUBY_PLATFORM =~ /cygwin/ and not $static
+ if File.exist? target + ".def"
+ defflag = "--def=" + target + ".def"
end
+ $libs = $libs + " @LIBRUBYARG@"
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
end
- $srcdir = $top_srcdir + "/ext/" + target
+ $srcdir = $top_srcdir + "/ext/" + $mdir
mfile = open("Makefile", "w")
mfile.printf "\
SHELL = /bin/sh
@@ -282,58 +412,66 @@ SHELL = /bin/sh
srcdir = #{$srcdir}
VPATH = #{$srcdir}
-hdrdir = #{$topdir}
+topdir = #{$topdir}
+hdrdir = #{$top_srcdir}
+DESTDIR =
CC = @CC@
-prefix = @prefix@
-CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s
-DLDFLAGS = #$DLDFLAGS @LDFLAGS@ #$LDFLAGS
-LDSHARED = @LDSHARED@
+CFLAGS = %s -I$(topdir) -I$(hdrdir) #{CFLAGS} #$CFLAGS -I@includedir@ %s
+DLDFLAGS = #$DLDFLAGS #$LDFLAGS
+LDSHARED = @LDSHARED@ #{defflag}
", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
mfile.printf "\
-program_transform_name = -e @program_transform_name@
-RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t`
+RUBY_INSTALL_NAME = @RUBY_INSTALL_NAME@
prefix = @prefix@
exec_prefix = @exec_prefix@
libdir = @libdir@
-pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)
+#pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)/@MAJOR@.@MINOR@
+pkglibdir = $(libdir)/ruby/@MAJOR@.@MINOR@
archdir = $(pkglibdir)/@arch@
@SET_MAKE@
#### End of system configuration section. ####
"
- mfile.printf "LOCAL_LIBS = %s\n", $local_libs unless $local_libs == ""
+ mfile.printf "LOCAL_LIBS = %s %s\n", $LOCAL_LIBS, $local_flags
mfile.printf "LIBS = %s\n", $libs
mfile.printf "OBJS = "
if !$objs then
$objs = []
- for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{c,cc}"]
+ for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{#{SRC_EXT.join(%q{,})}}"]
f = File.basename(f)
- f.sub!(/\.(c|cc)$/, ".o")
+ f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
$objs.push f
end
end
mfile.printf $objs.join(" ")
mfile.printf "\n"
+ ruby_interpreter = "$(topdir)/miniruby@EXEEXT@"
+ if /mswin32/ =~ RUBY_PLATFORM
+ ruby_interpreter = $topdir + "/miniruby@EXEEXT@"
+ ruby_interpreter.gsub!("/", "\\")
+ end
+
mfile.printf <<EOS
-TARGET = #{target}.#{$static ? "a" : "@DLEXT@"}
+TARGET = #{target}
+DLLIB = $(TARGET).#{$static ? $LIBEXT : "@DLEXT@"}
-INSTALL = #{$dots}@INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
+RUBY = #{ruby_interpreter} -I$(topdir) -I$(hdrdir)/lib
-binsuffix = @binsuffix@
+EXEEXT = @EXEEXT@
-all: $(TARGET)
+all: $(DLLIB)
-clean:; @rm -f *.o *.a *.so *.sl
+clean:; @rm -f *.#{$OBJEXT} *.so *.sl *.#{$LIBEXT} $(DLLIB)
+ @rm -f *.ilk *.exp *.pdb *.bak
@rm -f Makefile extconf.h conftest.*
- @rm -f core ruby$(binsuffix) *~
+ @rm -f core ruby$(EXEEXT) *~
realclean: clean
EOS
@@ -341,67 +479,65 @@ EOS
mfile.printf <<EOS
install:
- @test -d $(DESTDIR)$(libdir) || mkdir $(DESTDIR)$(libdir)
- @test -d $(DESTDIR)$(pkglibdir) || mkdir $(DESTDIR)$(pkglibdir)
- @test -d $(DESTDIR)$(archdir) || mkdir $(DESTDIR)$(archdir)
+ @$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(libdir) $(DESTDIR)$(pkglibdir) $(DESTDIR)$(archdir)
EOS
- if !$static
+ unless $static
mfile.printf "\
- $(INSTALL) $(TARGET) $(DESTDIR)$(archdir)/$(TARGET)
+ @$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(DESTDIR)$(archdir)/$(DLLIB)
"
end
- install_rb(mfile)
+ install_rb(mfile, $srcdir)
mfile.printf "\n"
if $static
+ if "@AR@" =~ /^lib\b/i
mfile.printf "\
-$(TARGET): $(OBJS)
- @AR@ cru $(TARGET) $(OBJS)
- @-@RANLIB@ $(TARGET) 2> /dev/null || true
-"
- elsif "@DLEXT@" != "o"
- mfile.printf "\
-$(TARGET): $(OBJS)
- $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS)
-"
- elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
- if PLATFORM == "m68k-human"
- mfile.printf "\
-$(TARGET): $(OBJS)
- ar cru $(TARGET) $(OBJS)
-"
- elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
- mfile.printf "\
-$(TARGET): $(OBJS)
- cc -r $(CFLAGS) -o $(TARGET) $(OBJS)
+$(DLLIB): $(OBJS)
+ @AR@ /OUT:$(DLLIB) $(OBJS)
"
else
mfile.printf "\
-$(TARGET): $(OBJS)
- ld $(DLDFLAGS) -r -o $(TARGET) $(OBJS)
+$(DLLIB): $(OBJS)
+ @AR@ cru $(DLLIB) $(OBJS)
+ @-@RANLIB@ $(DLLIB) 2> /dev/null || true
"
end
+ elsif "@DLEXT@" != $OBJEXT
+ mfile.printf "\
+$(DLLIB): $(OBJS)
+ $(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
+"
+ elsif RUBY_PLATFORM == "m68k-human"
+ mfile.printf "\
+$(DLLIB): $(OBJS)
+ ar cru $(DLLIB) $(OBJS)
+"
+ else
+ mfile.printf "\
+$(DLLIB): $(OBJS)
+ ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
+"
end
- if File.exist?("depend")
- dfile = open("depend", "r")
+ if File.exist?("#{$srcdir}/depend")
+ dfile = open("#{$srcdir}/depend", "r")
mfile.printf "###\n"
while line = dfile.gets()
- mfile.printf "%s", line
+ mfile.printf "%s", line.gsub('\$\(hdrdir\)/config.h', '$(topdir)/config.h')
end
dfile.close
end
mfile.close
- if PLATFORM =~ /beos/
- if PLATFORM =~ /^powerpc/ then
+ if RUBY_PLATFORM =~ /beos/
+ if RUBY_PLATFORM =~ /^powerpc/ then
deffilename = "ruby.exp"
else
deffilename = "ruby.def"
end
- print "creating ruby.def\n"
+ print "creating #{deffilename}\n"
open(deffilename, "w") do |file|
- file.print("EXPORTS\n") if PLATFORM =~ /^i/
+ file.print("EXPORTS\n") if RUBY_PLATFORM =~ /^i/
file.print("Init_#{target}\n")
end
end
@@ -411,57 +547,95 @@ def extmake(target)
if $force_static or $static_ext[target]
$static = target
else
- $static = FALSE
+ $static = false
end
- return if $nodynamic and not $static
+ unless $install or $clean
+ return if $nodynamic and not $static
+ end
+ $OBJEXT = "@OBJEXT@"
+ $LIBEXT = "a"
$objs = nil
- $libs = PLATFORM =~ /cygwin|beos|openstep|nextstep|rhapsody/ ? nil : "-lc"
- $local_libs = "" # to be assigned in extconf.rb
- $CFLAGS = ""
- $LDFLAGS = ""
+ $local_flags = ""
+ case RUBY_PLATFORM
+ when /cygwin|beos|openstep|nextstep|rhapsody/
+ $libs = ""
+ when /mswin32/
+ $LIBEXT = "lib"
+ $libs = ""
+ $local_flags = "$(topdir)/rubymw.lib -link /EXPORT:Init_$(TARGET)"
+ else
+ $libs = "-lc"
+ end
+ $LOCAL_LIBS = "" # to be assigned in extconf.rb
+ dir = with_config("opt-dir")
+ if dir
+ idir = "-I"+dir+"/include"
+ ldir = "-L"+dir+"/lib"
+ end
+ unless idir
+ dir = with_config("opt-include")
+ idir = "-I"+dir if dir
+ end
+ unless ldir
+ dir = with_config("opt-lib")
+ ldir = "-L"+dir if dir
+ end
+
+ $CFLAGS = idir || ""
+ $LDFLAGS = ldir || ""
begin
system "mkdir", target unless File.directory?(target)
Dir.chdir target
+ $target = target
$mdir = target
- if $static_ext.size > 0 ||
- !File.exist?("./Makefile") ||
- older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
- older("./Makefile", "../extmk.rb") ||
- older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
- then
- $defs = []
- if File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
- load "#{$top_srcdir}/ext/#{target}/extconf.rb"
- else
- create_makefile(target);
+ unless $install or $clean
+ if $static_ext.size > 0 ||
+ !File.exist?("./Makefile") ||
+ older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
+ older("./Makefile", "../extmk.rb") ||
+ older("./Makefile", "#{$top_srcdir}/ext/#{target}/makefile.rb") ||
+ older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
+ then
+ $defs = []
+ if File.exist?("#{$top_srcdir}/ext/#{target}/makefile.rb")
+ load "#{$top_srcdir}/ext/#{target}/makefile.rb"
+ elsif File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
+ load "#{$top_srcdir}/ext/#{target}/extconf.rb"
+ else
+ create_makefile(target)
+ end
end
end
if File.exist?("./Makefile")
if $static
- $extlist.push [$static,target]
+ $extlist.push [$static,$target]
end
if $install
- system "make install DESTDIR=#{$destdir}"
+ system "#{$make} install DESTDIR=#{$destdir}"
elsif $clean
- system "make clean"
+ system "#{$make} clean"
else
- system "make all"
+ system "#{$make} all" or exit
end
end
if $static
$extlibs ||= ""
$extlibs += " " + $LDFLAGS unless $LDFLAGS == ""
- $extlibs += " " + $libs if $libs
- $extlibs += " " + $local_libs unless $local_libs == ""
+ $extlibs += " " + $libs unless $libs == ""
+ $extlibs += " " + $LOCAL_LIBS unless $LOCAL_LIBS == ""
end
ensure
+ system "rm -f conftest*"
Dir.chdir ".."
end
end
+$make = ENV["MAKE"]
+$make ||= with_config("make-prog", "make")
+
# get static-link modules
$static_ext = {}
for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
@@ -472,10 +646,12 @@ for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
sub!(/#.*$/, '')
next if /^\s*$/
if /^option +nodynamic/
- $nodynamic = TRUE
+ $nodynamic = true
next
end
- $static_ext[$_.split[0]] = TRUE
+ target = $_.split[0]
+ target = target.downcase if /mswin32/ =~ RUBY_PLATFORM
+ $static_ext[target] = true
end
f.close
break
@@ -493,6 +669,9 @@ for d in Dir["#{$top_srcdir}/ext/*"]
print "cleaning ", d, "\n"
else
print "compiling ", d, "\n"
+ if RUBY_PLATFORM =~ /-aix/ and older("../ruby.imp", "../miniruby")
+ load "#{$top_srcdir}/ext/aix_mksym.rb"
+ end
end
extmake(d)
end
@@ -511,22 +690,29 @@ if $cache_mod
f.close
end
-exit if $install or $clean
+if $install or $clean
+ Dir.chdir ".."
+ exit
+end
$extinit = "" unless $extinit
+
+ruby = "@RUBY_INSTALL_NAME@@EXEEXT@"
+miniruby = "miniruby@EXEEXT@"
+
+$extobjs = "" unless $extobjs
if $extlist.size > 0
for s,t in $extlist
- f = format("%s/%s.a", s, t)
+ f = format("%s/%s.%s", s, t, $LIBEXT)
if File.exist?(f)
$extinit += format("\
\tInit_%s();\n\
-\trb_provide(\"%s.o\");\n\
+\trb_provide(\"%s.so\");\n\
", t, t)
- $extobjs = "" unless $extobjs
$extobjs += "ext/"
$extobjs += f
$extobjs += " "
else
- FALSE
+ false
end
end
@@ -537,7 +723,7 @@ if $extlist.size > 0
f.printf "}\n"
f.close
end
- if older("extinit.o", "extinit.c")
+ if older("extinit.#{$OBJEXT}", "extinit.c")
cmd = "@CC@ " + CFLAGS + " -c extinit.c"
print cmd, "\n"
system cmd or exit 1
@@ -545,24 +731,20 @@ if $extlist.size > 0
Dir.chdir ".."
- if older("ruby@binsuffix@", "#{$top_srcdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@")
- `rm -f ruby@binsuffix@`
+ if older(ruby, "#{$top_srcdir}/ext/@setup@") or older(ruby, miniruby)
+ system("rm -f #{ruby}")
end
- if $extobjs
- $extobjs = "ext/extinit.o " + $extobjs
- else
- $extobjs = "ext/extinit.o "
- end
- if PLATFORM =~ /m68k-human|beos/
+ $extobjs = "ext/extinit.#{$OBJEXT} " + $extobjs
+ if RUBY_PLATFORM =~ /m68k-human|beos/
$extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
end
- system format('make ruby@binsuffix@ EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
+ system format(%[#{$make} #{ruby} EXTOBJS="%s" EXTLIBS="%s"], $extobjs, $extlibs)
else
Dir.chdir ".."
- if older("ruby@binsuffix@", "miniruby@binsuffix@")
- `rm -f ruby@binsuffix@`
- system("make ruby@binsuffix@")
+ if older(ruby, miniruby)
+ system("rm -f #{ruby}")
+ system("#{$make} #{ruby}")
end
end
diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt
deleted file mode 100644
index 5836e5c681..0000000000
--- a/ext/extmk.rb.nt
+++ /dev/null
@@ -1,501 +0,0 @@
-#! /usr/local/bin/ruby
-
-$".push 'mkmf.rb' #"
-
-if ARGV[0] == 'static'
- $force_static = TRUE
- ARGV.shift
-elsif ARGV[0] == 'install'
- $install = TRUE
- ARGV.shift
-elsif ARGV[0] == 'clean'
- $clean = TRUE
- ARGV.shift
-end
-
-$extlist = []
-
-$cache_mod = FALSE;
-$lib_cache = {}
-$func_cache = {}
-$hdr_cache = {}
-
-#$dllopt = '-MD'
-$dllopt = ''
-
-if File.exist?("config.cache") then
- f = open("config.cache", "r")
- while f.gets
- case $_
- when /^lib: ([\w_]+) (yes|no)/
- $lib_cache[$1] = $2
- when /^func: ([\w_]+) (yes|no)/
- $func_cache[$1] = $2
- when /^hdr: (.+) (yes|no)/
- $hdr_cache[$1] = $2
- end
- end
- f.close
-end
-
-def older(file1, file2)
- if !File.exist?(file1) then
- return TRUE
- end
- if !File.exist?(file2) then
- return FALSE
- end
- if File.mtime(file1) < File.mtime(file2)
- return TRUE
- end
- return FALSE
-end
-
-#LINK = "cl -o conftest.exe -I../.. -Zi -O -I. %s conftest.c %s > nul"
-LINK = "cl -o conftest.exe -Zi -O %s conftest.c %s > nul"
-CPP = "cl -E -I../.. -I../../missing -I../../win32 -I. -Zi -O %s conftest.c > nul"
-
-def try_link(libs)
- #print(format("try #{LINK}", $CFLAGS, $LDFLAGS, libs))
- #system(format(LINK, $CFLAGS, $LDFLAGS, libs))
- print(format("try #{LINK}\n", $CFLAGS, libs))
- system(format(LINK, $CFLAGS, libs))
-end
-
-def try_cpp
- system(format(CPP, $CFLAGS))
-end
-
-def have_library(lib, func)
- #print format("have_library(%s, %s)\n", lib, func)
- if $lib_cache[lib]
- if $lib_cache[lib] == "yes"
- if $libs#
- $libs = lib + ".lib " + $libs
- else
- $libs = lib + ".lib "
- end
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <windows.h>
-#include <winsock.h>
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func
- cfile.close
-
- begin
- if $libs
- libs = lib + ".lib " + $libs
- else
- libs = lib + ".lib"
- end
- #print "libs=#{libs}\n"
- unless try_link(libs)
- #print "fail : #{libs}\n"
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
-
- $libs = libs
- $lib_cache[lib] = 'yes'
- $cache_mod = TRUE
- return TRUE
-end
-
-def have_func(func)
- if $func_cache[func]
- if $func_cache[func] == "yes"
- $defs.push(format("-DHAVE_%s", func.upcase))
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <windows.h>
-#include <winsock.h>
-//char %s();
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func, func
- cfile.close
-
- libs = $libs
- libs = "" if libs == nil
-
- begin
- #print "libs=#{libs}\n"
- unless try_link(libs)
- $func_cache[func] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
- $defs.push(format("-DHAVE_%s", func.upcase))
- $func_cache[func] = 'yes'
- $cache_mod = TRUE
- return TRUE
-end
-
-def have_header(header)
- if $hdr_cache[header]
- if $hdr_cache[header] == "yes"
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <%s>
-", header
- cfile.close
-
- begin
- unless try_cpp
- $hdr_cache[header] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
- $hdr_cache[header] = 'yes'
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- $cache_mod = TRUE
- return TRUE
-end
-
-def create_header()
- if $defs.length > 0
- hfile = open("extconf.h", "w")
- for line in $defs
- line =~ /^-D(.*)/
- hfile.printf "#define %s 1\n", $1
- end
- hfile.close
- end
-end
-
-def create_makefile(target)
-
- if $libs and "obj" == "obj"
- libs = $libs.split
- for lib in libs
- lib.sub!(/(.*)/, '"\1.lib"') if /.lib$/ !~ lib
- end
- $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
- end
- $libs = "" unless $libs
-
- mfile = open("Makefile", "w")
- mfile.printf "\
-SHELL = $(COMPSEC)
-
-#### Start of system configuration section. ####
-
-srcdir = .
-VPATH = .
-
-CC = cl
-
-CFLAGS = %s -I../.. -I../../missing -I../../win32 -I. -O -DNT %s #$CFLAGS %s
-
-RUBYLIB = ../../ruby.lib
-DLDFLAGS = /DLL
-LDSHARED =
-", if $static then "" else "-fpic" end, $dllopt, $defs.join(" ")
-
- if $force_static
- print "static\n"
- else
- print "non static\n"
- end
-
- mfile.printf "\
-
-libdir = /usr/local/lib/ruby/i386-mswin32
-
-
-#### End of system configuration section. ####
-"
- mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs
- mfile.printf "LIBS = %s\n", $libs
- mfile.printf "OBJS = "
- if !$objs then
- $objs = Dir["*.c"]
- for f in $objs
- f.sub!(/\.c$/, ".obj")
- end
- end
- mfile.printf $objs.join(" ")
- mfile.printf "\n"
-
- dots = if "ginstall -c" =~ /^\// then "" else "../" end
- mfile.printf "\
-TARGET = %s.%s
-
-INSTALL = %sginstall -c
-
-DEFFILE = %s.def
-
-all: $(TARGET)
-
-clean:; @rm -f *.obj *.lib *.exp vc*.pdb *.bak *.def
- @rm -f Makefile extconf.h conftest.*
-
-realclean: clean
-", target,
- if $force_static then "lib" else "dll" end, dots, target
-
- if !$static
- mfile.printf "\
-
-install: $(libdir)/$(TARGET)
-
-$(libdir)/$(TARGET): $(TARGET)
- @test -d $(libdir) || mkdir $(libdir)
- $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
-"
- else
- mfile.printf "\
-
-install:;
-"
- end
-
- if $force_static
- mfile.printf "\
-$(TARGET): $(OBJS)
- lib /OUT:$(TARGET) $(OBJS)
-"
- else
- mfile.printf "\
-$(DEFFILE):
- echo $(DEFFILE)
-
-$(TARGET): $(OBJS) $(DEFFILE)
- cl -DLL -o$(TARGET) $(OBJS) $(RUBYLIB) -link /DEF:$(DEFFILE)
-"
- end
-
- if File.exist?("depend")
- dfile = open("depend", "r")
- mfile.printf "###\n"
- while line = dfile.gets()
- mfile.printf "%s", line
- end
- dfile.close
- end
- mfile.close
- if $static
- #printf format("push %s,%s\n", $static, target); ##debug print##
- $extlist.push [$static,target]
- end
-end
-
-#template of .def file.
-def create_def(basename)
- defname = sprintf("%s.def", basename)
- f = open(defname, "w")
- f.printf "\
-LIBRARY %s.dll
-CODE LOADONCALL
-DATA LOADONCALL
-DESCRIPTION 'win32 %s.dll'
-EXPORTS
-
- Init_%s
-", basename, basename, basename
- f.close
-
-end
-
-def extmake(target)
- if $force_static or $static_ext[target]
- $static = target
- else
- $static = FALSE
- end
-
- return if $nodynamic and not $static
-
- $local_libs = nil
- $libs = nil
- $objs = nil
- $CFLAGS = nil
- $LDFLAGS = nil
-
- begin
- Dir.chdir target
- if $static_ext.size > 0 ||
- !File.exist?("./Makefile") ||
- older("./Makefile", "../Setup") ||
- older("./Makefile", "../extmk.rb") ||
- older("./Makefile", "./extconf.rb")
- then
- $defs = []
- if File.exist?("extconf.rb")
- load "extconf.rb"
- else
- create_makefile(target);
- end
- end
-
- if !File.exist?("#{target}.def")
- create_def(target)
- end
-
- if File.exist?("./Makefile")
- if $install
- system "nmake install"
- if File.directory? "./lib"
- for i in Dir["./lib/*.rb"]
- system "ginstall -c #{i} /usr/local/lib/ruby/i386-mswin32"
- end
- end
- elsif $clean
- system "nmake clean"
- else
- #print "!!!make!!!\n"
- system "nmake all"
- end
- end
- if $static
- $extlibs = " "
- $extlibs += " " + $LDFLAGS if $LDFLAGS
- $extlibs += " " + $local_libs if $local_libs
- $extlibs += " " + $libs if $libs
- end
- ensure
- Dir.chdir ".."
- end
-end
-
-# get static-link modules
-$static_ext = {}
-if File.file? "./Setup"
- f = open("./Setup")
- while f.gets()
- $_.chop!
- sub!(/#.*$/, '')
- next if /^\s*$/
- #print $_, "\n"
-
- if /^option +nodynamic/
- $nodynamic = TRUE
- next
- end
- $static_ext[$_.split[0]] = TRUE
- end
- f.close
-end
-
-for d in Dir["*"]
- File.directory?(d) || next
- File.file?(d + "/MANIFEST") || next
-
- d = $1 if d =~ /\/([\/]*)$/
- if $install
- print "installing ", d, "\n"
- elsif $clean
- print "cleaning ", d, "\n"
- else
- print "compiling ", d, "\n"
- end
- extmake(d)
-end
-
-if $cache_mod
- f = open("config.cache", "w")
- for k,v in $lib_cache
- f.printf "lib: %s %s\n", k, v
- end
- for k,v in $func_cache
- f.printf "func: %s %s\n", k, v
- end
- for k,v in $hdr_cache
- f.printf "hdr: %s %s\n", k, v
- end
- f.close
-end
-
-exit if $install or $clean
-$extinit = " " unless $extinit
-$extobjs = ""
-if $extlist.size > 0
- for s,t in $extlist
- #for s,t in $static_ext
- #f = format("%s/%s.obj", s, t)
- #f = format("%s/%s.obj", s, s)
- l = format("%s/%s.lib", s, s)
- if File.exist?(l)
- $extinit += format("\
-\tInit_%s();\n\
-\trb_provide(\"%s.o\");\n\
-", s, s)
- $extobjs += "ext/"
- #$extobjs += f # *.obj
- $extobjs += l # *.lib
- $extobjs += " "
- else
- FALSE
- end
- end
-
- if older("extinit.c", "Setup")
- f = open("extinit.c", "w")
- f.printf "void Init_ext() {\n"
- f.printf $extinit
- f.printf "}\n"
- f.close
- end
- if older("extinit.obj", "extinit.c")
- cmd = "cl -Zi -O -I. -c extinit.c"
- print cmd, "\n"
- system cmd or exit 1
- end
-
- Dir.chdir ".."
-
- if older("ruby.exe", "ext/Setup") or older("ruby.exe", "miniruby.exe")
- `rm -f ruby.exe`
- end
-
- $extobjs = "ext/extinit.obj " + $extobjs
- #$extlibs = ""
- #print "EXTLIBS=#{$extlibs}\n"
- $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
- $extlibs.gsub!(" +", " ") if $extlibs
- #print "EXTLIBS=#{$extlibs}\n"
-
- system format('nmake ruby.exe EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
-else
- Dir.chdir ".."
- if older("ruby.exe", "miniruby.exe")
- `rm -f ruby.exe`
- `cp miniruby.exe ruby.exe`
- end
-end
-#Local variables:
-# mode: ruby
-#end:
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index a7915c7d92..10eab64a46 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -1 +1 @@
-fcntl.o: fcntl.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+fcntl.o: fcntl.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 186f9ac893..80e0112e4c 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -34,6 +34,7 @@ pack up your own arguments to pass as args for locking functions, etc.
#include "ruby.h"
#include <fcntl.h>
+void
Init_fcntl()
{
VALUE mFcntl = rb_define_module("Fcntl");
diff --git a/ext/marshal/MANIFEST b/ext/gdbm/MANIFEST
index 54870ec71f..f4a8796d18 100644
--- a/ext/marshal/MANIFEST
+++ b/ext/gdbm/MANIFEST
@@ -1,5 +1,5 @@
MANIFEST
+README
depend
extconf.rb
-marshal.c
-marshal.doc
+gdbm.c
diff --git a/ext/gdbm/README b/ext/gdbm/README
new file mode 100644
index 0000000000..df7a261c68
--- /dev/null
+++ b/ext/gdbm/README
@@ -0,0 +1 @@
+gdbm ext-library for Ruby 1.3 or later
diff --git a/ext/gdbm/depend b/ext/gdbm/depend
new file mode 100644
index 0000000000..c080a81619
--- /dev/null
+++ b/ext/gdbm/depend
@@ -0,0 +1 @@
+gdbm.o: gdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/gdbm/extconf.rb b/ext/gdbm/extconf.rb
new file mode 100644
index 0000000000..5a09492e5e
--- /dev/null
+++ b/ext/gdbm/extconf.rb
@@ -0,0 +1,7 @@
+require 'mkmf'
+
+dir_config("gdbm")
+if have_library("gdbm", "gdbm_open") and
+ have_header("gdbm.h")
+ create_makefile("gdbm")
+end
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
new file mode 100644
index 0000000000..a9c2c64ef6
--- /dev/null
+++ b/ext/gdbm/gdbm.c
@@ -0,0 +1,604 @@
+/************************************************
+
+ gdbm.c -
+
+ $Author$
+ $Date$
+ modified at: Mon Jan 24 15:59:52 JST 1994
+
+************************************************/
+
+#include "ruby.h"
+
+#include <gdbm.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
+
+VALUE cGDBM;
+
+#define MY_BLOCK_SIZE (2048)
+#define MY_FATAL_FUNC (0)
+
+struct dbmdata {
+ int di_size;
+ GDBM_FILE di_dbm;
+};
+
+static void
+closed_dbm()
+{
+ rb_raise(rb_eRuntimeError, "closed GDBM file");
+}
+
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closed_dbm();\
+}
+
+static void
+free_dbm(dbmp)
+ struct dbmdata *dbmp;
+{
+ if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
+ free(dbmp);
+}
+
+static VALUE
+fgdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE file, vmode;
+ GDBM_FILE dbm;
+ struct dbmdata *dbmp;
+ int mode;
+ VALUE obj;
+
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ else if (NIL_P(vmode)) {
+ mode = -1; /* return nil if DB not exist */
+ }
+ else {
+ mode = NUM2INT(vmode);
+ }
+ Check_SafeStr(file);
+
+ dbm = 0;
+ if (mode >= 0)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ O_RDWR|O_CREAT, mode, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ O_RDWR, mode, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ O_RDONLY, mode, MY_FATAL_FUNC);
+
+ if (!dbm) {
+ if (mode == -1) return Qnil;
+ rb_sys_fail(RSTRING(file)->ptr);
+ }
+
+ obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp);
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
+ rb_obj_call_init(obj, argc, argv);
+
+ return obj;
+}
+
+static VALUE
+fgdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_dbm == 0) closed_dbm();
+ gdbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
+
+static VALUE
+fgdbm_fetch(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ value = gdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ return Qnil;
+ }
+ return rb_tainted_str_new(value.dptr, value.dsize);
+}
+
+static VALUE
+fgdbm_indexes(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE new;
+ int i;
+
+ new = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, fgdbm_fetch(obj, argv[i]));
+ }
+
+ return new;
+}
+
+static VALUE
+fgdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ value = gdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ if (rb_iterator_p()) rb_yield(keystr);
+ return Qnil;
+ }
+
+ if (gdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_shift(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ key = gdbm_firstkey(dbm);
+ if (!key.dptr) return Qnil;
+ val = gdbm_fetch(dbm, key);
+ gdbm_delete(dbm, key);
+
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ return rb_assoc_new(keystr, valstr);
+}
+
+static VALUE
+fgdbm_delete_if(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
+ if (gdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ }
+ }
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_clear(obj)
+ VALUE obj;
+{
+ datum key, nextkey;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ if (gdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ }
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_invert(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+ VALUE hash = rb_hash_new();
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_hash_aset(hash, valstr, keystr);
+ }
+ return obj;
+}
+
+static VALUE
+each_pair(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
+}
+
+static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
+
+static VALUE
+update_i(pair, dbm)
+ VALUE pair, dbm;
+{
+ Check_Type(pair, T_ARRAY);
+ if (RARRAY(pair)->len < 2) {
+ rb_raise(rb_eArgError, "pair must be [key, value]");
+ }
+ fgdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
+ return Qnil;
+}
+
+static VALUE
+fgdbm_update(obj, other)
+ VALUE obj, other;
+{
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fgdbm_replace(obj, other)
+ VALUE obj, other;
+{
+ fgdbm_clear(obj);
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fgdbm_store(obj, keystr, valstr)
+ VALUE obj, keystr, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ if (valstr == Qnil) {
+ fgdbm_delete(obj, keystr);
+ return Qnil;
+ }
+
+ rb_secure(4);
+ keystr = rb_obj_as_string(keystr);
+
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ if (NIL_P(valstr)) return fgdbm_delete(obj, keystr);
+
+ valstr = rb_obj_as_string(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ dbmp->di_size = -1;
+ dbm = dbmp->di_dbm;
+ if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
+#ifdef HAVE_DBM_CLAERERR
+ gdbm_clearerr(dbm);
+#endif
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eRuntimeError, "dbm_store failed");
+ }
+
+ return valstr;
+}
+
+static VALUE
+fgdbm_length(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int i = 0;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
+ dbm = dbmp->di_dbm;
+
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ i++;
+ }
+ dbmp->di_size = i;
+
+ return INT2FIX(i);
+}
+
+static VALUE
+fgdbm_empty_p(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int i = 0;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size < 0) {
+ dbm = dbmp->di_dbm;
+
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ i++;
+ }
+ }
+ else {
+ i = dbmp->di_size;
+ }
+ if (i == 0) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_each_value(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_each_key(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_each_pair(obj)
+ VALUE obj;
+{
+ datum key, val;
+ GDBM_FILE dbm;
+ struct dbmdata *dbmp;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_yield(rb_assoc_new(keystr, valstr));
+ }
+
+ return obj;
+}
+
+static VALUE
+fgdbm_keys(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_values(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_has_key(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ val = gdbm_fetch(dbm, key);
+ if (val.dptr) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_has_value(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ Check_Type(valstr, T_STRING);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_to_a(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = gdbm_firstkey(dbm); key.dptr; key = gdbm_nextkey(dbm, key)) {
+ val = gdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize)));
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_reorganize(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ gdbm_reorganize(dbm);
+ return obj;
+}
+
+void
+Init_gdbm()
+{
+ cGDBM = rb_define_class("GDBM", rb_cObject);
+ rb_include_module(cGDBM, rb_mEnumerable);
+
+ rb_define_singleton_method(cGDBM, "open", fgdbm_s_open, -1);
+ rb_define_singleton_method(cGDBM, "new", fgdbm_s_open, -1);
+ rb_define_method(cGDBM, "close", fgdbm_close, 0);
+ rb_define_method(cGDBM, "[]", fgdbm_fetch, 1);
+ rb_define_method(cGDBM, "[]=", fgdbm_store, 2);
+ rb_define_method(cGDBM, "indexes", fgdbm_indexes, -1);
+ rb_define_method(cGDBM, "indices", fgdbm_indexes, -1);
+ rb_define_method(cGDBM, "length", fgdbm_length, 0);
+ rb_define_alias(cGDBM, "size", "length");
+ rb_define_method(cGDBM, "empty?", fgdbm_empty_p, 0);
+ rb_define_method(cGDBM, "each", fgdbm_each_pair, 0);
+ rb_define_method(cGDBM, "each_value", fgdbm_each_value, 0);
+ rb_define_method(cGDBM, "each_key", fgdbm_each_key, 0);
+ rb_define_method(cGDBM, "each_pair", fgdbm_each_pair, 0);
+ rb_define_method(cGDBM, "keys", fgdbm_keys, 0);
+ rb_define_method(cGDBM, "values", fgdbm_values, 0);
+ rb_define_method(cGDBM, "shift", fgdbm_shift, 1);
+ rb_define_method(cGDBM, "delete", fgdbm_delete, 1);
+ rb_define_method(cGDBM, "delete_if", fgdbm_delete_if, 0);
+ rb_define_method(cGDBM, "clear", fgdbm_clear, 0);
+ rb_define_method(cGDBM,"invert", fgdbm_invert, 0);
+ rb_define_method(cGDBM,"update", fgdbm_update, 1);
+ rb_define_method(cGDBM,"replace", fgdbm_replace, 1);
+ rb_define_method(cGDBM,"reorganize", fgdbm_reorganize, 0);
+
+ rb_define_method(cGDBM, "include?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "has_key?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "has_value?", fgdbm_has_value, 1);
+ rb_define_method(cGDBM, "key?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "value?", fgdbm_has_value, 1);
+
+ rb_define_method(cGDBM, "to_a", fgdbm_to_a, 0);
+}
diff --git a/ext/gtk/MANIFEST b/ext/gtk/MANIFEST
deleted file mode 100644
index 3e1962e1f3..0000000000
--- a/ext/gtk/MANIFEST
+++ /dev/null
@@ -1,18 +0,0 @@
-MANIFEST
-extconf.rb
-gtk.c
-test.rb
-test.xpm
-test0.rb
-test1.rb
-test2.rb
-test3.rb
-test4.rb
-test5.rb
-test6.rb
-test7.rb
-test8.rb
-test9.rb
-testa.rb
-testb.rb
-testc.rb
diff --git a/ext/gtk/extconf.rb b/ext/gtk/extconf.rb
deleted file mode 100644
index 621e0739a5..0000000000
--- a/ext/gtk/extconf.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require "mkmf"
-if have_library("glib", "g_print") and
- have_library("gdk", "gdk_init") and
- have_library("gtk", "gtk_init")
- create_makefile("gtk")
-end
diff --git a/ext/gtk/gtk.c b/ext/gtk/gtk.c
deleted file mode 100644
index 9114312195..0000000000
--- a/ext/gtk/gtk.c
+++ /dev/null
@@ -1,5904 +0,0 @@
-/************************************************
-
- gtk.c -
-
- $Author$
- $Date$
- created at: Wed Jan 7 23:55:11 JST 1998
-
-************************************************/
-
-#include "ruby.h"
-#include "sig.h"
-#include <gtk/gtk.h>
-#include <signal.h>
-
-extern VALUE rb_argv, rb_argv0;
-extern VALUE cData;
-
-static VALUE mGtk;
-
-static VALUE gObject;
-static VALUE gWidget;
-static VALUE gContainer;
-static VALUE gBin;
-static VALUE gAlignment;
-static VALUE gMisc;
-static VALUE gArrow;
-static VALUE gFrame;
-static VALUE gAspectFrame;
-static VALUE gData;
-static VALUE gAdjustment;
-static VALUE gBox;
-static VALUE gButton;
-static VALUE gTButton;
-static VALUE gCButton;
-static VALUE gRButton;
-static VALUE gBBox;
-static VALUE gCList;
-static VALUE gWindow;
-static VALUE gDialog;
-static VALUE gFileSel;
-static VALUE gVBox;
-static VALUE gColorSel;
-static VALUE gColorSelDialog;
-static VALUE gImage;
-static VALUE gDrawArea;
-static VALUE gEntry;
-static VALUE gEventBox;
-static VALUE gFixed;
-static VALUE gGamma;
-static VALUE gHBBox;
-static VALUE gVBBox;
-static VALUE gHBox;
-static VALUE gPaned;
-static VALUE gHPaned;
-static VALUE gVPaned;
-static VALUE gRuler;
-static VALUE gHRuler;
-static VALUE gVRuler;
-static VALUE gRange;
-static VALUE gScale;
-static VALUE gHScale;
-static VALUE gVScale;
-static VALUE gScrollbar;
-static VALUE gHScrollbar;
-static VALUE gVScrollbar;
-static VALUE gSeparator;
-static VALUE gHSeparator;
-static VALUE gVSeparator;
-static VALUE gInputDialog;
-static VALUE gLabel;
-static VALUE gList;
-static VALUE gItem;
-static VALUE gListItem;
-static VALUE gMenuShell;
-static VALUE gMenu;
-static VALUE gMenuBar;
-static VALUE gMenuItem;
-static VALUE gCMenuItem;
-static VALUE gRMenuItem;
-static VALUE gNotebook;
-static VALUE gOptionMenu;
-static VALUE gPixmap;
-static VALUE gPreview;
-static VALUE gProgressBar;
-static VALUE gScrolledWin;
-static VALUE gTable;
-static VALUE gText;
-static VALUE gToolbar;
-static VALUE gTooltips;
-static VALUE gTree;
-static VALUE gTreeItem;
-static VALUE gViewPort;
-
-static VALUE gAcceleratorTable;
-static VALUE gStyle;
-static VALUE gPreviewInfo;
-static VALUE gAllocation;
-static VALUE gRequisiton;
-
-static VALUE mGdk;
-
-static VALUE gdkFont;
-static VALUE gdkColor;
-static VALUE gdkColormap;
-static VALUE gdkPixmap;
-static VALUE gdkBitmap;
-static VALUE gdkWindow;
-static VALUE gdkImage;
-static VALUE gdkVisual;
-static VALUE gdkGC;
-static VALUE gdkRectangle;
-static VALUE gdkGCValues;
-static VALUE gdkRectangle;
-static VALUE gdkSegment;
-static VALUE gdkWindowAttr;
-static VALUE gdkCursor;
-static VALUE gdkAtom;
-static VALUE gdkColorContext;
-static VALUE gdkEvent;
-
-ID id_gtkdata, id_relatives, id_call;
-
-static void gobj_free();
-
-static char*
-get_cstring(str)
- VALUE str;
-{
- if (NIL_P(str)) return NULL;
- Check_Type(str, T_STRING);
- return RSTRING(str)->ptr;
-}
-
-static GtkObject*
-get_gobject(obj)
- VALUE obj;
-{
- struct RData *data;
- GtkObject *gtkp;
-
- if (NIL_P(obj)) return NULL;
-
- Check_Type(obj, T_OBJECT);
- data = RDATA(rb_ivar_get(obj, id_gtkdata));
- if (NIL_P(data) || data->dfree != gobj_free) {
- TypeError("not a Gtk object");
- }
- Data_Get_Struct(data, GtkObject, gtkp);
- if (!GTK_IS_OBJECT(gtkp)) {
- TypeError("not a GtkObject");
- }
-
- return gtkp;
-}
-
-static GtkWidget*
-get_widget(obj)
- VALUE obj;
-{
- GtkObject *data = get_gobject(obj);
-
- return GTK_WIDGET(data);
-}
-
-static VALUE
-get_value_from_gobject(obj)
- GtkObject *obj;
-{
- return (VALUE)gtk_object_get_user_data(obj);
-}
-
-static void
-clear_gobject(obj)
- VALUE obj;
-{
- rb_ivar_set(obj, id_relatives, Qnil);
-}
-
-static void
-add_relative(obj, relative)
- VALUE obj, relative;
-{
- VALUE ary = rb_ivar_get(obj, id_relatives);
-
- if (TYPE(ary) != T_ARRAY) {
- ary = ary_new();
- rb_ivar_set(obj, id_relatives, ary);
- }
- ary_push(ary, relative);
-}
-
-static VALUE gtk_object_list;
-
-static void
-gobj_free(obj)
- GtkObject *obj;
-{
- VALUE self = get_value_from_gobject(obj);
-
- if (GTK_OBJECT_NEED_DESTROY(obj)) {
- gtk_object_destroy(obj);
- }
- rb_ivar_set(self, id_relatives, Qnil);
-}
-
-static void
-delete_gobject(obj)
- GtkObject *obj;
-{
- ary_delete(gtk_object_list, get_value_from_gobject(obj));
-}
-
-static VALUE
-make_gobject(klass, gtkobj)
- VALUE klass;
- GtkObject *gtkobj;
-{
- VALUE obj = obj_alloc(klass);
- VALUE data;
-
- data = Data_Wrap_Struct(cData, 0, gobj_free, gtkobj);
- gtk_object_set_user_data(gtkobj, (gpointer)obj);
-
- rb_ivar_set(obj, id_gtkdata, data);
- gtk_signal_connect(gtkobj, "destroy", (GtkSignalFunc)delete_gobject, 0);
- ary_push(gtk_object_list, obj);
- return obj;
-}
-
-static VALUE
-make_widget(klass, widget)
- VALUE klass;
- GtkWidget *widget;
-{
- return make_gobject(klass, GTK_OBJECT(widget));
-}
-
-static void
-free_gstyle(style)
- GtkStyle *style;
-{
- gtk_style_unref(style);
-}
-
-static VALUE
-make_gstyle(style)
- GtkStyle *style;
-{
- gtk_style_ref(style);
- return Data_Wrap_Struct(gStyle, 0, free_gstyle, style);
-}
-
-static GtkStyle*
-get_gstyle(style)
- VALUE style;
-{
- GtkStyle *gstyle;
-
- if (NIL_P(style)) return NULL;
- if (!obj_is_instance_of(style, gStyle)) {
- TypeError("not a GtkStyle");
- }
- Data_Get_Struct(style, GtkStyle, gstyle);
-
- return gstyle;
-}
-
-static void
-free_gaccel(tbl)
- GtkAcceleratorTable *tbl;
-{
- gtk_accelerator_table_unref(tbl);
-}
-
-static VALUE
-make_gtkacceltbl(tbl)
- GtkAcceleratorTable *tbl;
-{
- gtk_accelerator_table_ref(tbl);
- return Data_Wrap_Struct(gAcceleratorTable, 0, free_gaccel, tbl);
-}
-
-static GtkAcceleratorTable*
-get_gtkacceltbl(value)
- VALUE value;
-{
- GtkAcceleratorTable *tbl;
-
- if (NIL_P(value)) return NULL;
-
- if (!obj_is_instance_of(value, gAcceleratorTable)) {
- TypeError("not an AcceleratorTable");
- }
- Data_Get_Struct(value, GtkAcceleratorTable, tbl);
-
- return tbl;
-}
-
-static VALUE
-make_gtkprevinfo(info)
- GtkPreviewInfo *info;
-{
- return Data_Wrap_Struct(gAcceleratorTable, 0, 0, info);
-}
-
-static GtkPreviewInfo*
-get_gtkprevinfo(value)
- VALUE value;
-{
- GtkPreviewInfo *info;
-
- if (NIL_P(value)) return NULL;
-
- if (!obj_is_instance_of(value, gPreviewInfo)) {
- TypeError("not a PreviewInfo");
- }
- Data_Get_Struct(value, GtkPreviewInfo, info);
-
- return info;
-}
-
-static void
-exec_callback(widget, data, nparams, params)
- GtkWidget *widget;
- VALUE data;
- int nparams;
- GtkType *params;
-{
- VALUE self = get_value_from_gobject(GTK_OBJECT(widget));
- VALUE proc = RARRAY(data)->ptr[0];
- VALUE event = RARRAY(data)->ptr[1];
- ID id = NUM2INT(event);
-
- if (NIL_P(proc) && rb_respond_to(self, id)) {
- rb_funcall(self, id, 3, self,
- INT2FIX(nparams), INT2NUM((INT)params));
- }
- else {
- rb_funcall(proc, id_call, 1, self);
- }
-}
-
-static void
-free_ttips(tips)
- GtkTooltips *tips;
-{
- gtk_tooltips_unref(tips);
-}
-
-static VALUE
-make_ttips(klass, tips)
- VALUE klass;
- GtkTooltips *tips;
-{
- gtk_tooltips_ref(tips);
- return Data_Wrap_Struct(klass, 0, free_ttips, tips);
-}
-
-static GtkTooltips*
-get_ttips(tips)
- VALUE tips;
-{
- GtkTooltips *gtips;
-
- if (NIL_P(tips)) return NULL;
-
- if (!obj_is_instance_of(tips, gTooltips)) {
- TypeError("not a GtkTooltips");
- }
- Data_Get_Struct(tips, GtkTooltips, gtips);
-
- return gtips;
-}
-
-static void
-free_gdkfont(font)
- GdkFont *font;
-{
- gdk_font_unref(font);
-}
-
-static VALUE
-make_gdkfont(font)
- GdkFont *font;
-{
- gdk_font_ref(font);
- return Data_Wrap_Struct(gdkFont, 0, free_gdkfont, font);
-}
-
-static GdkFont*
-get_gdkfont(font)
- VALUE font;
-{
- GdkFont *gfont;
-
- if (NIL_P(font)) return NULL;
-
- if (!obj_is_instance_of(font, gdkFont)) {
- TypeError("not a GdkFont");
- }
- Data_Get_Struct(font, GdkFont, gfont);
-
- return gfont;
-}
-
-static VALUE
-gdkfnt_equal(fn1, fn2)
- VALUE fn1, fn2;
-{
- if (gdk_font_equal(get_gdkfont(fn1), get_gdkfont(fn2)))
- return TRUE;
- return FALSE;
-}
-
-static void
-free_tobj(obj)
- gpointer obj;
-{
- free(obj);
-}
-
-static VALUE
-make_tobj(obj, klass, size)
- gpointer obj;
- VALUE klass;
- int size;
-{
- gpointer copy;
- VALUE data;
-
- copy = xmalloc(size);
- memcpy(copy, obj, size);
- data = Data_Wrap_Struct(klass, 0, free_tobj, copy);
-
- return data;
-}
-
-static gpointer
-get_tobj(obj, klass)
- VALUE obj, klass;
-{
- void *ptr;
-
- if (NIL_P(obj)) return NULL;
-
- if (!obj_is_instance_of(obj, klass)) {
- TypeError("not a %s", rb_class2name(klass));
- }
- Data_Get_Struct(obj, void, ptr);
-
- return ptr;
-}
-
-#define make_gdkcolor(c) make_tobj(c, gdkColor, sizeof(GdkColor))
-#define get_gdkcolor(c) ((GdkColor*)get_tobj(c, gdkColor))
-
-#define make_gdkrect(c) make_tobj(c, gdkRectangle, sizeof(GdkRectangle))
-#define get_gdkrect(c) ((GdkRectangle*)get_tobj(c, gdkRectangle))
-
-#define make_gdksegment(c) make_tobj(c, gdkSegment, sizeof(GdkSegment))
-#define get_gdksegment(c) ((GdkSegment*)get_tobj(c, gdkSegment))
-
-#define make_gdkwinattr(c) make_tobj(c, gdkWindowAttr, sizeof(GdkWindowAttr))
-#define get_gdkwinattr(c) ((GdkWindowAttr*)get_tobj(c, gdkWindowAttr))
-
-#define make_gdkwinattr(c) make_tobj(c, gdkWindowAttr, sizeof(GdkWindowAttr))
-#define get_gdkwinattr(c) ((GdkWindowAttr*)get_tobj(c, gdkWindowAttr))
-
-#define make_gallocation(c) make_tobj(c, gAllocation, sizeof(GtkAllocation))
-#define get_gallocation(c) ((GtkAllocation*)get_tobj(c, gAllocation))
-
-#define make_grequisiton(c) make_tobj(c, gRequisiton, sizeof(GtkRequisition))
-#define get_grequisiton(c) ((GtkRequisition*)get_tobj(c, gRequisiton))
-
-#define make_gdkrectangle(r) make_tobj(r, gdkRectangle, sizeof(GdkRectangle))
-#define get_gdkrectangle(r) ((GdkRectangle*)get_tobj(r, gdkRectangle))
-
-static void
-free_gdkcmap(cmap)
- GdkColormap *cmap;
-{
- gdk_colormap_unref(cmap);
-}
-
-static VALUE
-make_gdkcmap(cmap)
- GdkColormap *cmap;
-{
- gdk_colormap_ref(cmap);
- return Data_Wrap_Struct(gdkColormap, 0, free_gdkcmap, cmap);
-}
-
-static GdkColormap*
-get_gdkcmap(cmap)
- VALUE cmap;
-{
- GdkColormap *gcmap;
-
- if (NIL_P(cmap)) return NULL;
-
- if (!obj_is_kind_of(cmap, gdkColormap)) {
- TypeError("not a GdkColormap");
- }
- Data_Get_Struct(cmap, GdkColormap, gcmap);
-
- return gcmap;
-}
-
-static VALUE
-make_gdkvisual(visual)
- GdkVisual *visual;
-{
- return Data_Wrap_Struct(gdkVisual, 0, 0, visual);
-}
-
-static GdkVisual*
-get_gdkvisual(visual)
- VALUE visual;
-{
- GdkVisual *gvisual;
-
- if (NIL_P(visual)) return NULL;
-
- if (!obj_is_kind_of(visual, gdkVisual)) {
- TypeError("not a GdkVisual");
- }
- Data_Get_Struct(visual, GdkVisual, gvisual);
-
- return gvisual;
-}
-
-static void
-free_gdkwindow(window)
- GdkWindow *window;
-{
- gdk_window_unref(window);
-}
-
-static VALUE
-make_gdkwindow(window)
- GdkWindow *window;
-{
- gdk_window_ref(window);
- return Data_Wrap_Struct(gdkWindow, 0, free_gdkwindow, window);
-}
-
-static GdkWindow*
-get_gdkwindow(window)
- VALUE window;
-{
- GdkWindow *gwindow;
-
- if (NIL_P(window)) return NULL;
-
- if (!obj_is_kind_of(window, gdkWindow)) {
- TypeError("not a GdkWindow");
- }
- Data_Get_Struct(window, GdkWindow, gwindow);
-
- return gwindow;
-}
-
-static void
-free_gdkpixmap(pixmap)
- GdkPixmap *pixmap;
-{
- gdk_pixmap_unref(pixmap);
-}
-
-static VALUE
-make_gdkpixmap(klass, pixmap)
- VALUE klass;
- GdkPixmap *pixmap;
-{
- gdk_pixmap_ref(pixmap);
- return Data_Wrap_Struct(klass, 0, free_gdkpixmap, pixmap);
-}
-
-static GdkPixmap*
-get_gdkpixmap(pixmap)
- VALUE pixmap;
-{
- GdkPixmap *gpixmap;
-
- if (NIL_P(pixmap)) return NULL;
-
- if (!obj_is_kind_of(pixmap, gdkPixmap)) {
- TypeError("not a GdkPixmap");
- }
- Data_Get_Struct(pixmap, GdkPixmap, gpixmap);
-
- return gpixmap;
-}
-
-static VALUE
-gdkpmap_s_new(self, win, w, h, depth)
- VALUE self, win, w, h, depth;
-{
- GdkPixmap *new;
- GdkWindow *window = get_gdkwindow(win);
-
- new = gdk_pixmap_new(window, NUM2INT(w), NUM2INT(h), NUM2INT(depth));
- return make_gdkpixmap(self, new);
-}
-
-static VALUE
-gdkpmap_create_from_data(self, win, data, w, h, depth, fg, bg)
- VALUE self, win, data, w, h, depth, fg, bg;
-{
- GdkPixmap *new;
- GdkWindow *window = get_gdkwindow(win);
-
- Check_Type(data, T_STRING);
- new = gdk_pixmap_create_from_data(window,
- RSTRING(data)->ptr,
- NUM2INT(w), NUM2INT(h),
- NUM2INT(depth),
- get_gdkcolor(fg),
- get_gdkcolor(bg));
- return make_gdkpixmap(self, new);
-}
-
-static VALUE
-gdkpmap_create_from_xpm(self, win, tcolor, fname)
- VALUE self, win, tcolor, fname;
-{
- GdkPixmap *new;
- GdkBitmap *mask;
- GdkWindow *window = get_gdkwindow(win);
-
- Check_Type(fname, T_STRING);
- new = gdk_pixmap_create_from_xpm(window, &mask,
- get_gdkcolor(tcolor),
- RSTRING(fname)->ptr);
- if (!new) {
- ArgError("Pixmap not created from %s", RSTRING(fname)->ptr);
- }
- return assoc_new(make_gdkpixmap(self, new),
- make_gdkpixmap(gdkBitmap, mask));
-}
-
-static VALUE
-gdkpmap_create_from_xpm_d(self, win, tcolor, data)
- VALUE self, win, tcolor, data;
-{
- GdkPixmap *new;
- GdkBitmap *mask;
- GdkWindow *window = get_gdkwindow(win);
- int i;
- gchar **buf;
-
- Check_Type(data, T_ARRAY);
- buf = ALLOCA_N(char*, RARRAY(data)->len);
- for (i=0; i<RARRAY(data)->len; i++) {
- Check_Type(RARRAY(data)->ptr[i], T_STRING);
- buf[i] = RSTRING(RARRAY(data)->ptr[i])->ptr;
- }
-
- new = gdk_pixmap_create_from_xpm_d(window, &mask,
- get_gdkcolor(tcolor),
- buf);
-
- return assoc_new(make_gdkpixmap(self, new),
- make_gdkpixmap(gdkBitmap, mask));
-}
-
-static VALUE
-gdkbmap_s_new(self, win, w, h)
- VALUE self, win, w, h;
-{
- GdkPixmap *new;
- GdkWindow *window = get_gdkwindow(win);
-
- new = gdk_pixmap_new(window, NUM2INT(w), NUM2INT(h), 1);
- return make_gdkpixmap(self, new);
-}
-
-static VALUE
-gdkbmap_create_from_data(self, win, data, w, h)
- VALUE self, win, data, w, h;
-{
- GdkBitmap *new;
- GdkWindow *window = get_gdkwindow(win);
-
- Check_Type(data, T_STRING);
- new = gdk_bitmap_create_from_data(window,
- RSTRING(data)->ptr,
- NUM2INT(w), NUM2INT(h));
- return make_gdkpixmap(self, (GdkPixmap*)new);
-}
-
-static void
-free_gdkimage(image)
- GdkImage *image;
-{
- gdk_image_destroy(image);
-}
-
-static VALUE
-make_gdkimage(image)
- GdkImage *image;
-{
- return Data_Wrap_Struct(gdkImage, 0, free_gdkimage, image);
-}
-
-static GdkImage*
-get_gdkimage(image)
- VALUE image;
-{
- GdkImage *gimage;
-
- if (NIL_P(image)) return NULL;
-
- if (!obj_is_instance_of(image, gdkImage)) {
- TypeError("not a GdkImage");
- }
- Data_Get_Struct(image, GdkImage, gimage);
-
- return gimage;
-}
-
-static void
-free_gdkevent(event)
- GdkEvent *event;
-{
- gdk_event_free(event);
-}
-
-static VALUE
-make_gdkevent(event)
- GdkEvent *event;
-{
- event = gdk_event_copy(event);
- return Data_Wrap_Struct(gdkEvent, 0, free_gdkevent, event);
-}
-
-static GdkEvent*
-get_gdkevent(event)
- VALUE event;
-{
- GdkEvent *gevent;
-
- if (NIL_P(event)) return NULL;
-
- if (!obj_is_instance_of(event, gdkEvent)) {
- TypeError("not a GdkEvent");
- }
- Data_Get_Struct(event, GdkEvent, gevent);
-
- return gevent;
-}
-
-static VALUE
-glist2ary(list)
- GList *list;
-{
- VALUE ary = ary_new();
-
- while (list) {
- ary_push(ary, get_value_from_gobject(GTK_OBJECT(list->data)));
- list = list->next;
- }
-
- return ary;
-}
-
-static GList*
-ary2glist(ary)
- VALUE ary;
-{
- int i;
- GList *glist = NULL;
-
- Check_Type(ary, T_ARRAY);
- for (i=0; i<RARRAY(ary)->len; i++) {
- glist = g_list_prepend(glist,get_widget(RARRAY(ary)->ptr[i]));
- }
-
- return g_list_reverse(glist);
-}
-
-static GSList*
-ary2gslist(ary)
- VALUE ary;
-{
- int i;
- GSList *glist = NULL;
-
- if (NIL_P(ary)) return NULL;
- Check_Type(ary, T_ARRAY);
- for (i=0; i<RARRAY(ary)->len; i++) {
- glist = g_slist_append(glist,get_widget(RARRAY(ary)->ptr[i]));
- }
-
- return glist;
-}
-
-static VALUE
-gslist2ary(list)
- GSList *list;
-{
- VALUE ary = ary_new();
-
- while (list) {
- ary_push(ary, get_value_from_gobject(GTK_OBJECT(list->data)));
- list = list->next;
- }
-
- return ary;
-}
-
-static VALUE
-gobj_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- Fail("can't instantiate class %s", rb_class2name(self));
-}
-
-static VALUE
-gobj_smethod_added(self, id)
- VALUE self, id;
-{
- GtkObject *obj = get_gobject(self);
- char *name = rb_id2name(NUM2INT(id));
-
-
- if (gtk_signal_lookup(name, GTK_OBJECT_TYPE(obj))) {
- VALUE handler = assoc_new(Qnil, id);
-
- add_relative(self, handler);
- gtk_signal_connect_interp(obj, name,
- exec_callback, (gpointer)handler,
- NULL, 0);
- }
- return Qnil;
-}
-
-static VALUE
-gobj_destroy(self)
- VALUE self;
-{
- printf("a\n");
- gtk_object_destroy(get_gobject(self));
- printf("b\n");
- clear_gobject(self);
- return Qnil;
-}
-
-static VALUE
-gobj_set_flags(self, flags)
- VALUE self, flags;
-{
- GtkObject *object = get_gobject(self);
- GTK_OBJECT_SET_FLAGS(object, NUM2INT(flags));
- return self;
-}
-
-static VALUE
-gobj_unset_flags(self, flags)
- VALUE self, flags;
-{
- GtkObject *object = get_gobject(self);
- GTK_OBJECT_UNSET_FLAGS(object, NUM2INT(flags));
- return self;
-}
-
-static VALUE
-gobj_sig_connect(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE sig, handler;
- GtkWidget *widget = get_widget(self);
- ID id = 0;
- int n;
-
- rb_scan_args(argc, argv, "11", &sig, &handler);
- Check_Type(sig, T_STRING);
- if (NIL_P(handler) && iterator_p()) {
- handler = f_lambda();
- id = rb_intern(RSTRING(sig)->ptr);
- }
- handler = assoc_new(handler, INT2NUM(id));
- add_relative(self, handler);
- n = gtk_signal_connect_interp(GTK_OBJECT(widget), RSTRING(sig)->ptr,
- exec_callback, (gpointer)handler,
- NULL, 0);
-
- return INT2FIX(n);
-}
-
-static VALUE
-gobj_sig_connect_after(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE sig, handler;
- GtkWidget *widget = get_widget(self);
- ID id = 0;
- int n;
-
- rb_scan_args(argc, argv, "11", &sig, &handler);
- Check_Type(sig, T_STRING);
- if (NIL_P(handler) && iterator_p()) {
- handler = f_lambda();
- id = rb_intern(RSTRING(sig)->ptr);
- }
- add_relative(self, handler);
- n = gtk_signal_connect_interp(GTK_OBJECT(widget), RSTRING(sig)->ptr,
- exec_callback, (gpointer)handler,
- NULL, 1);
-
- return INT2FIX(n);
-}
-
-static VALUE
-cont_bwidth(self, width)
- VALUE self, width;
-{
- GtkWidget *widget = get_widget(self);
- gtk_container_border_width(GTK_CONTAINER(widget), NUM2INT(width));
- return self;
-}
-
-static VALUE
-cont_add(self, other)
- VALUE self, other;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_add(GTK_CONTAINER(widget), get_widget(other));
- return self;
-}
-
-static VALUE
-cont_disable_resize(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_disable_resize(GTK_CONTAINER(widget));
- return self;
-}
-
-static VALUE
-cont_enable_resize(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_enable_resize(GTK_CONTAINER(widget));
- return self;
-}
-
-static VALUE
-cont_block_resize(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_block_resize(GTK_CONTAINER(widget));
- return self;
-}
-
-static VALUE
-cont_unblock_resize(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_unblock_resize(GTK_CONTAINER(widget));
- return self;
-}
-
-static VALUE
-cont_need_resize(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_need_resize(GTK_CONTAINER(widget));
- return self;
-}
-
-static VALUE
-cont_foreach(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE callback;
- GtkWidget *widget = get_widget(self);
-
- rb_scan_args(argc, argv, "01", &callback);
- if (NIL_P(callback)) {
- callback = f_lambda();
- }
- gtk_container_foreach(GTK_CONTAINER(widget),
- exec_callback, (gpointer)callback);
- return self;
-}
-
-static void
-yield_callback(widget)
- GtkWidget *widget;
-{
- rb_yield(get_value_from_gobject(GTK_OBJECT(widget)));
-}
-
-static VALUE
-cont_each(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_foreach(GTK_CONTAINER(widget),
- yield_callback, 0);
- return self;
-}
-
-static VALUE
-cont_focus(self, direction)
- VALUE self, direction;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_container_focus(GTK_CONTAINER(widget),
- (GtkDirectionType)NUM2INT(direction));
- return self;
-}
-
-static void
-cont_children_callback(widget, data)
- GtkWidget *widget;
- gpointer data;
-{
- VALUE ary = (VALUE)data;
-
- ary_push(ary, get_value_from_gobject(GTK_OBJECT(widget)));
-}
-
-static VALUE
-cont_children(self, direction)
- VALUE self, direction;
-{
- GtkWidget *widget = get_widget(self);
- VALUE ary = ary_new();
-
- gtk_container_foreach(GTK_CONTAINER(widget),
- cont_children_callback,
- (gpointer)ary);
- return ary;
-}
-
-static VALUE
-align_s_new(self, xalign, yalign, xscale, yscale)
- VALUE self, xalign, yalign, xscale, yscale;
-{
- return make_widget(self, gtk_alignment_new(NUM2DBL(xalign),
- NUM2DBL(yalign),
- NUM2DBL(xscale),
- NUM2DBL(yscale)));
-}
-
-static VALUE
-align_set(self, xalign, yalign, xscale, yscale)
- VALUE self, xalign, yalign, xscale, yscale;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_alignment_set(GTK_ALIGNMENT(widget),
- NUM2DBL(xalign), NUM2DBL(yalign),
- NUM2DBL(xscale), NUM2DBL(yscale));
- return self;
-}
-
-static VALUE
-misc_set_align(self, xalign, yalign)
- VALUE self, xalign, yalign;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_misc_set_alignment(GTK_MISC(widget),
- NUM2DBL(xalign), NUM2DBL(yalign));
- return self;
-}
-
-static VALUE
-misc_set_padding(self, xpad, ypad)
- VALUE self, xpad, ypad;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_misc_set_padding(GTK_MISC(widget),
- NUM2DBL(xpad), NUM2DBL(ypad));
- return self;
-}
-
-static VALUE
-arrow_s_new(self, arrow_t, shadow_t)
- VALUE self, arrow_t, shadow_t;
-{
- return make_widget(self, gtk_arrow_new((GtkArrowType)NUM2INT(arrow_t),
- (GtkShadowType)NUM2INT(shadow_t)));
-}
-
-static VALUE
-arrow_set(self, arrow_t, shadow_t)
- VALUE self, arrow_t, shadow_t;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_arrow_set(GTK_ARROW(widget),
- (GtkArrowType)NUM2INT(arrow_t),
- (GtkShadowType)NUM2INT(shadow_t));
- return self;
-}
-
-static VALUE
-frame_s_new(self, label)
- VALUE self, label;
-{
- return make_widget(self, gtk_frame_new(get_cstring(label)));
-}
-
-static VALUE
-frame_set_label(self, label)
- VALUE self, label;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_frame_set_label(GTK_FRAME(widget), get_cstring(label));
- return self;
-}
-
-static VALUE
-frame_set_label_align(self, xalign, yalign)
- VALUE self, xalign, yalign;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_frame_set_label_align(GTK_FRAME(widget),
- NUM2DBL(xalign),
- NUM2DBL(yalign));
-
- return self;
-}
-
-static VALUE
-frame_set_shadow_type(self, type)
- VALUE self, type;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_frame_set_shadow_type(GTK_FRAME(widget),
- (GtkShadowType)NUM2INT(type));
- return self;
-}
-
-static VALUE
-aframe_s_new(self, label, xalign, yalign, ratio, obey_child)
- VALUE self, label, xalign, yalign, ratio, obey_child;
-{
- return make_widget(self, gtk_aspect_frame_new(get_cstring(label),
- NUM2DBL(xalign),
- NUM2DBL(yalign),
- NUM2DBL(ratio),
- RTEST(obey_child)));
-}
-
-static VALUE
-aframe_set(self, xalign, yalign, ratio, obey_child)
- VALUE self, xalign, yalign, ratio, obey_child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_aspect_frame_set(GTK_ASPECT_FRAME(widget),
- NUM2DBL(xalign), NUM2DBL(yalign),
- NUM2DBL(ratio), RTEST(obey_child));
- return self;
-}
-
-static VALUE
-adj_s_new(self, value, lower, upper, step_inc, page_inc, page_size)
- VALUE self, value, lower, upper, step_inc, page_inc, page_size;
-{
- return make_widget(self, gtk_adjustment_new(NUM2DBL(value),
- NUM2DBL(lower),
- NUM2DBL(upper),
- NUM2DBL(step_inc),
- NUM2DBL(page_inc),
- NUM2DBL(page_size)));
-}
-
-static VALUE
-widget_destroy(self)
- VALUE self;
-{
- gtk_widget_destroy(get_widget(self));
- clear_gobject(self);
-
- return Qnil;
-}
-
-static VALUE
-widget_show(self)
- VALUE self;
-{
- gtk_widget_show(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_show_all(self)
- VALUE self;
-{
- gtk_widget_show_all(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_hide(self)
- VALUE self;
-{
- gtk_widget_hide(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_hide_all(self)
- VALUE self;
-{
- gtk_widget_hide_all(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_map(self)
- VALUE self;
-{
- gtk_widget_map(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_unmap(self)
- VALUE self;
-{
- gtk_widget_unmap(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_realize(self)
- VALUE self;
-{
- gtk_widget_realize(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_unrealize(self)
- VALUE self;
-{
- gtk_widget_unrealize(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_queue_draw(self)
- VALUE self;
-{
- gtk_widget_queue_draw(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_queue_resize(self)
- VALUE self;
-{
- gtk_widget_queue_resize(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_draw(self, rect)
- VALUE self, rect;
-{
- gtk_widget_draw(get_widget(self), get_gdkrectangle(rect));
- return self;
-}
-
-static VALUE
-widget_draw_focus(self)
- VALUE self;
-{
- gtk_widget_draw_focus(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_draw_default(self)
- VALUE self;
-{
- gtk_widget_draw_default(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_draw_children(self)
- VALUE self;
-{
- gtk_widget_draw_children(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_size_request(self, req)
- VALUE self, req;
-{
- gtk_widget_size_request(get_widget(self), get_grequisiton(req));
- return self;
-}
-
-static VALUE
-widget_size_allocate(self, alloc)
- VALUE self, alloc;
-{
- gtk_widget_size_allocate(get_widget(self), get_gallocation(alloc));
- return self;
-}
-
-static VALUE
-widget_inst_accel(self, accel, sig, key, mod)
- VALUE self, accel, sig, key, mod;
-{
- gtk_widget_install_accelerator(get_widget(self),
- get_gtkacceltbl(accel),
- get_cstring(sig),
- NUM2INT(key),
- (guint8)NUM2INT(mod));
- return self;
-}
-
-static VALUE
-widget_rm_accel(self, accel, sig)
- VALUE self, accel, sig;
-{
- gtk_widget_remove_accelerator(get_widget(self),
- get_gtkacceltbl(accel),
- get_cstring(sig));
- return self;
-}
-
-static VALUE
-widget_event(self, event)
- VALUE self, event;
-{
- int n = gtk_widget_event(get_widget(self), get_gdkevent(event));
- return NUM2INT(n);
-}
-
-static VALUE
-widget_activate(self)
- VALUE self;
-{
- gtk_widget_activate(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_grab_focus(self)
- VALUE self;
-{
- gtk_widget_grab_focus(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_grab_default(self)
- VALUE self;
-{
- gtk_widget_grab_default(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_restore_state(self)
- VALUE self;
-{
- gtk_widget_restore_state(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_visible(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- if (GTK_WIDGET_VISIBLE(widget))
- return TRUE;
- return FALSE;
-}
-
-static VALUE
-widget_reparent(self, parent)
- VALUE self, parent;
-{
- gtk_widget_reparent(get_widget(self), get_widget(parent));
- return self;
-}
-
-static VALUE
-widget_popup(self, x, y)
- VALUE self, x, y;
-{
- gtk_widget_popup(get_widget(self), NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-widget_intersect(self, area, intersect)
- VALUE self, area, intersect;
-{
- int n = gtk_widget_intersect(get_widget(self),
- get_gdkrectangle(area),
- get_gdkrectangle(intersect));
- return NUM2INT(n);
-}
-
-static VALUE
-widget_basic(self)
- VALUE self;
-{
- int n = gtk_widget_basic(get_widget(self));
- return NUM2INT(n);
-}
-
-static VALUE
-widget_set_state(self, state)
- VALUE self, state;
-{
- gtk_widget_set_state(get_widget(self), (GtkStateType)NUM2INT(state));
- return self;
-}
-
-static VALUE
-widget_set_style(self, style)
- VALUE self, style;
-{
- gtk_widget_set_style(get_widget(self),
- get_gstyle(style));
- return self;
-}
-
-static VALUE
-widget_set_parent(self, parent)
- VALUE self, parent;
-{
- gtk_widget_set_parent(get_widget(self), get_widget(parent));
- return self;
-}
-
-static VALUE
-widget_set_name(self, name)
- VALUE self, name;
-{
- gtk_widget_set_name(get_widget(self), get_cstring(name));
- return self;
-}
-
-static VALUE
-widget_get_name(self)
- VALUE self;
-{
- char *name = gtk_widget_get_name(get_widget(self));
-
- return str_new2(name);
-}
-
-static VALUE
-widget_set_sensitive(self, sensitive)
- VALUE self, sensitive;
-{
- gtk_widget_set_sensitive(get_widget(self), RTEST(sensitive));
- return self;
-}
-
-static VALUE
-widget_set_uposition(self, x, y)
- VALUE self, x, y;
-{
- gtk_widget_set_uposition(get_widget(self), NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-widget_set_usize(self, w, h)
- VALUE self, w, h;
-{
- gtk_widget_set_usize(get_widget(self), NUM2INT(w), NUM2INT(h));
- return self;
-}
-
-static VALUE
-widget_set_events(self, events)
- VALUE self, events;
-{
- gtk_widget_set_events(get_widget(self), NUM2INT(events));
- return self;
-}
-
-static VALUE
-widget_set_eevents(self, mode)
- VALUE self, mode;
-{
- gtk_widget_set_extension_events(get_widget(self),
- (GdkExtensionMode)NUM2INT(mode));
- return self;
-}
-
-static VALUE
-widget_unparent(self)
- VALUE self;
-{
- gtk_widget_unparent(get_widget(self));
- return self;
-}
-
-static VALUE
-widget_window(self)
- VALUE self;
-{
- return make_gdkwindow(get_widget(self)->window);
-}
-
-static VALUE
-widget_get_toplevel(self)
- VALUE self;
-{
- return get_value_from_gobject(gtk_widget_get_toplevel(get_widget(self)));
-}
-
-static VALUE
-widget_get_ancestor(self, type)
- VALUE self, type;
-{
- GtkWidget *widget = get_widget(self);
-#if 0
- if (obj_is_kind_of(type, cClass)) {
- }
-#endif
- widget = gtk_widget_get_ancestor(widget, NUM2INT(type));
-
- return get_value_from_gobject(widget);
-}
-
-static VALUE
-widget_get_colormap(self)
- VALUE self;
-{
- GdkColormap *cmap = gtk_widget_get_colormap(get_widget(self));
-
- return make_gdkcmap(cmap);
-}
-
-static VALUE
-widget_get_visual(self)
- VALUE self;
-{
- GdkVisual *v = gtk_widget_get_visual(get_widget(self));
-
- return make_gdkvisual(v);
-}
-
-static VALUE
-widget_get_style(self)
- VALUE self;
-{
- GtkStyle *s = gtk_widget_get_style(get_widget(self));
-
- return make_gstyle(s);
-}
-
-static VALUE
-widget_get_pointer(self)
- VALUE self;
-{
- int x, y;
-
- gtk_widget_get_pointer(get_widget(self), &x, &y);
- return assoc_new(INT2FIX(x), INT2FIX(y));
-}
-
-static VALUE
-widget_is_ancestor(self, ancestor)
- VALUE self, ancestor;
-{
- if (gtk_widget_is_ancestor(get_widget(self), get_widget(ancestor))) {
- return TRUE;
- }
- return FALSE;
-}
-
-static VALUE
-widget_is_child(self, child)
- VALUE self, child;
-{
- if (gtk_widget_is_child(get_widget(self), get_widget(child))) {
- return TRUE;
- }
- return FALSE;
-}
-
-static VALUE
-widget_get_events(self)
- VALUE self;
-{
- int n = gtk_widget_get_events(get_widget(self));
- return NUM2INT(n);
-}
-
-static VALUE
-widget_get_eevents(self)
- VALUE self;
-{
- GdkExtensionMode m;
- m = gtk_widget_get_extension_events(get_widget(self));
- return NUM2INT((int)m);
-}
-
-static VALUE
-widget_push_cmap(self, cmap)
- VALUE self, cmap;
-{
- gtk_widget_push_colormap(get_gdkcmap(cmap));
- return Qnil;
-}
-
-static VALUE
-widget_push_visual(self, visual)
- VALUE self, visual;
-{
- gtk_widget_push_visual(get_gdkvisual(visual));
- return make_gdkcmap(visual);
-}
-
-static VALUE
-widget_push_style(self, style)
- VALUE self, style;
-{
- gtk_widget_push_style(get_gstyle(style));
- return Qnil;
-}
-
-static VALUE
-widget_pop_cmap(self, cmap)
- VALUE self, cmap;
-{
- gtk_widget_pop_colormap();
- return Qnil;
-}
-
-static VALUE
-widget_pop_visual(self, visual)
- VALUE self, visual;
-{
- gtk_widget_pop_visual();
- return Qnil;
-}
-
-static VALUE
-widget_pop_style(self, style)
- VALUE self, style;
-{
- gtk_widget_pop_style();
- return Qnil;
-}
-
-static VALUE
-widget_set_default_cmap(self, cmap)
- VALUE self, cmap;
-{
- gtk_widget_set_default_colormap(get_gdkcmap(cmap));
- return Qnil;
-}
-
-static VALUE
-widget_set_default_visual(self, visual)
- VALUE self, visual;
-{
- gtk_widget_set_default_visual(get_gdkvisual(visual));
- return make_gdkcmap(visual);
-}
-
-static VALUE
-widget_set_default_style(self, style)
- VALUE self, style;
-{
- gtk_widget_set_default_style(get_gstyle(style));
- return Qnil;
-}
-
-static VALUE
-widget_get_default_cmap(self)
- VALUE self;
-{
- GdkColormap *cmap = gtk_widget_get_default_colormap();
-
- return make_gdkcmap(cmap);
-}
-
-static VALUE
-widget_get_default_visual(self)
- VALUE self;
-{
- GdkVisual *v = gtk_widget_get_default_visual();
-
- return make_gdkvisual(v);
-}
-
-static VALUE
-widget_get_default_style(self)
- VALUE self;
-{
- GtkStyle *s = gtk_widget_get_default_style();
-
- return make_gstyle(s);
-}
-
-static VALUE
-widget_propagate_default_style(self)
- VALUE self;
-{
- gtk_widget_propagate_default_style();
- return Qnil;
-}
-
-static VALUE
-bbox_get_child_size_default(self)
- VALUE self;
-{
- int min_width, max_width;
-
- gtk_button_box_get_child_size_default(&min_width, &max_width);
-
- return assoc_new(INT2FIX(min_width), INT2FIX(max_width));
-}
-
-static VALUE
-bbox_get_child_ipadding_default(self)
- VALUE self;
-{
- int ipad_x, ipad_y;
-
- gtk_button_box_get_child_ipadding_default(&ipad_x, &ipad_y);
- return assoc_new(INT2FIX(ipad_x), INT2FIX(ipad_y));
-}
-
-static VALUE
-bbox_set_child_size_default(self, min_width, max_width)
- VALUE self, min_width, max_width;
-{
- gtk_button_box_set_child_size_default(NUM2INT(min_width),
- NUM2INT(max_width));
- return Qnil;
-}
-
-static VALUE
-bbox_set_child_ipadding_default(self, ipad_x, ipad_y)
- VALUE self, ipad_x, ipad_y;
-{
- gtk_button_box_set_child_ipadding_default(NUM2INT(ipad_x),
- NUM2INT(ipad_y));
- return Qnil;
-}
-
-static VALUE
-bbox_get_spacing(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int n = gtk_button_box_get_spacing(GTK_BUTTON_BOX(widget));
-
- return INT2FIX(n);
-}
-
-static VALUE
-bbox_get_layout(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int n = gtk_button_box_get_layout(GTK_BUTTON_BOX(widget));
-
- return INT2FIX(n);
-}
-
-static VALUE
-bbox_get_child_size(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int min_width, max_width;
-
- gtk_button_box_get_child_size(GTK_BUTTON_BOX(widget),
- &min_width, &max_width);
- return assoc_new(INT2FIX(min_width), INT2FIX(max_width));
-}
-
-static VALUE
-bbox_get_child_ipadding(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int ipad_x, ipad_y;
-
- gtk_button_box_get_child_ipadding(GTK_BUTTON_BOX(widget),
- &ipad_x, &ipad_y);
- return assoc_new(INT2FIX(ipad_x), INT2FIX(ipad_y));
-}
-
-static VALUE
-bbox_set_spacing(self, spacing)
- VALUE self, spacing;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_box_set_spacing(GTK_BUTTON_BOX(widget),
- NUM2INT(spacing));
- return self;
-}
-
-static VALUE
-bbox_set_layout(self, layout)
- VALUE self, layout;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_box_set_layout(GTK_BUTTON_BOX(widget),
- NUM2INT(layout));
- return self;
-}
-
-static VALUE
-bbox_set_child_size(self, min_width, max_width)
- VALUE self, min_width, max_width;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_box_set_child_size(GTK_BUTTON_BOX(widget),
- NUM2INT(min_width),
- NUM2INT(max_width));
- return self;
-}
-
-static VALUE
-bbox_set_child_ipadding(self, ipad_x, ipad_y)
- VALUE self, ipad_x, ipad_y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(widget),
- NUM2INT(ipad_x),
- NUM2INT(ipad_y));
- return self;
-}
-
-static VALUE
-clist_s_new(self, titles)
- VALUE self, titles;
-{
- char **buf;
- int i, len;
-
- Check_Type(titles, T_ARRAY);
- len = RARRAY(titles)->len;
- buf = ALLOCA_N(char*, len);
- for (i=0; i<len; i++) {
- Check_Type(RARRAY(titles)->ptr[i], T_STRING);
- buf[i] = RSTRING(RARRAY(titles)->ptr[i])->ptr;
- }
- return make_widget(self, gtk_clist_new(len, buf));
-}
-
-static VALUE
-clist_set_border(self, border)
- VALUE self, border;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_border(GTK_CLIST(widget), (GtkShadowType)NUM2INT(border));
- return self;
-}
-
-static VALUE
-clist_set_sel_mode(self, mode)
- VALUE self, mode;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_selection_mode(GTK_CLIST(widget),
- (GtkSelectionMode)NUM2INT(mode));
- return self;
-}
-
-static VALUE
-clist_set_policy(self, vpolicy, hpolicy)
- VALUE self, vpolicy, hpolicy;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_policy(GTK_CLIST(widget),
- (GtkPolicyType)NUM2INT(vpolicy),
- (GtkPolicyType)NUM2INT(hpolicy));
- return self;
-}
-
-static VALUE
-clist_freeze(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_freeze(GTK_CLIST(widget));
- return self;
-}
-
-static VALUE
-clist_thaw(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_thaw(GTK_CLIST(widget));
- return self;
-}
-
-static VALUE
-clist_set_col_title(self, col, title)
- VALUE self, col, title;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_column_title(GTK_CLIST(widget),
- NUM2INT(col),
- get_cstring(title));
- return self;
-}
-
-static VALUE
-clist_set_col_wigdet(self, col, win)
- VALUE self, col, win;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_column_widget(GTK_CLIST(widget),
- NUM2INT(col),
- get_widget(win));
- return self;
-}
-
-static VALUE
-clist_set_col_just(self, col, just)
- VALUE self, col, just;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_column_justification(GTK_CLIST(widget),
- NUM2INT(col),
- (GtkJustification)NUM2INT(just));
- return self;
-}
-
-static VALUE
-clist_set_col_width(self, col, width)
- VALUE self, col, width;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_column_width(GTK_CLIST(widget),
- NUM2INT(col), NUM2INT(width));
- return self;
-}
-
-static VALUE
-clist_set_row_height(self, height)
- VALUE self, height;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_row_height(GTK_CLIST(widget), NUM2INT(height));
- return self;
-}
-
-static VALUE
-clist_moveto(self, row, col, row_align, col_align)
- VALUE self, row, col, row_align, col_align;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_moveto(GTK_CLIST(widget),
- NUM2INT(row), NUM2INT(col),
- NUM2INT(row_align), NUM2INT(col_align));
- return self;
-}
-
-static VALUE
-clist_set_text(self, row, col, text)
- VALUE self, row, col, text;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_text(GTK_CLIST(widget),
- NUM2INT(row), NUM2INT(col),
- get_cstring(text));
- return self;
-}
-
-static VALUE
-clist_set_pixmap(self, row, col, pixmap, mask)
- VALUE self, row, col, pixmap, mask;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_pixmap(GTK_CLIST(widget),
- NUM2INT(row), NUM2INT(col),
- get_gdkpixmap(pixmap),
- (GdkBitmap*)get_gdkpixmap(mask));
- return self;
-}
-
-static VALUE
-clist_set_pixtext(self, row, col, text, spacing, pixmap, mask)
- VALUE self, row, col, text, spacing, pixmap, mask;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_pixtext(GTK_CLIST(widget),
- NUM2INT(row), NUM2INT(col),
- get_cstring(text),
- NUM2INT(spacing),
- get_gdkpixmap(pixmap),
- (GdkBitmap*)get_gdkpixmap(mask));
- return self;
-}
-
-static VALUE
-clist_set_foreground(self, row, color)
- VALUE self, row, color;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_foreground(GTK_CLIST(widget),
- NUM2INT(row), get_gdkcolor(color));
- return self;
-}
-
-static VALUE
-clist_set_background(self, row, color)
- VALUE self, row, color;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_background(GTK_CLIST(widget),
- NUM2INT(row), get_gdkcolor(color));
- return self;
-}
-
-static VALUE
-clist_set_shift(self, row, col, verticle, horizontal)
- VALUE self, row, col, verticle, horizontal;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_set_shift(GTK_CLIST(widget),
- NUM2INT(row), NUM2INT(col),
- NUM2INT(verticle), NUM2INT(horizontal));
- return self;
-}
-
-static VALUE
-clist_append(self, text)
- VALUE self, text;
-{
- GtkWidget *widget = get_widget(self);
- char **buf;
- int i, len;
-
- Check_Type(text, T_ARRAY);
- len = GTK_CLIST(widget)->columns;
- if (len > RARRAY(text)->len) {
- ArgError("text too short");
- }
- buf = ALLOCA_N(char*, len);
- for (i=0; i<len; i++) {
- Check_Type(RARRAY(text)->ptr[i], T_STRING);
- buf[i] = RSTRING(RARRAY(text)->ptr[i])->ptr;
- }
- i = gtk_clist_append(GTK_CLIST(widget), buf);
- return INT2FIX(i);
-}
-
-static VALUE
-clist_insert(self, row, text)
- VALUE self, row, text;
-{
- GtkWidget *widget = get_widget(self);
- char **buf;
- int i, len;
-
- Check_Type(text, T_ARRAY);
- len = GTK_CLIST(widget)->columns;
- if (len > RARRAY(text)->len) {
- ArgError("text too short");
- }
- buf = ALLOCA_N(char*, len);
- for (i=0; i<len; i++) {
- Check_Type(RARRAY(text)->ptr[i], T_STRING);
- buf[i] = RSTRING(RARRAY(text)->ptr[i])->ptr;
- }
- gtk_clist_insert(GTK_CLIST(widget), NUM2INT(row), buf);
- return self;
-}
-
-static VALUE
-clist_remove(self, row)
- VALUE self, row;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_remove(GTK_CLIST(widget), NUM2INT(row));
- return self;
-}
-
-static VALUE
-clist_set_row_data(self, row, data)
- VALUE self, row, data;
-{
- GtkWidget *widget = get_widget(self);
-
- add_relative(self, data);
- gtk_clist_set_row_data(GTK_CLIST(widget), NUM2INT(row), (gpointer)data);
- return self;
-}
-
-static VALUE
-clist_get_row_data(self, row)
- VALUE self, row;
-{
- GtkWidget *widget = get_widget(self);
-
- return (VALUE)gtk_clist_get_row_data(GTK_CLIST(widget), NUM2INT(row));
-}
-
-static VALUE
-clist_select_row(self, row, col)
- VALUE self, row, col;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_select_row(GTK_CLIST(widget), NUM2INT(row), NUM2INT(col));
- return self;
-}
-
-static VALUE
-clist_unselect_row(self, row, col)
- VALUE self, row, col;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_unselect_row(GTK_CLIST(widget), NUM2INT(row), NUM2INT(col));
- return self;
-}
-
-static VALUE
-clist_clear(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_clist_clear(GTK_CLIST(widget));
- return self;
-}
-
-static VALUE
-gwin_s_new(self, type)
- VALUE self, type;
-{
- return make_widget(self, gtk_window_new(NUM2INT(type)));
-}
-
-static VALUE
-gwin_set_policy(self, shrink, grow, auto_shrink)
- VALUE self, shrink, grow, auto_shrink;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_set_policy(GTK_WINDOW(widget),
- RTEST(shrink), RTEST(grow), RTEST(auto_shrink));
- return self;
-}
-
-static VALUE
-gwin_set_title(self, title)
- VALUE self, title;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_set_title(GTK_WINDOW(widget), get_cstring(title));
- return self;
-}
-
-static VALUE
-gwin_position(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_position(GTK_WINDOW(widget),
- (GtkWindowPosition)NUM2INT(pos));
-
- return self;
-}
-
-static VALUE
-gwin_set_wmclass(self, wmclass1, wmclass2)
- VALUE self, wmclass1, wmclass2;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_set_wmclass(GTK_WINDOW(widget),
- get_cstring(wmclass1),
- get_cstring(wmclass2));
- return self;
-}
-
-static VALUE
-gwin_set_focus(self, win)
- VALUE self, win;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_set_focus(GTK_WINDOW(widget), get_widget(win));
- return self;
-}
-
-static VALUE
-gwin_set_default(self, win)
- VALUE self, win;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_set_default(GTK_WINDOW(widget), get_widget(win));
- return self;
-}
-
-static VALUE
-gwin_add_accel(self, accel)
- VALUE self, accel;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_add_accelerator_table(GTK_WINDOW(widget),
- get_gtkacceltbl(accel));
- return self;
-}
-
-static VALUE
-gwin_rm_accel(self, accel)
- VALUE self, accel;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_window_remove_accelerator_table(GTK_WINDOW(widget),
- get_gtkacceltbl(accel));
- return self;
-}
-
-static VALUE
-dialog_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_dialog_new());
-}
-
-static VALUE
-fsel_s_new(self, title)
- VALUE self, title;
-{
- return make_widget(self, gtk_file_selection_new(get_cstring(title)));
-}
-
-static VALUE
-fsel_set_fname(self, fname)
- VALUE self, fname;
-{
- GtkWidget *widget = get_widget(self);
-
- Check_Type(fname, T_STRING);
- gtk_file_selection_set_filename(GTK_FILE_SELECTION(widget),
- RSTRING(fname)->ptr);
-
- return self;
-}
-
-static VALUE
-fsel_get_fname(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- gchar *fname;
-
- fname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(widget));
-
- return str_new2(fname);
-}
-
-static VALUE
-fsel_ok_button(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- VALUE b = rb_iv_get(self, "ok_button");
-
- if (NIL_P(b)) {
- GtkWidget *w = GTK_FILE_SELECTION(widget)->ok_button;
- b = make_widget(gButton, w);
- rb_iv_set(self, "ok_button", b);
- }
-
- return b;
-}
-
-static VALUE
-fsel_cancel_button(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- VALUE b = rb_iv_get(self, "cancel_button");
-
- if (NIL_P(b)) {
- GtkWidget *w = GTK_FILE_SELECTION(widget)->cancel_button;
- b = make_widget(gButton, w);
- rb_iv_set(self, "cancel_button", b);
- }
-
- return b;
-}
-
-static VALUE
-fsel_help_button(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- VALUE b = rb_iv_get(self, "help_button");
-
- if (NIL_P(b)) {
- GtkWidget *w = GTK_FILE_SELECTION(widget)->help_button;
- b = make_widget(gButton, w);
- rb_iv_set(self, "help_button", b);
- }
-
- return b;
-}
-
-static VALUE
-label_s_new(self, label)
- VALUE self, label;
-{
- return make_widget(self, gtk_label_new(get_cstring(label)));
-}
-
-static VALUE
-list_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_list_new());
-}
-
-static VALUE
-list_set_sel_mode(self, mode)
- VALUE self, mode;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_set_selection_mode(GTK_LIST(widget),
- (GtkSelectionMode)NUM2INT(mode));
- return self;
-}
-
-static VALUE
-list_sel_mode(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return INT2FIX(GTK_LIST(widget)->selection_mode);
-}
-
-static VALUE
-list_selection(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- return glist2ary(GTK_LIST(widget)->selection);
-}
-
-static VALUE
-list_insert_items(self, items, pos)
- VALUE self, items, pos;
-{
- GtkWidget *widget = get_widget(self);
- GList *glist;
-
- glist = ary2glist(items);
-
- gtk_list_insert_items(GTK_LIST(widget), glist, NUM2INT(pos));
- g_list_free(glist);
-
- return self;
-}
-
-static VALUE
-list_append_items(self, items)
- VALUE self, items;
-{
- GtkWidget *widget = get_widget(self);
- GList *glist;
-
- glist = ary2glist(items);
-
- gtk_list_append_items(GTK_LIST(widget), glist);
- g_list_free(glist);
-
- return self;
-}
-
-static VALUE
-list_prepend_items(self, items)
- VALUE self, items;
-{
- GtkWidget *widget = get_widget(self);
- GList *glist;
-
- glist = ary2glist(items);
- gtk_list_prepend_items(GTK_LIST(widget), glist);
- g_list_free(glist);
-
- return self;
-}
-
-static VALUE
-list_remove_items(self, items)
- VALUE self, items;
-{
- GtkWidget *widget = get_widget(self);
- GList *glist;
-
- glist = ary2glist(items);
- gtk_list_remove_items(GTK_LIST(widget), glist);
- g_list_free(glist);
-
- return self;
-}
-
-static VALUE
-list_clear_items(self, start, end)
- VALUE self, start, end;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_clear_items(GTK_LIST(widget), NUM2INT(start), NUM2INT(end));
- return self;
-}
-
-static VALUE
-list_select_item(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_select_item(GTK_LIST(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-list_unselect_item(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_unselect_item(GTK_LIST(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-list_select_child(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_select_child(GTK_LIST(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-list_unselect_child(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_list_unselect_child(GTK_LIST(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-list_child_position(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
- gint pos;
-
- pos = gtk_list_child_position(GTK_LIST(widget), get_widget(child));
- return INT2FIX(pos);
-}
-
-static VALUE
-item_select(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_item_select(GTK_ITEM(widget));
- return self;
-}
-
-static VALUE
-item_deselect(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_item_deselect(GTK_ITEM(widget));
- return self;
-}
-
-static VALUE
-item_toggle(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_item_toggle(GTK_ITEM(widget));
- return self;
-}
-
-static VALUE
-litem_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- widget = gtk_list_item_new_with_label(get_cstring(label));
- }
- else {
- widget = gtk_list_item_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-mshell_append(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-mshell_prepend(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_shell_prepend(GTK_MENU_SHELL(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-mshell_insert(self, child, pos)
- VALUE self, child, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_shell_insert(GTK_MENU_SHELL(widget), get_widget(child),
- NUM2INT(pos));
- return self;
-}
-
-static VALUE
-mshell_deactivate(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_shell_deactivate(GTK_MENU_SHELL(widget));
- return self;
-}
-
-static VALUE
-menu_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_menu_new());
-}
-
-static VALUE
-menu_append(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_append(GTK_MENU(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-menu_prepend(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_prepend(GTK_MENU(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-menu_insert(self, child, pos)
- VALUE self, child, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_insert(GTK_MENU(widget), get_widget(child), NUM2INT(pos));
- return self;
-}
-
-static void
-menu_pos_func(menu, x, y, data)
- GtkMenu *menu;
- gint x, y;
- gpointer data;
-{
- VALUE m = get_value_from_gobject(GTK_OBJECT(menu));
-
- rb_funcall((VALUE)data, 3, m, INT2FIX(x), INT2FIX(y));
-}
-
-static VALUE
-menu_popup(self, pshell, pitem, func, button, activate_time)
- VALUE self, pshell, pitem, func, button, activate_time;
-{
- GtkWidget *widget = get_widget(self);
- GtkMenuPositionFunc pfunc = NULL;
- gpointer data = NULL;
-
- if (!NIL_P(func)) {
- pfunc = menu_pos_func;
- data = (gpointer)func;
- add_relative(self, func);
- }
- gtk_menu_popup(GTK_MENU(widget),
- get_widget(pshell), get_widget(pitem),
- pfunc,
- data,
- NUM2INT(button),
- NUM2INT(activate_time));
- return self;
-}
-
-static VALUE
-menu_popdown(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_popdown(GTK_MENU(widget));
- return self;
-}
-
-static VALUE
-menu_get_active(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- GtkWidget *mitem = gtk_menu_get_active(GTK_MENU(widget));
-
- return make_widget(gMenuItem, mitem);
-}
-
-static VALUE
-menu_set_active(self, active)
- VALUE self, active;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_set_active(GTK_MENU(widget), NUM2INT(active));
- return self;
-}
-
-static VALUE
-menu_set_acceltbl(self, table)
- VALUE self, table;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_set_accelerator_table(GTK_MENU(widget),
- get_gtkacceltbl(table));
- return self;
-}
-
-static VALUE
-mbar_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_menu_bar_new());
-}
-
-static VALUE
-mbar_append(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_bar_append(GTK_MENU_BAR(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-mbar_prepend(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_bar_prepend(GTK_MENU_BAR(widget), get_widget(child));
- return self;
-}
-static VALUE
-mbar_insert(self, child, pos)
- VALUE self, child, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_bar_insert(GTK_MENU_BAR(widget),
- get_widget(child), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-mitem_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- widget = gtk_menu_item_new_with_label(get_cstring(label));
- }
- else {
- widget = gtk_menu_item_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-mitem_set_submenu(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-mitem_set_placement(self, place)
- VALUE self, place;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_set_placement(GTK_MENU_ITEM(widget),
- (GtkSubmenuPlacement)NUM2INT(place));
- return self;
-}
-
-static VALUE
-mitem_accelerator_size(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_accelerator_size(GTK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-mitem_accelerator_text(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- char buf[1024]; /* enough? */
-
- gtk_menu_item_accelerator_text(GTK_MENU_ITEM(widget), buf);
- return str_new2(buf);
-}
-
-static VALUE
-mitem_configure(self, show_toggle, show_submenu)
- VALUE self, show_toggle, show_submenu;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_configure(GTK_MENU_ITEM(widget),
- NUM2INT(show_toggle),
- NUM2INT(show_submenu));
- return self;
-}
-
-static VALUE
-mitem_select(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_select(GTK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-mitem_deselect(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_deselect(GTK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-mitem_activate(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_activate(GTK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-mitem_right_justify(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_menu_item_right_justify(GTK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-cmitem_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- widget = gtk_check_menu_item_new_with_label(get_cstring(label));
- }
- else {
- widget = gtk_check_menu_item_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-cmitem_set_state(self, state)
- VALUE self, state;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_check_menu_item_set_state(GTK_CHECK_MENU_ITEM(widget),
- NUM2INT(state));
- return self;
-}
-
-static VALUE
-cmitem_set_show_toggle(self, always)
- VALUE self, always;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(widget),
- (gboolean)RTEST(always));
- return self;
-}
-
-static VALUE
-cmitem_toggled(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_check_menu_item_toggled(GTK_CHECK_MENU_ITEM(widget));
- return self;
-}
-
-static VALUE
-rmitem_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE arg1, arg2;
- GtkWidget *widget;
- GSList *list = NULL;
- char *label = NULL;
-
- if (rb_scan_args(argc, argv, "02", &arg1, &arg2) == 1 &&
- TYPE(arg1) == T_STRING) {
- label = RSTRING(arg1)->ptr;
- }
- else {
- if (!NIL_P(arg2)) {
- Check_Type(arg2, T_STRING);
- label = RSTRING(arg2)->ptr;
- }
- if (obj_is_kind_of(arg1, gRMenuItem)) {
- GtkWidget *b = get_widget(arg1);
- list = GTK_RADIO_MENU_ITEM(b)->group;
- }
- else {
- list = ary2gslist(arg1);
- }
- }
- if (label) {
- widget = gtk_radio_menu_item_new_with_label(list, label);
- }
- else {
- widget = gtk_radio_menu_item_new(list);
- }
- return make_widget(self, widget);
-}
-
-static VALUE
-rmitem_group(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return gslist2ary(gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(widget)));
-}
-
-static VALUE
-note_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_notebook_new());
-}
-
-static VALUE
-note_append_page(self, child, label)
- VALUE self, child, label;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_append_page(GTK_NOTEBOOK(widget),
- get_widget(child),
- get_widget(label));
- return self;
-}
-
-static VALUE
-note_prepend_page(self, child, label)
- VALUE self, child, label;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_prepend_page(GTK_NOTEBOOK(widget),
- get_widget(child),
- get_widget(label));
- return self;
-}
-
-static VALUE
-note_insert_page(self, child, label, pos)
- VALUE self, child, label, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_insert_page(GTK_NOTEBOOK(widget),
- get_widget(child),
- get_widget(label),
- NUM2INT(pos));
- return self;
-}
-
-static VALUE
-note_remove_page(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_remove_page(GTK_NOTEBOOK(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-note_set_page(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_set_page(GTK_NOTEBOOK(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-note_cur_page(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return INT2FIX(GTK_NOTEBOOK(widget)->cur_page);
-}
-
-static VALUE
-note_next_page(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_next_page(GTK_NOTEBOOK(widget));
- return self;
-}
-
-static VALUE
-note_prev_page(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_prev_page(GTK_NOTEBOOK(widget));
- return self;
-}
-
-static VALUE
-note_set_tab_pos(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-note_tab_pos(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- return INT2FIX(GTK_NOTEBOOK(widget)->tab_pos);
-}
-
-static VALUE
-note_set_show_tabs(self, show_tabs)
- VALUE self, show_tabs;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget), RTEST(show_tabs));
- return self;
-}
-
-static VALUE
-note_show_tabs(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return GTK_NOTEBOOK(widget)->show_tabs?TRUE:FALSE;
-}
-
-static VALUE
-note_set_show_border(self, show_border)
- VALUE self, show_border;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget), RTEST(show_border));
- return self;
-}
-
-static VALUE
-note_show_border(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return GTK_NOTEBOOK(widget)->show_border?TRUE:FALSE;
-}
-
-static VALUE
-omenu_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_option_menu_new());
-}
-
-static VALUE
-omenu_set_menu(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- rb_iv_set(self, "option_menu", child);
- gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-omenu_get_menu(self)
- VALUE self;
-{
- return rb_iv_get(self, "option_menu");
-}
-
-static VALUE
-omenu_remove_menu(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_option_menu_remove_menu(GTK_OPTION_MENU(widget));
- return self;
-}
-
-static VALUE
-omenu_set_history(self, index)
- VALUE self, index;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_option_menu_set_history(GTK_OPTION_MENU(widget), NUM2INT(index));
- return self;
-}
-
-static VALUE
-image_s_new(self, val, mask)
- VALUE self, val, mask;
-{
- return make_widget(self, gtk_image_new(get_gdkimage(val),
- (GdkBitmap*)get_gdkpixmap(mask)));
-}
-
-static VALUE
-image_set(self, val, mask)
- VALUE self, val, mask;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_image_set(GTK_IMAGE(widget), get_gdkimage(val), get_gdkpixmap(mask));
- return self;
-}
-
-static VALUE
-image_get(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- GdkImage *val;
- GdkBitmap *mask;
-
- gtk_image_get(GTK_IMAGE(widget), &val, &mask);
-
- return assoc_new(make_gdkimage(self, val),
- make_gdkpixmap(self, mask));
-}
-
-static VALUE
-preview_s_new(self, type)
- VALUE self, type;
-{
- return make_widget(self, gtk_preview_new((GtkPreviewType)NUM2INT(type)));
-}
-
-
-static VALUE
-preview_size(self, w, h)
- VALUE self, w, h;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_preview_size(GTK_PREVIEW(widget), NUM2INT(w), NUM2INT(h));
- return self;
-}
-
-#if 0
- rb_define_method(gPixmap, "put", preview_size, 8);
- rb_define_method(gPixmap, "put_row", preview_size, 5);
- rb_define_method(gPixmap, "draw_row", preview_size, 4);
-#endif
-
-static VALUE
-preview_set_expand(self, expand)
- VALUE self, expand;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_preview_set_expand(GTK_PREVIEW(widget), NUM2INT(expand));
- return self;
-}
-
-static VALUE
-preview_set_gamma(self, gamma)
- VALUE self, gamma;
-{
- gtk_preview_set_gamma(NUM2DBL(gamma));
- return Qnil;
-}
-
-static VALUE
-preview_set_color_cube(self, nred, ngreen, nblue, ngray)
- VALUE self, nred, ngreen, nblue, ngray;
-{
- gtk_preview_set_color_cube(NUM2INT(nred),
- NUM2INT(ngreen),
- NUM2INT(nblue),
- NUM2INT(ngray));
- return Qnil;
-}
-
-static VALUE
-preview_set_install_cmap(self, cmap)
- VALUE self, cmap;
-{
- gtk_preview_set_install_cmap(NUM2INT(cmap));
- return Qnil;
-}
-
-static VALUE
-preview_set_reserved(self, nreserved)
- VALUE self, nreserved;
-{
- gtk_preview_set_reserved(NUM2INT(nreserved));
- return Qnil;
-}
-
-static VALUE
-preview_get_visual(self)
- VALUE self;
-{
- GdkVisual *v = gtk_preview_get_visual();
- return make_gdkvisual(v);
-}
-
-static VALUE
-preview_get_cmap(self)
- VALUE self;
-{
- GdkColormap *c = gtk_preview_get_cmap();
- return make_gdkcmap(c);
-}
-
-static VALUE
-preview_get_info(self)
- VALUE self;
-{
- GtkPreviewInfo *i = gtk_preview_get_info();
- return make_gtkprevinfo(i);
-}
-
-static VALUE
-pbar_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_progress_bar_new());
-}
-
-static VALUE
-pbar_update(self, percentage)
- VALUE self, percentage;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_progress_bar_update(GTK_PROGRESS_BAR(widget),
- NUM2DBL(percentage));
- return self;
-}
-
-static VALUE
-scwin_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1, arg2;
- GtkAdjustment *h_adj = NULL;
- GtkAdjustment *v_adj = NULL;
-
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- if (!NIL_P(arg1)) h_adj = (GtkAdjustment*)get_gobject(arg1);
- if (!NIL_P(arg2)) v_adj = (GtkAdjustment*)get_gobject(arg2);
-
- return make_widget(self, gtk_scrolled_window_new(h_adj, v_adj));
-}
-
-static VALUE
-scwin_set_policy(self, hpolicy, vpolicy)
- VALUE self, hpolicy, vpolicy;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
- (GtkPolicyType)NUM2INT(hpolicy),
- (GtkPolicyType)NUM2INT(vpolicy));
- return self;
-}
-
-
-static VALUE
-tbl_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE row, col, homogeneous;
-
- rb_scan_args(argc, argv, "21", &row, &col, &homogeneous);
- return make_widget(self, gtk_table_new(NUM2INT(row),
- NUM2INT(col),
- RTEST(homogeneous)));
-}
-
-static VALUE
-tbl_attach(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- VALUE child, left, right, top, bottom;
- VALUE arg0, arg1, arg2, arg3;
- int xopt, yopt, xspc, yspc;
-
- xopt = yopt = GTK_EXPAND | GTK_FILL;
- xspc = yspc = 0;
- rb_scan_args(argc, argv, "54",
- &child, &left, &right, &top, &bottom,
- &arg0, &arg1, &arg2, &arg3);
- if (!NIL_P(arg0)) xopt = NUM2INT(arg0);
- if (!NIL_P(arg1)) yopt = NUM2INT(arg1);
- if (!NIL_P(arg2)) xspc = NUM2INT(arg2);
- if (!NIL_P(arg3)) yspc = NUM2INT(arg3);
-
- gtk_table_attach(GTK_TABLE(widget),
- get_widget(child),
- NUM2INT(left),NUM2INT(right),
- NUM2INT(top),NUM2INT(bottom),
- xopt, yopt, xspc, yspc);
-
- return self;
-}
-
-static VALUE
-tbl_set_row_spacing(self, row, spc)
- VALUE self, row, spc;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_table_set_row_spacing(GTK_TABLE(widget), NUM2INT(row), NUM2INT(spc));
- return self;
-}
-
-static VALUE
-tbl_set_col_spacing(self, col, spc)
- VALUE self, col, spc;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_table_set_col_spacing(GTK_TABLE(widget), NUM2INT(col), NUM2INT(spc));
- return self;
-}
-
-static VALUE
-tbl_set_row_spacings(self, spc)
- VALUE self, spc;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_table_set_row_spacings(GTK_TABLE(widget), NUM2INT(spc));
- return self;
-}
-
-static VALUE
-tbl_set_col_spacings(self, spc)
- VALUE self, spc;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_table_set_col_spacings(GTK_TABLE(widget), NUM2INT(spc));
- return self;
-}
-
-static VALUE
-txt_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1, arg2;
- GtkAdjustment *h_adj = NULL;
- GtkAdjustment *v_adj = NULL;
-
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- if (!NIL_P(arg1)) h_adj = (GtkAdjustment*)get_gobject(arg1);
- if (!NIL_P(arg2)) v_adj = (GtkAdjustment*)get_gobject(arg2);
-
- return make_widget(self, gtk_text_new(h_adj, v_adj));
-}
-
-static VALUE
-txt_set_editable(self, editable)
- VALUE self, editable;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_set_editable(GTK_TEXT(widget), RTEST(editable));
- return self;
-}
-
-static VALUE
-txt_set_adjustment(self, h_adj, v_adj)
- VALUE self, h_adj, v_adj;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_set_adjustments(GTK_TEXT(widget),
- (GtkAdjustment*)get_gobject(h_adj),
- (GtkAdjustment*)get_gobject(v_adj));
-
- return self;
-}
-
-static VALUE
-txt_set_point(self, index)
- VALUE self, index;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_set_point(GTK_TEXT(widget), NUM2INT(index));
- return self;
-}
-
-static VALUE
-txt_get_point(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int index = gtk_text_get_point(GTK_TEXT(widget));
-
- return INT2FIX(index);
-}
-
-static VALUE
-txt_get_length(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int len = gtk_text_get_length(GTK_TEXT(widget));
-
- return INT2FIX(len);
-}
-
-static VALUE
-txt_freeze(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_freeze(GTK_TEXT(widget));
- return self;
-}
-
-static VALUE
-txt_thaw(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_thaw(GTK_TEXT(widget));
- return self;
-}
-
-static VALUE
-txt_insert(self, font, fore, back, str)
- VALUE self, font, fore, back, str;
-{
- GtkWidget *widget = get_widget(self);
-
- Check_Type(str, T_STRING);
- gtk_text_insert(GTK_TEXT(widget),
- get_gdkfont(font),
- get_gdkcolor(fore),
- get_gdkcolor(back),
- RSTRING(str)->ptr,
- RSTRING(str)->len);
-
- return self;
-}
-
-static VALUE
-txt_backward_delete(self, nchars)
- VALUE self, nchars;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_backward_delete(GTK_TEXT(widget), NUM2INT(nchars));
- return self;
-}
-
-static VALUE
-txt_forward_delete(self, nchars)
- VALUE self, nchars;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_text_forward_delete(GTK_TEXT(widget), NUM2INT(nchars));
- return self;
-}
-
-static VALUE
-tbar_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1, arg2;
- GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
- GtkToolbarStyle style = GTK_TOOLBAR_BOTH;
-
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- if (!NIL_P(arg1)) orientation = (GtkOrientation)NUM2INT(arg1);
- if (!NIL_P(arg2)) style = (GtkToolbarStyle)NUM2INT(arg2);
-
- return make_widget(self, gtk_toolbar_new(orientation, style));
-}
-
-static VALUE
-tbar_append_item(self, text, ttext, icon, func)
- VALUE self, text, ttext, icon, func;
-{
- GtkWidget *widget = get_widget(self);
- GtkObject *pixmap = get_gobject(icon);
-
- if (NIL_P(func)) {
- func = f_lambda();
- }
- gtk_toolbar_append_item(GTK_TOOLBAR(widget),
- get_cstring(text),
- get_cstring(ttext),
- GTK_PIXMAP(pixmap),
- exec_callback,
- (gpointer)ary_new3(1, func));
- return self;
-}
-
-static VALUE
-tbar_prepend_item(self, text, ttext, icon, func)
- VALUE self, text, ttext, icon, func;
-{
- GtkWidget *widget = get_widget(self);
- GtkObject *pixmap = get_gobject(icon);
-
- if (NIL_P(func)) {
- func = f_lambda();
- }
- gtk_toolbar_prepend_item(GTK_TOOLBAR(widget),
- get_cstring(text),
- get_cstring(ttext),
- GTK_PIXMAP(pixmap),
- exec_callback,
- (gpointer)ary_new3(1, func));
- return self;
-}
-
-static VALUE
-tbar_insert_item(self, text, ttext, icon, func, pos)
- VALUE self, text, ttext, icon, func, pos;
-{
- GtkWidget *widget = get_widget(self);
- GtkObject *pixmap = get_gobject(icon);
-
- if (NIL_P(func)) {
- func = f_lambda();
- }
- gtk_toolbar_insert_item(GTK_TOOLBAR(widget),
- get_cstring(text),
- get_cstring(ttext),
- GTK_PIXMAP(pixmap),
- exec_callback,
- (gpointer)ary_new3(1, func),
- NUM2INT(pos));
- return self;
-}
-
-static VALUE
-tbar_append_space(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_append_space(GTK_TOOLBAR(widget));
- return self;
-}
-
-static VALUE
-tbar_prepend_space(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_prepend_space(GTK_TOOLBAR(widget));
- return self;
-}
-
-static VALUE
-tbar_insert_space(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_insert_space(GTK_TOOLBAR(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-tbar_set_orientation(self, orientation)
- VALUE self, orientation;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_set_orientation(GTK_TOOLBAR(widget),
- (GtkOrientation)NUM2INT(orientation));
- return self;
-}
-
-static VALUE
-tbar_set_style(self, style)
- VALUE self, style;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_set_style(GTK_TOOLBAR(widget),
- (GtkToolbarStyle)NUM2INT(style));
- return self;
-}
-
-static VALUE
-tbar_set_space_size(self, size)
- VALUE self, size;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_set_space_size(GTK_TOOLBAR(widget), NUM2INT(size));
- return self;
-}
-
-static VALUE
-tbar_set_tooltips(self, enable)
- VALUE self, enable;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toolbar_set_tooltips(GTK_TOOLBAR(widget), RTEST(enable));
- return self;
-}
-
-static VALUE
-ttips_s_new(self)
- VALUE self;
-{
- return make_ttips(self, gtk_tooltips_new());
-}
-
-static VALUE
-ttips_set_tips(self, win, text)
- VALUE self, win, text;
-{
- Check_Type(text, T_STRING);
- gtk_tooltips_set_tips(get_ttips(self),
- get_widget(win),
- RSTRING(text)->ptr);
-
- return self;
-}
-
-static VALUE
-ttips_set_delay(self, delay)
- VALUE self, delay;
-{
- gtk_tooltips_set_delay(get_ttips(self), NUM2INT(delay));
-
- return self;
-}
-
-static VALUE
-ttips_enable(self)
- VALUE self;
-{
- gtk_tooltips_enable(get_ttips(self));
- return self;
-}
-
-static VALUE
-ttips_disable(self)
- VALUE self;
-{
- gtk_tooltips_enable(get_ttips(self));
- return self;
-}
-
-static VALUE
-tree_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_tree_new());
-}
-
-static VALUE
-tree_append(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_append(GTK_TREE(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-tree_prepend(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_prepend(GTK_TREE(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-tree_insert(self, child, pos)
- VALUE self, child, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_insert(GTK_TREE(widget), get_widget(child), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-titem_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- Check_Type(label, T_STRING);
- widget = gtk_tree_item_new_with_label(RSTRING(label)->ptr);
- }
- else {
- widget = gtk_tree_item_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-titem_set_subtree(self, subtree)
- VALUE self, subtree;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_item_set_subtree(GTK_TREE_ITEM(widget), get_widget(subtree));
- return self;
-}
-
-static VALUE
-titem_select(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_item_select(GTK_TREE_ITEM(widget));
- return self;
-}
-
-static VALUE
-titem_deselect(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_item_deselect(GTK_TREE_ITEM(widget));
- return self;
-}
-
-static VALUE
-titem_expand(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_item_expand(GTK_TREE_ITEM(widget));
- return self;
-}
-
-static VALUE
-titem_collapse(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_tree_item_collapse(GTK_TREE_ITEM(widget));
- return self;
-}
-
-static VALUE
-vport_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1, arg2;
- GtkAdjustment *h_adj = NULL;
- GtkAdjustment *v_adj = NULL;
-
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- if (!NIL_P(arg1)) h_adj = (GtkAdjustment*)get_gobject(arg1);
- if (!NIL_P(arg2)) v_adj = (GtkAdjustment*)get_gobject(arg2);
-
- return make_widget(self, gtk_viewport_new(h_adj, v_adj));
-}
-
-static VALUE
-vport_get_hadj(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- GtkAdjustment *adj = gtk_viewport_get_hadjustment(GTK_VIEWPORT(widget));
-
- return make_gobject(gAdjustment, GTK_OBJECT(adj));
-}
-
-static VALUE
-vport_get_vadj(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- GtkAdjustment *adj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(widget));
-
- return make_gobject(gAdjustment, GTK_OBJECT(adj));
-}
-
-static VALUE
-vport_set_vadj(self, adj)
- VALUE self, adj;
-{
- GtkWidget *widget = get_widget(self);
- GtkObject *adjustment = get_gobject(adj);
-
- gtk_viewport_set_vadjustment(GTK_VIEWPORT(widget),
- GTK_ADJUSTMENT(adj));
-
- return self;
-}
-
-static VALUE
-vport_set_hadj(self, adj)
- VALUE self, adj;
-{
- GtkWidget *widget = get_widget(self);
- GtkObject *adjustment = get_gobject(adj);
-
- gtk_viewport_set_hadjustment(GTK_VIEWPORT(widget),
- GTK_ADJUSTMENT(adj));
-
- return self;
-}
-
-static VALUE
-vport_set_shadow(self, type)
- VALUE self, type;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_viewport_set_shadow_type(GTK_VIEWPORT(widget),
- (GtkShadowType)NUM2INT(type));
-
- return self;
-}
-
-static VALUE
-button_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- Check_Type(label, T_STRING);
- widget = gtk_button_new_with_label(RSTRING(label)->ptr);
- }
- else {
- widget = gtk_button_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-button_pressed(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_pressed(GTK_BUTTON(widget));
- return self;
-}
-
-static VALUE
-button_released(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_released(GTK_BUTTON(widget));
- return self;
-}
-
-static VALUE
-button_clicked(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_clicked(GTK_BUTTON(widget));
- return self;
-}
-
-static VALUE
-button_enter(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_enter(GTK_BUTTON(widget));
- return self;
-}
-
-static VALUE
-button_leave(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_button_leave(GTK_BUTTON(widget));
- return self;
-}
-
-static VALUE
-tbtn_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- Check_Type(label, T_STRING);
- widget = gtk_toggle_button_new_with_label(RSTRING(label)->ptr);
- }
- else {
- widget = gtk_toggle_button_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-tbtn_set_mode(self, mode)
- VALUE self, mode;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(widget), NUM2INT(mode));
- return self;
-}
-
-static VALUE
-tbtn_set_state(self, state)
- VALUE self, state;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), NUM2INT(state));
- return self;
-}
-
-static VALUE
-tbtn_toggled(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(widget));
- return self;
-}
-
-static VALUE
-cbtn_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE label;
- GtkWidget *widget;
-
- if (rb_scan_args(argc, argv, "01", &label) == 1) {
- Check_Type(label, T_STRING);
- widget = gtk_check_button_new_with_label(RSTRING(label)->ptr);
- }
- else {
- widget = gtk_check_button_new();
- }
-
- return make_widget(self, widget);
-}
-
-static VALUE
-rbtn_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
-{
- VALUE arg1, arg2;
- GtkWidget *widget;
- GSList *list = NULL;
- char *label = NULL;
-
- if (rb_scan_args(argc, argv, "02", &arg1, &arg2) == 1 &&
- TYPE(arg1) == T_STRING) {
- label = RSTRING(arg1)->ptr;
- }
- else {
- if (!NIL_P(arg2)) {
- Check_Type(arg2, T_STRING);
- label = RSTRING(arg2)->ptr;
- }
- if (obj_is_kind_of(arg1, gRButton)) {
- GtkWidget *b = get_widget(arg1);
- list = GTK_RADIO_BUTTON(b)->group;
- }
- else {
- list = ary2gslist(arg1);
- }
- }
- if (label) {
- widget = gtk_radio_button_new_with_label(list, label);
- }
- else {
- widget = gtk_radio_button_new(list);
- }
- return make_widget(self, widget);
-}
-
-static VALUE
-rbtn_group(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return gslist2ary(gtk_radio_button_group(GTK_RADIO_BUTTON(widget)));
-}
-
-static void
-box_pack_start_or_end(argc, argv, self, start)
- int argc;
- VALUE *argv;
- VALUE self;
- int start;
-{
- VALUE arg0, arg1, arg2, arg3;
- gint expand, fill, padding;
- GtkWidget *widget, *child;
-
- expand = fill = TRUE; padding = 0;
- switch (rb_scan_args(argc, argv, "13", &arg0, &arg1, &arg2, &arg3)) {
- case 4:
- padding = NUM2INT(arg3);
- case 3:
- fill = RTEST(arg2);
- case 2:
- expand = RTEST(arg1);
- default:
- child = get_widget(arg0);
- break;
- }
- widget = get_widget(self);
-
- if (start)
- gtk_box_pack_start(GTK_BOX(widget), child, expand, fill, padding);
- else
- gtk_box_pack_end(GTK_BOX(widget), child, expand, fill, padding);
-}
-
-static VALUE
-box_pack_start(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- box_pack_start_or_end(argc, argv, self, 1);
- return self;
-}
-
-static VALUE
-box_pack_end(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- box_pack_start_or_end(argc, argv, self, 0);
- return self;
-}
-
-static VALUE
-vbox_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE homogeneous, spacing;
- GtkWidget *widget;
-
- rb_scan_args(argc, argv, "02", &homogeneous, &spacing);
- widget = gtk_vbox_new(RTEST(homogeneous), NUM2INT(spacing));
-
- return make_widget(self, widget);
-}
-
-static VALUE
-colorsel_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_color_selection_new());
-}
-
-static VALUE
-colorsel_set_update_policy(self, policy)
- VALUE self, policy;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_color_selection_set_update_policy(GTK_COLOR_SELECTION(widget),
- (GtkUpdateType)NUM2INT(policy));
- return self;
-}
-
-static VALUE
-colorsel_set_opacity(self, opacity)
- VALUE self, opacity;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_color_selection_set_opacity(GTK_COLOR_SELECTION(widget),
- RTEST(opacity));
- return self;
-}
-
-static VALUE
-colorsel_set_color(self, color)
- VALUE self, color;
-{
- GtkWidget *widget = get_widget(self);
- double buf[3];
-
- Check_Type(color, T_ARRAY);
- if (RARRAY(color)->len < 3) {
- ArgError("color array too small");
- }
- buf[0] = NUM2DBL(RARRAY(color)->ptr[0]);
- buf[1] = NUM2DBL(RARRAY(color)->ptr[1]);
- buf[2] = NUM2DBL(RARRAY(color)->ptr[2]);
-
- gtk_color_selection_set_color(GTK_COLOR_SELECTION(widget), buf);
- return self;
-}
-
-static VALUE
-colorsel_get_color(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- double buf[3];
- VALUE ary;
-
- gtk_color_selection_get_color(GTK_COLOR_SELECTION(widget), buf);
- ary = ary_new2(3);
- ary_push(ary, NUM2DBL(buf[0]));
- ary_push(ary, NUM2DBL(buf[1]));
- ary_push(ary, NUM2DBL(buf[2]));
- return ary;
-}
-
-static VALUE
-cdialog_s_new(self, title)
- VALUE self;
-{
- char *t;
-
- Check_Type(title, T_STRING);
- t = RSTRING(title)->ptr;
- return make_widget(self, gtk_color_selection_dialog_new(t));
-}
-
-static VALUE
-pixmap_s_new(self, val, mask)
- VALUE self, val, mask;
-{
- return make_widget(self, gtk_pixmap_new(get_gdkpixmap(val),
- get_gdkpixmap(mask)));
-}
-
-static VALUE
-pixmap_set(self, val, mask)
- VALUE self, val, mask;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_pixmap_set(GTK_PIXMAP(widget),
- get_gdkpixmap(val), get_gdkpixmap(mask));
- return self;
-}
-
-static VALUE
-pixmap_get(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- GdkPixmap *val;
- GdkBitmap *mask;
-
- gtk_pixmap_get(GTK_PIXMAP(widget), &val, &mask);
-
- return assoc_new(make_gdkpixmap(self, val),
- make_gdkpixmap(self, mask));
-}
-
-static VALUE
-darea_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_drawing_area_new());
-}
-
-static VALUE
-darea_size(self, w, h)
- VALUE self, w, h;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_drawing_area_size(GTK_DRAWING_AREA(widget), NUM2INT(w), NUM2INT(h));
- return self;
-}
-
-static VALUE
-entry_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_entry_new());
-}
-
-static VALUE
-entry_set_text(self, text)
- VALUE self, text;
-{
- GtkWidget *widget = get_widget(self);
-
- Check_Type(text, T_STRING);
- gtk_entry_set_text(GTK_ENTRY(widget), RSTRING(text)->ptr);
-
- return self;
-}
-
-static VALUE
-eventbox_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_event_box_new());
-}
-
-static VALUE
-fixed_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_fixed_new());
-}
-
-static VALUE
-fixed_put(self, win, x, y)
- VALUE self, win, x, y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_fixed_put(GTK_FIXED(widget), get_widget(win), NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-fixed_move(self, win, x, y)
- VALUE self, win, x, y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_fixed_move(GTK_FIXED(widget), get_widget(win), NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-gamma_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_gamma_curve_new());
-}
-
-static VALUE
-gamma_gamma(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- return float_new(GTK_GAMMA_CURVE(widget)->gamma);
-}
-
-static VALUE
-hbbox_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_hbutton_box_new());
-}
-
-static VALUE
-hbbox_get_spacing_default(self)
- VALUE self;
-{
- int n = gtk_hbutton_box_get_spacing_default();
-
- return INT2FIX(n);
-}
-
-static VALUE
-hbbox_get_layout_default(self)
- VALUE self;
-{
- int n = gtk_hbutton_box_get_layout_default();
-
- return INT2FIX(n);
-}
-
-static VALUE
-hbbox_set_spacing_default(self, spacing)
- VALUE self, spacing;
-{
- gtk_hbutton_box_set_spacing_default(NUM2INT(spacing));
- return Qnil;
-}
-
-static VALUE
-hbbox_set_layout_default(self, layout)
- VALUE self, layout;
-{
- gtk_hbutton_box_set_layout_default(NUM2INT(layout));
- return Qnil;
-}
-
-static VALUE
-vbbox_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_vbutton_box_new());
-}
-
-static VALUE
-vbbox_get_spacing_default(self)
- VALUE self;
-{
- int n = gtk_vbutton_box_get_spacing_default();
-
- return INT2FIX(n);
-}
-
-static VALUE
-vbbox_get_layout_default(self)
- VALUE self;
-{
- int n = gtk_vbutton_box_get_layout_default();
-
- return INT2FIX(n);
-}
-
-static VALUE
-vbbox_set_spacing_default(self, spacing)
- VALUE self, spacing;
-{
- gtk_vbutton_box_set_spacing_default(NUM2INT(spacing));
- return Qnil;
-}
-
-static VALUE
-vbbox_set_layout_default(self, layout)
- VALUE self, layout;
-{
- gtk_vbutton_box_set_layout_default(NUM2INT(layout));
- return Qnil;
-}
-
-static VALUE
-hbox_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE homogeneous, spacing;
- GtkWidget *widget;
-
- rb_scan_args(argc, argv, "02", &homogeneous, &spacing);
- widget = gtk_hbox_new(RTEST(homogeneous), NUM2INT(spacing));
-
- return make_widget(self, widget);
-}
-
-static VALUE
-paned_add1(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_paned_add1(GTK_PANED(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-paned_add2(self, child)
- VALUE self, child;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_paned_add2(GTK_PANED(widget), get_widget(child));
- return self;
-}
-
-static VALUE
-paned_handle_size(self, size)
- VALUE self, size;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_paned_handle_size(GTK_PANED(widget), NUM2INT(size));
- return self;
-}
-
-static VALUE
-paned_gutter_size(self, size)
- VALUE self, size;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_paned_gutter_size(GTK_PANED(widget), NUM2INT(size));
- return self;
-}
-
-static VALUE
-hpaned_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_hpaned_new());
-}
-
-static VALUE
-vpaned_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_vpaned_new());
-}
-
-static VALUE
-ruler_set_metric(self, metric)
- VALUE self, metric;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_ruler_set_metric(GTK_RULER(widget),
- (GtkMetricType)NUM2INT(metric));
-
- return self;
-}
-
-static VALUE
-ruler_set_range(self, lower, upper, position, max_size)
- VALUE self, lower, upper, position, max_size;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_ruler_set_range(GTK_RULER(widget),
- NUM2DBL(lower), NUM2DBL(upper),
- NUM2DBL(position), NUM2DBL(max_size));
-
- return self;
-}
-
-static VALUE
-ruler_draw_ticks(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_ruler_draw_ticks(GTK_RULER(widget));
- return self;
-}
-
-static VALUE
-ruler_draw_pos(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_ruler_draw_pos(GTK_RULER(widget));
- return self;
-}
-
-static VALUE
-hruler_s_new(self)
-{
- return make_widget(self, gtk_hruler_new());
-}
-
-static VALUE
-vruler_s_new(self)
-{
- return make_widget(self, gtk_vruler_new());
-}
-
-static VALUE
-range_get_adj(self)
-{
- GtkWidget *widget = get_widget(self);
- GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget));
-
- return make_gobject(gAdjustment, GTK_OBJECT(adj));
-}
-
-static VALUE
-range_set_update_policy(self, policy)
- VALUE self, policy;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_set_update_policy(GTK_RANGE(widget),
- (GtkUpdateType)NUM2INT(policy));
- return self;
-}
-
-static VALUE
-range_set_adj(self, adj)
- VALUE self, adj;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_set_adjustment(GTK_RANGE(widget),
- (GtkAdjustment*)get_gobject(adj));
-
- return self;
-}
-
-static VALUE
-range_draw_bg(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_draw_background(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_draw_trough(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_draw_trough(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_draw_slider(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_draw_slider(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_draw_step_forw(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_draw_step_forw(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_draw_step_back(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_draw_step_back(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_slider_update(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_slider_update(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_trough_click(self, x, y)
- VALUE self, x, y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_trough_click(GTK_RANGE(widget), NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-range_default_hslider_update(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_hslider_update(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_default_vslider_update(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_vslider_update(GTK_RANGE(widget));
- return self;
-}
-
-static VALUE
-range_default_htrough_click(self, x, y)
- VALUE self, x, y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_htrough_click(GTK_RANGE(widget),
- NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-range_default_vtrough_click(self, x, y)
- VALUE self, x, y;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_vtrough_click(GTK_RANGE(widget),
- NUM2INT(x), NUM2INT(y));
- return self;
-}
-
-static VALUE
-range_default_hmotion(self, xdelta, ydelta)
- VALUE self, xdelta, ydelta;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_hmotion(GTK_RANGE(widget),
- NUM2INT(xdelta), NUM2INT(ydelta));
- return self;
-}
-
-static VALUE
-range_default_vmotion(self, xdelta, ydelta)
- VALUE self, xdelta, ydelta;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_default_vmotion(GTK_RANGE(widget),
- NUM2INT(xdelta), NUM2INT(ydelta));
- return self;
-}
-
-static VALUE
-range_calc_value(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_range_calc_value(GTK_RANGE(widget), NUM2INT(pos));
- return self;
-}
-
-static VALUE
-scale_set_digits(self, digits)
- VALUE self, digits;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_scale_set_digits(GTK_SCALE(widget), NUM2INT(digits));
- return self;
-}
-
-static VALUE
-scale_set_draw_value(self, draw_value)
- VALUE self, draw_value;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_scale_set_draw_value(GTK_SCALE(widget), NUM2INT(draw_value));
- return self;
-}
-
-static VALUE
-scale_set_value_pos(self, pos)
- VALUE self, pos;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_scale_set_value_pos(GTK_SCALE(widget),
- (GtkPositionType)NUM2INT(pos));
- return self;
-}
-
-static VALUE
-scale_value_width(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
- int i = gtk_scale_value_width(GTK_SCALE(widget));
-
- return INT2FIX(i);
-}
-
-static VALUE
-scale_draw_value(self)
- VALUE self;
-{
- GtkWidget *widget = get_widget(self);
-
- gtk_scale_draw_value(GTK_SCALE(widget));
- return self;
-}
-
-static VALUE
-hscale_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1;
- GtkAdjustment *adj = NULL;
-
- rb_scan_args(argc, argv, "01", &arg1);
- if (!NIL_P(arg1)) adj = (GtkAdjustment*)get_gobject(arg1);
-
- return make_widget(self, gtk_hscale_new(adj));
-}
-
-static VALUE
-vscale_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1;
- GtkAdjustment *adj = NULL;
-
- rb_scan_args(argc, argv, "01", &arg1);
- if (!NIL_P(arg1)) adj = (GtkAdjustment*)get_gobject(arg1);
-
- return make_widget(self, gtk_vscale_new(adj));
-}
-
-static VALUE
-hscrollbar_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1;
- GtkAdjustment *adj = NULL;
-
- rb_scan_args(argc, argv, "01", &arg1);
- if (!NIL_P(arg1)) adj = (GtkAdjustment*)get_gobject(arg1);
-
- return make_widget(self, gtk_hscrollbar_new(adj));
-}
-
-static VALUE
-vscrollbar_s_new(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE arg1;
- GtkAdjustment *adj = NULL;
-
- rb_scan_args(argc, argv, "01", &arg1);
- if (!NIL_P(arg1)) adj = (GtkAdjustment*)get_gobject(arg1);
-
- return make_widget(self, gtk_vscrollbar_new(adj));
-}
-
-static VALUE
-hsep_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_hseparator_new());
-}
-
-static VALUE
-vsep_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_vseparator_new());
-}
-
-static VALUE
-idiag_s_new(self)
- VALUE self;
-{
- return make_widget(self, gtk_input_dialog_new());
-}
-
-static VALUE
-gtk_m_main(self)
- VALUE self;
-{
- gtk_main();
- return Qnil;
-}
-
-static gint
-idle()
-{
- CHECK_INTS;
- return TRUE;
-}
-
-static void
-exec_interval(proc)
- VALUE proc;
-{
- rb_funcall(proc, id_call, 0);
-}
-
-static VALUE
-timeout_add(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE interval, func;
- int id;
-
- rb_scan_args(argc, argv, "11", &interval, &func);
- if (NIL_P(func)) {
- func = f_lambda();
- }
- id = gtk_timeout_add_interp(NUM2INT(interval), exec_interval,
- (gpointer)func, 0);
- return INT2FIX(id);
-}
-
-static VALUE
-timeout_remove(self, id)
- VALUE self, id;
-{
- gtk_timeout_remove(NUM2INT(id));
- return Qnil;
-}
-
-static VALUE
-idle_add(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE func;
- int id;
-
- rb_scan_args(argc, argv, "01", &func);
- if (NIL_P(func)) {
- func = f_lambda();
- }
- id = gtk_idle_add_interp(exec_interval, (gpointer)func, 0);
- return INT2FIX(id);
-}
-
-static VALUE
-idle_remove(self, id)
- VALUE self, id;
-{
- gtk_idle_remove(NUM2INT(id));
- return Qnil;
-}
-
-static VALUE warn_handler;
-static VALUE mesg_handler;
-static VALUE print_handler;
-
-static void
-gtkwarn(mesg)
- char *mesg;
-{
- rb_funcall(warn_handler, id_call, 1, str_new2(mesg));
-}
-
-static void
-gtkmesg(mesg)
- char *mesg;
-{
- rb_funcall(mesg_handler, id_call, 1, str_new2(mesg));
-}
-
-static void
-gtkprint(mesg)
- char *mesg;
-{
- rb_funcall(print_handler, id_call, 1, str_new2(mesg));
-}
-
-static VALUE
-set_warning_handler(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE handler;
-
- rb_scan_args(argc, argv, "01", &handler);
- if (NIL_P(handler)) {
- handler = f_lambda();
- }
- g_set_warning_handler(gtkwarn);
-}
-
-static VALUE
-set_message_handler(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE handler;
-
- rb_scan_args(argc, argv, "01", &handler);
- if (NIL_P(handler)) {
- handler = f_lambda();
- }
- g_set_message_handler(gtkmesg);
-}
-
-static VALUE
-set_print_handler(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE handler;
-
- rb_scan_args(argc, argv, "01", &handler);
- if (NIL_P(handler)) {
- handler = f_lambda();
- }
- g_set_print_handler(gtkprint);
-}
-
-static void
-gtkerr(mesg)
- char *mesg;
-{
- Fail("%s", mesg);
-}
-
-void
-Init_gtk()
-{
- int argc, i;
- char **argv;
-
- gtk_object_list = ary_new();
- rb_global_variable(&gtk_object_list);
-
- mGtk = rb_define_module("Gtk");
-
- gObject = rb_define_class_under(mGtk, "GtkObject", cObject);
- gWidget = rb_define_class_under(mGtk, "Widget", gObject);
- gContainer = rb_define_class_under(mGtk, "Container", gWidget);
- gBin = rb_define_class_under(mGtk, "Bin", gContainer);
- gAlignment = rb_define_class_under(mGtk, "Alignment", gBin);
- gMisc = rb_define_class_under(mGtk, "Misc", gWidget);
- gArrow = rb_define_class_under(mGtk, "Arrow", gMisc);
- gFrame = rb_define_class_under(mGtk, "Frame", gBin);
- gAspectFrame = rb_define_class_under(mGtk, "AspectFrame", gFrame);
- gData = rb_define_class_under(mGtk, "Data", gObject);
- gAdjustment = rb_define_class_under(mGtk, "Adjustment", gData);
- gBox = rb_define_class_under(mGtk, "Box", gContainer);
- gButton = rb_define_class_under(mGtk, "Button", gContainer);
- gTButton = rb_define_class_under(mGtk, "ToggleButton", gButton);
- gCButton = rb_define_class_under(mGtk, "CheckButton", gTButton);
- gRButton = rb_define_class_under(mGtk, "RadioButton", gCButton);
- gBBox = rb_define_class_under(mGtk, "ButtonBox", gBox);
- gCList = rb_define_class_under(mGtk, "CList", gContainer);
- gWindow = rb_define_class_under(mGtk, "Window", gBin);
- gDialog = rb_define_class_under(mGtk, "Dialog", gWindow);
- gFileSel = rb_define_class_under(mGtk, "FileSelection", gWindow);
- gVBox = rb_define_class_under(mGtk, "VBox", gBox);
- gColorSel = rb_define_class_under(mGtk, "ColorSelection", gVBox);
- gColorSelDialog = rb_define_class_under(mGtk, "ColorSelectionDialog", gWindow);
- gImage = rb_define_class_under(mGtk, "Image", gMisc);
- gDrawArea = rb_define_class_under(mGtk, "DrawingArea", gWidget);
- gEntry = rb_define_class_under(mGtk, "Entry", gWidget);
- gEventBox = rb_define_class_under(mGtk, "EventBox", gBin);
- gFixed = rb_define_class_under(mGtk, "Fixed", gContainer);
- gGamma = rb_define_class_under(mGtk, "GammaCurve", gVBox);
- gHBBox = rb_define_class_under(mGtk, "HButtonBox", gBBox);
- gVBBox = rb_define_class_under(mGtk, "VButtonBox", gBBox);
- gHBox = rb_define_class_under(mGtk, "HBox", gBox);
- gPaned = rb_define_class_under(mGtk, "Paned", gContainer);
- gHPaned = rb_define_class_under(mGtk, "HPaned", gPaned);
- gVPaned = rb_define_class_under(mGtk, "VPaned", gPaned);
- gRuler = rb_define_class_under(mGtk, "Ruler", gWidget);
- gHRuler = rb_define_class_under(mGtk, "HRuler", gRuler);
- gVRuler = rb_define_class_under(mGtk, "VRuler", gRuler);
- gRange = rb_define_class_under(mGtk, "Range", gWidget);
- gScale = rb_define_class_under(mGtk, "Scale", gRange);
- gHScale = rb_define_class_under(mGtk, "HScale", gScale);
- gVScale = rb_define_class_under(mGtk, "VScale", gScale);
- gScrollbar = rb_define_class_under(mGtk, "Scrollbar", gRange);
- gHScrollbar = rb_define_class_under(mGtk, "HScrollbar", gScrollbar);
- gVScrollbar = rb_define_class_under(mGtk, "VScrollbar", gScrollbar);
- gSeparator = rb_define_class_under(mGtk, "Separator", gWidget);
- gHSeparator = rb_define_class_under(mGtk, "HSeparator", gSeparator);
- gVSeparator = rb_define_class_under(mGtk, "VSeparator", gSeparator);
- gInputDialog = rb_define_class_under(mGtk, "InputDialog", gDialog);
- gLabel = rb_define_class_under(mGtk, "Label", gMisc);
- gList = rb_define_class_under(mGtk, "List", gContainer);
- gItem = rb_define_class_under(mGtk, "Item", gBin);
- gListItem = rb_define_class_under(mGtk, "ListItem", gItem);
- gMenuShell = rb_define_class_under(mGtk, "MenuShell", gContainer);
- gMenu = rb_define_class_under(mGtk, "Menu", gMenuShell);
- gMenuBar = rb_define_class_under(mGtk, "MenuBar", gMenuShell);
- gMenuItem = rb_define_class_under(mGtk, "MenuItem", gItem);
- gCMenuItem = rb_define_class_under(mGtk, "CheckMenuItem", gMenuItem);
- gRMenuItem = rb_define_class_under(mGtk, "RadioMenuItem", gCMenuItem);
- gNotebook = rb_define_class_under(mGtk, "Notebook", gContainer);
- gOptionMenu = rb_define_class_under(mGtk, "OptionMenu", gButton);
- gPixmap = rb_define_class_under(mGtk, "Pixmap", gMisc);
- gPreview = rb_define_class_under(mGtk, "Preview", gWidget);
- gProgressBar = rb_define_class_under(mGtk, "ProgressBar", gWidget);
- gScrolledWin = rb_define_class_under(mGtk, "ScrolledWindow", gContainer);
- gTable = rb_define_class_under(mGtk, "Table", gContainer);
- gText = rb_define_class_under(mGtk, "Text", gWidget);
- gToolbar = rb_define_class_under(mGtk, "Toolbar", gContainer);
- gTooltips = rb_define_class_under(mGtk, "Tooltips", cObject);
- gTree = rb_define_class_under(mGtk, "Tree", gContainer);
- gTreeItem = rb_define_class_under(mGtk, "TreeItem", gItem);
- gViewPort = rb_define_class_under(mGtk, "ViewPort", gBin);
-
- gAcceleratorTable = rb_define_class_under(mGtk, "AcceleratorTable", cObject);
- gStyle = rb_define_class_under(mGtk, "Style", cObject);
- gPreviewInfo = rb_define_class_under(mGtk, "PreviewInfo", cObject);
- gRequisiton = rb_define_class_under(mGtk, "Requisiton", cObject);
- gAllocation = rb_define_class_under(mGtk, "Allocation", cObject);
-
- mGdk = rb_define_module("Gdk");
-
- gdkFont = rb_define_class_under(mGdk, "Font", cObject);
- gdkColor = rb_define_class_under(mGdk, "Color", cObject);
- gdkPixmap = rb_define_class_under(mGdk, "Pixmap", cObject);
- gdkBitmap = rb_define_class_under(mGdk, "Bitmap", gdkPixmap);
- gdkWindow = rb_define_class_under(mGdk, "Window", cObject);
- gdkImage = rb_define_class_under(mGdk, "Image", cObject);
- gdkVisual = rb_define_class_under(mGdk, "Visual", cObject);
- gdkGC = rb_define_class_under(mGdk, "GC", cObject);
- gdkGCValues = rb_define_class_under(mGdk, "GCValues", cObject);
- gdkRectangle = rb_define_class_under(mGdk, "Rectangle", cObject);
- gdkSegment = rb_define_class_under(mGdk, "Segment", cObject);
- gdkWindowAttr = rb_define_class_under(mGdk, "WindowAttr", cObject);
- gdkCursor = rb_define_class_under(mGdk, "Cursor", cObject);
- gdkAtom = rb_define_class_under(mGdk, "Atom", cObject);
- gdkColorContext = rb_define_class_under(mGdk, "ColotContext", cObject);
- gdkEvent = rb_define_class_under(mGdk, "gdkEvent", cObject);
-
- /* GtkObject */
- rb_define_singleton_method(gObject, "new", gobj_s_new, -1);
- rb_define_method(gObject, "set_flags", gobj_set_flags, 1);
- rb_define_method(gObject, "unset_flags", gobj_unset_flags, 1);
- rb_define_method(gObject, "destroy", gobj_destroy, 0);
- rb_define_method(gObject, "signal_connect", gobj_sig_connect, -1);
- rb_define_method(gObject, "signal_connect_after", gobj_sig_connect_after, -1);
- rb_define_method(gObject, "singleton_method_added", gobj_smethod_added, 1);
-
- /* Widget */
- rb_define_method(gWidget, "destroy", widget_destroy, 0);
- rb_define_method(gWidget, "show", widget_show, 0);
- rb_define_method(gWidget, "show_all", widget_show_all, 0);
- rb_define_method(gWidget, "hide", widget_hide, 0);
- rb_define_method(gWidget, "hide_all", widget_hide_all, 0);
- rb_define_method(gWidget, "map", widget_map, 0);
- rb_define_method(gWidget, "unmap", widget_unmap, 0);
- rb_define_method(gWidget, "realize", widget_realize, 0);
- rb_define_method(gWidget, "unrealize", widget_unrealize, 0);
- rb_define_method(gWidget, "queue_draw", widget_queue_draw, 0);
- rb_define_method(gWidget, "queue_resize", widget_queue_resize, 0);
- rb_define_method(gWidget, "draw", widget_draw, 1);
- rb_define_method(gWidget, "draw_focus", widget_draw_focus, 0);
- rb_define_method(gWidget, "draw_default", widget_draw_default, 0);
- rb_define_method(gWidget, "draw_children", widget_draw_children, 0);
- rb_define_method(gWidget, "size_request", widget_size_request, 1);
- rb_define_method(gWidget, "size_alocate", widget_size_allocate, 1);
- rb_define_method(gWidget, "install_accelerator", widget_inst_accel, 4);
- rb_define_method(gWidget, "remove_accelerator", widget_rm_accel, 4);
- rb_define_method(gWidget, "event", widget_event, 1);
- rb_define_method(gWidget, "activate", widget_activate, 0);
- rb_define_method(gWidget, "grab_focus", widget_grab_focus, 0);
- rb_define_method(gWidget, "grab_default", widget_grab_default, 0);
- rb_define_method(gWidget, "restore_state", widget_restore_state, 0);
- rb_define_method(gWidget, "visible?", widget_visible, 0);
- rb_define_method(gWidget, "reparent", widget_reparent, 1);
- rb_define_method(gWidget, "popup", widget_popup, 2);
- rb_define_method(gWidget, "intersect", widget_intersect, 2);
- rb_define_method(gWidget, "basic", widget_basic, 0);
- rb_define_method(gWidget, "get_name", widget_set_name, 0);
- rb_define_method(gWidget, "set_name", widget_set_name, 1);
- rb_define_method(gWidget, "set_parent", widget_set_parent, 1);
- rb_define_method(gWidget, "set_sensitive", widget_set_sensitive, 1);
- rb_define_method(gWidget, "set_usize", widget_set_usize, 2);
- rb_define_method(gWidget, "set_uposition", widget_set_uposition, 2);
- rb_define_method(gWidget, "set_style", widget_set_style, 1);
- rb_define_method(gWidget, "set_events", widget_set_events, 1);
- rb_define_method(gWidget, "set_extension_events", widget_set_eevents, 1);
- rb_define_method(gWidget, "unparent", widget_unparent, 0);
- rb_define_method(gWidget, "get_toplevel", widget_get_toplevel, 0);
- rb_define_method(gWidget, "get_ancestor", widget_get_ancestor, 1);
- rb_define_method(gWidget, "get_colormap", widget_get_colormap, 0);
- rb_define_method(gWidget, "get_visual", widget_get_visual, 0);
- rb_define_method(gWidget, "get_style", widget_get_style, 0);
- rb_define_method(gWidget, "style", widget_get_style, 0);
- rb_define_method(gWidget, "get_events", widget_get_events, 0);
- rb_define_method(gWidget, "get_extension_events", widget_get_eevents, 0);
- rb_define_method(gWidget, "get_pointer", widget_get_eevents, 0);
- rb_define_method(gWidget, "ancestor?", widget_is_ancestor, 1);
- rb_define_method(gWidget, "child?", widget_is_child, 1);
- rb_define_method(gWidget, "window", widget_window, 0);
-
- rb_define_singleton_method(gWidget, "push_colomap", widget_push_cmap, 1);
- rb_define_singleton_method(gWidget, "push_visual", widget_push_visual, 1);
- rb_define_singleton_method(gWidget, "push_style", widget_push_style, 1);
- rb_define_singleton_method(gWidget, "pop_colomap", widget_pop_cmap, 0);
- rb_define_singleton_method(gWidget, "pop_visual", widget_pop_visual, 0);
- rb_define_singleton_method(gWidget, "pop_style", widget_pop_style, 0);
-
- rb_define_singleton_method(gWidget, "set_default_colomap",
- widget_set_default_cmap, 1);
- rb_define_singleton_method(gWidget, "set_default_visual",
- widget_set_default_visual, 1);
- rb_define_singleton_method(gWidget, "set_default_style",
- widget_set_default_style, 1);
- rb_define_singleton_method(gWidget, "get_default_colomap",
- widget_get_default_cmap, 0);
- rb_define_singleton_method(gWidget, "get_default_visual",
- widget_get_default_visual, 0);
- rb_define_singleton_method(gWidget, "get_default_style",
- widget_get_default_style, 0);
- rb_define_singleton_method(gWidget, "set_default_colomap",
- widget_set_default_cmap, 1);
- rb_define_singleton_method(gWidget, "set_default_visual",
- widget_set_default_visual, 1);
- rb_define_singleton_method(gWidget, "set_default_style",
- widget_set_default_style, 1);
- rb_define_singleton_method(gWidget, "set_default_colomap",
- widget_set_default_cmap, 1);
- rb_define_singleton_method(gWidget, "set_default_visual",
- widget_set_default_visual, 1);
- rb_define_singleton_method(gWidget, "propagage_default_style",
- widget_propagate_default_style, 0);
-
- /* Container */
- rb_define_method(gContainer, "border_width", cont_bwidth, 1);
- rb_define_method(gContainer, "add", cont_add, 1);
- rb_define_method(gContainer, "disable_resize", cont_disable_resize, 0);
- rb_define_method(gContainer, "enable_resize", cont_enable_resize, 0);
- rb_define_method(gContainer, "block_resize", cont_block_resize, 0);
- rb_define_method(gContainer, "unblock_resize", cont_unblock_resize, 0);
- rb_define_method(gContainer, "need_resize", cont_need_resize, 0);
- rb_define_method(gContainer, "foreach", cont_foreach, -1);
- rb_define_method(gContainer, "each", cont_each, 0);
- rb_define_method(gContainer, "focus", cont_focus, 1);
- rb_define_method(gContainer, "children", cont_children, 0);
-
- /* Bin */
- /* -- */
-
- /* Alignment */
- rb_define_singleton_method(gAlignment, "new", align_s_new, 4);
- rb_define_method(gAlignment, "set", align_set, 4);
-
- /* Misc */
- rb_define_method(gMisc, "set_alignment", misc_set_align, 2);
- rb_define_method(gMisc, "set_padding", misc_set_padding, 2);
-
- /* Arrow */
- rb_define_singleton_method(gArrow, "new", arrow_s_new, 2);
- rb_define_method(gArrow, "set", arrow_s_new, 2);
-
- /* Frame */
- rb_define_singleton_method(gFrame, "new", frame_s_new, 1);
- rb_define_method(gFrame, "set_label", frame_set_label, 1);
- rb_define_method(gFrame, "set_label_align", frame_set_label_align, 2);
- rb_define_method(gFrame, "set_shadow_type", frame_set_shadow_type, 1);
-
- /* AspectFrame */
- rb_define_singleton_method(gAspectFrame, "new", aframe_s_new, 5);
- rb_define_method(gAspectFrame, "set", aframe_set, 4);
-
- /* Data */
- /* -- */
-
- /* Adjustment */
- rb_define_singleton_method(gAdjustment, "new", adj_s_new, 6);
-
- /* Box */
- rb_define_method(gBox, "pack_start", box_pack_start, -1);
- rb_define_method(gBox, "pack_end", box_pack_end, -1);
-
- /* Button */
- rb_define_singleton_method(gButton, "new", button_s_new, -1);
- rb_define_method(gButton, "pressed", button_pressed, 0);
- rb_define_method(gButton, "released", button_released, 0);
- rb_define_method(gButton, "clicked", button_clicked, 0);
- rb_define_method(gButton, "enter", button_enter, 0);
- rb_define_method(gButton, "leave", button_leave, 0);
-
- /* ToggleButton */
- rb_define_singleton_method(gTButton, "new", tbtn_s_new, -1);
- rb_define_method(gTButton, "set_mode", tbtn_set_mode, 1);
- rb_define_method(gTButton, "set_state", tbtn_set_state, 1);
- rb_define_method(gTButton, "toggled", tbtn_toggled, 0);
-
- /* CheckButton */
- rb_define_singleton_method(gCButton, "new", cbtn_s_new, -1);
-
- /* RadioButton */
- rb_define_singleton_method(gCButton, "new", rbtn_s_new, -1);
- rb_define_method(gCButton, "group", rbtn_group, 0);
-
- /* ButtonBox */
- rb_define_singleton_method(gBBox, "get_child_size_default",
- bbox_get_child_size_default, 0);
- rb_define_singleton_method(gBBox, "get_child_ipadding_default",
- bbox_get_child_ipadding_default, 0);
- rb_define_singleton_method(gBBox, "set_child_size_default",
- bbox_set_child_size_default, 2);
- rb_define_singleton_method(gBBox, "set_child_ipadding_default",
- bbox_set_child_ipadding_default, 2);
- rb_define_method(gBBox, "get_spacing", bbox_get_spacing, 0);
- rb_define_method(gBBox, "get_layout", bbox_get_layout, 0);
- rb_define_method(gBBox, "get_child_size", bbox_get_child_size, 0);
- rb_define_method(gBBox, "get_child_ipadding", bbox_get_child_ipadding, 0);
- rb_define_method(gBBox, "set_spacing", bbox_set_spacing, 1);
- rb_define_method(gBBox, "set_layout", bbox_set_layout, 1);
- rb_define_method(gBBox, "set_child_size", bbox_set_child_size, 2);
- rb_define_method(gBBox, "set_child_ipadding", bbox_set_child_ipadding, 2);
-
- /* CList */
- rb_define_singleton_method(gCList, "new", clist_s_new, 1);
- rb_define_method(gCList, "set_border", clist_set_border, 1);
- rb_define_method(gCList, "set_selection_mode", clist_set_sel_mode, 1);
- rb_define_method(gCList, "set_policy", clist_set_policy, 2);
- rb_define_method(gCList, "freeze", clist_freeze, 0);
- rb_define_method(gCList, "thaw", clist_thaw, 0);
- rb_define_method(gCList, "set_column_title", clist_set_col_title, 2);
- rb_define_method(gCList, "set_column_widget", clist_set_col_wigdet, 2);
- rb_define_method(gCList, "set_column_justification", clist_set_col_just, 2);
- rb_define_method(gCList, "set_column_width", clist_set_col_width, 2);
- rb_define_method(gCList, "set_row_height", clist_set_row_height, 1);
- rb_define_method(gCList, "moveto", clist_moveto, 4);
- rb_define_method(gCList, "set_text", clist_set_text, 3);
- rb_define_method(gCList, "set_pixmap", clist_set_text, 4);
- rb_define_method(gCList, "set_pixtext", clist_set_pixtext, 6);
- rb_define_method(gCList, "set_foreground", clist_set_foreground, 2);
- rb_define_method(gCList, "set_background", clist_set_background, 2);
- rb_define_method(gCList, "set_shift", clist_set_shift, 4);
- rb_define_method(gCList, "append", clist_append, 1);
- rb_define_method(gCList, "insert", clist_insert, 2);
- rb_define_method(gCList, "remove", clist_remove, 1);
- rb_define_method(gCList, "set_row_data", clist_set_row_data, 2);
- rb_define_method(gCList, "get_row_data", clist_set_row_data, 1);
- rb_define_method(gCList, "select_row", clist_select_row, 2);
- rb_define_method(gCList, "unselect_row", clist_unselect_row, 2);
- rb_define_method(gCList, "clear", clist_clear, 0);
-
- /* Window */
- rb_define_singleton_method(gWindow, "new", gwin_s_new, 1);
- rb_define_method(gWindow, "set_title", gwin_set_title, 1);
- rb_define_method(gWindow, "set_policy", gwin_set_policy, 3);
- rb_define_method(gWindow, "set_wmclass", gwin_set_wmclass, 1);
- rb_define_method(gWindow, "set_focus", gwin_set_focus, 1);
- rb_define_method(gWindow, "set_default", gwin_set_focus, 1);
- rb_define_method(gWindow, "add_accelerator_table", gwin_add_accel, 1);
- rb_define_method(gWindow, "remove_accelerator_table", gwin_rm_accel, 1);
- rb_define_method(gWindow, "position", gwin_position, 1);
-
- /* Dialog */
- rb_define_singleton_method(gDialog, "new", dialog_s_new, 0);
-
- /* FileSelection */
- rb_define_singleton_method(gFileSel, "new", fsel_s_new, 1);
- rb_define_method(gFileSel, "set_filename", fsel_set_fname, 1);
- rb_define_method(gFileSel, "get_filename", fsel_get_fname, 0);
- rb_define_method(gFileSel, "ok_button", fsel_ok_button, 0);
- rb_define_method(gFileSel, "cancel_button", fsel_cancel_button, 0);
- rb_define_method(gFileSel, "help_button", fsel_help_button, 0);
-
- /* VBox */
- rb_define_singleton_method(gVBox, "new", vbox_s_new, -1);
-
- /* ColorSelection */
- rb_define_singleton_method(gColorSel, "new", colorsel_s_new, 0);
- rb_define_method(gColorSel, "set_update_policy", colorsel_set_update_policy, 1);
- rb_define_method(gColorSel, "set_opacity", colorsel_set_opacity, 1);
- rb_define_method(gColorSel, "set_color", colorsel_set_color, 1);
- rb_define_method(gColorSel, "get_color", colorsel_get_color, 0);
-
- /* ColorSelectionDialog */
- rb_define_singleton_method(gColorSelDialog, "new", cdialog_s_new, 1);
-
- /* Image */
- rb_define_singleton_method(gImage, "new", image_s_new, 2);
- rb_define_method(gImage, "set", image_set, 2);
- rb_define_method(gImage, "get", image_get, 0);
-
- /* DrawingArea */
- rb_define_singleton_method(gDrawArea, "new", darea_s_new, 0);
- rb_define_method(gDrawArea, "size", darea_size, 2);
-
- /* Entry */
- rb_define_singleton_method(gEntry, "new", entry_s_new, 0);
- rb_define_method(gEntry, "set_text", entry_set_text, 1);
-
- /* EventBox */
- rb_define_singleton_method(gEventBox, "new", eventbox_s_new, 0);
-
- /* Fixed */
- rb_define_singleton_method(gFixed, "new", fixed_s_new, 0);
- rb_define_method(gFixed, "put", fixed_put, 3);
- rb_define_method(gFixed, "move", fixed_move, 3);
-
- /* GammaCurve */
- rb_define_singleton_method(gGamma, "new", gamma_s_new, 0);
- rb_define_method(gGamma, "gamma", gamma_gamma, 0);
-
- /* HButtonBox */
- rb_define_singleton_method(gHBBox, "new", hbbox_s_new, 0);
- rb_define_singleton_method(gHBBox, "get_spacing_default",
- hbbox_get_spacing_default, 0);
- rb_define_singleton_method(gHBBox, "get_layout_default",
- hbbox_get_spacing_default, 0);
- rb_define_singleton_method(gHBBox, "set_spacing_default",
- hbbox_set_spacing_default, 1);
- rb_define_singleton_method(gHBBox, "set_layout_default",
- hbbox_set_layout_default, 1);
-
- /* VButtonBox */
- rb_define_singleton_method(gVBBox, "new", vbbox_s_new, 0);
- rb_define_singleton_method(gVBBox, "get_spacing_default",
- vbbox_get_spacing_default, 0);
- rb_define_singleton_method(gVBBox, "get_layout_default",
- vbbox_get_spacing_default, 0);
- rb_define_singleton_method(gVBBox, "set_spacing_default",
- vbbox_set_spacing_default, 1);
- rb_define_singleton_method(gVBBox, "set_layout_default",
- vbbox_set_layout_default, 1);
-
- /* HBox */
- rb_define_singleton_method(gHBox, "new", hbox_s_new, -1);
-
- /* Paned */
- rb_define_method(gPaned, "add1", paned_add1, 1);
- rb_define_method(gPaned, "add2", paned_add1, 1);
- rb_define_method(gPaned, "handle_size", paned_handle_size, 1);
- rb_define_method(gPaned, "gutter_size", paned_gutter_size, 1);
-
- /* HPaned */
- rb_define_singleton_method(gHPaned, "new", hpaned_s_new, 0);
-
- /* VPaned */
- rb_define_singleton_method(gVPaned, "new", vpaned_s_new, 0);
-
- /* Ruler */
- rb_define_method(gRuler, "set_metric", ruler_set_metric, 1);
- rb_define_method(gRuler, "set_range", ruler_set_range, 4);
- rb_define_method(gRuler, "draw_ticks", ruler_draw_ticks, 0);
- rb_define_method(gRuler, "draw_pos", ruler_draw_pos, 0);
-
- /* HRuler */
- rb_define_singleton_method(gHRuler, "new", hruler_s_new, 0);
-
- /* VRuler */
- rb_define_singleton_method(gVRuler, "new", vruler_s_new, 0);
-
- /* Range */
- rb_define_method(gRange, "get_adjustment", range_get_adj, 0);
- rb_define_method(gRange, "set_update_policy", range_set_update_policy, 1);
- rb_define_method(gRange, "set_adjustment", range_set_adj, 1);
- rb_define_method(gRange, "draw_background", range_draw_bg, 0);
- rb_define_method(gRange, "draw_trough", range_draw_trough, 0);
- rb_define_method(gRange, "draw_slider", range_draw_slider, 0);
- rb_define_method(gRange, "draw_step_forw", range_draw_step_forw, 0);
- rb_define_method(gRange, "draw_step_back", range_draw_step_back, 0);
- rb_define_method(gRange, "slider_update", range_slider_update, 0);
- rb_define_method(gRange, "trough_click", range_trough_click, 2);
- rb_define_method(gRange, "draw_background", range_draw_bg, 2);
- rb_define_method(gRange, "default_hslider_update", range_default_hslider_update, 0);
- rb_define_method(gRange, "default_vslider_update", range_default_vslider_update, 0);
- rb_define_method(gRange, "default_htrough_click", range_default_htrough_click, 2);
- rb_define_method(gRange, "default_vtrough_click", range_default_vtrough_click, 2);
- rb_define_method(gRange, "default_hmotion", range_default_hmotion, 2);
- rb_define_method(gRange, "default_vmotion", range_default_vmotion, 2);
- rb_define_method(gRange, "calc_value", range_calc_value, 1);
-
- /* Scale */
- rb_define_method(gScale, "set_digits", scale_set_digits, 1);
- rb_define_method(gScale, "set_draw_value", scale_set_draw_value, 1);
- rb_define_method(gScale, "set_value_pos", scale_set_value_pos, 1);
- rb_define_method(gScale, "value_width", scale_value_width, 0);
- rb_define_method(gScale, "draw_value", scale_draw_value, 0);
-
- /* HScale */
- rb_define_singleton_method(gHScale, "new", hscale_s_new, -1);
-
- /* VScale */
- rb_define_singleton_method(gVScale, "new", vscale_s_new, -1);
-
- /* Scrollbar */
- /* -- */
-
- /* HScrollbar */
- rb_define_singleton_method(gHScrollbar, "new", hscrollbar_s_new, -1);
-
- /* VScrollbar */
- rb_define_singleton_method(gVScrollbar, "new", vscrollbar_s_new, -1);
-
- /* Separator */
- /* -- */
-
- /* HSeparator */
- rb_define_singleton_method(gHSeparator, "new", hsep_s_new, 0);
-
- /* VSeparator */
- rb_define_singleton_method(gVSeparator, "new", vsep_s_new, 0);
-
- /* InputDialog */
- rb_define_singleton_method(gInputDialog, "new", idiag_s_new, 0);
-
- /* Label */
- rb_define_singleton_method(gLabel, "new", label_s_new, 1);
-
- /* List */
- rb_define_singleton_method(gList, "new", list_s_new, 0);
- rb_define_method(gList, "set_selection_mode", list_set_sel_mode, 1);
- rb_define_method(gList, "selection_mode", list_sel_mode, 1);
- rb_define_method(gList, "selection", list_selection, 0);
- rb_define_method(gList, "insert_items", list_insert_items, 2);
- rb_define_method(gList, "append_items", list_append_items, 1);
- rb_define_method(gList, "prepend_items", list_prepend_items, 1);
- rb_define_method(gList, "remove_items", list_remove_items, 1);
- rb_define_method(gList, "clear_items", list_clear_items, 2);
- rb_define_method(gList, "select_item", list_select_item, 1);
- rb_define_method(gList, "unselect_item", list_unselect_item, 1);
- rb_define_method(gList, "select_child", list_select_child, 1);
- rb_define_method(gList, "unselect_child", list_unselect_child, 1);
- rb_define_method(gList, "child_position", list_child_position, 1);
-
- /* Item */
- rb_define_method(gItem, "select", item_select, 0);
- rb_define_method(gItem, "deselect", item_deselect, 0);
- rb_define_method(gItem, "toggle", item_toggle, 0);
-
- /* ListItem */
- rb_define_singleton_method(gListItem, "new", litem_s_new, -1);
-
- /* MenuShell */
- rb_define_method(gMenuShell, "append", mshell_append, 1);
- rb_define_method(gMenuShell, "prepend", mshell_prepend, 1);
- rb_define_method(gMenuShell, "insert", mshell_insert, 2);
- rb_define_method(gMenuShell, "deactivate", mshell_deactivate, 0);
-
- /* Menu */
- rb_define_singleton_method(gMenu, "new", menu_s_new, 0);
- rb_define_method(gMenu, "append", menu_append, 1);
- rb_define_method(gMenu, "prepend", menu_prepend, 1);
- rb_define_method(gMenu, "insert", menu_insert, 2);
- rb_define_method(gMenu, "popup", menu_popup, 6);
- rb_define_method(gMenu, "popdown", menu_popup, 0);
- rb_define_method(gMenu, "get_active", menu_get_active, 0);
- rb_define_method(gMenu, "set_active", menu_set_active, 1);
- rb_define_method(gMenu, "set_accelerator_table", menu_set_acceltbl, 1);
-
- /* MenuBar */
- rb_define_singleton_method(gMenuBar, "new", mbar_s_new, 0);
- rb_define_method(gMenuBar, "append", mbar_append, 1);
- rb_define_method(gMenuBar, "prepend", mbar_prepend, 1);
- rb_define_method(gMenuBar, "insert", mbar_insert, 2);
-
- /* MenuItem */
- rb_define_singleton_method(gMenuItem, "new", mitem_s_new, -1);
- rb_define_method(gMenuItem, "set_submenu", mitem_set_submenu, 1);
- rb_define_method(gMenuItem, "set_placement", mitem_set_placement, 1);
- rb_define_method(gMenuItem, "accelerator_size", mitem_accelerator_size, 0);
- rb_define_method(gMenuItem, "accelerator_text", mitem_accelerator_text, 0);
- rb_define_method(gMenuItem, "configure", mitem_configure, 2);
- rb_define_method(gMenuItem, "select", mitem_select, 0);
- rb_define_method(gMenuItem, "deselect", mitem_deselect, 0);
- rb_define_method(gMenuItem, "activate", mitem_activate, 0);
- rb_define_method(gMenuItem, "right_justify", mitem_right_justify, 0);
-
- /* CheckMenuItem */
- rb_define_singleton_method(gCMenuItem, "new", cmitem_s_new, -1);
- rb_define_method(gCMenuItem, "set_state", cmitem_set_state, 1);
- rb_define_method(gCMenuItem, "set_show_toggle", cmitem_set_show_toggle, 1);
- rb_define_method(gCMenuItem, "toggled", cmitem_toggled, 0);
-
- /* RadioMenuItem */
- rb_define_singleton_method(gRMenuItem, "new", rmitem_s_new, -1);
- rb_define_method(gRMenuItem, "group", rmitem_group, 0);
-
- /* NoteBook */
- rb_define_singleton_method(gNotebook, "new", note_s_new, 0);
- rb_define_method(gNotebook, "append_page", note_append_page, 2);
- rb_define_method(gNotebook, "prepend_page", note_prepend_page, 2);
- rb_define_method(gNotebook, "insert_page", note_insert_page, 3);
- rb_define_method(gNotebook, "remove_page", note_remove_page, 1);
- rb_define_method(gNotebook, "set_page", note_set_page, 1);
- rb_define_method(gNotebook, "cur_page", note_cur_page, 0);
- rb_define_method(gNotebook, "page", note_cur_page, 0);
- rb_define_method(gNotebook, "next_page", note_next_page, 0);
- rb_define_method(gNotebook, "prev_page", note_prev_page, 0);
- rb_define_method(gNotebook, "set_tab_pos", note_set_tab_pos, 1);
- rb_define_method(gNotebook, "tab_pos", note_tab_pos, 0);
- rb_define_method(gNotebook, "set_show_tabs", note_set_show_tabs, 1);
- rb_define_method(gNotebook, "show_tabs", note_show_tabs, 0);
- rb_define_method(gNotebook, "set_show_border", note_set_show_border, 1);
- rb_define_method(gNotebook, "show_border", note_show_border, 0);
-
- /* OptionMenu */
- rb_define_singleton_method(gOptionMenu, "new", omenu_s_new, 0);
- rb_define_method(gOptionMenu, "get_menu", omenu_get_menu, 0);
- rb_define_method(gOptionMenu, "set_menu", omenu_set_menu, 1);
- rb_define_method(gOptionMenu, "remove_menu", omenu_set_menu, 0);
- rb_define_method(gOptionMenu, "set_history", omenu_set_history, 1);
-
- /* Pixmap */
- rb_define_singleton_method(gPixmap, "new", pixmap_s_new, 2);
- rb_define_method(gPixmap, "set", pixmap_set, 2);
- rb_define_method(gPixmap, "get", pixmap_get, 0);
-
- /* Preview */
- rb_define_singleton_method(gPreview, "new", preview_s_new, 1);
- rb_define_method(gPreview, "size", preview_size, 2);
- rb_define_method(gPreview, "put", preview_size, 8);
- rb_define_method(gPreview, "put_row", preview_size, 5);
- rb_define_method(gPreview, "draw_row", preview_size, 4);
- rb_define_method(gPreview, "set_expand", preview_set_expand, 1);
- rb_define_singleton_method(gPreview, "set_gamma", preview_set_gamma, 1);
- rb_define_singleton_method(gPreview, "set_color_cube",
- preview_set_color_cube, 4);
- rb_define_singleton_method(gPreview, "set_install_cmap",
- preview_set_install_cmap, 1);
- rb_define_singleton_method(gPreview, "set_reserved",
- preview_set_reserved, 1);
- rb_define_singleton_method(gPreview, "get_visual", preview_get_visual, 0);
- rb_define_singleton_method(gPreview, "get_cmap", preview_get_cmap, 0);
- rb_define_singleton_method(gPreview, "get_info", preview_get_info, 0);
-
- /* ProgressBar */
- rb_define_singleton_method(gProgressBar, "new", pbar_s_new, 0);
- rb_define_method(gProgressBar, "update", pbar_update, 1);
-
- /* ScrolledWindow */
- rb_define_singleton_method(gScrolledWin, "new", scwin_s_new, -1);
- rb_define_method(gScrolledWin, "set_policy", scwin_set_policy, 2);
-
- /* Table */
- rb_define_singleton_method(gTable, "new", tbl_s_new, -1);
- rb_define_method(gTable, "attach", tbl_attach, -1);
- rb_define_method(gTable, "set_row_spacing", tbl_set_row_spacing, 2);
- rb_define_method(gTable, "set_col_spacing", tbl_set_col_spacing, 2);
- rb_define_method(gTable, "set_row_spacings", tbl_set_row_spacings, 1);
- rb_define_method(gTable, "set_col_spacings", tbl_set_col_spacings, 1);
-
- /* Text */
- rb_define_singleton_method(gText, "new", txt_s_new, -1);
- rb_define_method(gText, "set_editable", txt_set_editable, 1);
- rb_define_method(gText, "set_adjustment", txt_set_adjustment, 2);
- rb_define_method(gText, "set_point", txt_set_point, 1);
- rb_define_method(gText, "get_point", txt_get_point, 0);
- rb_define_method(gText, "get_length", txt_get_length, 0);
- rb_define_method(gText, "freeze", txt_freeze, 0);
- rb_define_method(gText, "thaw", txt_thaw, 0);
- rb_define_method(gText, "insert", txt_insert, 4);
- rb_define_method(gText, "backward_delete", txt_backward_delete, 1);
- rb_define_method(gText, "forward_delete", txt_forward_delete, 1);
-
- /* Toolbar */
- rb_define_singleton_method(gToolbar, "new", tbar_s_new, -1);
- rb_define_method(gToolbar, "append_item", tbar_append_item, 4);
- rb_define_method(gToolbar, "prepend_item", tbar_prepend_item, 4);
- rb_define_method(gToolbar, "insert_item", tbar_append_item, 5);
- rb_define_method(gToolbar, "append_space", tbar_append_space, 0);
- rb_define_method(gToolbar, "prepend_space", tbar_prepend_space, 0);
- rb_define_method(gToolbar, "insert_space", tbar_append_space, 1);
- rb_define_method(gToolbar, "set_orientation", tbar_set_orientation, 1);
- rb_define_method(gToolbar, "set_style", tbar_set_style, 1);
- rb_define_method(gToolbar, "set_space_size", tbar_set_space_size, 1);
- rb_define_method(gToolbar, "set_tooltips", tbar_set_tooltips, 1);
-
- /* Tooltips */
- rb_define_singleton_method(gTooltips, "new", ttips_s_new, 0);
- rb_define_method(gTooltips, "set_tips", ttips_set_tips, 2);
- rb_define_method(gTooltips, "set_delay", ttips_set_delay, 1);
- rb_define_method(gTooltips, "enable", ttips_enable, 0);
- rb_define_method(gTooltips, "disable", ttips_disable, 0);
-
- /* Tree */
- rb_define_singleton_method(gTree, "new", tree_s_new, 0);
- rb_define_method(gTree, "append", tree_append, 1);
- rb_define_method(gTree, "prepend", tree_prepend, 1);
- rb_define_method(gTree, "insert", tree_insert, 2);
-
- /* TreeItem */
- rb_define_singleton_method(gTreeItem, "new", titem_s_new, -1);
- rb_define_method(gTreeItem, "set_subtree", titem_set_subtree, 1);
- rb_define_method(gTreeItem, "select", titem_select, 0);
- rb_define_method(gTreeItem, "deselect", titem_deselect, 0);
- rb_define_method(gTreeItem, "expand", titem_expand, 0);
- rb_define_method(gTreeItem, "collapse", titem_collapse, 0);
-
- /* ViewPort */
- rb_define_singleton_method(gViewPort, "new", vport_s_new, -1);
- rb_define_method(gViewPort, "get_hadjustment", vport_get_hadj, 0);
- rb_define_method(gViewPort, "get_vadjustment", vport_get_vadj, 0);
- rb_define_method(gViewPort, "set_hadjustment", vport_set_hadj, 1);
- rb_define_method(gViewPort, "set_vadjustment", vport_set_vadj, 1);
- rb_define_method(gViewPort, "set_shadow_type", vport_set_shadow, 1);
-
- /* AcceleratorTable */
- /* Style */
-
- /* Gtk module */
- rb_define_module_function(mGtk, "main", gtk_m_main, 0);
- rb_define_module_function(mGtk, "timeout_add", timeout_add, -1);
- rb_define_module_function(mGtk, "timeout_remove", timeout_remove, 1);
- rb_define_module_function(mGtk, "idle_add", idle_add, -1);
- rb_define_module_function(mGtk, "idle_remove", idle_remove, 1);
-
- rb_define_module_function(mGtk, "set_warning_handler",
- set_warning_handler, -1);
- rb_define_module_function(mGtk, "set_message_handler",
- set_message_handler, -1);
- rb_define_module_function(mGtk, "set_print_handler",
- set_print_handler, -1);
-
- /* Gdk module */
- /* GdkFont */
- rb_define_method(gdkFont, "==", gdkfnt_equal, 1);
-
- /* GdkBitmap */
- rb_define_singleton_method(gdkBitmap, "new", gdkbmap_s_new, 3);
- rb_define_singleton_method(gdkBitmap, "create_from_data",
- gdkbmap_create_from_data, 4);
-
- /* GdkPixmap */
- rb_define_singleton_method(gdkPixmap, "new", gdkpmap_s_new, 4);
- rb_define_singleton_method(gdkPixmap, "create_from_xpm",
- gdkpmap_create_from_xpm, 3);
- rb_define_singleton_method(gdkPixmap, "create_from_xpm_d",
- gdkpmap_create_from_xpm, 3);
-
- /* GdkWindow */
-
- /* GdkImage */
-
- rb_define_const(mGtk, "VISIBLE", INT2FIX(GTK_VISIBLE));
- rb_define_const(mGtk, "MAPPED", INT2FIX(GTK_MAPPED));
- rb_define_const(mGtk, "UNMAPPED", INT2FIX(GTK_UNMAPPED));
- rb_define_const(mGtk, "REALIZED", INT2FIX(GTK_REALIZED));
- rb_define_const(mGtk, "SENSITIVE", INT2FIX(GTK_SENSITIVE));
- rb_define_const(mGtk, "PARENT_SENSITIVE", INT2FIX(GTK_PARENT_SENSITIVE));
- rb_define_const(mGtk, "NO_WINDOW", INT2FIX(GTK_NO_WINDOW));
- rb_define_const(mGtk, "HAS_FOCUS", INT2FIX(GTK_HAS_FOCUS));
- rb_define_const(mGtk, "CAN_FOCUS", INT2FIX(GTK_CAN_FOCUS));
- rb_define_const(mGtk, "HAS_DEFAULT", INT2FIX(GTK_HAS_DEFAULT));
- rb_define_const(mGtk, "CAN_DEFAULT", INT2FIX(GTK_CAN_DEFAULT));
- rb_define_const(mGtk, "PROPAGATE_STATE", INT2FIX(GTK_PROPAGATE_STATE));
- rb_define_const(mGtk, "ANCHORED", INT2FIX(GTK_ANCHORED));
- rb_define_const(mGtk, "BASIC", INT2FIX(GTK_BASIC));
- rb_define_const(mGtk, "USER_STYLE", INT2FIX(GTK_USER_STYLE));
- rb_define_const(mGtk, "GRAB_ALL", INT2FIX(GTK_GRAB_ALL));
- rb_define_const(mGtk, "REDRAW_PENDING", INT2FIX(GTK_REDRAW_PENDING));
- rb_define_const(mGtk, "RESIZE_PENDING", INT2FIX(GTK_RESIZE_PENDING));
- rb_define_const(mGtk, "RESIZE_NEEDED", INT2FIX(GTK_RESIZE_NEEDED));
- rb_define_const(mGtk, "HAS_SHAPE_MASK", INT2FIX(GTK_HAS_SHAPE_MASK));
-
- /* GtkWindowType */
- rb_define_const(mGtk, "WINDOW_TOPLEVEL", INT2FIX(GTK_WINDOW_TOPLEVEL));
- rb_define_const(mGtk, "WINDOW_DIALOG", INT2FIX(GTK_WINDOW_DIALOG));
- rb_define_const(mGtk, "WIN_POS_NONE", INT2FIX(GTK_WIN_POS_NONE));
- rb_define_const(mGtk, "WIN_POS_CENTER", INT2FIX(GTK_WIN_POS_CENTER));
- rb_define_const(mGtk, "WIN_POS_MOUSE", INT2FIX(GTK_WIN_POS_MOUSE));
-
- /* GtkDirectionType */
- rb_define_const(mGtk, "DIR_TAB_FORWARD", INT2FIX(GTK_DIR_TAB_FORWARD));
- rb_define_const(mGtk, "DIR_TAB_BACKWARD", INT2FIX(GTK_DIR_TAB_BACKWARD));
- rb_define_const(mGtk, "DIR_UP", INT2FIX(GTK_DIR_UP));
- rb_define_const(mGtk, "DIR_DOWN", INT2FIX(GTK_DIR_DOWN));
- rb_define_const(mGtk, "DIR_LEFT", INT2FIX(GTK_DIR_LEFT));
- rb_define_const(mGtk, "DIR_RIGHT", INT2FIX(GTK_DIR_RIGHT));
-
- /* GtkPolicyType */
- rb_define_const(mGtk, "POLICY_ALWAYS", INT2FIX(GTK_POLICY_ALWAYS));
- rb_define_const(mGtk, "POLICY_AUTOMATIC", INT2FIX(GTK_POLICY_AUTOMATIC));
-
- /* GtkSelectionMode */
- rb_define_const(mGtk, "SELECTION_SINGLE", INT2FIX(GTK_SELECTION_SINGLE));
- rb_define_const(mGtk, "SELECTION_BROWSE", INT2FIX(GTK_SELECTION_BROWSE));
- rb_define_const(mGtk, "SELECTION_MULTIPLE", INT2FIX(GTK_SELECTION_MULTIPLE));
- rb_define_const(mGtk, "SELECTION_EXTENDED", INT2FIX(GTK_SELECTION_EXTENDED));
- /* GtkPositionType */
- rb_define_const(mGtk, "POS_LEFT", INT2FIX(GTK_POS_LEFT));
- rb_define_const(mGtk, "POS_RIGHT", INT2FIX(GTK_POS_RIGHT));
- rb_define_const(mGtk, "POS_TOP", INT2FIX(GTK_POS_TOP));
- rb_define_const(mGtk, "POS_BOTTOM", INT2FIX(GTK_POS_BOTTOM));
-
- /* GtkShadowType */
- rb_define_const(mGtk, "SHADOW_NONE", INT2FIX(GTK_SHADOW_NONE));
- rb_define_const(mGtk, "SHADOW_IN", INT2FIX(GTK_SHADOW_IN));
- rb_define_const(mGtk, "SHADOW_OUT", INT2FIX(GTK_SHADOW_OUT));
- rb_define_const(mGtk, "SHADOW_ETCHED_IN", INT2FIX(GTK_SHADOW_ETCHED_IN));
- rb_define_const(mGtk, "SHADOW_ETCHED_OUT", INT2FIX(GTK_SHADOW_ETCHED_OUT));
- /* GtkStateType */
- rb_define_const(mGtk, "STATE_NORMAL", INT2FIX(GTK_STATE_NORMAL));
- rb_define_const(mGtk, "STATE_ACTIVE", INT2FIX(GTK_STATE_ACTIVE));
- rb_define_const(mGtk, "STATE_PRELIGHT", INT2FIX(GTK_STATE_PRELIGHT));
- rb_define_const(mGtk, "STATE_SELECTED", INT2FIX(GTK_STATE_SELECTED));
- rb_define_const(mGtk, "STATE_INSENSITIVE", INT2FIX(GTK_STATE_INSENSITIVE));
- /* GtkAttachOptions */
- rb_define_const(mGtk, "EXPAND", INT2FIX(GTK_EXPAND));
- rb_define_const(mGtk, "SHRINK", INT2FIX(GTK_SHRINK));
- rb_define_const(mGtk, "FILL", INT2FIX(GTK_FILL));
- /* GtkSubmenuDirection */
- rb_define_const(mGtk, "DIRECTION_LEFT", INT2FIX(GTK_DIRECTION_LEFT));
- rb_define_const(mGtk, "DIRECTION_RIGHT", INT2FIX(GTK_DIRECTION_RIGHT));
- /* GtkSubmenuPlacement */
- rb_define_const(mGtk, "TOP_BOTTOM", INT2FIX(GTK_TOP_BOTTOM));
- rb_define_const(mGtk, "LEFT_RIGHT", INT2FIX(GTK_LEFT_RIGHT));
- /* GtkMetricType */
- rb_define_const(mGtk, "PIXELS", INT2FIX(GTK_PIXELS));
- rb_define_const(mGtk, "INCHES", INT2FIX(GTK_INCHES));
- rb_define_const(mGtk, "CENTIMETERS", INT2FIX(GTK_CENTIMETERS));
-
- /* GtkArrowType */
- rb_define_const(mGtk, "ARROW_UP", INT2FIX(GTK_ARROW_UP));
- rb_define_const(mGtk, "ARROW_DOWN", INT2FIX(GTK_ARROW_DOWN));
- rb_define_const(mGtk, "ARROW_LEFT", INT2FIX(GTK_ARROW_LEFT));
- rb_define_const(mGtk, "ARROW_RIGHT", INT2FIX(GTK_ARROW_RIGHT));
-
- /* GtkPreviewType */
- rb_define_const(mGtk, "PREVIEW_COLOR", INT2FIX(GTK_PREVIEW_COLOR));
- rb_define_const(mGtk, "PREVIEW_GRAYSCALE", INT2FIX(GTK_PREVIEW_GRAYSCALE));
-
- rb_define_const(mGtk, "BUTTONBOX_DEFAULT", INT2FIX(GTK_BUTTONBOX_DEFAULT));
- rb_define_const(mGtk, "BUTTONBOX_SPREAD", INT2FIX(GTK_BUTTONBOX_SPREAD));
- rb_define_const(mGtk, "BUTTONBOX_EDGE", INT2FIX(GTK_BUTTONBOX_EDGE));
- rb_define_const(mGtk, "BUTTONBOX_START", INT2FIX(GTK_BUTTONBOX_START));
- rb_define_const(mGtk, "BUTTONBOX_END", INT2FIX(GTK_BUTTONBOX_END));
-
- /* GtkToolbarStyle */
- rb_define_const(mGtk, "TOOLBAR_ICONS", INT2FIX(GTK_TOOLBAR_ICONS));
- rb_define_const(mGtk, "TOOLBAR_TEXT", INT2FIX(GTK_TOOLBAR_TEXT));
- rb_define_const(mGtk, "TOOLBAR_BOTH", INT2FIX(GTK_TOOLBAR_BOTH));
-
- /* GtkOrientation */
- rb_define_const(mGtk, "ORIENTATION_HORIZONTAL", INT2FIX(GTK_ORIENTATION_HORIZONTAL));
- rb_define_const(mGtk, "ORIENTATION_VERTICAL", INT2FIX(GTK_ORIENTATION_VERTICAL));
-
- /* GdkExtensionMode */
- rb_define_const(mGdk, "EXTENSION_EVENTS_NONE", INT2FIX(GDK_EXTENSION_EVENTS_NONE));
- rb_define_const(mGdk, "EXTENSION_EVENTS_ALL", INT2FIX(GDK_EXTENSION_EVENTS_ALL));
- rb_define_const(mGdk, "EXTENSION_EVENTS_CURSOR", INT2FIX(GDK_EXTENSION_EVENTS_CURSOR));
-
- argc = RARRAY(rb_argv)->len;
- argv = ALLOCA_N(char*,argc+1);
- argv[0] = RSTRING(rb_argv0)->ptr;
- for (i=0;i<argc;i++) {
- if (TYPE(RARRAY(rb_argv)->ptr[i]) == T_STRING) {
- argv[i+1] = RSTRING(RARRAY(rb_argv)->ptr[i])->ptr;
- }
- else {
- argv[i+1] = "";
- }
- }
- argc++;
- {
- /* Gdk modifies sighandlers, sigh */
- RETSIGTYPE (*sigfunc[7])();
-
- sigfunc[0] = signal(SIGHUP, SIG_IGN);
- sigfunc[1] = signal(SIGINT, SIG_IGN);
- sigfunc[2] = signal(SIGQUIT, SIG_IGN);
- sigfunc[3] = signal(SIGBUS, SIG_IGN);
- sigfunc[4] = signal(SIGSEGV, SIG_IGN);
- sigfunc[5] = signal(SIGPIPE, SIG_IGN);
- sigfunc[6] = signal(SIGTERM, SIG_IGN);
-
- gdk_init(&argc, &argv);
-
- signal(SIGHUP, sigfunc[0]);
- signal(SIGINT, sigfunc[1]);
- signal(SIGQUIT, sigfunc[2]);
- signal(SIGBUS, sigfunc[3]);
- signal(SIGSEGV, sigfunc[4]);
- signal(SIGPIPE, sigfunc[5]);
- signal(SIGTERM, sigfunc[6]);
- }
-
- for (i=1;i<argc;i++) {
- RARRAY(rb_argv)->ptr[i] = str_taint(str_new2(argv[i]));
- }
- RARRAY(rb_argv)->len = argc-1;
-
- id_gtkdata = rb_intern("gtkdata");
- id_relatives = rb_intern("relatives");
- id_call = rb_intern("call");
- gtk_idle_add((GtkFunction)idle, 0);
-
- g_set_error_handler(gtkerr);
- g_set_warning_handler(gtkerr);
- rb_global_variable(&warn_handler);
- rb_global_variable(&mesg_handler);
- rb_global_variable(&print_handler);
-}
diff --git a/ext/gtk/test.rb b/ext/gtk/test.rb
deleted file mode 100644
index 52ce5db7e0..0000000000
--- a/ext/gtk/test.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-require 'gtk'
-
-def create_menu(depth)
- return nil if depth < 1
-
- menu = Gtk::Menu::new()
- group = nil
- submenu = nil
-
- for i in 0..4
- buf = sprintf("item %2d - %d", depth, i+1)
-# menuitem = Gtk::MenuItem::new(buf)
- menuitem = Gtk::RadioMenuItem.new(group, buf)
- group = menuitem.group
- if depth % 2
- menuitem.set_show_toggle TRUE
- end
- menu.append menuitem
- menuitem.show
- if depth > 0
- unless submenu
- submenu = create_menu(depth - 1)
- end
- menuitem.set_submenu submenu
- end
- end
- return menu
-end
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.signal_connect("destroy") do
- exit
-end
-window.signal_connect("delete_event") do
- exit
-end
-window.set_title("menus")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add box1
-box1.show
-
-menubar = Gtk::MenuBar::new()
-box1.pack_start menubar, FALSE, TRUE, 0
-menubar.show
-
-menu = create_menu(2)
-menuitem = Gtk::MenuItem::new("test\nline2")
-menuitem.set_submenu menu
-menubar.append menuitem
-menuitem.show
-
-menuitem = Gtk::MenuItem::new("foo")
-menuitem.set_submenu menu
-menubar.append menuitem
-menuitem.show
-
-menuitem = Gtk::MenuItem::new("bar")
-menuitem.set_submenu menu
-menubar.append menuitem
-menuitem.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width 10
-box1.pack_start box2, TRUE, TRUE, 0
-box2.show
-
-optionmenu = Gtk::OptionMenu::new()
-optionmenu.set_menu create_menu(1)
-optionmenu.set_history 4
-box2.pack_start optionmenu, TRUE, TRUE, 0
-optionmenu.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::HBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test.xpm b/ext/gtk/test.xpm
deleted file mode 100644
index 9b0d2efdb2..0000000000
--- a/ext/gtk/test.xpm
+++ /dev/null
@@ -1,92 +0,0 @@
-/* XPM */
-static char *openfile[] = {
-/* width height num_colors chars_per_pixel */
-" 20 19 66 2",
-/* colors */
-".. c None",
-".# c #000000",
-".a c #dfdfdf",
-".b c #7f7f7f",
-".c c #006f6f",
-".d c #00efef",
-".e c #009f9f",
-".f c #004040",
-".g c #00bfbf",
-".h c #ff0000",
-".i c #ffffff",
-".j c #7f0000",
-".k c #007070",
-".l c #00ffff",
-".m c #00a0a0",
-".n c #004f4f",
-".o c #00cfcf",
-".p c #8f8f8f",
-".q c #6f6f6f",
-".r c #a0a0a0",
-".s c #7f7f00",
-".t c #007f7f",
-".u c #5f5f5f",
-".v c #707070",
-".w c #00f0f0",
-".x c #009090",
-".y c #ffff00",
-".z c #0000ff",
-".A c #00afaf",
-".B c #00d0d0",
-".C c #00dfdf",
-".D c #005f5f",
-".E c #00b0b0",
-".F c #001010",
-".G c #00c0c0",
-".H c #000f0f",
-".I c #00007f",
-".J c #005050",
-".K c #002f2f",
-".L c #dfcfcf",
-".M c #dfd0d0",
-".N c #006060",
-".O c #00e0e0",
-".P c #00ff00",
-".Q c #002020",
-".R c #dfc0c0",
-".S c #008080",
-".T c #001f1f",
-".U c #003f3f",
-".V c #007f00",
-".W c #00000f",
-".X c #000010",
-".Y c #00001f",
-".Z c #000020",
-".0 c #00002f",
-".1 c #000030",
-".2 c #00003f",
-".3 c #000040",
-".4 c #00004f",
-".5 c #000050",
-".6 c #00005f",
-".7 c #000060",
-".8 c #00006f",
-".9 c #000070",
-"#. c #7f7f80",
-"## c #9f9f9f",
-/* pixels */
-"........................................",
-"........................................",
-"........................................",
-".......................#.#.#............",
-".....................#.......#...#......",
-"...............................#.#......",
-".......#.#.#.................#.#.#......",
-".....#.y.i.y.#.#.#.#.#.#.#..............",
-".....#.i.y.i.y.i.y.i.y.i.#..............",
-".....#.y.i.y.i.y.i.y.i.y.#..............",
-".....#.i.y.i.y.#.#.#.#.#.#.#.#.#.#.#....",
-".....#.y.i.y.#.s.s.s.s.s.s.s.s.s.#......",
-".....#.i.y.#.s.s.s.s.s.s.s.s.s.#........",
-".....#.y.#.s.s.s.s.s.s.s.s.s.#..........",
-".....#.#.s.s.s.s.s.s.s.s.s.#............",
-".....#.#.#.#.#.#.#.#.#.#.#..............",
-"........................................",
-"........................................",
-"........................................"
-};
diff --git a/ext/gtk/test0.rb b/ext/gtk/test0.rb
deleted file mode 100644
index 4ff802d6ca..0000000000
--- a/ext/gtk/test0.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.border_width(10)
-button = Gtk::Button::new("Hello World")
-button.signal_connect("clicked") do
- print "hello world\n"
- exit
-end
-window.add(button)
-button.show
-window.show
-Gtk::main()
diff --git a/ext/gtk/test1.rb b/ext/gtk/test1.rb
deleted file mode 100644
index 7d24199580..0000000000
--- a/ext/gtk/test1.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("entry")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-entry = Gtk::Entry::new()
-entry.set_text("hello world")
-box2.pack_start(entry, TRUE, TRUE, 0)
-entry.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test2.rb b/ext/gtk/test2.rb
deleted file mode 100644
index 170de96185..0000000000
--- a/ext/gtk/test2.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("list")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-scrolled_win = Gtk::ScrolledWindow::new()
-scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
-box2.pack_start(scrolled_win, TRUE, TRUE, 0)
-scrolled_win.show
-
-list = Gtk::List::new()
-list.set_selection_mode(Gtk::SELECTION_MULTIPLE)
-list.set_selection_mode(Gtk::SELECTION_BROWSE)
-scrolled_win.add(list)
-list.show
-
-for i in [
- "hello",
- "world",
- "blah",
- "foo",
- "bar",
- "argh",
- "spencer",
- "is a",
- "wussy",
- "programmer",
- ]
- list_item = Gtk::ListItem::new(i)
- list.add(list_item)
- list_item.show
-end
-
-button = Gtk::Button::new("add")
-button.set_flags(Gtk::CAN_FOCUS);
-i = 1
-button.signal_connect("clicked") do
- list_item = Gtk::ListItem::new(format("added item %d", i))
- list.add(list_item)
- list_item.show
- i += 1
-end
-box2.pack_start(button, FALSE, TRUE, 0)
-button.show
-
-button = Gtk::Button::new("remove")
-button.set_flags(Gtk::CAN_FOCUS);
-button.signal_connect("clicked") do
- tmp_list = list.selection
- list.remove_items(tmp_list)
- for i in tmp_list
- i.destroy
- end
-end
-box2.pack_start(button, FALSE, TRUE, 0)
-button.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test3.rb b/ext/gtk/test3.rb
deleted file mode 100644
index d73f72f9fa..0000000000
--- a/ext/gtk/test3.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'gtk'
-
-window = Gtk::FileSelection::new("file selection dialog")
-window.position(Gtk::WIN_POS_MOUSE)
-window.border_width(0)
-
-window.ok_button.signal_connect("clicked") do
- print window.get_filename, "\n"
-end
-window.cancel_button.signal_connect("clicked") do
- window.destroy
- exit
-end
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test4.rb b/ext/gtk/test4.rb
deleted file mode 100644
index da0000c420..0000000000
--- a/ext/gtk/test4.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("notebook")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-notebook = Gtk::Notebook::new()
-notebook.set_tab_pos(Gtk::POS_TOP)
-box2.pack_start(notebook, TRUE, TRUE, 0)
-notebook.show
-
-for i in 1..5
- frame = Gtk::Frame::new(format("Page %d", i))
- frame.border_width(10)
- frame.set_usize(200, 150)
- frame.show
-
- label = Gtk::Label::new(format("Box %d", i))
- frame.add label
- label.show
-
- label = Gtk::Label::new(format("Tab %d", i))
- notebook.append_page frame, label
-end
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::HBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-
-button = Gtk::Button::new("next")
-button.signal_connect("clicked") do
- notebook.next_page
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::Button::new("prev")
-button.signal_connect("clicked") do
- notebook.prev_page
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::Button::new("rotate")
-button.signal_connect("clicked") do
- notebook.set_tab_pos((notebook.tab_pos+1)%4)
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test5.rb b/ext/gtk/test5.rb
deleted file mode 100644
index 714232079b..0000000000
--- a/ext/gtk/test5.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("buttons")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-table = Gtk::Table::new(3, 3, FALSE)
-table.set_row_spacings(5)
-table.set_col_spacings(5)
-table.border_width(10)
-box1.pack_start(table, TRUE, TRUE, 0)
-table.show
-
-button = []
-0.upto(8) do |i|
- button.push Gtk::Button::new("button"+(i+1))
-end
-0.upto(8) do |i|
- button[i].signal_connect("clicked") do |w|
- if button[i+1].visible?
- button[i+1].hide
- else
- button[i+1].show
- end
- end
- button[i].show
-end
-table.attach(button[0], 0, 1, 0, 1, nil, nil, 0, 0)
-table.attach(button[1], 1, 2, 1, 2, nil, nil, 0, 0)
-table.attach(button[2], 2, 3, 2, 3, nil, nil, 0, 0)
-table.attach(button[3], 0, 1, 2, 3, nil, nil, 0, 0)
-table.attach(button[4], 2, 3, 0, 1, nil, nil, 0, 0)
-table.attach(button[5], 1, 2, 2, 3, nil, nil, 0, 0)
-table.attach(button[6], 1, 2, 0, 1, nil, nil, 0, 0)
-table.attach(button[7], 2, 3, 1, 2, nil, nil, 0, 0)
-table.attach(button[8], 0, 1, 1, 2, nil, nil, 0, 0)
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-close = Gtk::Button::new("close")
-close.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(close, TRUE, TRUE, 0)
-close.set_flags(Gtk::CAN_DEFAULT);
-close.grab_default
-close.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test6.rb b/ext/gtk/test6.rb
deleted file mode 100644
index a589530ab0..0000000000
--- a/ext/gtk/test6.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("toggle buttons")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-button = Gtk::ToggleButton::new("button1")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::ToggleButton::new("button2")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::ToggleButton::new("button3")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-close = Gtk::Button::new("close")
-close.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(close, TRUE, TRUE, 0)
-close.set_flags(Gtk::CAN_DEFAULT);
-close.grab_default
-close.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test7.rb b/ext/gtk/test7.rb
deleted file mode 100644
index 4d78648a3c..0000000000
--- a/ext/gtk/test7.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("check buttons")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-button = Gtk::CheckButton::new("button1")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::CheckButton::new("button2")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::CheckButton::new("button3")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-close = Gtk::Button::new("close")
-close.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(close, TRUE, TRUE, 0)
-close.set_flags(Gtk::CAN_DEFAULT);
-close.grab_default
-close.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test8.rb b/ext/gtk/test8.rb
deleted file mode 100644
index 4ac4b0b8ad..0000000000
--- a/ext/gtk/test8.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("radio buttons")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add(box1)
-box1.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width 10
-box1.pack_start(box2, TRUE, TRUE, 0)
-box2.show
-
-button = Gtk::RadioButton::new("button1")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::RadioButton::new(button, "button2")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-button = Gtk::RadioButton::new(button, "button3")
-box2.pack_start(button, TRUE, TRUE, 0)
-button.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::VBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-close = Gtk::Button::new("close")
-close.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(close, TRUE, TRUE, 0)
-close.set_flags(Gtk::CAN_DEFAULT);
-close.grab_default
-close.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/test9.rb b/ext/gtk/test9.rb
deleted file mode 100644
index 7bb3bf305e..0000000000
--- a/ext/gtk/test9.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-require 'gtk'
-
-def create_bbox_window(horizontal, title, pos, spacing, cw, ch, layout)
- window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
- window.set_title(title)
- window.signal_connect("destroy") do
- window.destroy
- end
- window.signal_connect("delete_event") do
- window.hide
- window.destroy
- end
- if horizontal
- window.set_usize(550, 60)
- window.set_uposition(150, pos)
- else
- window.set_usize(150, 400)
- window.set_uposition(pos, 200)
- end
- box1 = Gtk::VBox::new(FALSE, 0)
- window.add box1
- box1.show
- if horizontal
- bbox = Gtk::HButtonBox::new()
- else
- bbox = Gtk::VButtonBox::new()
- end
- bbox.set_layout layout
- bbox.set_spacing spacing
- bbox.set_child_size cw, ch
- bbox.show
- box1.border_width 25
- box1.pack_start(bbox, TRUE, TRUE, 0)
- button = Gtk::Button::new("OK")
- bbox.add button
- button.signal_connect("clicked") do
- window.hide
- window.destroy
- end
- button.show
-
- button = Gtk::Button::new("Cancel")
- bbox.add button
- button.signal_connect("clicked") do
- window.hide
- window.destroy
- end
- button.show
-
- button = Gtk::Button::new("Help")
- bbox.add button
- button.show
-
- window.show
-end
-
-def test_hbbox
- create_bbox_window(TRUE, "Spread", 50, 40, 85, 25, Gtk::BUTTONBOX_SPREAD);
- create_bbox_window(TRUE, "Edge", 250, 40, 85, 28, Gtk::BUTTONBOX_EDGE);
- create_bbox_window(TRUE, "Start", 450, 40, 85, 25, Gtk::BUTTONBOX_START);
- create_bbox_window(TRUE, "End", 650, 15, 30, 25, Gtk::BUTTONBOX_END);
-end
-
-def test_vbbox
- create_bbox_window(FALSE, "Spread", 50, 40, 85, 25, Gtk::BUTTONBOX_SPREAD);
- create_bbox_window(FALSE, "Edge", 250, 40, 85, 28, Gtk::BUTTONBOX_EDGE);
- create_bbox_window(FALSE, "Start", 450, 40, 85, 25, Gtk::BUTTONBOX_START);
- create_bbox_window(FALSE, "End", 650, 15, 30, 25, Gtk::BUTTONBOX_END);
-end
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.signal_connect("delete_event") do
- window.destroy
- exit
-end
-window.set_title("button box")
-window.border_width(20)
-
-bbox = Gtk::HButtonBox::new()
-window.add(bbox)
-bbox.show
-
-button = Gtk::Button::new("Horizontal")
-def button.clicked(*args)
- test_hbbox
-end
-bbox.add button
-button.show
-
-button = Gtk::Button::new("Vertical")
-def button.clicked(*args)
- test_vbbox
-end
-bbox.add button
-button.show
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/testa.rb b/ext/gtk/testa.rb
deleted file mode 100644
index 00a6603dfd..0000000000
--- a/ext/gtk/testa.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.set_title("toolbar test")
-window.set_policy(TRUE, TRUE, TRUE)
-window.signal_connect("destroy") do
- exit
-end
-window.signal_connect("delete_event") do
- exit
-end
-window.border_width(0)
-window.realize
-
-toolbar = Gtk::Toolbar::new(Gtk::ORIENTATION_HORIZONTAL, Gtk::TOOLBAR_BOTH)
-toolbar.append_item "Horizontal", "Horizontal toolbar layout",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,
- #window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_orientation Gtk::ORIENTATION_HORIZONTAL
-end
-toolbar.append_item "Vertival", "Vertical toolbar layout",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil, #window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_orientation Gtk::ORIENTATION_VERTICAL
-end
-toolbar.append_space
-toolbar.append_item "Icons", "Only show toolbar icons",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil, #window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_style Gtk::TOOLBAR_ICONS
-end
-toolbar.append_item "Text", "Only show toolbar text",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,#window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_style Gtk::TOOLBAR_TEXT
-end
-toolbar.append_item "Both", "Show toolbar icons and text",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil, #window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_style Gtk::TOOLBAR_BOTH
-end
-toolbar.append_space
-toolbar.append_item "Small", "User small spaces",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,#window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_space_size 5
-end
-toolbar.append_item "Big", "User big spaces",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,#window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_space_size 10
-end
-toolbar.append_space
-toolbar.append_item "Enable", "Enable tooltips",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,#window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_tooltips TRUE
-end
-toolbar.append_item "Disable", "Disable tooltips",
- Gtk::Pixmap::new(*Gdk::Pixmap::create_from_xpm(window.window,
- nil,#window.style.bg[Gtk::STATE_NORMAL],
- "test.xpm")), nil do
- toolbar.set_tooltips FALSE
-end
-window.add toolbar
-toolbar.show
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/testb.rb b/ext/gtk/testb.rb
deleted file mode 100644
index 4e707bcf87..0000000000
--- a/ext/gtk/testb.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.signal_connect("destroy") do
- exit
-end
-window.signal_connect("delete_event") do
- exit
-end
-window.set_title("buttons")
-window.border_width(0)
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add box1
-box1.show
-
-box2 = Gtk::HBox::new(FALSE, 5)
-box2.border_width 10
-box1.pack_start box2, TRUE, TRUE, 0
-box2.show
-
-label = Gtk::Label::new("Hello World")
-frame = Gtk::Frame::new("Frame 1")
-box2.pack_start frame, TRUE, TRUE, 0
-frame.show
-
-box3 = Gtk::VBox::new(FALSE, 5)
-box3.border_width 5
-frame.add box3
-box3.show
-
-button = Gtk::Button::new("switch")
-button.signal_connect("clicked") do
- label.reparent box3
-end
-box3.pack_start button, FALSE, TRUE, 0
-button.show
-box3.pack_start label, FALSE, TRUE, 0
-label.show
-
-frame = Gtk::Frame::new("Frame 2")
-box2.pack_start frame, TRUE, TRUE, 0
-frame.show
-
-box4 = Gtk::VBox::new(FALSE, 5)
-box4.border_width 5
-frame.add box4
-box4.show
-
-button = Gtk::Button::new("switch")
-button.signal_connect("clicked") do
- label.reparent box4
-end
-box4.pack_start button, FALSE, TRUE, 0
-button.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::HBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/gtk/testc.rb b/ext/gtk/testc.rb
deleted file mode 100644
index 98c6466beb..0000000000
--- a/ext/gtk/testc.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-require 'gtk'
-
-window = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
-window.signal_connect("destroy") do
- exit
-end
-window.signal_connect("delete_event") do
- exit
-end
-window.set_title("pixmap")
-window.border_width(0)
-window.realize
-
-box1 = Gtk::VBox::new(FALSE, 0)
-window.add box1
-box1.show
-
-box2 = Gtk::HBox::new(FALSE, 10)
-box2.border_width 10
-box1.pack_start box2, TRUE, TRUE, 0
-box2.show
-
-button = Gtk::Button::new()
-box2.pack_start button, FALSE, FALSE, 0
-button.show
-
-style = button.style
-pixmap, mask = Gdk::Pixmap::create_from_xpm(window.window,
- nil,
- #style.bg[Gtk::STATE_NORMAL],
- "test.xpm")
-pixmapwid = Gtk::Pixmap::new(pixmap, mask)
-label = Gtk::Label::new("Pixmap\ntest")
-box3 = Gtk::HBox::new(FALSE, 0)
-box3.border_width 2
-box3.add pixmapwid
-box3.add label
-button.add box3
-pixmapwid.show
-label.show
-box3.show
-
-separator = Gtk::HSeparator::new()
-box1.pack_start(separator, FALSE, TRUE, 0)
-separator.show
-
-box2 = Gtk::HBox::new(FALSE, 10)
-box2.border_width(10)
-box1.pack_start(box2, FALSE, TRUE, 0)
-box2.show
-
-button = Gtk::Button::new("close")
-button.signal_connect("clicked") do
- window.destroy
- exit
-end
-box2.pack_start(button, TRUE, TRUE, 0)
-button.set_flags(Gtk::CAN_DEFAULT);
-button.grab_default
-button.show
-
-window.show
-
-Gtk::main()
diff --git a/ext/kconv/MANIFEST b/ext/kconv/MANIFEST
deleted file mode 100644
index cb89e8239c..0000000000
--- a/ext/kconv/MANIFEST
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-depend
-kconv.c
diff --git a/ext/kconv/depend b/ext/kconv/depend
deleted file mode 100644
index 8f09d95130..0000000000
--- a/ext/kconv/depend
+++ /dev/null
@@ -1 +0,0 @@
-kconv.o: kconv.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/mandel/MANIFEST b/ext/mandel/MANIFEST
deleted file mode 100644
index 8a72d2c3a9..0000000000
--- a/ext/mandel/MANIFEST
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-mandel.c
-tkmandel.rb
diff --git a/ext/mandel/mandel.c b/ext/mandel/mandel.c
deleted file mode 100644
index 359c0756da..0000000000
--- a/ext/mandel/mandel.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/************************************************
-
- mandel.c -
-
- $Author$
-
-************************************************/
-
-#include "ruby.h"
-#include "math.h"
-
-static VALUE
-mandel(self, re, im, max)
- VALUE self;
- VALUE re;
- VALUE im;
- VALUE max;
-{
- double real, image;
- double z_real, z_image;
- double tmp_real;
- int maximum;
- int i;
-
- Check_Type(re, T_FLOAT);
- Check_Type(im, T_FLOAT);
- Check_Type(max, T_FIXNUM);
-
- real = RFLOAT(re)->value;
- image = RFLOAT(im)->value;
- maximum = FIX2INT(max);
-
- /***
- z = c = Complex(re, im)
- for i in 0 .. $max_deapth
- z = (z * z) + c
- break if z.abs > 2
- end
- return i
- ***/
-
- z_real = real;
- z_image = image;
- for (i = 0; i < maximum; i++) {
- tmp_real = ((z_real * z_real) - (z_image * z_image)) + real;
- z_image = ((z_real * z_image) + (z_image * z_real)) + image;
- z_real = tmp_real;
- if ( ((z_real * z_real) + (z_image * z_image)) > 4.0 ) {
- break;
- }
- }
- return INT2FIX(i);
-}
-
-Init_mandel()
-{
- VALUE mMandel = rb_define_module("Mandel");
- rb_define_module_function(mMandel, "mandel", mandel, 3);
-}
diff --git a/ext/mandel/tkmandel.rb b/ext/mandel/tkmandel.rb
deleted file mode 100644
index 5ebe90fb80..0000000000
--- a/ext/mandel/tkmandel.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-# require "complex"
-require "mandel"
-require "tkclass"
-
-DefaultMaxDepth = 30
-DefaultSX = -2.25
-DefaultSY = 1.75
-DefaultEX = 1.25
-DefaultEY = -1.75
-
-def reset
- $max_depth = DefaultMaxDepth
- $s_re = DefaultSX
- $s_im = DefaultSY
- $e_re = DefaultEX
- $e_im = DefaultEY
- $dx = ($e_re - $s_re).abs / Width
- $dy = ($e_im - $s_im).abs / Height
- $photo.blank
-end
-
-
-Width = 400
-Height = 400
-
-$c = Canvas.new {
- width Width
- height Height
- }
-$c.pack
-
-$c_rect = Rectangle.new($c, 0, 0, Width+1, Height+1)
-$c_rect.fill "white"
-
-$colors = []
-
-def colors_init
- $colors = []
- for i in 0 .. 125
- $colors.push(format("#%02x%02x%02x", 250 - (i*2), i*2, 0))
- end
- for i in 0 .. 125
- $colors.push(format("#%02x%02x%02x", 0, 250 - (i*2), i*2))
- end
- $color_max = $colors.size - 1
-end
-
-def zoom(a, b, c, d)
- center_x = (a + c) / 2
- center_y = (b + d) / 2
- size = (c - a).abs
- size = (d - b).abs if (size < (d - b).abs)
- size = 1 if (size < 1)
- zoom_rate = ((Width + Height) / 2).to_f / size
- $max_depth = ($max_depth.to_f * Math.sqrt(Math.sqrt(Math.sqrt(zoom_rate)))).to_i
-
- move_x_rate = (center_x - (Width / 2)).to_f / (Width / 2)
- move_y_rate = (center_y - (Height / 2)).to_f / (Height / 2)
-
- center_re = ($s_re + $e_re) / 2
- center_im = ($s_im + $e_im) / 2
- c_size_re = ($e_re - $s_re).abs
- c_size_im = ($e_im - $s_im).abs
-
- center_re = center_re + (move_x_rate * (c_size_re / 2))
- center_im = center_im - (move_y_rate * (c_size_im / 2))
-
- $s_re = center_re - ((c_size_re / 2) / zoom_rate)
- $s_im = center_im + ((c_size_im / 2) / zoom_rate)
- $e_re = center_re + ((c_size_re / 2) / zoom_rate)
- $e_im = center_im - ((c_size_im / 2) / zoom_rate)
-
- $dx = ($e_re - $s_re).abs / Width
- $dy = ($e_im - $s_im).abs / Height
- p [$s_re, $dx, $s_im, $dy]
-end
-
-
-def mandel(x, y)
- re = $s_re + ($dx * x)
- im = $s_im - ($dy * y)
-# z = c = Complex(re, im)
-# for i in 0 .. $max_depth
-# z = (z * z) + c
-# break if z.abs > 2
-# end
-# return i
- return Mandel.mandel(re, im, $max_depth)
-end
-
-$buf = "{"+" "*Width+"}"
-def calc
- $c.update
- return if $current_rect
- depth = 0
-
- for x in 0 .. Width - 1
- depth = mandel(x, $calc_y)
- if depth >= $max_depth
- $buf[x*8+1,7] = "#000000"
- else
- $buf[x*8+1,7] = $colors[$color_max * depth / $max_depth]
- end
- end
- $photo.put($buf, 0, $calc_y)
-
- $calc_y += 1
- if (($calc_y % 20) == 0)
- print "#{($calc_y * 100 / Height)}% done. -- depth #{$max_depth}\n"
-# $mandel.image $photo
- end
-
- if ($calc_y > Height - 1)
- $calc_y = StartCalcY
- $calc_on = false
-# exit
- end
-
- if $calc_on
- Tk.after(1) { calc() }
- end
-end
-
-$photo = TkPhotoImage.new({'width'=>Width, 'height'=>Height})
-$mandel = TkcImage.new($c, Width/2, Height/2) { image $photo }
-reset()
-colors_init()
-$calc_y = StartCalcY = 0
-$calc_on = true
-calc()
-
-def clear
-# $mandel.destroy if $mandel
- $calc_y = StartCalcY
-end
-
-$start_x = $start_y = 0
-$current_rect = nil
-
-def do_press(x, y)
- $start_x = x
- $start_y = y
- $current_rect = Rectangle.new($c, x, y, x, y) { outline "white" }
-end
-
-def do_motion(x, y)
- if $current_rect
- $current_rect.coords $start_x, $start_y, x, y
- end
-end
-
-def do_release(x, y)
- if $current_rect
- $current_rect.coords $start_x, $start_y, x, y
- $current_rect.destroy
- $current_rect = nil
- clear()
- $calc_on = true
- zoom($start_x, $start_y, x, y)
- calc()
- end
-end
-
-$c.bind("1", proc{|e| do_press e.x, e.y})
-$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
-$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
-
-begin
- Tk.mainloop
-ensure
-# File.delete("#tmpmandel#.gif")
-end
diff --git a/ext/marshal/depend b/ext/marshal/depend
deleted file mode 100644
index c955eb2d59..0000000000
--- a/ext/marshal/depend
+++ /dev/null
@@ -1,2 +0,0 @@
-marshal.o: marshal.c ../../ruby.h ../../config.h ../../defines.h ../../io.h \
- ../../st.h
diff --git a/ext/marshal/extconf.rb b/ext/marshal/extconf.rb
deleted file mode 100644
index ab30bd117b..0000000000
--- a/ext/marshal/extconf.rb
+++ /dev/null
@@ -1 +0,0 @@
-create_makefile("marshal")
diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c
deleted file mode 100644
index 99e87d0b5f..0000000000
--- a/ext/marshal/marshal.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/************************************************
-
- marshal.c -
-
- $Author$
- $Revision$
- $Date$
- created at: Thu Apr 27 16:30:01 JST 1995
-
-************************************************/
-
-#include "ruby.h"
-#include "io.h"
-#include "st.h"
-
-#define MARSHAL_MAJOR 4
-#define MARSHAL_MINOR 0
-
-#define TYPE_NIL '0'
-#define TYPE_TRUE 'T'
-#define TYPE_FALSE 'F'
-#define TYPE_FIXNUM 'i'
-
-#define TYPE_UCLASS 'C'
-#define TYPE_OBJECT 'o'
-#define TYPE_USERDEF 'u'
-#define TYPE_FLOAT 'f'
-#define TYPE_BIGNUM 'l'
-#define TYPE_STRING '"'
-#define TYPE_REGEXP '/'
-#define TYPE_ARRAY '['
-#define TYPE_HASH '{'
-#define TYPE_STRUCT 'S'
-#define TYPE_MODULE 'M'
-
-#define TYPE_SYMBOL ':'
-#define TYPE_SYMLINK ';'
-
-#define TYPE_LINK '@'
-
-extern VALUE cString;
-extern VALUE cRegexp;
-extern VALUE cArray;
-extern VALUE cHash;
-
-VALUE rb_path2class();
-
-static ID s_dump, s_load;
-
-struct dump_arg {
- VALUE obj;
- FILE *fp;
- VALUE str;
- st_table *symbol;
- st_table *data;
-};
-
-struct dump_call_arg {
- VALUE obj;
- struct dump_arg *arg;
- int limit;
-};
-
-static void w_long _((long, struct dump_arg*));
-
-static void
-w_byte(c, arg)
- char c;
- struct dump_arg *arg;
-{
- if (arg->fp) putc(c, arg->fp);
- else str_cat(arg->str, (UCHAR*)&c, 1);
-}
-
-static void
-w_bytes(s, n, arg)
- char *s;
- int n;
- struct dump_arg *arg;
-{
- w_long(n, arg);
- if (arg->fp) {
- fwrite(s, 1, n, arg->fp);
- }
- else {
- str_cat(arg->str, s, n);
- }
-}
-
-static void
-w_short(x, arg)
- int x;
- struct dump_arg *arg;
-{
- int i;
-
- for (i=0; i<sizeof(USHORT); i++) {
- w_byte((x >> (i*8)) & 0xff, arg);
- }
-}
-
-static void
-w_long(x, arg)
- long x;
- struct dump_arg *arg;
-{
- char buf[sizeof(long)+1];
- int i, len = 0;
-
- if (x == 0) {
- w_byte(0, arg);
- return;
- }
- for (i=1;i<sizeof(long)+1;i++) {
- buf[i] = x & 0xff;
- x = RSHIFT(x,8);
- if (x == 0) {
- buf[0] = i;
- break;
- }
- if (x == -1) {
- buf[0] = -i;
- break;
- }
- }
- len = i;
- for (i=0;i<=len;i++) {
- w_byte(buf[i], arg);
- }
-}
-
-static void
-w_float(d, arg)
- double d;
- struct dump_arg *arg;
-{
- char buf[100];
-
- sprintf(buf, "%.12g", d);
- w_bytes(buf, strlen(buf), arg);
-}
-
-static void
-w_symbol(id, arg)
- ID id;
- struct dump_arg *arg;
-{
- char *sym = rb_id2name(id);
- int num;
-
- if (st_lookup(arg->symbol, id, &num)) {
- w_byte(TYPE_SYMLINK, arg);
- w_long(num, arg);
- }
- else {
- w_byte(TYPE_SYMBOL, arg);
- w_bytes(sym, strlen(sym), arg);
- st_insert(arg->symbol, id, arg->symbol->num_entries);
- }
-}
-
-static void
-w_unique(s, arg)
- char *s;
- struct dump_arg *arg;
-{
- w_symbol(rb_intern(s), arg);
-}
-
-static void w_object _((VALUE,struct dump_arg*,int));
-extern VALUE cIO, cBignum, cStruct;
-
-static int
-hash_each(key, value, arg)
- VALUE key, value;
- struct dump_call_arg *arg;
-{
- w_object(key, arg->arg, arg->limit);
- w_object(value, arg->arg, arg->limit);
- return ST_CONTINUE;
-}
-
-static int
-obj_each(id, value, arg)
- ID id;
- VALUE value;
- struct dump_call_arg *arg;
-{
- w_symbol(id, arg->arg);
- w_object(value, arg->arg, arg->limit);
- return ST_CONTINUE;
-}
-
-static void
-w_uclass(obj, class, arg)
- VALUE obj, class;
- struct dump_arg *arg;
-{
- if (CLASS_OF(obj) != class) {
- w_byte(TYPE_UCLASS, arg);
- w_unique(rb_class2name(CLASS_OF(obj)), arg);
- }
-}
-
-static void
-w_object(obj, arg, limit)
- VALUE obj;
- struct dump_arg *arg;
- int limit;
-{
- int n;
- struct dump_call_arg c_arg;
-
- if (limit == 0) {
- Fail("exceed depth limit");
- }
- limit--;
- c_arg.limit = limit;
- c_arg.arg = arg;
-
- if (obj == Qnil) {
- w_byte(TYPE_NIL, arg);
- }
- else if (obj == TRUE) {
- w_byte(TYPE_TRUE, arg);
- }
- else if (obj == FALSE) {
- w_byte(TYPE_FALSE, arg);
- }
- else if (FIXNUM_P(obj)) {
-#if SIZEOF_LONG <= 4
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2INT(obj), arg);
-#else
- if (RSHIFT(obj, 32) == 0 || RSHIFT(obj, 32) == -1) {
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2INT(obj), arg);
- }
- else {
- obj = int2big(FIX2INT(obj));
- goto write_bignum;
- }
-#endif
- }
- else {
- int num;
-
- if (st_lookup(arg->data, obj, &num)) {
- w_byte(TYPE_LINK, arg);
- w_long(num, arg);
- return;
- }
- st_insert(arg->data, obj, arg->data->num_entries);
- if (rb_respond_to(obj, s_dump)) {
- VALUE v;
-
- w_byte(TYPE_USERDEF, arg);
- w_unique(rb_class2name(CLASS_OF(obj)), arg);
- v = rb_funcall(obj, s_dump, 1, limit);
- if (TYPE(v) != T_STRING) {
- TypeError("_dump_to must return String");
- }
- w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
- return;
- }
-
- switch (BUILTIN_TYPE(obj)) {
- case T_MODULE:
- case T_CLASS:
- w_byte(TYPE_MODULE, arg);
- {
- VALUE path = rb_class_path(obj);
- w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
- }
- return;
-
- case T_FLOAT:
- w_byte(TYPE_FLOAT, arg);
- w_float(RFLOAT(obj)->value, arg);
- return;
-
- case T_BIGNUM:
- write_bignum:
- w_byte(TYPE_BIGNUM, arg);
- {
- char sign = RBIGNUM(obj)->sign?'+':'-';
- int len = RBIGNUM(obj)->len;
- USHORT *d = RBIGNUM(obj)->digits;
-
- w_byte(sign, arg);
- w_long(len, arg);
- while (len--) {
- w_short(*d, arg);
- d++;
- }
- }
- return;
-
- case T_STRING:
- w_uclass(obj, cString, arg);
- w_byte(TYPE_STRING, arg);
- w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg);
- return;
-
- case T_REGEXP:
- w_uclass(obj, cRegexp, arg);
- w_byte(TYPE_REGEXP, arg);
- w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg);
- w_byte(FL_TEST(obj, FL_USER1), arg);
- return;
-
- case T_ARRAY:
- w_uclass(obj, cArray, arg);
- w_byte(TYPE_ARRAY, arg);
- {
- int len = RARRAY(obj)->len;
- VALUE *ptr = RARRAY(obj)->ptr;
-
- w_long(len, arg);
- while (len--) {
- w_object(*ptr, arg, limit);
- ptr++;
- }
- }
- break;
-
- case T_HASH:
- w_uclass(obj, cHash, arg);
- w_byte(TYPE_HASH, arg);
- w_long(RHASH(obj)->tbl->num_entries, arg);
- st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
- break;
-
- case T_STRUCT:
- w_byte(TYPE_STRUCT, arg);
- {
- int len = RSTRUCT(obj)->len;
- char *path = rb_class2name(CLASS_OF(obj));
- VALUE mem;
- int i;
-
- w_unique(path, arg);
- w_long(len, arg);
- mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__"));
- if (mem == Qnil) {
- Fatal("non-initialized struct");
- }
- for (i=0; i<len; i++) {
- w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), arg);
- w_object(RSTRUCT(obj)->ptr[i], arg, limit);
- }
- }
- break;
-
- case T_OBJECT:
- w_byte(TYPE_OBJECT, arg);
- {
- VALUE class = CLASS_OF(obj);
- char *path;
-
- if (FL_TEST(class, FL_SINGLETON)) {
- TypeError("singleton can't be dumped");
- }
- path = rb_class2name(class);
- w_unique(path, arg);
- if (ROBJECT(obj)->iv_tbl) {
- w_long(ROBJECT(obj)->iv_tbl->num_entries, arg);
- st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg);
- }
- else {
- w_long(0, arg);
- }
- }
- break;
-
- default:
- TypeError("can't dump %s", rb_class2name(CLASS_OF(obj)));
- break;
- }
- }
-}
-
-static VALUE
-dump(arg)
- struct dump_call_arg *arg;
-{
- w_object(arg->obj, arg->arg, arg->limit);
-}
-
-static VALUE
-dump_ensure(arg)
- struct dump_arg *arg;
-{
- st_free_table(arg->symbol);
- st_free_table(arg->data);
-}
-
-static VALUE
-marshal_dump(argc, argv)
- int argc;
- VALUE argv;
-{
- VALUE obj, port, a1, a2;
- int limit = -1;
- extern VALUE cIO;
- struct dump_arg arg;
- struct dump_call_arg c_arg;
-
- port = 0;
- rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
- if (argc == 3) {
- limit = NUM2INT(a2);
- port = a1;
- }
- else if (argc == 2) {
- if (FIXNUM_P(a1)) limit = FIX2INT(a1);
- else port = a1;
- }
- if (port) {
- if (obj_is_kind_of(port, cIO)) {
- OpenFile *fptr;
-
- io_binmode(port);
- GetOpenFile(port, fptr);
- io_writable(fptr);
- arg.fp = (fptr->f2) ? fptr->f2 : fptr->f;
- }
- else {
- TypeError("instance of IO needed");
- }
- }
- else {
- arg.fp = 0;
- port = str_new(0, 0);
- arg.str = port;
- }
-
- arg.symbol = st_init_numtable();
- arg.data = st_init_numtable();
- c_arg.obj = obj;
- c_arg.arg = &arg;
- c_arg.limit = limit;
-
- w_byte(MARSHAL_MAJOR, &arg);
- w_byte(MARSHAL_MINOR, &arg);
-
- rb_ensure(dump, &c_arg, dump_ensure, &arg);
-
- return port;
-}
-
-struct load_arg {
- FILE *fp;
- UCHAR *ptr, *end;
- st_table *symbol;
- st_table *data;
-};
-
-static int
-r_byte(arg)
- struct load_arg *arg;
-{
- if (arg->fp) return getc(arg->fp);
- if (arg->ptr < arg->end) return *arg->ptr++;
- return EOF;
-}
-
-static USHORT
-r_short(arg)
- struct load_arg *arg;
-{
- USHORT x;
- int i;
-
- x = 0;
- for (i=0; i<sizeof(USHORT); i++) {
- x |= r_byte(arg)<<(i*8);
- }
-
- return x;
-}
-
-static void
-long_toobig(size)
- int size;
-{
- TypeError("long too big for this architecture (size %d, given %d)",
- sizeof(long), size);
-}
-
-static long
-r_long(arg)
- struct load_arg *arg;
-{
- int c = r_byte(arg), i;
- register long x;
-
- if (c == 0) return 0;
- if (c > 0) {
- if (c > sizeof(long)) long_toobig((int)c);
- x = 0;
- for (i=0;i<c;i++) {
- x |= (long)r_byte(arg) << (8*i);
- }
- }
- else if (c < 0) {
- c = -c;
- if (c > sizeof(long)) long_toobig((int)c);
- x = -1;
- for (i=0;i<c;i++) {
- x &= ~(0xff << (8*i));
- x |= (long)r_byte(arg) << (8*i);
- }
- }
- return x;
-}
-
-#define r_bytes(s, arg) \
- (s = (char*)r_long(arg), r_bytes0(&s,ALLOCA_N(char,(long)s),(long)s,arg))
-
-static int
-r_bytes0(sp, s, len, arg)
- char **sp, *s;
- int len;
- struct load_arg *arg;
-{
- if (arg->fp) {
- len = fread(s, 1, len, arg->fp);
- }
- else {
- if (arg->ptr + len > arg->end) {
- len = arg->end - arg->ptr;
- }
- memcpy(s, arg->ptr, len);
- arg->ptr += len;
- }
-
- (s)[len] = '\0';
- *sp = s;
-
- return len;
-}
-
-static ID
-r_symbol(arg)
- struct load_arg *arg;
-{
- char *buf;
- ID id;
- char type;
-
- if (r_byte(arg) == TYPE_SYMLINK) {
- int num = r_long(arg);
-
- if (st_lookup(arg->symbol, num, &id)) {
- return id;
- }
- TypeError("bad symbol");
- }
- r_bytes(buf, arg);
- id = rb_intern(buf);
- st_insert(arg->symbol, arg->symbol->num_entries, id);
-
- return id;
-}
-
-static char*
-r_unique(arg)
- struct load_arg *arg;
-{
- return rb_id2name(r_symbol(arg));
-}
-
-static VALUE
-r_string(arg)
- struct load_arg *arg;
-{
- char *buf;
- int len = r_bytes(buf, arg);
-
- return str_taint(str_new(buf, len));
-}
-
-static VALUE
-r_regist(v, arg)
- VALUE v;
- struct load_arg *arg;
-{
- st_insert(arg->data, arg->data->num_entries, v);
- return v;
-}
-
-static VALUE
-r_object(arg)
- struct load_arg *arg;
-{
- VALUE v;
- int type = r_byte(arg);
-
- switch (type) {
- case EOF:
- eof_error();
- return Qnil;
-
- case TYPE_LINK:
- if (st_lookup(arg->data, r_long(arg), &v)) {
- return v;
- }
- ArgError("dump format error (unlinked)");
- break;
-
- case TYPE_UCLASS:
- {
- VALUE c = rb_path2class(r_unique(arg));
- v = r_object(arg);
- if (rb_special_const_p(v)) {
- ArgError("dump format error (user class)");
- }
- RBASIC(v)->class = c;
- return v;
- }
-
- case TYPE_NIL:
- return Qnil;
-
- case TYPE_TRUE:
- return TRUE;
-
- case TYPE_FALSE:
- return FALSE;
-
- case TYPE_FIXNUM:
- {
- int i = r_long(arg);
- return INT2FIX(i);
- }
-
- case TYPE_FLOAT:
- {
-#ifndef atof
- double atof();
-#endif
- char *buf;
-
- r_bytes(buf, arg);
- v = float_new(atof(buf));
- return r_regist(v, arg);
- }
-
- case TYPE_BIGNUM:
- {
- int len;
- USHORT *digits;
-
- NEWOBJ(big, struct RBignum);
- OBJSETUP(big, cBignum, T_BIGNUM);
- big->sign = (r_byte(arg) == '+');
- big->len = len = r_long(arg);
- big->digits = digits = ALLOC_N(USHORT, len);
- while (len--) {
- *digits++ = r_short(arg);
- }
- big = RBIGNUM(big_norm((VALUE)big));
- if (TYPE(big) == T_BIGNUM) {
- r_regist(big, arg);
- }
- return (VALUE)big;
- }
-
- case TYPE_STRING:
- return r_regist(r_string(arg), arg);
-
- case TYPE_REGEXP:
- {
- char *buf;
- int len = r_bytes(buf, arg);
- int ci = r_byte(arg);
- return r_regist(reg_new(buf, len, ci), arg);
- }
-
- case TYPE_ARRAY:
- {
- volatile int len = r_long(arg);
- v = ary_new2(len);
- r_regist(v, arg);
- while (len--) {
- ary_push(v, r_object(arg));
- }
- return v;
- }
-
- case TYPE_HASH:
- {
- int len = r_long(arg);
-
- v = hash_new();
- r_regist(v, arg);
- while (len--) {
- VALUE key = r_object(arg);
- VALUE value = r_object(arg);
- hash_aset(v, key, value);
- }
- return v;
- }
-
- case TYPE_STRUCT:
- {
- VALUE class, mem, values;
- int i, len;
- int num = arg->data->num_entries;
-
- class = rb_path2class(r_unique(arg));
- mem = rb_ivar_get(class, rb_intern("__member__"));
- if (mem == Qnil) {
- Fatal("non-initialized struct");
- }
- len = r_long(arg);
-
- values = ary_new2(len);
- for (i=0; i<len; i++) {
- ary_push(values, Qnil);
- }
- v = struct_alloc(class, values);
- r_regist(v, arg);
- for (i=0; i<len; i++) {
- ID slot = r_symbol(arg);
- if (RARRAY(mem)->ptr[i] != INT2FIX(slot))
- TypeError("struct not compatible");
- struct_aset(v, INT2FIX(i), r_object(arg));
- }
- return v;
- }
- break;
-
- case TYPE_USERDEF:
- {
- VALUE class;
- int len;
-
- class = rb_path2class(r_unique(arg));
- if (rb_respond_to(class, s_load)) {
- v = rb_funcall(class, s_load, 1, r_string(arg));
- return r_regist(v, arg);
- }
- TypeError("class %s needs to have method `_load_from'",
- rb_class2name(class));
- }
- break;
-
- case TYPE_OBJECT:
- {
- VALUE class;
- int len;
-
- class = rb_path2class(r_unique(arg));
- len = r_long(arg);
- v = obj_alloc(class);
- r_regist(v, arg);
- if (len > 0) {
- while (len--) {
- ID id = r_symbol(arg);
- VALUE val = r_object(arg);
- rb_ivar_set(v, id, val);
- }
- }
- return v;
- }
- break;
-
- case TYPE_MODULE:
- {
- char *buf;
- r_bytes(buf, arg);
- return rb_path2class(buf);
- }
-
- default:
- ArgError("dump format error(0x%x)", type);
- break;
- }
-}
-
-static VALUE
-load(arg)
- struct load_arg *arg;
-{
- return r_object(arg);
-}
-
-static VALUE
-load_ensure(arg)
- struct load_arg *arg;
-{
- st_free_table(arg->symbol);
- st_free_table(arg->data);
-}
-
-static VALUE
-marshal_load(self, port)
- VALUE self, port;
-{
- FILE *fp;
- int major;
- VALUE v;
- OpenFile *fptr;
- struct load_arg arg;
-
- if (TYPE(port) == T_STRING) {
- arg.fp = 0;
- arg.ptr = RSTRING(port)->ptr;
- arg.end = arg.ptr + RSTRING(port)->len;
- }
- else {
- if (obj_is_kind_of(port, cIO)) {
- io_binmode(port);
- GetOpenFile(port, fptr);
- io_readable(fptr);
- arg.fp = fptr->f;
- }
- else {
- TypeError("instance of IO needed");
- }
- }
-
- major = r_byte(&arg);
- if (major == MARSHAL_MAJOR) {
- if (r_byte(&arg) != MARSHAL_MINOR) {
- Warning("Old marshal file format (can be read)");
- }
- arg.symbol = st_init_numtable();
- arg.data = st_init_numtable();
- v = rb_ensure(load, &arg, load_ensure, &arg);
- }
- else {
- TypeError("Old marshal file format (can't read)");
- }
-
- return v;
-}
-
-Init_marshal()
-{
- VALUE mMarshal = rb_define_module("Marshal");
-
- s_dump = rb_intern("_dump_to");
- s_load = rb_intern("_load_from");
- rb_define_module_function(mMarshal, "dump", marshal_dump, -1);
- rb_define_module_function(mMarshal, "load", marshal_load, 1);
- rb_define_module_function(mMarshal, "restore", marshal_load, 1);
-}
diff --git a/ext/marshal/marshal.doc b/ext/marshal/marshal.doc
deleted file mode 100644
index 7529e7942f..0000000000
--- a/ext/marshal/marshal.doc
+++ /dev/null
@@ -1,48 +0,0 @@
-.\" marshal.doc - -*- Indented-Text -*- created at: Tue May 16 12:18:08 JST 1995
-
-** Marshal(¥â¥¸¥å¡¼¥ë)
-
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤·¤¿¤ê¡¤ÆɤߤâÅÙ¤·¤¿¤ê¤¹¤ëµ¡Ç½¤òÄó¶¡
-¤¹¤ë¥â¥¸¥å¡¼¥ë¡¥ÂçÉôʬ¤Î¥¯¥é¥¹¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ò½ñ¤­½Ð¤¹»ö¤¬¤Ç¤­¤ë¤¬¡¤¥Õ¥¡
-¥¤¥ë¤Ø¤ÎÉÔ²Äǽ¤Ê¥¯¥é¥¹¤â¸ºß¤·(Îã:IO)¡¤¤½¤Î¤è¤¦¤Ê¥¯¥é¥¹¤ò½ñ¤­½Ð¤½¤¦¤È
-¤¹¤ë¤ÈÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥
-
-Methods:
-Single Methods:
-
- dump(obj, port[, limit])
-
- obj¤òºÆµ¢Åª¤Ë¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹¡¥¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤»¤Ê¤¤¥¯¥é¥¹¤Î¥¤
- ¥ó¥¹¥¿¥ó¥¹¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤½¤¦¤È¤¹¤ë¤ÈÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥¥Õ¥¡¥¤¥ë
- ¤Ë½ñ¤­½Ð¤»¤Ê¤¤¥¯¥é¥¹¤Ï°Ê²¼¤ÎÄ̤ꡥ
-
- Class, Module, Data
-
- ¤Þ¤¿¡¤¤³¤ì¤é¤Î¥¯¥é¥¹¤ò´ÖÀÜŪ¤Ë»Ø¤¹¥¯¥é¥¹(Î㤨¤ÐIO¤Î¥µ¥Ö¥¯¥é¥¹)¤Ê¤É
- ¤â½ñ¤­½Ð¤»¤Ê¤¤¡¥port¤ÏIO(¤Þ¤¿¤Ï¤½¤Î¥µ¥Ö¥¯¥é¥¹)¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ò»ØÄê
- ¤¹¤ë¡¥
-
- ½ÐÎϤ¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬¥á¥½¥Ã¥É`_dump_to'¤òÄêµÁ¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¡¤¥Õ¥¡
- ¥¤¥ë½ÐÎϤϤ½¤Î¥á¥½¥Ã¥É¤ò»È¤Ã¤Æ¹Ô¤ï¤ì¤ë¡¥¥á¥½¥Ã¥É`_dump_to'¤Ï°ú¿ô¤È
- ¤·¤Æ½ÐÎÏÀè¤Î¥Õ¥¡¥¤¥ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¼õ¤±¼è¤ë¡¥¥¤¥ó¥¹¥¿¥ó¥¹¤¬¥á¥½¥Ã¥É
- `_dump_to'¤ò»ý¤Ä¥¯¥é¥¹¤Ïɬ¤ºÆ±¤¸¥Õ¥©¡¼¥Þ¥Ã¥È¤òÆɤßÌ᤹Æðۥ᥽¥Ã¥É
- `_load_from'¤òÄêµÁ¤¹¤ëɬÍפ¬¤¢¤ë¡¥
-
- limit¤ò»ØÄꤷ¤¿¾ì¹ç¡¤limitÃʰʾ忼¤¯¥ê¥ó¥¯¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ò¥À¥ó¥×
- ¤Ç¤­¤Ê¤¤(¥Ç¥Õ¥©¥ë¥È¤Ï100¥ì¥Ù¥ë)¡£Éé¤Îlimit¤ò»ØÄꤹ¤ë¤È¿¼¤µ¥Á¥§¥Ã¥¯
- ¤ò¹Ô¤ï¤Ê¤¤¡£
-
- dumps(obj)
-
- dump()¤¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹¤Î¤ÈƱ¤¸ÆâÍƤò´Þ¤àʸ»úÎó¤òÊÖ¤¹¡¥
-
- load(port)
-
- port¤«¤é¥ª¥Ö¥¸¥§¥¯¥È¤òÆɤ߹þ¤ó¤ÇÍè¤Æ¡¤¸µ¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ÈƱ¤¸¾õÂÖ¤ò
- ¤â¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥port¤Ïʸ»úÎó¤«IO(¤Þ¤¿¤Ï¤½¤Î¥µ¥Ö¥¯¥é¥¹)
- ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤¢¤ë¡¥
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST
index e4f0004b4a..8057ebb06c 100644
--- a/ext/md5/MANIFEST
+++ b/ext/md5/MANIFEST
@@ -1,6 +1,7 @@
MANIFEST
depend
-md5.doc
+md5.txt
+md5.txt.jp
md5.h
md5c.c
md5init.c
diff --git a/ext/md5/depend b/ext/md5/depend
index abb2a47419..c99f78ee90 100644
--- a/ext/md5/depend
+++ b/ext/md5/depend
@@ -1,2 +1,2 @@
md5c.o: md5c.c md5.h
-md5init.o: md5init.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h md5.h
+md5init.o: md5init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h md5.h
diff --git a/ext/md5/md5.txt b/ext/md5/md5.txt
new file mode 100644
index 0000000000..0eca7c9025
--- /dev/null
+++ b/ext/md5/md5.txt
@@ -0,0 +1,38 @@
+.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
+
+** MD5(Class)
+
+A class to implement MD5 Message-Digest Algorithm by RSA Data
+Security, Inc., described in RFC1321.
+
+SuperClass: Object
+
+Class Methods:
+
+ new([str])
+ md5([str])
+
+ creates a new MD5 object. If a string argument is given, it
+ is added to the object. (see update.)
+
+Methods:
+
+ clone
+
+ copies the MD5 object.
+
+ digest
+
+ returns have value of the added strings as a 16 bytes string.
+
+ update(str)
+
+ Update the MD5 object with the string. Repeated calls are
+ equivalent to a single call with the concatenation of all the
+ arguments, i.e. m.update(a); m.update(b) is equivalent to
+ m.update(a+b).
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/ext/md5/md5.doc b/ext/md5/md5.txt.jp
index 2203404602..a1451f1175 100644
--- a/ext/md5/md5.doc
+++ b/ext/md5/md5.txt.jp
@@ -28,7 +28,8 @@ Methods:
update(str)
- key¤ò¥­¡¼¤È¤¹¤ëÃͤòÊÖ¤¹¡¥
+ MD5¥ª¥Ö¥¸¥§¥¯¥È¤Ëʸ»úÎó¤òÄɲ乤롣ʣ¿ô²óupdate¤ò¸Æ¤Ö¤³¤È¤Ïʸ
+ »úÎó¤òÏ¢·ë¤·¤Æupdate¤ò¸Æ¤Ö¤³¤È¤ÈÅù¤·¤¤¡¥
-------------------------------------------------------
Local variables:
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
index a825f96d47..552a407c6d 100644
--- a/ext/md5/md5init.c
+++ b/ext/md5/md5init.c
@@ -29,8 +29,9 @@ md5_update(obj, str)
Data_Get_Struct(obj, MD5_CTX, md5);
MD5Update(md5, str->ptr, str->len);
- return Qnil;
+ return obj;
}
+
static VALUE
md5_digest(obj)
VALUE obj;
@@ -46,10 +47,28 @@ md5_digest(obj)
}
static VALUE
+md5_hexdigest(obj)
+ VALUE obj;
+{
+ MD5_CTX *md5, ctx;
+ unsigned char digest[16];
+ char buf[33];
+ int i;
+
+ Data_Get_Struct(obj, MD5_CTX, md5);
+ ctx = *md5;
+ MD5Final(digest, &ctx);
+
+ for (i=0; i<16; i++) {
+ sprintf(buf+i*2, "%02x", digest[i]);
+ }
+ return rb_str_new(buf, 32);
+}
+
+static VALUE
md5_clone(obj)
VALUE obj;
{
- VALUE clone;
MD5_CTX *md5, *md5_new;
Data_Get_Struct(obj, MD5_CTX, md5);
@@ -65,7 +84,6 @@ md5_new(argc, argv, class)
VALUE* argv;
VALUE class;
{
- int i;
VALUE arg, obj;
MD5_CTX *md5;
@@ -77,11 +95,12 @@ md5_new(argc, argv, class)
if (!NIL_P(arg)) {
md5_update(obj, arg);
}
- rb_obj_call_init(obj);
+ rb_obj_call_init(obj, argc, argv);
return obj;
}
+void
Init_md5()
{
cMD5 = rb_define_class("MD5", rb_cObject);
@@ -90,5 +109,6 @@ Init_md5()
rb_define_method(cMD5, "update", md5_update, 1);
rb_define_method(cMD5, "digest", md5_digest, 0);
+ rb_define_method(cMD5, "hexdigest", md5_hexdigest, 0);
rb_define_method(cMD5, "clone", md5_clone, 0);
}
diff --git a/ext/nkf/MANIFEST b/ext/nkf/MANIFEST
new file mode 100644
index 0000000000..5114a3762a
--- /dev/null
+++ b/ext/nkf/MANIFEST
@@ -0,0 +1,7 @@
+MANIFEST
+depend
+extconf.rb
+lib/kconv.rb
+nkf.c
+nkf1.7/nkf.c
+test.rb
diff --git a/ext/nkf/depend b/ext/nkf/depend
new file mode 100644
index 0000000000..645bc869c8
--- /dev/null
+++ b/ext/nkf/depend
@@ -0,0 +1 @@
+nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h nkf1.7/nkf.c
diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb
new file mode 100644
index 0000000000..710662f19c
--- /dev/null
+++ b/ext/nkf/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('nkf')
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
new file mode 100644
index 0000000000..bfd276330d
--- /dev/null
+++ b/ext/nkf/lib/kconv.rb
@@ -0,0 +1,58 @@
+require 'nkf'
+
+module Kconv
+ AUTO = NKF::AUTO
+ JIS = NKF::JIS
+ EUC = NKF::EUC
+ SJIS = NKF::SJIS
+ BINARY = NKF::BINARY
+ NOCONV = NKF::NOCONV
+ UNKNOWN = NKF::UNKNOWN
+ def kconv(str, out_code, in_code = AUTO)
+ opt = '-'
+ case in_code
+ when NKF::JIS
+ opt << 'J'
+ when NKF::EUC
+ opt << 'E'
+ when NKF::SJIS
+ opt << 'S'
+ end
+
+ case out_code
+ when NKF::JIS
+ opt << 'j'
+ when NKF::EUC
+ opt << 'e'
+ when NKF::SJIS
+ opt << 's'
+ when NKF::NOCONV
+ return str
+ end
+
+ opt = '' if opt == '-'
+
+ NKF::nkf(opt, str)
+ end
+ module_function :kconv
+
+ def tojis(str)
+ NKF::nkf('-j', str)
+ end
+ module_function :tojis
+
+ def toeuc(str)
+ NKF::nkf('-e', str)
+ end
+ module_function :toeuc
+
+ def tosjis(str)
+ NKF::nkf('-s', str)
+ end
+ module_function :tosjis
+
+ def guess(str)
+ NKF::guess(str)
+ end
+ module_function :guess
+end
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
new file mode 100644
index 0000000000..35d9295a74
--- /dev/null
+++ b/ext/nkf/nkf.c
@@ -0,0 +1,206 @@
+#include "ruby.h"
+
+#define _AUTO 0
+#define _JIS 1
+#define _EUC 2
+#define _SJIS 3
+#define _BINARY 4
+#define _NOCONV 4
+#define _UNKNOWN _AUTO
+
+#undef getc
+#undef ungetc
+#define getc(f) (input_ctr>i_len?-1:input[input_ctr++])
+#define ungetc(c,f) input_ctr--
+
+#undef putchar
+#define putchar(c) rb_nkf_putchar(c)
+
+#define INCSIZE 32
+static int incsize;
+
+static unsigned char *input, *output;
+static int input_ctr, i_len;
+static int output_ctr, o_len;
+
+static VALUE dst;
+
+static int
+rb_nkf_putchar(c)
+ unsigned int c;
+{
+ if (output_ctr >= o_len) {
+ o_len += incsize;
+ rb_str_cat(dst, "", incsize);
+ incsize *= 2;
+ }
+
+ output[output_ctr++] = c;
+/*
+printf("[[%c][%c][%d]]\n", c, output[output_ctr - 1], output_ctr);
+*/
+ return c;
+}
+
+#define PERL_XS 1
+#include "nkf1.7/nkf.c"
+
+static VALUE
+rb_nkf_kconv(obj, opt, src)
+ VALUE obj, opt, src;
+{
+ int i;
+ char *opt_ptr, *opt_end;
+
+ reinit();
+ opt_ptr = str2cstr(opt, &i);
+ opt_end = opt_ptr + i;
+ for (; opt_ptr < opt_end; opt_ptr++) {
+ if (*opt_ptr != '-') {
+ continue;
+ }
+ arguments(opt_ptr);
+ }
+
+ incsize = INCSIZE;
+
+ input_ctr = 0;
+ input = str2cstr(src, &i_len);
+ dst = rb_str_new(0, i_len*3 + 10); /* large enough? */
+
+ output_ctr = 0;
+ output = RSTRING(dst)->ptr;
+ o_len = RSTRING(dst)->len;
+ *output = '\0';
+
+ if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
+ iso8859_f = FALSE;
+ }
+
+ kanji_convert(NULL);
+ if (output_ctr > 0) output_ctr--;
+ if (output[output_ctr] == '\0') {
+/*
+printf("([%c][%d])\n", output[output_ctr], output_ctr);
+*/
+ RSTRING(dst)->len = output_ctr;
+ } else {
+/*
+printf("<[%c][%d]>\n", output[output_ctr], output_ctr);
+*/
+ RSTRING(dst)->len = output_ctr + 1;
+ }
+
+ return dst;
+}
+
+/*
+ * Character code detection - Algorithm described in:
+ * Ken Lunde. `Understanding Japanese Information Processing'
+ * Sebastopol, CA: O'Reilly & Associates.
+ */
+
+static VALUE
+rb_nkf_guess(obj, src)
+ VALUE obj, src;
+{
+ unsigned char *p;
+ unsigned char *pend;
+ int plen;
+ int sequence_counter = 0;
+
+ Check_Type(src, T_STRING);
+
+ p = str2cstr(src, &plen);
+ pend = p + plen;
+
+#define INCR do {\
+ p++;\
+ if (p==pend) return INT2FIX(_UNKNOWN);\
+ sequence_counter++;\
+ if (sequence_counter % 2 == 1 && *p != 0xa4)\
+ sequence_counter = 0;\
+ if (6 <= sequence_counter) {\
+ sequence_counter = 0;\
+ return INT2FIX(_EUC);\
+ }\
+} while (0)
+
+ if (*p == 0xa4)
+ sequence_counter = 1;
+
+ while (p<pend) {
+ if (*p == '\033') {
+ return INT2FIX(_JIS);
+ }
+ if (*p < '\006' || *p == 0x7f || *p == 0xff) {
+ return INT2FIX(_BINARY);
+ }
+ if (0x81 <= *p && *p <= 0x8d) {
+ return INT2FIX(_SJIS);
+ }
+ if (0x8f <= *p && *p <= 0x9f) {
+ return INT2FIX(_SJIS);
+ }
+ if (*p == 0x8e) { /* SS2 */
+ INCR;
+ if ((0x40 <= *p && *p <= 0x7e) ||
+ (0x80 <= *p && *p <= 0xa0) ||
+ (0xe0 <= *p && *p <= 0xfc))
+ return INT2FIX(_SJIS);
+ }
+ else if (0xa1 <= *p && *p <= 0xdf) {
+ INCR;
+ if (0xf0 <= *p && *p <= 0xfe)
+ return INT2FIX(_EUC);
+ if (0xe0 <= *p && *p <= 0xef) {
+ while (p < pend && *p >= 0x40) {
+ if (*p >= 0x81) {
+ if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
+ return INT2FIX(_SJIS);
+ }
+ else if (0xfd <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ }
+ INCR;
+ }
+ }
+ else if (*p <= 0x9f) {
+ return INT2FIX(_SJIS);
+ }
+ }
+ else if (0xf0 <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ else if (0xe0 <= *p && *p <= 0xef) {
+ INCR;
+ if ((0x40 <= *p && *p <= 0x7e) ||
+ (0x80 <= *p && *p <= 0xa0)) {
+ return INT2FIX(_SJIS);
+ }
+ if (0xfd <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ }
+ INCR;
+ }
+ return INT2FIX(_UNKNOWN);
+}
+
+void
+Init_nkf()
+{
+ VALUE mKconv = rb_define_module("NKF");
+
+ rb_define_module_function(mKconv, "nkf", rb_nkf_kconv, 2);
+ rb_define_module_function(mKconv, "guess", rb_nkf_guess, 1);
+
+ rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
+ rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
+ rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
+ rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
+ rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
+ rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
+ rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
+}
diff --git a/ext/kconv/kconv.c b/ext/nkf/nkf1.7/nkf.c
index a3349826f1..26ef657021 100644
--- a/ext/kconv/kconv.c
+++ b/ext/nkf/nkf1.7/nkf.c
@@ -1,39 +1,31 @@
/** Network Kanji Filter. (PDS Version)
************************************************************************
** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-** Ï¢ÍíÀ衧 ¡Ê³ô¡ËÉÙ»ÎÄ̸¦µæ½ê¡¡¥½¥Õ¥È£³¸¦¡¡»ÔÀî¡¡»ê
-** ¡ÊE-Mail Address: ichikawa@flab.fujitsu.co.jp¡Ë
-** Copyright (C) 1996
-** Ï¢ÍíÀ衧 ΰµåÂç³Ø¾ðÊó¹©³Ø²Ê ²ÏÌî ¿¿¼£ mine/X0208 support
-** ¡ÊE-Mail Address: kono@ie.u-ryukyu.ac.jp¡Ë
-** Ï¢ÍíÀ衧 COW for DOS & Win16 & Win32 & OS/2
-** ¡ÊE-Mail Address: GHG00637@niftyserve.or.jp¡Ë
-** ±ÄÍø¤òÌÜŪ¤È¤·¤Ê¤¤¸Â¤ê¡¢¤³¤Î¥½¡¼¥¹¤Î¤¤¤«¤Ê¤ë
-** Ê£¼Ì¡¤²þÊÑ¡¤½¤Àµ¤âµöÂú¤·¤Þ¤¹¡£¤½¤ÎºÝ¤Ë¤Ï¡¢¤³¤ÎÉôʬ¤ò»Ä¤¹¤³¤È¡£
-** ¤³¤Î¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤Æ¤ÏÆä˲¿¤ÎÊݾڤ⤷¤Ê¤¤¡¢°­¤·¤«¤é¤º¡£
+** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B
+** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
+** Copyright (C) 1996,1998
+** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B mine/X0208 support
+** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
+** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
+** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
+** $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
+** $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
+** $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
+** $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
** Everyone is permitted to do anything on this program
-** including copying, modifying, improving
-** as long as you don't try to make money off it,
-** or pretend that you wrote it.
+** including copying, modifying, improving.
+** as long as you don't try to pretend that you wrote it.
** i.e., the above copyright notice has to appear in all copies.
+** You don't have to ask before copying or publishing.
** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
***********************************************************************/
-/***********************************************************************
-** 1996/03/10 modified for Kconv - by Ikuo Nakagawa
-***********************************************************************/
-/***********************************************************************
-** 1996/12/18 modified for kconv(ruby) - by matz@ruby.club.or.jp
-***********************************************************************/
-
static char *CopyRight =
- "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW";
+ "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1998 S. Kono, COW";
static char *Version =
- "1.62";
+ "1.7";
static char *Patchlevel =
- "5/9612/Shinji Kono, COW matz";
-
-#include "ruby.h"
+ "0/9711/Shinji Kono";
/*
**
@@ -76,27 +68,20 @@ static char *Patchlevel =
** c Add \r in line feed
**/
/******************************/
-/* ¥Ç¥Õ¥©¥ë¥È¤Î½ÐÎÏ¥³¡¼¥ÉÁªÂò */
+/* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
/* Select DEFAULT_CODE */
-#define DEFAULT_CODE_JIS
+#define DEFAULT_CODE_JIS
/* #define DEFAULT_CODE_SJIS */
/* #define DEFAULT_CODE_EUC */
/******************************/
-/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */
-#define _AUTO 0
-#define _JIS 1
-#define _EUC 2
-#define _SJIS 3
-#define _BINARY 4
-#define _NOCONV 4
-#define _UNKNOWN _AUTO
-
#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
#define MSDOS
#endif
+#ifndef PERL_XS
#include <stdio.h>
+#endif
#if defined(MSDOS) || defined(__OS2__)
#include <stdlib.h>
@@ -126,10 +111,8 @@ static char *Patchlevel =
#include <windows.h>
#endif
-#ifndef FALSE
#define FALSE 0
#define TRUE 1
-#endif
/* state of output_mode and input_mode */
@@ -145,7 +128,7 @@ static char *Patchlevel =
#define NL 0x0a
#define ESC 0x1b
-#define SP 0x20
+#define SPACE 0x20
#define AT 0x40
#define SSP 0xa0
#define DEL 0x7f
@@ -165,25 +148,55 @@ static char *Patchlevel =
/* MIME preprocessor */
-#define _GETC() (*inptr ? (int)(*inptr++) : EOF)
-#define _UNGETC(c) (*--inptr = (c))
-#define PUTCHAR(c) (outlen + 1 < outsiz ? \
- ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF)
-#define GETC() ((!mime_mode)?_GETC():mime_getc())
-#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c))
+#undef STRICT_MIME /* do stupid strict mime integrity check */
+#define GETC(p) ((!mime_mode)?getc(p):mime_getc(p))
+#define UNGETC(c,p) ((!mime_mode)?ungetc(c,p):mime_ungetc(c))
+
#ifdef EASYWIN /*Easy Win */
extern POINT _BufferSize;
#endif
+/* function prototype */
+
+#ifndef _
+# ifdef __STDC__
+# define _(args) args
+# else
+# define _(args) ()
+# endif
+#endif
+
+#ifndef PERL_XS
+static void noconvert _((FILE *f));
+static int mime_integrity _((FILE *f,unsigned char *p));
+static int usage _((void));
+static char stdibuf[IOBUF_SIZE];
+static char stdobuf[IOBUF_SIZE];
+static unsigned int mime_input = 0; /* undecoded */
+static int end_check;
+#endif
+
+static void kanji_convert _((FILE *f));
+static void h_conv _((FILE *f,int c2,int c1));
+static int push_hold_buf _((int c2,int c1));
+static void s_iconv _((int c2,int c1));
+static void e_oconv _((int c2,int c1));
+static void s_oconv _((int c2,int c1));
+static void j_oconv _((int c2,int c1));
+static int line_fold _((int c2,int c1));
+static int pre_convert _((int c1,int c2));
+static int mime_begin _((FILE *f));
+static int mime_getc _((FILE *f));
+static int mime_ungetc _((unsigned int c));
+static int base64decode _((int c));
+static void arguments _((char *c));
+static void reinit _((void));
+
/* buffers */
static unsigned char hold_buf[HOLD_SIZE*2];
static int hold_count;
-static unsigned char *inptr;
-static char *outptr;
-static int outsiz;
-static int outlen;
/* MIME preprocessor fifo */
@@ -193,15 +206,16 @@ static int outlen;
static unsigned char mime_buf[MIME_BUF_SIZE];
static unsigned int mime_top = 0;
static unsigned int mime_last = 0; /* decoded */
-static unsigned int mime_input = 0; /* undecoded */
/* flags */
static int unbuf_f = FALSE;
static int estab_f = FALSE;
+static int nop_f = FALSE;
+static int binmode_f = TRUE; /* binary mode */
static int rot_f = FALSE; /* rot14/43 mode */
static int input_f = FALSE; /* non fixed input code */
static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
-static int mime_f = FALSE; /* convert MIME B base64 or Q */
+static int mime_f = TRUE; /* convert MIME B base64 or Q */
static int mimebuf_f = FALSE; /* MIME buffered input */
static int broken_f = FALSE; /* convert ESC-less broken JIS */
static int iso8859_f = FALSE; /* ISO8859 through */
@@ -218,30 +232,47 @@ static int c1_return;
/* fold parameter */
static int line = 0; /* chars in line */
static int prev = 0;
-static int fold_f = FALSE;
-static int fold_len = 0;
+static int fold_f = FALSE;
+static int fold_len = 0;
/* options */
-static char kanji_intro = DEFAULT_J,
+static char kanji_intro = DEFAULT_J,
ascii_intro = DEFAULT_R;
/* Folding */
+int line_fold();
#define FOLD_MARGIN 10
#define DEFAULT_FOLD 60
+/* converters */
+
+#ifdef DEFAULT_CODE_JIS
+# define DEFAULT_CONV j_oconv
+#endif
+#ifdef DEFAULT_CODE_SJIS
+# define DEFAULT_CONV s_oconv
+#endif
+#ifdef DEFAULT_CODE_EUC
+# define DEFAULT_CONV e_oconv
+#endif
+
+static void (*iconv) _((int c2,int c1));
+ /* s_iconv or oconv */
+static void (*oconv) _((int c2,int c1)) = DEFAULT_CONV;
+ /* [ejs]_oconv */
+
/* Global states */
-static int output_mode = ASCII, /* output kanji mode */
+static int output_mode = ASCII, /* output kanji mode */
input_mode = ASCII, /* input kanji mode */
shift_mode = FALSE; /* TRUE shift out, or X0201 */
-static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
+static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
-/* X0208 -> ASCII translation table */
/* X0201 / X0208 conversion tables */
/* X0201 kana conversion table */
/* 90-9F A0-DF */
-static unsigned char cv[]= {
+unsigned char cv[]= {
0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
@@ -263,7 +294,7 @@ static unsigned char cv[]= {
/* X0201 kana conversion table for daguten */
/* 90-9F A0-DF */
-static unsigned char dv[]= {
+unsigned char dv[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -284,7 +315,7 @@ static unsigned char dv[]= {
/* X0201 kana conversion table for han-daguten */
/* 90-9F A0-DF */
-static unsigned char ev[]= {
+unsigned char ev[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -306,7 +337,8 @@ static unsigned char ev[]= {
/* X0208 kigou conversion table */
/* 0x8140 - 0x819e */
-static unsigned char fv[] = {
+unsigned char fv[] = {
+
0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
@@ -322,179 +354,26 @@ static unsigned char fv[] = {
} ;
-/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
-
-static unsigned char *mime_pattern[] = {
- (unsigned char *)"\075?ISO-8859-1?Q?",
- (unsigned char *)"\075?ISO-2022-JP?B?",
- (unsigned char *)"\075?ISO-2022-JP?Q?",
- NULL
-};
+static int file_out = FALSE;
+static int add_cr = FALSE;
+static int del_cr = FALSE;
-static int mime_encode[] = {
- 'Q', 'B', 'Q',
- 0
-};
-
-static int add_cr = FALSE;
-static int del_cr = FALSE;
-
-static void (*iconv) _((register int c2,register int c1)); /* s_iconv or oconv */
-static void (*oconv) _((register int c2,register int c1)); /* [ejs]_oconv */
-static int do_kconv _((char *i, char *o, int siz, int out_code, int in_code));
-static void h_conv _((register int c2,register int c1));
-static int push_hold_buf _((int c2,int c1));
-static void s_iconv _((register int c2,register int c1));
-static void e_oconv _((register int c2,register int c1));
-static void s_oconv _((register int c2,register int c1));
-static void j_oconv _((register int c2,register int c1));
-static int fold _((register int c2,register int c1));
-static int pre_convert _((register int c1,register int c2));
-static int mime_begin _((void));
-static int mime_getc _((void));
-static int mime_ungetc _((unsigned int c));
-static int mime_integrity _((unsigned char *p));
-static int base64decode _((int c));
-
-#ifdef notdef
-main (argc, argv)
+#ifndef PERL_XS
+int
+main(argc, argv)
int argc;
char **argv;
{
- register FILE *fin;
- register char *cp;
+ FILE *fin;
+ char *cp;
#ifdef EASYWIN /*Easy Win */
_BufferSize.y = 400;/*Set Scroll Buffer Size*/
#endif
-#ifdef DEFAULT_CODE_JIS
- oconv = j_oconv; /* DEFAULT Code is JIS */
-#endif
-#ifdef DEFAULT_CODE_SJIS
- oconv = s_oconv; /* DEFAULT Code is S-JIS */
-#endif
-#ifdef DEFAULT_CODE_EUC
- oconv = e_oconv; /* DEFAULT Code is EUC */
-#endif
for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
cp = *argv;
- while (*cp) {
- switch (*cp++) {
- case 'b': /* buffered mode */
- unbuf_f = FALSE;
- continue;
- case 'u': /* non bufferd mode */
- unbuf_f = TRUE;
- continue;
- case 'j': /* JIS output */
- case 'n':
- oconv = j_oconv;
- continue;
- case 'e': /* AT&T EUC output */
- oconv = e_oconv;
- continue;
- case 's': /* SJIS output */
- oconv = s_oconv;
- continue;
- case 'l': /* ISO8859 Latin-1 support, no conversion */
- iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
- input_f = LATIN1_INPUT;
- continue;
- case 'i': /* Kanji IN ESC-$-@/B */
- if(*cp=='@'||*cp=='B')
- kanji_intro = *cp++;
- continue;
- case 'o': /* ASCII IN ESC-(-J/B */
- if(*cp=='J'||*cp=='B'||*cp=='H')
- ascii_intro = *cp++;
- continue;
- case 'r':
- rot_f = TRUE;
- continue;
-#if defined(MSDOS) || defined(__OS2__)
- case 'T':
- binmode_f = FALSE;
- continue;
-#endif
- case 'v':
- usage();
- exit(1);
- break;
- /* Input code assumption */
- case 'J': /* JIS input */
- case 'E': /* AT&T EUC input */
- input_f = JIS_INPUT;
- continue;
- case 'S': /* MS Kanji input */
- input_f = SJIS_INPUT;
- if(x0201_f==NO_X0201) x0201_f=TRUE;
- continue;
- case 'Z': /* Convert X0208 alphabet to asii */
- /* bit:0 Convert X0208
- bit:1 Convert Kankaku to one space
- bit:2 Convert Kankaku to two spaces
- */
- if('9'>= *cp && *cp>='0')
- alpha_f |= 1<<(*cp++ -'0');
- else
- alpha_f |= TRUE;
- continue;
- case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
- x0201_f = FALSE; /* No X0201->X0208 conversion */
- /* accept X0201
- ESC-(-I in JIS, EUC, MS Kanji
- SI/SO in JIS, EUC, MS Kanji
- SSO in EUC, JIS, not in MS Kanji
- MS Kanji (0xa0-0xdf)
- output X0201
- ESC-(-I in JIS (0x20-0x5f)
- SSO in EUC (0xa0-0xdf)
- 0xa0-0xd in MS Kanji (0xa0-0xdf)
- */
- continue;
- case 'X': /* Assume X0201 kana */
- /* Default value is NO_X0201 for EUC/MS-Kanji mix */
- x0201_f = TRUE;
- continue;
- case 'f': /* folding -f60 or -f */
- fold_f = TRUE;
- fold_len = atoi(cp);
- if(!(0<fold_len && fold_len<BUFSIZ))
- fold_len = DEFAULT_FOLD;
- while('0'<= *cp && *cp <='9') cp++;
- continue;
- case 'm': /* MIME support */
- mime_f = TRUE;
- if(*cp=='B'||*cp=='Q') {
- mime_mode = *cp++;
- mimebuf_f = FIXED_MIME;
- }
- continue;
- case 'B': /* Broken JIS support */
- /* bit:0 no ESC JIS
- bit:1 allow any x on ESC-(-x or ESC-$-x
- bit:2 reset to ascii on NL
- */
- if('9'>= *cp && *cp>='0')
- broken_f |= 1<<(*cp++ -'0');
- else
- broken_f |= TRUE;
- continue;
- case 'O':/* for Output file */
- file_out = TRUE;
- continue;
- case 'c':/* add cr code */
- add_cr = TRUE;
- continue;
- case 'd':/* delete cr code */
- del_cr = TRUE;
- continue;
- default:
- /* bogus option but ignored */
- continue;
- }
- }
+ arguments(cp);
}
if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
@@ -511,9 +390,9 @@ main (argc, argv)
#endif
if(unbuf_f)
- setbuf (stdout, (char *) NULL);
+ setbuf(stdout, (char *) NULL);
else
- setvbuffer (stdout, stdobuf, IOBUF_SIZE);
+ setvbuffer(stdout, stdobuf, IOBUF_SIZE);
if(argc == 0) {
if(binmode_f == TRUE)
@@ -522,25 +401,28 @@ main (argc, argv)
#else
setbinmode(stdin);
#endif
- setvbuffer (stdin, stdibuf, IOBUF_SIZE);
- convert (stdin);
+ setvbuffer(stdin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert(stdin);
+ else
+ kanji_convert(stdin);
} else {
while (argc--) {
- if((fin = fopen (*argv++, "r")) == NULL) {
- perror (*--argv);
- return (-1);
+ if((fin = fopen(*argv++, "r")) == NULL) {
+ perror(*--argv);
+ return(-1);
} else {
/* reopen file for stdout */
if(file_out == TRUE){
if(argc == 1 ) {
if(freopen(*argv++, "w", stdout) == NULL) {
- perror (*--argv);
+ perror(*--argv);
return (-1);
}
argc--;
} else {
if(freopen("nkf.out", "w", stdout) == NULL) {
- perror (*--argv);
+ perror(*--argv);
return (-1);
}
}
@@ -560,9 +442,12 @@ main (argc, argv)
#else
setbinmode(fin);
#endif
- setvbuffer (fin, stdibuf, IOBUF_SIZE);
- convert (fin);
- fclose (fin);
+ setvbuffer(fin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert(fin);
+ else
+ kanji_convert(fin);
+ fclose(fin);
}
}
}
@@ -577,60 +462,162 @@ main (argc, argv)
#endif
return (0);
}
-#endif /* notdef */
+#endif
-static int
-do_kconv(i, o, siz, out_code, in_code)
- char *i;
- char *o;
- int siz, out_code, in_code;
+static void
+arguments(cp)
+ char *cp;
{
- register int c1,
- c2;
+ while (*cp) {
+ switch (*cp++) {
+ case 'b': /* buffered mode */
+ unbuf_f = FALSE;
+ continue;
+ case 'u': /* non bufferd mode */
+ unbuf_f = TRUE;
+ continue;
+ case 't': /* transparent mode */
+ nop_f = TRUE;
+ continue;
+ case 'j': /* JIS output */
+ case 'n':
+ oconv = j_oconv;
+ continue;
+ case 'e': /* AT&T EUC output */
+ oconv = e_oconv;
+ continue;
+ case 's': /* SJIS output */
+ oconv = s_oconv;
+ continue;
+ case 'l': /* ISO8859 Latin-1 support, no conversion */
+ iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
+ input_f = LATIN1_INPUT;
+ continue;
+ case 'i': /* Kanji IN ESC-$-@/B */
+ if(*cp=='@'||*cp=='B')
+ kanji_intro = *cp++;
+ continue;
+ case 'o': /* ASCII IN ESC-(-J/B */
+ if(*cp=='J'||*cp=='B'||*cp=='H')
+ ascii_intro = *cp++;
+ continue;
+ case 'r':
+ rot_f = TRUE;
+ continue;
+#if defined(MSDOS) || defined(__OS2__)
+ case 'T':
+ binmode_f = FALSE;
+ continue;
+#endif
+#ifndef PERL_XS
+ case 'v':
+ usage();
+ exit(1);
+ break;
+#endif
+ /* Input code assumption */
+ case 'J': /* JIS input */
+ case 'E': /* AT&T EUC input */
+ input_f = JIS_INPUT;
+ continue;
+ case 'S': /* MS Kanji input */
+ input_f = SJIS_INPUT;
+ if(x0201_f==NO_X0201) x0201_f=TRUE;
+ continue;
+ case 'Z': /* Convert X0208 alphabet to asii */
+ /* bit:0 Convert X0208
+ bit:1 Convert Kankaku to one space
+ bit:2 Convert Kankaku to two spaces
+ */
+ if('9'>= *cp && *cp>='0')
+ alpha_f |= 1<<(*cp++ -'0');
+ else
+ alpha_f |= TRUE;
+ continue;
+ case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
+ x0201_f = FALSE; /* No X0201->X0208 conversion */
+ /* accept X0201
+ ESC-(-I in JIS, EUC, MS Kanji
+ SI/SO in JIS, EUC, MS Kanji
+ SSO in EUC, JIS, not in MS Kanji
+ MS Kanji (0xa0-0xdf)
+ output X0201
+ ESC-(-I in JIS (0x20-0x5f)
+ SSO in EUC (0xa0-0xdf)
+ 0xa0-0xd in MS Kanji (0xa0-0xdf)
+ */
+ continue;
+ case 'X': /* Assume X0201 kana */
+ /* Default value is NO_X0201 for EUC/MS-Kanji mix */
+ x0201_f = TRUE;
+ continue;
+ case 'f': /* folding -f60 or -f */
+ fold_f = TRUE;
+ fold_len = atoi(cp);
+ if(!(0<fold_len && fold_len<BUFSIZ))
+ fold_len = DEFAULT_FOLD;
+ while('0'<= *cp && *cp <='9') cp++;
+ continue;
+ case 'm': /* MIME support */
+ mime_f = TRUE;
+ if(*cp=='B'||*cp=='Q') {
+ mime_mode = *cp++;
+ mimebuf_f = FIXED_MIME;
+ } else if (*cp=='0') {
+ mime_f = FALSE;
+ }
+ continue;
+ case 'M': /* MIME output */
+ oconv = j_oconv; /* sorry... not yet done.. */
+ continue;
+ case 'B': /* Broken JIS support */
+ /* bit:0 no ESC JIS
+ bit:1 allow any x on ESC-(-x or ESC-$-x
+ bit:2 reset to ascii on NL
+ */
+ if('9'>= *cp && *cp>='0')
+ broken_f |= 1<<(*cp++ -'0');
+ else
+ broken_f |= TRUE;
+ continue;
+#ifndef PERL_XS
+ case 'O':/* for Output file */
+ file_out = TRUE;
+ continue;
+#endif
+ case 'c':/* add cr code */
+ add_cr = TRUE;
+ continue;
+ case 'd':/* delete cr code */
+ del_cr = TRUE;
+ continue;
+ default:
+ /* bogus option but ignored */
+ continue;
+ }
+ }
+}
- c2 = 0;
+#ifndef PERL_XS
+static void
+noconvert(f)
+ FILE *f;
+{
+ int c;
- if (siz <= 0) {
- return 0;
- }
- *o = '\0';
-
- inptr = (unsigned char *)i; /* input buffer */
- outptr = o; /* output buffer */
- outsiz = siz; /* output buffer size */
- outlen = 0; /* current length of output string */
- x0201_f = TRUE; /* don't assume JISX0201 kana */
- rot_f = FALSE; /* rot14/43 mode */
- input_f = FALSE; /* non fixed input code */
- alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */
- mime_f = TRUE; /* convert MIME base64 */
- broken_f = FALSE; /* convert ESC-less broken JIS */
-
- switch (out_code) {
- case _SJIS:
- oconv = s_oconv;
- break;
- case _EUC:
- oconv = e_oconv;
- break;
- default:
- oconv = j_oconv;
- break;
- }
+ while ((c = getc(f)) != EOF)
+ putchar(c);
+}
+#endif
- switch (in_code) {
- case _SJIS:
- input_f = SJIS_INPUT;
- x0201_f = TRUE;
- break;
- case _EUC:
- case _JIS:
- input_f = JIS_INPUT;
- break;
- default:
- input_f = FALSE;
- break;
- }
+
+static void
+kanji_convert(f)
+ FILE *f;
+{
+ int c1, c2;
+
+ c2 = 0;
if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
estab_f = TRUE; iconv = oconv;
@@ -642,23 +629,12 @@ do_kconv(i, o, siz, out_code, in_code)
input_mode = ASCII;
output_mode = ASCII;
shift_mode = FALSE;
- mime_mode = FALSE;
#define NEXT continue /* no output, get next */
#define SEND ; /* output c1 and c2, get next */
#define LAST break /* end of loop, go closing */
- while ((c1 = GETC()) != EOF) {
- if(!c2 && !input_mode && c1<DEL && !mime_mode && !output_mode
- && !shift_mode && !fold_f && !rot_f) {
- /* plain ASCII tight loop, no conversion and no fold */
- while(c1!='=' && c1!=SO && c1!=EOF &&
- c1!=ESC && c1!='$' && c1<DEL && c1!='\r' && c1!='\n') {
- PUTCHAR(c1);
- c1 = _GETC();
- }
- if(c1==EOF) LAST;
- }
+ while ((c1 = GETC(f)) != EOF) {
if(c2) {
/* second byte */
if(c2 > DEL) {
@@ -667,7 +643,7 @@ do_kconv(i, o, siz, out_code, in_code)
/* in case of not established yet */
if(c1 > SSP) {
/* It is still ambiguious */
- h_conv (c2, c1);
+ h_conv(f, c2, c1);
c2 = 0;
NEXT;
} else if(c1 < AT) {
@@ -692,7 +668,7 @@ do_kconv(i, o, siz, out_code, in_code)
} else
/* 7 bit code */
/* it might be kanji shitfted */
- if((c1 == DEL) || (c1 <= SP)) {
+ if((c1 == DEL) || (c1 <= SPACE)) {
/* ignore bogus first code */
c2 = 0;
NEXT;
@@ -731,20 +707,20 @@ do_kconv(i, o, siz, out_code, in_code)
if(x0201_f) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
/* look ahead for X0201/X0208conversion */
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
- } else if(c2==(0xde)) { /* ÂùÅÀ */
+ } else if(c2==(0xde)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
}
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
}
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
@@ -758,29 +734,29 @@ do_kconv(i, o, siz, out_code, in_code)
c2 = 0;
NEXT;
} */
- c1 = GETC(); /* skip SSO */
+ c1 = GETC(f); /* skip SSO */
euc_1byte_check:
if(x0201_f && SSP<=c1 && c1<0xe0) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
}
- /* forward lookup ÂùÅÀ/ȾÂùÅÀ */
+ /* forward lookup $BByE@(B/$BH>ByE@(B */
if(c2 != SSO) {
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
- } else if((c2 = GETC()) == EOF) {
+ } else if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
(*oconv)(0,SSO);
LAST;
- } else if(c2==(0xde)) { /* ÂùÅÀ */
+ } else if(c2==(0xde)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
@@ -807,7 +783,7 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
}
}
- } else if((c1 > SP) && (c1 != DEL)) {
+ } else if((c1 > SPACE) && (c1 != DEL)) {
/* in case of Roman characters */
if(shift_mode) {
c1 |= 0x80;
@@ -815,20 +791,20 @@ do_kconv(i, o, siz, out_code, in_code)
if(x0201_f && (!iso8859_f||input_mode==X0201) &&
SSP<=c1 && c1<0xe0 ) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
- } else if(c2==(0xde&0x7f)) { /* ÂùÅÀ */
+ } else if(c2==(0xde&0x7f)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
}
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
}
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
@@ -837,15 +813,15 @@ do_kconv(i, o, siz, out_code, in_code)
} else if(c1 == '(' && broken_f && input_mode == X0208
&& !mime_mode ) {
/* Try to recover missing escape */
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, '(');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, '(');
LAST;
} else {
if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
input_mode = ASCII; shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, '(');
+ (*oconv)(0, '(');
/* do not modify various input_mode */
/* It can be vt100 sequence */
SEND;
@@ -857,24 +833,24 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
/* goto next_byte */
} else if(c1 == '=' && mime_f && !mime_mode ) {
- if((c1 = _GETC()) == EOF) {
- (*oconv) (0, '=');
+ if((c1 = getc(f)) == EOF) {
+ (*oconv)(0, '=');
LAST;
} else if(c1 == '?') {
- /* =? is mime conversion start sequence */
- if(mime_begin() == EOF) /* check in detail */
+ /* =? is mime conversiooon start sequence */
+ if(mime_begin(f) == EOF) /* check in detail */
LAST;
else
NEXT;
} else {
- (*oconv) (0, '=');
- _UNGETC(c1);
+ (*oconv)(0, '=');
+ ungetc(c1,f);
NEXT;
}
} else if(c1 == '$' && broken_f && !mime_mode) {
/* try to recover missing escape */
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, '$');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, '$');
LAST;
} else if(c1 == '@'|| c1 == 'B') {
/* in case of Kanji in ESC sequence */
@@ -883,8 +859,8 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
} else {
/* sorry */
- (*oconv) (0, '$');
- (*oconv) (0, c1);
+ (*oconv)(0, '$');
+ (*oconv)(0, c1);
NEXT;
}
} else
@@ -896,33 +872,51 @@ do_kconv(i, o, siz, out_code, in_code)
shift_mode = TRUE;
NEXT;
} else if(c1 == ESC ) {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
LAST;
} else if(c1 == '$') {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
- (*oconv) (0, '$');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
LAST;
} else if(c1 == '@'|| c1 == 'B') {
/* This is kanji introduction */
input_mode = X0208;
shift_mode = FALSE;
NEXT;
+ } else if(c1 == '(') {
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ LAST;
+ } else if(c1 == '@'|| c1 == 'B') {
+ /* This is kanji introduction */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ (*oconv)(0, c1);
+ NEXT;
+ }
} else if(broken_f&0x2) {
input_mode = X0208;
shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, ESC);
- (*oconv) (0, '$');
- (*oconv) (0, c1);
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, c1);
NEXT;
}
} else if(c1 == '(') {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
- (*oconv) (0, '(');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '(');
LAST;
} else {
if(c1 == 'I') {
@@ -937,15 +931,15 @@ do_kconv(i, o, siz, out_code, in_code)
input_mode = ASCII; shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, ESC);
- (*oconv) (0, '(');
+ (*oconv)(0, ESC);
+ (*oconv)(0, '(');
/* maintain various input_mode here */
SEND;
}
}
} else {
/* lonely ESC */
- (*oconv) (0, ESC);
+ (*oconv)(0, ESC);
SEND;
}
} else if(c1 == NL && broken_f&4) {
@@ -956,26 +950,27 @@ do_kconv(i, o, siz, out_code, in_code)
}
/* send: */
if(input_mode == X0208)
- (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */
+ (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
else
- (*iconv) (c2, c1); /* can be EUC/SJIS */
+ (*iconv)(c2, c1); /* can be EUC/SJIS */
c2 = 0;
continue;
/* goto next_word */
}
/* epilogue */
- (*iconv) (EOF, 0);
- return outlen;
+ (*iconv)(EOF, 0);
}
+
+
static void
-h_conv (c2, c1)
- register int c1,
- c2;
+h_conv(f, c2, c1)
+ FILE *f;
+ int c1, c2;
{
- register int wc;
+ int wc;
/** it must NOT be in the kanji shifte sequence */
@@ -983,10 +978,10 @@ h_conv (c2, c1)
/** and it must be after 2 byte 8bit code */
hold_count = 0;
- push_hold_buf (c2, c1);
+ push_hold_buf(c2, c1);
c2 = 0;
- while ((c1 = GETC()) != EOF) {
+ while ((c1 = GETC(f)) != EOF) {
if(c2) {
/* second byte */
if(!estab_f) {
@@ -1029,7 +1024,7 @@ h_conv (c2, c1)
SEND;
}
/* send: */
- if((push_hold_buf (c2, c1) == EOF) || estab_f)
+ if((push_hold_buf(c2, c1) == EOF) || estab_f)
break;
c2 = 0;
continue;
@@ -1047,7 +1042,7 @@ h_conv (c2, c1)
for (wc = 0; wc < hold_count; wc += 2) {
c2 = hold_buf[wc];
c1 = hold_buf[wc+1];
- (*iconv) (c2, c1);
+ (*iconv)(c2, c1);
}
return;
}
@@ -1055,9 +1050,8 @@ h_conv (c2, c1)
static int
-push_hold_buf (c2, c1)
- int c2,
- c1;
+push_hold_buf(c2, c1)
+ int c2, c1;
{
if(hold_count >= HOLD_SIZE*2)
return (EOF);
@@ -1068,8 +1062,8 @@ push_hold_buf (c2, c1)
static void
-s_iconv (c2, c1)
- register int c2,
+s_iconv(c2, c1)
+ int c2,
c1;
{
if((c2 == EOF) || (c2 == 0)) {
@@ -1077,30 +1071,29 @@ s_iconv (c2, c1)
} else {
c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
if(c1 < 0x9f)
- c1 = c1 - ((c1 > DEL) ? SP : 0x1f);
+ c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
else {
c1 = c1 - 0x7e;
c2++;
}
}
- (*oconv) (c2, c1);
+ (*oconv)(c2, c1);
}
static void
-e_oconv (c2, c1)
- register int c2,
- c1;
+e_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
break;
case 0: return;
case '\r':
@@ -1113,46 +1106,46 @@ e_oconv (c2, c1)
}
}
if(c2==DOUBLE_SPACE) {
- PUTCHAR(' '); PUTCHAR(' ');
+ putchar(' '); putchar(' ');
return;
}
if(c2 == EOF)
return;
else if(c2 == 0 && (c1&0x80)) {
- PUTCHAR(SSO); PUTCHAR(c1);
+ putchar(SSO); putchar(c1);
} else if(c2 == 0) {
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if((c1<0x20 || 0x7e<c1) ||
(c2<0x20 || 0x7e<c2)) {
estab_f = FALSE;
return; /* too late to rescue this char */
}
- PUTCHAR(c2 | 0x080);
- PUTCHAR(c1 | 0x080);
+ putchar(c2 | 0x080);
+ putchar(c1 | 0x080);
}
+ return;
}
static void
-s_oconv (c2, c1)
- register int c2,
- c1;
+s_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
break;
case '\r':
c1 = '\n'; c2 = 0;
@@ -1165,48 +1158,49 @@ s_oconv (c2, c1)
}
}
if(c2==DOUBLE_SPACE) {
- PUTCHAR(' '); PUTCHAR(' ');
+ putchar(' '); putchar(' ');
return;
}
if(c2 == EOF)
return;
else if(c2 == 0) {
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if((c1<0x20 || 0x7e<c1) ||
(c2<0x20 || 0x7e<c2)) {
estab_f = FALSE;
return; /* too late to rescue this char */
}
- PUTCHAR((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
- PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
+ putchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
+ putchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
}
+ return;
}
+
static void
-j_oconv (c2, c1)
- register int c2,
- c1;
+j_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
}
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
output_mode = ASCII;
break;
case '\r':
@@ -1221,16 +1215,16 @@ j_oconv (c2, c1)
}
if(c2 == EOF) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
}
} else if(c2 == 0 && (c1 & 0x80)) {
if(input_mode==X0201 || !iso8859_f) {
if(output_mode!=X0201) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR('I');
+ putchar(ESC);
+ putchar('(');
+ putchar('I');
output_mode = X0201;
}
c1 &= 0x7f;
@@ -1239,56 +1233,58 @@ j_oconv (c2, c1)
/* Can we convert in 7bit form using ESC-'-'-A ?
Is this popular? */
}
- PUTCHAR(c1);
+ putchar(c1);
} else if(c2 == 0) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
output_mode = ASCII;
}
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else if(c2 == DOUBLE_SPACE) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
output_mode = ASCII;
}
- PUTCHAR(' ');
+ putchar(' ');
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if(output_mode != X0208) {
- PUTCHAR(ESC);
- PUTCHAR('$');
- PUTCHAR(kanji_intro);
+ putchar(ESC);
+ putchar('$');
+ putchar(kanji_intro);
output_mode = X0208;
}
if(c1<0x20 || 0x7e<c1)
return;
if(c2<0x20 || 0x7e<c2)
return;
- PUTCHAR(c2);
+ putchar(c2);
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
}
+ return;
}
+
#define rot13(c) ( \
( c < 'A' ) ? c: \
(c <= 'M') ? (c + 13): \
@@ -1306,8 +1302,9 @@ j_oconv (c2, c1)
c \
)
+
/*
- Return value of fold()
+ Return value of line_fold()
\n add newline and output char
\r add newline and output nothing
@@ -1327,8 +1324,8 @@ j_oconv (c2, c1)
*/
static int
-fold(c2,c1)
-register int c2,c1;
+line_fold(c2,c1)
+int c2,c1;
{
int prev0;
if(c1=='\r')
@@ -1403,11 +1400,11 @@ register int c2,c1;
}
/* simple kinsoku rules return 1 means no folding */
if(c2==0) {
- if(c1==0xde) return 1; /* ¡«*/
- if(c1==0xdf) return 1; /* ¡¬*/
- if(c1==0xa4) return 1; /* ¡£*/
- if(c1==0xa3) return 1; /* ¡¤*/
- if(c1==0xa1) return 1; /* ¡×*/
+ if(c1==0xde) return 1; /* $B!+(B*/
+ if(c1==0xdf) return 1; /* $B!,(B*/
+ if(c1==0xa4) return 1; /* $B!#(B*/
+ if(c1==0xa3) return 1; /* $B!$(B*/
+ if(c1==0xa1) return 1; /* $B!W(B*/
if(c1==0xb0) return 1; /* - */
if(SSP<=c1 && c1<=0xdf) { /* X0201 */
line = 1;
@@ -1433,16 +1430,16 @@ register int c2,c1;
return 1; /* default no fold in ASCII */
} else {
if(c2=='!') {
- if(c1=='"') return 1; /* ¡¢ */
- if(c1=='#') return 1; /* ¡£ */
- if(c1=='$') return 1; /* ¡¤ */
- if(c1=='%') return 1; /* ¡¥ */
- if(c1=='\'') return 1; /* ¡Ü */
- if(c1=='(') return 1; /* ¡¨ */
- if(c1==')') return 1; /* ¡© */
- if(c1=='*') return 1; /* ¡ª */
- if(c1=='+') return 1; /* ¡« */
- if(c1==',') return 1; /* ¡¬ */
+ if(c1=='"') return 1; /* $B!"(B */
+ if(c1=='#') return 1; /* $B!#(B */
+ if(c1=='$') return 1; /* $B!$(B */
+ if(c1=='%') return 1; /* $B!%(B */
+ if(c1=='\'') return 1; /* $B!\(B */
+ if(c1=='(') return 1; /* $B!((B */
+ if(c1==')') return 1; /* $B!)(B */
+ if(c1=='*') return 1; /* $B!*(B */
+ if(c1=='+') return 1; /* $B!+(B */
+ if(c1==',') return 1; /* $B!,(B */
}
line = 2;
return '\n'; /* add one new line before this character */
@@ -1451,7 +1448,7 @@ register int c2,c1;
static int
pre_convert(c1,c2)
-register int c1,c2;
+ int c1,c2;
{
if(c2) c1 &= 0x7f;
c1_return = c1;
@@ -1490,27 +1487,49 @@ register int c1,c2;
}
-static int iso8859_f_save;
+#ifdef STRICT_MIME
+/* This converts */
+
+unsigned char *mime_pattern[] = {
+ (unsigned char *)"\075?ISO-8859-1?Q?",
+ (unsigned char *)"\075?ISO-2022-JP?B?",
+ (unsigned char *)"\075?ISO-2022-JP?Q?",
+ (unsigned char *)"\075?JAPANESE_EUC?B?",
+ (unsigned char *)"\075?SHIFT_JIS?B?",
+ NULL
+};
+
+int mime_encode[] = {
+ 'Q', 'B', 'Q',
+ 0
+};
+#endif
+
+#define MAXRECOVER 20
+int iso8859_f_save;
+
+#ifdef STRICT_MIME
#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
/* I don't trust portablity of toupper */
static int
-mime_begin()
+mime_begin(f)
+ FILE *f;
{
int c1;
int i,j,k;
unsigned char *p,*q;
- int r[20]; /* recovery buffer, max mime pattern lenght */
+ int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
mime_mode = FALSE;
- /* =? has been checked */
+ /* =? has been checked */
j = 0;
p = mime_pattern[j];
r[0]='='; r[1]='?';
for(i=2;p[i]>' ';i++) { /* start at =? */
- if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) {
+ if( ((((r[i] = c1 = getc(f))==EOF) || nkf_toupper(c1) != p[i] ) {
/* pattern fails, try next one */
q = p;
while (p = mime_pattern[++j]) {
@@ -1520,34 +1539,92 @@ mime_begin()
}
if(p) continue; /* found next one, continue */
/* all fails, output from recovery buffer */
- _UNGETC(c1);
+ ungetc(c1,f);
for(j=0;j<i;j++) {
(*oconv)(0,r[j]);
}
return c1;
}
}
+ mime_mode = mime_encode[j];
iso8859_f_save = iso8859_f;
if(j==0) {
iso8859_f = TRUE;
}
- mime_mode = mime_encode[j];
if(mime_mode=='B') {
mimebuf_f = unbuf_f;
if(!unbuf_f) {
/* do MIME integrity check */
- return mime_integrity(mime_pattern[j]);
+ return mime_integrity(f,mime_pattern[j]);
}
}
mimebuf_f = TRUE;
return c1;
}
-#define mime_getc0() (mimebuf_f?_GETC():Fifo(mime_input++))
-#define mime_ungetc0(c) (mimebuf_f?_UNGETC(c):mime_input--)
+#define mime_getc0(f) (mimebuf_f?getc(f):Fifo(mime_input++))
+#define mime_ungetc0(c,f) (mimebuf_f?ungetc(c,f):mime_input--)
+
+#else
+static int
+mime_begin(f)
+FILE *f;
+{
+ int c1;
+ int i,j;
+ int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
+
+ mime_mode = FALSE;
+ /* =? has been checked */
+ j = 0;
+ r[0]='='; r[1]='?';
+ for(i=2;i<MAXRECOVER;i++) { /* start at =? */
+ /* We accept any charcter type even if it is breaked by new lines */
+ if( (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='=') break;
+ if(c1<' '&& c1!='\r' && c1!='\n') break;
+ if(c1=='?') {
+ i++;
+ if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='b'||c1=='B') {
+ mime_mode = 'B';
+ } else if(c1=='q'||c1=='Q') {
+ mime_mode = 'Q';
+ } else {
+ break;
+ }
+ i++;
+ if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='?') {
+ break;
+ } else {
+ mime_mode = FALSE;
+ }
+ break;
+ }
+ }
+ if(!mime_mode || c1==EOF || i==MAXRECOVER) {
+ ungetc(c1,f);
+ if (i == MAXRECOVER)
+ i--;
+ for(j=0;j<i;j++) {
+ (*oconv)(0,r[j]);
+ }
+ return c1;
+ }
+ iso8859_f_save = iso8859_f;
+ /* do no MIME integrity check */
+ return c1; /* used only for checking EOF */
+}
+
+#define mime_getc0(f) getc(f)
+#define mime_ungetc0(c,f) ungetc(c,f)
+
+#endif
static int
-mime_getc()
+mime_getc(f)
+ FILE *f;
{
int c1, c2, c3, c4, cc;
int t1, t2, t3, t4, mode, exit_mode;
@@ -1561,26 +1638,26 @@ mime_getc()
else
exit_mode = FALSE;
if(mime_mode == 'Q') {
- if((c1 = mime_getc0()) == EOF) return (EOF);
+ if((c1 = mime_getc0(f)) == EOF) return (EOF);
if(c1=='_') return ' ';
if(c1!='=' && c1!='?')
return c1;
mime_mode = exit_mode; /* prepare for quit */
if(c1<=' ') return c1;
- if((c2 = mime_getc0()) == EOF) return (EOF);
+ if((c2 = mime_getc0(f)) == EOF) return (EOF);
if(c2<=' ') return c2;
if(c1=='?'&&c2=='=') {
/* end Q encoding */
input_mode = exit_mode;
iso8859_f = iso8859_f_save;
- return _GETC();
+ return getc(f);
}
if(c1=='?') {
mime_mode = 'Q'; /* still in MIME */
- mime_ungetc0(c2);
+ mime_ungetc0(c2,f);
return c1;
}
- if((c3 = mime_getc0()) == EOF) return (EOF);
+ if((c3 = mime_getc0(f)) == EOF) return (EOF);
if(c2<=' ') return c2;
mime_mode = 'Q'; /* still in MIME */
#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\
@@ -1590,7 +1667,7 @@ mime_getc()
if(mime_mode != 'B') {
mime_mode = FALSE;
- return _GETC();
+ return getc(f);
}
@@ -1605,11 +1682,11 @@ mime_getc()
mode = mime_mode;
mime_mode = exit_mode; /* prepare for quit */
- while ((c1 = mime_getc0())<=' ') {
+ while ((c1 = mime_getc0(f))<=' ') {
if(c1==EOF)
return (EOF);
}
- if((c2 = mime_getc0())<=' ') {
+ if((c2 = mime_getc0(f))<=' ') {
if(c2==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
@@ -1617,16 +1694,16 @@ mime_getc()
}
if((c1 == '?') && (c2 == '=')) {
input_mode = ASCII;
- while((c1 = _GETC())==' ' /* || c1=='\n' || c1=='\r' */);
+ while((c1 = getc(f))==' ' /* || c1=='\n' || c1=='\r' */);
return c1;
}
- if((c3 = mime_getc0())<=' ') {
+ if((c3 = mime_getc0(f))<=' ') {
if(c3==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
return c3;
}
- if((c4 = mime_getc0())<=' ') {
+ if((c4 = mime_getc0(f))<=' ') {
if(c4==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
@@ -1659,27 +1736,28 @@ mime_getc()
static int
mime_ungetc(c)
-unsigned int c;
+ unsigned int c;
{
Fifo(mime_last++) = c;
return c;
}
-
-static int
-mime_integrity(p)
-unsigned char *p;
+#ifdef STRICT_MIME
+int
+mime_integrity(f,p)
+ FILE *f;
+ unsigned char *p;
{
int c,d;
unsigned int q;
- /* In buffered mode, read until =? or NL or buffer full
+ /* In buffered mode, read until =? or NL or buffer fffull
*/
mime_input = mime_top;
mime_last = mime_top;
while(*p) Fifo(mime_input++) = *p++;
d = 0;
q = mime_input;
- while((c=_GETC())!=EOF) {
+ while((c=getc(f))!=EOF) {
if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;
if(c=='=' && d=='?') {
/* checked. skip header, start decode */
@@ -1700,10 +1778,11 @@ unsigned char *p;
mime_mode = 1; /* no decode on Fifo last in mime_getc */
return 1;
}
+#endif
static int
base64decode(c)
- int c;
+ int c;
{
int i;
if(c > '@')
@@ -1720,7 +1799,36 @@ base64decode(c)
return (i);
}
-#ifdef notdef
+static void
+reinit()
+{
+ unbuf_f = FALSE;
+ estab_f = FALSE;
+ nop_f = FALSE;
+ binmode_f = TRUE;
+ rot_f = FALSE;
+ input_f = FALSE;
+ alpha_f = FALSE;
+ mime_f = TRUE;
+ mimebuf_f = FALSE;
+ broken_f = FALSE;
+ iso8859_f = FALSE;
+ x0201_f = TRUE;
+ x0201_f = NO_X0201;
+ fold_f = FALSE;
+ kanji_intro = DEFAULT_J;
+ ascii_intro = DEFAULT_R;
+ oconv = DEFAULT_CONV;
+ output_mode = ASCII;
+ input_mode = ASCII;
+ shift_mode = FALSE;
+ mime_mode = FALSE;
+ file_out = FALSE;
+ add_cr = FALSE;
+ del_cr = FALSE;
+}
+
+#ifndef PERL_XS
int
usage()
{
@@ -1742,7 +1850,7 @@ usage()
fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n");
fprintf(stderr,"r {de/en}crypt ROT13/47\n");
fprintf(stderr,"v Show this usage\n");
- fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n");
+ fprintf(stderr,"m[BQ0] MIME decode [B:base64,Q:quoted,0:no decode]\n");
fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
fprintf(stderr,"f Folding: -f60 or -f\n");
fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n");
@@ -1770,234 +1878,10 @@ usage()
fprintf(stderr,"\n%s\n",CopyRight);
return 0;
}
-#endif /* notdef */
-
-static VALUE
-kconv_kconv(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE src, dst;
- VALUE in, out;
- int in_code, out_code;
- char *codename = 0;
-
- rb_scan_args(argc, argv, "12", &src, &out, &in);
- Check_Type(src, T_STRING);
-
- if (NIL_P(out)) {
- codename = rb_get_kcode();
- goto codeselect;
- }
- else if (TYPE(out) == T_STRING) {
- codename = RSTRING(out)->ptr;
- codeselect:
- switch (codename[0]) {
- case 'E': case 'e':
- out_code = _EUC;
- break;
- case 'S': case 's':
- out_code = _SJIS;
- break;
- case 'J': case 'j':
- default:
- out_code = _JIS;
- break;
- }
- }
- else {
- out_code = NUM2INT(out);
- if (out_code == _NOCONV) return (VALUE)src;
- }
- if (NIL_P(in)) {
- in_code = _AUTO;
- }
- else if (TYPE(in) == T_STRING) {
- switch (RSTRING(in)->ptr[0]) {
- case 'E': case 'e':
- in_code = _EUC;
- break;
- case 'S': case 's':
- in_code = _SJIS;
- break;
- case 'J': case 'j':
- in_code = _JIS;
- break;
- default:
- in_code = _AUTO;
- break;
- }
- }
- else {
- in_code = NUM2INT(in);
- if (in_code == _NOCONV) return (VALUE)src;
- }
-
- dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, out_code, in_code);
-
- return dst;
-}
-
-static VALUE
-kconv_tojis(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _JIS, _AUTO);
-
- return dst;
-}
-
-static VALUE
-kconv_toeuc(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _EUC, _AUTO);
-
- return (VALUE)dst;
-}
-
-static VALUE
-kconv_tosjis(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _SJIS, _AUTO);
-
- return dst;
-}
-
-/*
- * Character code detection - Algorithm described in:
- * Ken Lunde. `Understanding Japanese Information Processing'
- * Sebastopol, CA: O'Reilly & Associates.
- */
-
-static VALUE
-kconv_guess(obj, src)
- VALUE obj, src;
-{
- unsigned char *p;
- unsigned char *pend;
- int sequence_counter = 0;
-
- Check_Type(src, T_STRING);
-
- p = RSTRING(src)->ptr;
- pend = p + RSTRING(src)->len;
-
-#define INCR do {\
- p++;\
- if (p==pend) return INT2FIX(_UNKNOWN);\
- sequence_counter++;\
- if (sequence_counter % 2 == 1 && *p != 0xa4)\
- sequence_counter = 0;\
- if (6 <= sequence_counter) {\
- sequence_counter = 0;\
- return INT2FIX(_EUC);\
- }\
-} while (0)
-
- if (*p == 0xa4)
- sequence_counter = 1;
-
- while (p<pend) {
- if (*p == '\033') {
- return INT2FIX(_JIS);
- }
- if ('\000' < *p && *p < '\006'
- || *p == 0x7f
- || *p == 0xdf) {
- return INT2FIX(_BINARY);
- }
- if (0x81 <= *p && *p <= 0x8d) {
- return INT2FIX(_SJIS);
- }
- if (0x8f <= *p && *p <= 0x9f) {
- return INT2FIX(_SJIS);
- }
- if (*p == 0x8e) { /* SS2 */
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0) ||
- (0xe0 <= *p && *p <= 0xfc))
- return INT2FIX(_SJIS);
- }
- else if (0xa1 <= *p && *p <= 0xdf) {
- INCR;
- if (0xf0 <= *p && *p <= 0xfe)
- return INT2FIX(_EUC);
- if (0xe0 <= *p && *p <= 0xef) {
- while (p < pend && *p >= 0x40) {
- if (*p >= 0x81) {
- if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
- return INT2FIX(_SJIS);
- }
- else if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- INCR;
- }
- }
- else if (*p <= 0x9f) {
- return INT2FIX(_SJIS);
- }
- }
- else if (0xf0 <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- else if (0xe0 <= *p && *p <= 0xef) {
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0)) {
- return INT2FIX(_SJIS);
- }
- if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- INCR;
- }
- return INT2FIX(_UNKNOWN);
-}
-
-void
-Init_kconv()
-{
- VALUE mKconv = rb_define_module("Kconv");
-
- rb_define_module_function(mKconv, "kconv", kconv_kconv, -1);
- rb_define_module_function(mKconv, "tojis", kconv_tojis, 1);
- rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1);
- rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1);
- rb_define_module_function(mKconv, "guess", kconv_guess, 1);
-
- rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
- rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
- rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
- rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
- rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
- rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
- rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
-}
+#endif
/**
- ** ¥Ñ¥Ã¥ÁÀ©ºî¼Ô
+ ** $B%Q%C%A@):n<T(B
** void@merope.pleiades.or.jp (Kusakabe Youichi)
** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
** ohta@src.ricoh.co.jp (Junn Ohta)
@@ -2007,10 +1891,9 @@ Init_kconv()
** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
** GHG00637@nifty-serve.or.jp (COW)
- ** j_kuro@pluto.ai.kyutech.ac.jp (Jun Kuroda)
**
- ** ºÇ½ª¹¹¿·Æü
- ** 1996.12.18
+ ** $B:G=*99?7F|(B
+ ** 1998.11.7
**/
/* end */
diff --git a/ext/nkf/test.rb b/ext/nkf/test.rb
new file mode 100644
index 0000000000..4519f8ba7e
--- /dev/null
+++ b/ext/nkf/test.rb
@@ -0,0 +1,318 @@
+$counter = 0
+def result(result, message = nil)
+ $counter += 1
+ printf("%s %d%s\n",
+ result ? 'ok' : 'no',
+ $counter,
+ message ? ' ... ' + message : '')
+end
+
+begin
+ require 'nkf'
+ include NKF
+rescue LoadError
+ result(false)
+end
+result(true)
+
+if nkf('-me', '1')
+ result(true);
+else
+ result(false);
+end
+
+output = nkf('-e', "\033\$@#1#3#2%B")
+if output
+ # print output, "\n"
+ result(true, output)
+else
+ result(false)
+end
+
+output = nkf('-Zj', "\033\$@#1#3#2%B")
+if output
+ # print output, "\n"
+ result(true, output)
+else
+ result(false)
+end
+
+output = "\244\306 " * 1024
+old = output.length
+output = nkf("-j", output)
+if output
+ # print output, "\n"
+ result(true, "#{old} #{output.length}")
+else
+ result(false)
+end
+
+
+$detail = false
+def test(opt, input, expect)
+ print "\nINPUT:\n", input if $detail
+ print "\nEXPECT:\n", expect if $detail
+ result = nkf(opt, input)
+ print "\nGOT:\n", result if $detail
+
+ print result == expect ? "Ok\n" : "Fail\n"
+ return result
+end
+
+# Basic Conversion
+print "\nBasic Conversion test\n\n"
+
+example = {}
+example['jis'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@&R1"(3DQ(3%^2R%+?D]3&RA"(%-E8V]N9"!3=&%G92`;
+M)$)0)TU:&RA"($AI<F%G86YA(!LD0B0B)"0D)B0H)"HD;R1R)',;*$(*2V%T
+M86MA;F$@&R1")2(E)"4F)2@E*B5O)7(E<QLH0B!+:6=O=2`;)$(A)B%G(S`C
+/029!)E@G(B=!*$`;*$(*
+eofeof
+#'
+
+example['sjis'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@@5B)0(F>ED"6GIAR(%-E8V]N9"!3=&%G92"8I9=Y($AI
+M<F%G86YA((*@@J*"I(*F@JB"[8+P@O$*2V%T86MA;F$@@T&#0X-%@T>#28./
+>@Y*#DR!+:6=O=2"!18&'@D^"8(._@]:$081@A+X*
+eofeof
+#'
+
+example['euc'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@H;FQH;'^RZ'+_L_3(%-E8V]N9"!3=&%G92#0I\W:($AI
+M<F%G86YA(*2BI*2DIJ2HI*JD[Z3RI/,*2V%T86MA;F$@I:*EI*6FI:BEJJ7O
+>I?*E\R!+:6=O=2"AIJ'GH["CP:;!IMBGHJ?!J,`*
+eofeof
+#'
+
+example['amb'] = <<'eofeof'.unpack('u')[0]
+MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&E
+MPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*P
+ML:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&E
+MPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"
+ML+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"Q
+MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"
+ML+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*
+eofeof
+
+example['amb.euc'] = <<'eofeof'.unpack('u')[0]
+M&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
+M*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+M)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
+eofeof
+
+example['amb.sjis'] = <<'eofeof'.unpack('u')[0]
+M&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
+M*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+M)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
+eofeof
+
+example['x0201.sjis'] = <<'eofeof'.unpack('u')[0]
+MD5.*<(-*@TR#3H-0@U*#2X--@T^#48-3"I%3B7""8()A@F*"8X)D@F6"9H*!
+M@H*"@X*$@H6"AH*'"I%3BTR-AH%)@9>!E(&0@9.!3X&5@9:!:8%J@7R!>X&!
+M@6V!;H%O@7"!CPJ4O(IPMK>X/;FZMMZWWKC>N=ZZWH+&"I2\BG#*W\O?S-_-
+MW\[?M]^QW@K*W\O?S`IH86YK86MU(,K?R]_,I`K*W\O?S-VA"I2\BG""S(SC
+!"@!"
+eofeof
+#'
+
+example['x0201.euc'] = <<'eofeof'.unpack('u')[0]
+MP;2ST:6KI:VEKZ6QI;.EK*6NI;"ELJ6T"L&TL=&CP:/"H\.CQ*/%H\:CQZ/A
+MH^*CXZ/DH^6CYJ/G"L&TM:VYYJ&JH?>A]*'PH?.AL*'UH?:ARJ'+H=VAW*'A
+MH<ZASZ'0H=&A[PK(OK/1CK:.MXZX/8ZYCKJ.MH[>CK>.WHZXCMZ.N8[>CKJ.
+MWJ3("LB^L]&.RH[?CLN.WX[,CM^.S8[?CLZ.WXZWCM^.L8[>"H[*CM^.RX[?
+MCLP*:&%N:V%K=2".RH[?CLN.WX[,CJ0*CLJ.WX[+CM^.S([=CJ$*R+ZST:3.
+#N.4*
+eofeof
+#'
+
+example['x0201.jis'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$C02-"(T,C
+M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA""ALD0D$T-2TY9B$J(7<A="%P(7,A
+M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH0@H;)$)(/C-1&RA)-C<X&RA"
+M/1LH23DZ-EXW7CA>.5XZ7ALD0B1(&RA""ALD0D@^,U$;*$E*7TM?3%]-7TY?
+M-U\Q7ALH0@H;*$E*7TM?3!LH0@IH86YK86MU(!LH24I?2U],)!LH0@H;*$E*
+97TM?3%TA&RA""ALD0D@^,U$D3CAE&RA""@``
+eofeof
+#`
+
+example['x0201.sosi'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA*"ALD0D$T,5$C02-"(T,C
+M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA*"ALD0D$T-2TY9B$J(7<A="%P(7,A
+M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH2@H;)$)(/C-1&RA*#C8W.`\;
+M*$H]#CDZ-EXW7CA>.5XZ7@\;)$(D2!LH2@H;)$)(/C-1&RA*#DI?2U],7TU?
+M3E\W7S%>#PH.2E]+7TP/&RA*"FAA;FMA:W4@#DI?2U],)`\;*$H*#DI?2U],
+672$/&RA*"ALD0D@^,U$D3CAE&RA""@``
+eofeof
+#"
+
+example['x0201.x0208'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$;*$)!0D-$
+M149'86)C9&5F9PH;)$)!-#4M.68;*$(A0",D)5XF*B@I+2L]6UU[?1LD0B%O
+M&RA""ALD0D@^,U$E*R4M)2\;*$(]&R1")3$E,R4L)2XE,"4R)30D2!LH0@H;
+M)$)(/C-1)5$E5"57)5HE724M(2PE(B$K&RA""ALD0B51)50E51LH0@IH86YK
+M86MU(!LD0B51)50E52$B&RA""ALD0B51)50E525S(2,;*$(*&R1"2#XS421.
+&.&4;*$(*
+eofeof
+#`
+
+example['mime.iso2022'] = <<'eofeof'.unpack('u')[0]
+M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23TI566Q/4U9)1WEH2S\]"CT_
+M:7-O+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3U-624=Y:$L_/0H]/VES
+M;RTR,#(R+4I0/U$_/3%")$(D1B11/3%"*$)?96YD/ST*&R1`)#TD)B0K)$H;
+M*$H@/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]
+M(&5N9"!O9B!L:6YE"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]0>6LW
+M9&AS;U-G/3T_/2`]/TE33RTR,#(R+4I0/T(_1WE204Y%13=E:5)/4'EK-V1H
+M<V]39ST]/ST*0G)O:V5N(&-A<V4*/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W
+M96E23U!Y:S=D"FAS;U-G/3T_/2`]/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W
+M96E23U!Y:S=D:'-O4V<]/3\]"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I
+44D]*55EL3QM;2U-624=Y:$L_/0H_
+eofeof
+#'
+
+example['mime.ans.strict'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D"FAS;U-G/3T_/2`]
+M/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]"CT_
+L25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3QM;2U-624=Y:$L_/0H_
+eofeof
+#'
+
+example['mime.unbuf.strict'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@/3])4T\M,C`*,C(M2E`_0C]'>5)!
+M3D5%-V5I4D]0>6LW9&AS;U-G/3T_/0H;)$(T03MZ)$XE1ALH0EM+4U9)1WEH
+$2S\]"F5I
+eofeof
+
+example['mime.ans'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
+603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
+eofeof
+#"
+
+example['mime.unbuf'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
+603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
+eofeof
+#"
+
+example['mime.base64'] = <<'eofeof'.unpack('u')[0]
+M9W-M5"])3&YG<FU#>$I+-&=Q=4,S24LS9W%Q0E%:3TUI-39,,S0Q-&=S5T)1
+M43!+9VUA1%9O3T@*9S)+1%1O3'=K8C)1;$E+;V=Q2T-X24MG9W5M0W%*3EEG
+<<T=#>$E+9V=U;4,X64Q&9W)70S592VMG<6U""F=Q
+eofeof
+#"
+
+example['mime.base64.ans'] = <<'eofeof'.unpack('u')[0]
+M&R1")$M&?B1I)#LD1D0Z)"TD7B0Y)"PA(D5L-7XV83E9)$<A(ALH0@T*&R1"
+M(T<E-R5G)4,E+R1R0C\_="0J)"0D1B0B)&LD*D4Y)$,D1B0B)&LD<R1')#<D
+(9R0F)"L;*$(E
+eofeof
+#'
+
+example['mime.is8859'] = <<'eofeof'.unpack('u')[0]
+M/3])4T\M.#@U.2TQ/U$_*CU#-V%V83\_/2`*4&5E<B!4]G)N9W)E;@I,87-S
+M92!(:6QL97+X92!0971E<G-E;B`@7"`B36EN(&MA97!H97-T(&AA<B!F86%E
+M="!E="!F;V5L(2(*06%R:'5S(%5N:79E<G-I='DL($1%3DU!4DL@(%P@(DUI
+<;B!KYG!H97-T(&AA<B!FY65T(&5T(&;X;"$B"@!K
+eofeof
+
+example['mime.is8859.ans'] = <<'eofeof'.unpack('u')[0]
+M*L=A=F$_(`I0965R(%3V<FYG<F5N"DQA<W-E($AI;&QE<OAE(%!E=&5R<V5N
+M("!<(")-:6X@:V%E<&AE<W0@:&%R(&9A865T(&5T(&9O96PA(@I!87)H=7,@
+M56YI=F5R<VET>2P@1$5.34%22R`@7"`B36EN(&OF<&AE<W0@:&%R(&;E970@
+)970@9OAL(2(*
+eofeof
+#"
+
+print 'JIS to JIS ... '; test(' ', example['jis'], example['jis'])
+print 'JIS to SJIS... '; test('-s', example['jis'], example['sjis'])
+print 'JIS to EUC ... '; test('-e', example['jis'], example['euc'])
+
+print 'SJIS to JIS ... '; test('-j', example['sjis'], example['jis'])
+print 'SJIS to SJIS... '; test('-s', example['sjis'], example['sjis'])
+print 'SJIS to EUC ... '; test('-e', example['sjis'], example['euc'])
+
+print 'EUC to JIS ... '; test(' ', example['euc'], example['jis'])
+print 'EUC to SJIS... '; test('-s', example['euc'], example['sjis'])
+print 'EUC to EUC ... '; test('-e', example['euc'], example['euc'])
+
+
+# Ambigous Case
+print 'Ambiguous Case. '; test('' , example['amb'], example['amb.euc'])
+
+# Input assumption
+print 'SJIS Input assumption '
+test('-Sx', example['amb'], example['amb.sjis'])
+
+# X0201 ²¾Ì¾
+# X0201->X0208 conversion
+# X0208 aphabet -> ASCII
+# X0201 Áê¸ßÊÑ´¹
+
+print "\nX0201 test\n\n"
+
+# -X is necessary to allow X0201 in SJIS
+# -Z convert X0208 alphabet to ASCII
+print 'X0201 conversion: SJIS '
+test('-XZ', example['x0201.sjis'], example['x0201.x0208'])
+print 'X0201 conversion: JIS '
+test('-Z', example['x0201.jis'], example['x0201.x0208'])
+print 'X0201 conversion:SI/SO '
+test('-Z', example['x0201.sosi'], example['x0201.x0208'])
+print 'X0201 conversion: EUC '
+test('-Z', example['x0201.euc'], example['x0201.x0208'])
+# -x means X0201 output
+print 'X0201 output: SJIS '
+test('-xs', example['x0201.euc'], example['x0201.sjis'])
+print 'X0201 output: JIS '
+test('-xj', example['x0201.sjis'], example['x0201.jis'])
+print 'X0201 output: EUC '
+test('-xe', example['x0201.jis'], example['x0201.euc'])
+
+# MIME decode
+
+print "\nMIME test\n\n"
+
+# MIME ISO-2022-JP
+
+print "Next test is expeced to Fail.\n"
+
+print 'MIME decode (strict) '
+tmp = test('-m', example['mime.iso2022'], example['mime.ans.strict'])
+print 'MIME decode (nonstrict)'
+tmp = test('-m', example['mime.iso2022'], example['mime.ans'])
+# open(OUT,'>tmp1');print OUT pack('u',$tmp);close(OUT);
+# unbuf mode implies more pessimistic decode
+print 'MIME decode (unbuf) '
+test('-mu', example['mime.iso2022'], example['mime.unbuf'])
+print 'MIME decode (base64) '
+t = test('-mB', example['mime.base64'], example['mime.base64.ans'])
+
+# MIME ISO-8859-1
+
+# Without -l, ISO-8859-1 was handled as X0201.
+
+print 'MIME ISO-8859-1 (Q) '
+test('-ml', example['mime.is8859'], example['mime.is8859.ans'])
diff --git a/ext/pty/MANIFEST b/ext/pty/MANIFEST
new file mode 100644
index 0000000000..5e5af7dd6b
--- /dev/null
+++ b/ext/pty/MANIFEST
@@ -0,0 +1,11 @@
+MANIFEST
+README
+README.expect
+README.expect.jp
+README.jp
+expect_sample.rb
+extconf.rb
+lib/expect.rb
+pty.c
+script.rb
+shl.rb
diff --git a/ext/pty/README b/ext/pty/README
new file mode 100644
index 0000000000..a09469d39c
--- /dev/null
+++ b/ext/pty/README
@@ -0,0 +1,93 @@
+pty extension version 0.3 by A.ito
+
+1. Introduction
+
+This extension module adds ruby a functionality to execute an
+arbitrary command through pseudo tty (pty).
+
+2. Install
+
+Follow the instruction below.
+
+(1) Execute
+
+ ruby extconf.rb
+
+ then Makefile is generated.
+
+(3) Do make; make install.
+
+3. What you can do
+
+This extension module defines a module named PTY, which contains
+following module fungtions:
+
+ getpty(command)
+ spawn(command)
+
+ This function reserves a pty, executes command over the pty
+ and returns an array. The return value is an array with three
+ elements. The first element in the array is for reading and the
+ second for writing. The third element is the process ID of the
+ child process. If this function is called with an iterator block,
+ the array is passed to the block as block parameters, and the
+ function itself returns nil.
+
+ While the process spawned by this function is active, SIGCHLD
+ is captured to handle the change of the child process. When the
+ child process is suspended or finished, an exception is raised.
+ As all SIGCHLD signal is captured and processed by PTY module,
+ you can't use other function or method which spawns subprosesses
+ (including signal() and IO.popen()) while the PTY subprocesses
+ are active. Otherwise, unexpected exception will occur. To avoid
+ this problem, see protect_signal() below.
+
+ If this function is called with an iterator block, SIGCHLD signal
+ is captured only within the block. Therefore, it is risky to use
+ File objects for PTY subprocess outside the iterator block.
+
+
+ protect_signal
+
+ This function takes an iterator block. Within the iterator block,
+ no exception is raised even if any subprocess is terminated.
+ This function is used to enable functions like system() or IO.popen()
+ while PTY subprocess is active. For example,
+
+ PTY.spawn("command_foo") do |r,w|
+ ...
+ ...
+ PTY.protect_signal do
+ system "some other commands"
+ end
+ ...
+ end
+
+ disables to send exception when "some other commands" is
+ terminated.
+
+ reset_signal
+
+ Disables to handle SIGCHLD while PTY subprocess is active.
+
+
+4. License
+
+(C) Copyright 1998 by Akinori Ito.
+
+This software may be redistributed freely for this purpose, in full
+or in part, provided that this entire copyright notice is included
+on any copies of this software and applications and derivations thereof.
+
+This software is provided on an "as is" basis, without warranty of any
+kind, either expressed or implied, as to any matter including, but not
+limited to warranty of fitness of purpose, or merchantability, or
+results obtained from use of this software.
+
+5. Bug report
+
+Please feel free to send E-mail to
+
+ aito@ei5sun.yz.yamagata-u.ac.jp
+
+for any bug report, opinion, contribution, etc.
diff --git a/ext/pty/README.expect b/ext/pty/README.expect
new file mode 100644
index 0000000000..fddbb6fdad
--- /dev/null
+++ b/ext/pty/README.expect
@@ -0,0 +1,22 @@
+ README for expect
+ by A. Ito, 28 October, 1998
+
+ Expect library adds IO class a method called expect(), which
+does similar act to tcl's expect extension.
+
+The usage of the method is:
+
+ IO#expect(pattern,timeout=9999999)
+
+where `pattern' is an instance of String or Regexp and `timeout'
+is Fixnum, which can be omitted.
+ When the method is called without block, it waits until the
+input which matches the pattern is obtained from the IO or the time
+specified as the timeout passes. When the pattern is obtained from the
+IO, the method returns an array. The first element of the array is the
+entire string obtained from the IO until the pattern matches. The
+following elements indicates the specific pattern which matched to the
+anchor in the regular expression. If the method ends because of
+timeout, it returns nil.
+ When the method is called with block, the array is passed as
+the block parameter.
diff --git a/ext/pty/README.expect.jp b/ext/pty/README.expect.jp
new file mode 100644
index 0000000000..db84695ee5
--- /dev/null
+++ b/ext/pty/README.expect.jp
@@ -0,0 +1,21 @@
+ README for expect
+ by A. Ito, 28 October, 1998
+
+ Expect¥é¥¤¥Ö¥é¥ê¤Ï¡¤tcl ¤Î expect ¥Ñ¥Ã¥±¡¼¥¸¤È»÷¤¿¤è¤¦¤Êµ¡Ç½¤ò
+IO¥¯¥é¥¹¤ËÄɲä·¤Þ¤¹¡¥
+
+ Äɲ䵤ì¤ë¥á¥½¥Ã¥É¤Î»È¤¤Êý¤Ï¼¡¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ IO#expect(pattern,timeout=9999999)
+
+pattern ¤Ï String ¤« Regexp ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¡¤timeout ¤Ï Fixnum
+¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤¹¡¥timeout ¤Ï¾Êά¤Ç¤­¤Þ¤¹¡¥
+ ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯¤Ê¤·¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤Þ¤º¥ì¥·¡¼¥Ð¤Ç¤¢¤ë
+IO¥ª¥Ö¥¸¥§¥¯¥È¤«¤é pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¥Ñ¥¿¡¼¥ó¤¬Æɤߤ³¤Þ¤ì¤ë
+¤Þ¤ÇÂÔ¤Á¤Þ¤¹¡¥¥Ñ¥¿¡¼¥ó¤¬ÆÀ¤é¤ì¤¿¤é¡¤¤½¤Î¥Ñ¥¿¡¼¥ó¤Ë´Ø¤¹¤ëÇÛÎó¤ò
+ÊÖ¤·¤Þ¤¹¡¥ÇÛÎó¤ÎºÇ½é¤ÎÍ×ÁǤϡ¤pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¤Þ¤Ç¤ËÆɤߤ³
+¤Þ¤ì¤¿ÆâÍƤÎʸ»úÎó¤Ç¤¹¡¥2ÈÖÌܰʹߤÎÍ×ÁǤϡ¤pattern ¤ÎÀµµ¬É½¸½
+¤ÎÃæ¤Ë¥¢¥ó¥«¡¼¤¬¤¢¤Ã¤¿¾ì¹ç¤Ë¡¤¤½¤Î¥¢¥ó¥«¡¼¤Ë¥Þ¥Ã¥Á¤¹¤ëÉôʬ¤Ç¤¹¡¥
+¤â¤·¥¿¥¤¥à¥¢¥¦¥È¤¬µ¯¤­¤¿¾ì¹ç¤Ï¡¤¤³¤Î¥á¥½¥Ã¥É¤Ïnil¤òÊÖ¤·¤Þ¤¹¡¥
+ ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¥Þ¥Ã¥Á¤·¤¿Í×ÁǤÎ
+ÇÛÎ󤬥֥í¥Ã¥¯°ú¿ô¤È¤·¤ÆÅϤµ¤ì¡¤¥Ö¥í¥Ã¥¯¤¬É¾²Á¤µ¤ì¤Þ¤¹¡¥
diff --git a/ext/pty/README.jp b/ext/pty/README.jp
new file mode 100644
index 0000000000..5ae4fb06a0
--- /dev/null
+++ b/ext/pty/README.jp
@@ -0,0 +1,89 @@
+pty ³ÈÄ¥¥â¥¸¥å¡¼¥ë version 0.3 by A.ito
+
+1. ¤Ï¤¸¤á¤Ë
+
+¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤²¾ÁÛtty (pty) ¤òÄ̤·¤ÆŬÅö¤Ê¥³¥Þ¥ó¥É¤ò
+¼Â¹Ô¤¹¤ëµ¡Ç½¤ò ruby ¤ËÄ󶡤·¤Þ¤¹¡¥
+
+2. ¥¤¥ó¥¹¥È¡¼¥ë
+
+¼¡¤Î¤è¤¦¤Ë¤·¤Æ¥¤¥ó¥¹¥È¡¼¥ë¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+(1) ruby extconf.rb
+
+ ¤ò¼Â¹Ô¤¹¤ë¤È Makefile ¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥
+
+(2) make; make install ¤ò¼Â¹Ô¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+3. ²¿¤¬¤Ç¤­¤ë¤«
+
+¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤PTY ¤È¤¤¤¦¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¤Þ¤¹¡¥¤½¤ÎÃæ
+¤Ë¤Ï¡¤¼¡¤Î¤è¤¦¤Ê¥â¥¸¥å¡¼¥ë´Ø¿ô¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ getpty(command)
+ spawn(command)
+
+ ¤³¤Î´Ø¿ô¤Ï¡¤²¾ÁÛtty¤ò³ÎÊݤ·¡¤»ØÄꤵ¤ì¤¿¥³¥Þ¥ó¥É¤ò¤½¤Î²¾ÁÛtty
+ ¤Î¸þ¤³¤¦¤Ç¼Â¹Ô¤·¡¤ÇÛÎó¤òÊÖ¤·¤Þ¤¹¡¥Ìá¤êÃͤÏ3¤Ä¤ÎÍ×ÁǤ«¤é¤Ê¤ë
+ ÇÛÎó¤Ç¤¹¡¥ºÇ½é¤ÎÍ×ÁǤϲ¾ÁÛtty¤«¤éÆɤ߽Ф¹¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤
+ 2ÈÖÌܤϽñ¤­¤³¤à¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤3ÈÖÌÜ¤Ï»Ò¥×¥í¥»¥¹¤Î¥×¥í
+ ¥»¥¹ID¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤¬¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤³¤ì¤é¤Î
+ Í×ÁǤϥ֥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿¤È¤·¤ÆÅϤµ¤ì¡¤´Ø¿ô¼«ÂΤÏnil¤òÊÖ¤·¤Þ¤¹¡¥
+
+ ¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¥µ¥Ö¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¡¤»Ò¥×¥í¥»¥¹
+ ¤Î¾õÂÖ¤ò´Æ»ë¤¹¤ë¤¿¤á¤Ë SIGCHLD ¥·¥°¥Ê¥ë¤òÊ᪤·¤Þ¤¹¡¥»Ò¥×¥í¥»¥¹
+ ¤¬½ªÎ»¤·¤¿¤êÄä»ß¤·¤¿¾ì¹ç¤Ë¤Ï¡¤Îã³°¤¬È¯À¸¤·¤Þ¤¹¡¥¤³¤Î´Ö¡¤¤¹¤Ù¤Æ¤Î
+ SIGCHLD ¤¬ PTY ¥â¥¸¥å¡¼¥ë¤Î¥·¥°¥Ê¥ë¥Ï¥ó¥É¥é¤ËÊ᪤µ¤ì¤ë¤Î¤Ç¡¤
+ ¥µ¥Ö¥×¥í¥»¥¹¤òÀ¸À®¤¹¤ë¾¤Î´Ø¿ô(system() ¤È¤« IO.popen()¤Ê¤É)¤ò
+ »È¤¦¤È¡¤Í½´ü¤·¤Ê¤¤Îã³°¤¬È¯À¸¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤ì¤òËɤ°¤¿¤á
+ ¤Ë¤Ï¡¤²¼µ­¤Îprotect_signal()¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+ ¤³¤Î´Ø¿ô¤¬¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¤½¤Î¥Ö¥í¥Ã¥¯
+ ¤ÎÃæ¤Ç¤Î¤ß SIGCHLD ¤¬Ê᪤µ¤ì¤Þ¤¹¡¥¤·¤¿¤¬¤Ã¤Æ¡¤¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿
+ ¤È¤·¤ÆÅϤµ¤ì¤¿IO¥ª¥Ö¥¸¥§¥¯¥È¤ò¡¤¥Ö¥í¥Ã¥¯¤Î³°¤Ë»ý¤Á½Ð¤·¤Æ»È¤¦¤Î
+ ¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
+
+
+ protect_signal
+
+ ¤³¤Î´Ø¿ô¤Ï¥¤¥Æ¥ì¡¼¥¿¤Ç¤¹¡¥¤³¤³¤Ç»ØÄꤵ¤ì¤¿¥Ö¥í¥Ã¥¯¤ÎÃæ¤Ç¤Ï¡¤
+ »Ò¥×¥í¥»¥¹¤¬½ªÎ»¤·¤Æ¤âÎã³°¤òȯÀ¸¤·¤Þ¤»¤ó¡¥¤³¤Î´Ø¿ô¤ò»È¤¦¤³¤È¤Ç¡¤
+ PTY¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¤Ç¤â¡¤system()¤ä IO.popen()¤Ê¤É¤Î
+ ´Ø¿ô¤ò°ÂÁ´¤Ë»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥Î㤨¤Ð¡¤
+
+ PTY.spawn("command_foo") do |r,w|
+ ...
+ ...
+ PTY.protect_signal do
+ system "some other commands"
+ end
+ ...
+ end
+
+ ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ë¤è¤ê¡¤"some other commands" ¤¬½ªÎ»¤·¤¿¤È¤­¤Ë
+ Îã³°¤¬È¯À¸¤¹¤ë¤Î¤òËɤ²¤Þ¤¹¡¥
+
+ reset_signal
+
+ PTY ¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤Æ¤â¡¤¤½¤Î¥×¥í¥»¥¹¤Î½ªÎ»»þ¤ËÎã³°¤¬È¯À¸
+ ¤·¤Ê¤¤¤è¤¦¤Ë¤·¤Þ¤¹¡¥
+
+4. ÍøÍѤˤĤ¤¤Æ
+
+°ËÆ£¾´Â§¤¬Ãøºî¸¢¤òÊÝÍ­¤·¤Þ¤¹¡¥
+
+¥½¡¼¥¹¥×¥í¥°¥é¥à¤Þ¤¿¤Ï¥É¥­¥å¥á¥ó¥È¤Ë¸µ¤ÎÃøºî¸¢É½¼¨¤¬²þÊѤµ¤ì¤º¤Ë
+ɽ¼¨¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ë¸Â¤ê¡¤Ã¯¤Ç¤â¡¤¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ò̵½þ¤«¤ÄÃøºî
+¸¢¼Ô¤Ë̵ÃǤÇÍøÍÑ¡¦ÇÛÉÛ¡¦²þÊѤǤ­¤Þ¤¹¡¥ÍøÍÑÌÜŪ¤Ï¸ÂÄꤵ¤ì¤Æ¤¤¤Þ¤»
+¤ó¡¥
+
+¤³¤Î¥×¥í¥°¥é¥à¤ÎÍøÍÑ¡¦ÇÛÉÛ¤½¤Î¾¤³¤Î¥×¥í¥°¥é¥à¤Ë´Ø·¸¤¹¤ë¹Ô°Ù¤Ë¤è
+¤Ã¤ÆÀ¸¤¸¤¿¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤â¡¤ºî¼Ô¤Ï°ìÀÚÀÕǤ¤òÉ餤¤Þ¤»¤ó¡¥
+
+5. ¥Ð¥°Êó¹ðÅù
+
+¥Ð¥°¥ì¥Ý¡¼¥È¤Ï´¿·Þ¤·¤Þ¤¹¡¥
+
+ aito@ei5sun.yz.yamagata-u.ac.jp
+
+¤Þ¤ÇÅŻҥ᡼¥ë¤Ç¥Ð¥°¥ì¥Ý¡¼¥È¤ò¤ªÁ÷¤ê¤¯¤À¤µ¤¤¡¥
diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb
new file mode 100644
index 0000000000..1311476c5d
--- /dev/null
+++ b/ext/pty/expect_sample.rb
@@ -0,0 +1,56 @@
+#
+# sample program of expect.rb
+#
+# by A. Ito
+#
+# This program reports the latest version of ruby interpreter
+# by connecting to ftp server at netlab.co.jp.
+#
+require 'pty'
+require 'expect'
+
+fnames = []
+PTY.spawn("ftp ftp.netlab.co.jp") do
+ |r_f,w_f,pid|
+ w_f.sync = true
+
+ $expect_verbose = true
+
+ r_f.expect(/^Name.*: /) do
+ w_f.print "ftp\n"
+ end
+
+ if !ENV['USER'].nil?
+ username = ENV['USER']
+ elsif !ENV['LOGNAME'].nil?
+ username = ENV['LOGNAME']
+ else
+ username = 'guest'
+ end
+
+ r_f.expect('word:') do
+ w_f.print username+"@\n"
+ end
+ r_f.expect("ftp> ") do
+ w_f.print "cd pub/lang/ruby\n"
+ end
+ r_f.expect("ftp> ") do
+ w_f.print "dir\n"
+ end
+
+ r_f.expect("ftp> ") do |output|
+ for x in output[0].split("\n")
+ if x =~ /(ruby.*\.tar\.gz)/ then
+ fnames.push $1
+ end
+ end
+ end
+ begin
+ w_f.print "quit\n"
+ rescue
+ end
+end
+
+print "The latest ruby interpreter is "
+print fnames.sort.pop
+print "\n"
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
new file mode 100644
index 0000000000..63383f7faf
--- /dev/null
+++ b/ext/pty/extconf.rb
@@ -0,0 +1,10 @@
+require 'mkmf'
+
+have_header("sys/stropts.h")
+have_func("setresuid")
+$CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === PLATFORM
+if have_func("openpty") or
+ have_func("_getpty") or
+ have_func("ioctl")
+ create_makefile('pty')
+end
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
new file mode 100644
index 0000000000..54c69edadb
--- /dev/null
+++ b/ext/pty/lib/expect.rb
@@ -0,0 +1,36 @@
+$expect_verbose = false
+
+class IO
+ def expect(pat,timeout=9999999)
+ buf = ''
+ case pat
+ when String
+ e_pat = Regexp.new(Regexp.quote(pat))
+ when Regexp
+ e_pat = pat
+ end
+ while true
+ if IO.select([self],nil,nil,timeout).nil? then
+ result = nil
+ break
+ end
+ c = getc.chr
+ buf << c
+ if $expect_verbose
+ STDOUT.print c
+ STDOUT.flush
+ end
+ if buf =~ e_pat then
+ result = [buf,$1,$2,$3,$4,$5,$6,$7,$8,$9]
+ break
+ end
+ end
+ if iterator? then
+ yield result
+ else
+ return result
+ end
+ nil
+ end
+end
+
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
new file mode 100644
index 0000000000..98be9044b7
--- /dev/null
+++ b/ext/pty/pty.c
@@ -0,0 +1,497 @@
+#include "config.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pwd.h>
+#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else
+#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+#endif
+#include <ctype.h>
+
+#include <ruby.h>
+#include <rubyio.h>
+
+#include <signal.h>
+#ifdef HAVE_SYS_STROPTS_H
+#include <sys/stropts.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define DEVICELEN 16
+
+#if !defined(HAVE_OPENPTY)
+#ifdef __hpux
+char *MasterDevice = "/dev/ptym/pty%s",
+ *SlaveDevice = "/dev/pty/tty%s",
+ *deviceNo[] = {
+ "p0","p1","p2","p3","p4","p5","p6","p7",
+ "p8","p9","pa","pb","pc","pd","pe","pf",
+ "q0","q1","q2","q3","q4","q5","q6","q7",
+ "q8","q9","qa","qb","qc","qd","qe","qf",
+ "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8","r9","ra","rb","rc","rd","re","rf",
+ "s0","s1","s2","s3","s4","s5","s6","s7",
+ "s8","s9","sa","sb","sc","sd","se","sf",
+ "t0","t1","t2","t3","t4","t5","t6","t7",
+ "t8","t9","ta","tb","tc","td","te","tf",
+ "u0","u1","u2","u3","u4","u5","u6","u7",
+ "u8","u9","ua","ub","uc","ud","ue","uf",
+ "v0","v1","v2","v3","v4","v5","v6","v7",
+ "v8","v9","va","vb","vc","vd","ve","vf",
+ "w0","w1","w2","w3","w4","w5","w6","w7",
+ "w8","w9","wa","wb","wc","wd","we","wf",
+ 0,
+ };
+#else /* NOT HPUX */
+#ifdef _IBMESA /* AIX/ESA */
+char *MasterDevice = "/dev/ptyp%s",
+ *SlaveDevice = "/dev/ttyp%s",
+ *deviceNo[] = {
+"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
+"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
+"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
+"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
+"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
+"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
+"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
+"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
+"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
+"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
+"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
+"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
+"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
+"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
+"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
+"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
+ };
+#else
+char *MasterDevice = "/dev/pty%s",
+ *SlaveDevice = "/dev/tty%s",
+ *deviceNo[] = {
+ "p0","p1","p2","p3","p4","p5","p6","p7",
+ "p8","p9","pa","pb","pc","pd","pe","pf",
+ "q0","q1","q2","q3","q4","q5","q6","q7",
+ "q8","q9","qa","qb","qc","qd","qe","qf",
+ "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8","r9","ra","rb","rc","rd","re","rf",
+ 0,
+ };
+#endif /* _IBMESA */
+#endif /* HPUX */
+#endif /* !defined(HAVE_OPENPTY) */
+
+char SlaveName[DEVICELEN];
+
+extern int errno;
+
+#define MAX_PTY 16
+static int n_pty,last_pty;
+static int chld_pid[MAX_PTY];
+
+#ifndef HAVE_SETEUID
+# ifdef HAVE_SETREUID
+# define seteuid(e) setreuid(-1, (e))
+# else /* NOT HAVE_SETREUID */
+# ifdef HAVE_SETRESUID
+# define seteuid(e) setresuid(-1, (e), -1)
+# else /* NOT HAVE_SETRESUID */
+ /* I can't set euid. (;_;) */
+# endif /* HAVE_SETRESUID */
+# endif /* HAVE_SETREUID */
+#endif /* NO_SETEUID */
+
+struct pty_info {
+ int fd;
+ pid_t child_pid;
+};
+
+static void
+set_signal_action(action)
+ RETSIGTYPE (*action)();
+{
+#ifdef __hpux
+ struct sigvec sv;
+ /*
+ * signal SIGCHLD should be delivered on stop of the child
+ */
+ sv.sv_handler = action;
+ sv.sv_mask = sigmask(SIGCHLD);
+ sv.sv_flags = SV_BSDSIG;
+ sigvector(SIGCHLD, &sv, (struct sigvec *) 0);
+#else /* not HPUX */
+#if defined(SA_NOCLDSTOP)
+ struct sigaction sa;
+ /*
+ * signal SIGCHLD should be delivered on stop of the child
+ * (for SVR4)
+ */
+ sa.sa_handler = action;
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGCHLD);
+ sa.sa_flags = 0; /* SA_NOCLDSTOP flag is removed */
+ sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+#else
+ signal(SIGCHLD,action);
+#endif
+#endif /* not HPUX */
+
+}
+
+static void
+reset_signal_action()
+{
+ set_signal_action(SIG_DFL);
+}
+
+static RETSIGTYPE
+chld_changed()
+{
+ int cpid;
+ int i,n = -1;
+ int statusp;
+
+ for (;;) {
+#ifdef HAVE_WAITPID
+ cpid = waitpid(-1, &statusp, WUNTRACED|WNOHANG);
+#else
+ cpid = wait3(&statusp, WUNTRACED|WNOHANG, 0);
+#endif
+ if (cpid == 0 || cpid == -1)
+ return;
+ for (i = 0; i < last_pty; i++) {
+ if (chld_pid[i] == cpid) {
+ n = i;
+ goto catched;
+ }
+ }
+ rb_raise(rb_eRuntimeError, "fork: %d", cpid);
+ }
+ catched:
+
+#ifdef IF_STOPPED
+ if (IF_STOPPED(statusp)) { /* suspend */
+ rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
+ }
+#else
+#ifdef WIFSTOPPED
+ if (WIFSTOPPED(statusp)) { /* suspend */
+ rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
+ }
+#else
+---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
+#endif /* WIFSTOPPED */
+#endif /* IF_STOPPED */
+ if (n >= 0) {
+ chld_pid[n] = 0;
+ n_pty--;
+ if (n_pty == 0)
+ reset_signal_action();
+ }
+ rb_raise(rb_eRuntimeError, "Child_changed: %d",cpid);
+}
+
+static void getDevice _((int*, int*));
+
+static void
+establishShell(shellname, info)
+ char *shellname;
+ struct pty_info *info;
+{
+ static int i,j,master,slave,currentPid;
+ char *p,*getenv();
+ struct passwd *pwent;
+ RETSIGTYPE chld_changed();
+
+ if (shellname[0] == '\0') {
+ if ((p = getenv("SHELL")) != NULL) {
+ shellname = p;
+ }
+ else {
+ pwent = getpwuid(getuid());
+ if (pwent && pwent->pw_shell)
+ shellname = pwent->pw_shell;
+ else
+ shellname = "/bin/sh";
+ }
+ }
+ getDevice(&master,&slave);
+
+ currentPid = getpid();
+ set_signal_action(chld_changed);
+ if((i = vfork()) < 0) {
+ rb_sys_fail("fork failed");
+ }
+
+ if(i == 0) { /* child */
+ int argc;
+ char *argv[1024];
+ currentPid = getpid();
+
+ /*
+ * Set free from process group and controlling terminal
+ */
+#ifdef HAVE_SETSID
+ (void) setsid();
+#else /* HAS_SETSID */
+# ifdef HAVE_SETPGRP
+# ifdef SETGRP_VOID
+ if (setpgrp() == -1)
+ perror("setpgrp()");
+# else /* SETGRP_VOID */
+ if (setpgrp(0, currentPid) == -1)
+ rb_sys_fail("setpgrp()");
+ if ((i = open("/dev/tty", O_RDONLY)) < 0)
+ rb_sys_fail("/dev/tty");
+ else {
+ if (ioctl(i, TIOCNOTTY, (char *)0))
+ perror("ioctl(TIOCNOTTY)");
+ close(i);
+ }
+# endif /* SETGRP_VOID */
+# endif /* HAVE_SETPGRP */
+#endif /* HAS_SETSID */
+
+ /*
+ * obtain new controlling terminal
+ */
+#if defined(TIOCSCTTY)
+ close(master);
+ (void) ioctl(slave, TIOCSCTTY, (char *)0);
+ /* errors ignored for sun */
+#else
+ close(slave);
+ slave = open(SlaveName, O_RDWR);
+ if (slave < 0) {
+ perror("open: pty slave");
+ _exit(1);
+ }
+ close(master);
+#endif
+ dup2(slave,0);
+ dup2(slave,1);
+ dup2(slave,2);
+ close(slave);
+
+ seteuid(getuid());
+
+ argc = 0;
+ for (i = 0; shellname[i];) {
+ while (isspace(shellname[i])) i++;
+ for (j = i; shellname[j] && !isspace(shellname[j]); j++);
+ argv[argc] = (char*)xmalloc(j-i+1);
+ strncpy(argv[argc],&shellname[i],j-i);
+ argv[argc][j-i] = 0;
+ i = j;
+ argc++;
+ }
+ argv[argc] = NULL;
+ execvp(argv[0],argv);
+ sleep(1);
+ _exit(1);
+ }
+
+ close(slave);
+
+ if (n_pty == last_pty) {
+ chld_pid[n_pty] = i;
+ n_pty++;
+ last_pty++;
+ }
+ else {
+ for (j = 0; j < last_pty; j++) {
+ if (chld_pid[j] == 0) {
+ chld_pid[j] = i;
+ n_pty++;
+ }
+ }
+ }
+ info->child_pid = i;
+ info->fd = master;
+}
+
+#ifdef HAVE_OPENPTY
+/*
+ * Use openpty(3) of 4.3BSD Reno and later,
+ * or the same interface function.
+ */
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ if (openpty(master, slave, SlaveName,
+ (struct termios *)0, (struct winsize *)0) == -1) {
+ rb_raise(rb_eRuntimeError, "openpty() failed");
+ }
+}
+#else /* HAVE_OPENPTY */
+#ifdef HAVE__GETPTY
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ char *name;
+
+ if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
+ rb_raise(rb_eRuntimeError, "_getpty() failed");
+ }
+
+ *slave = open(name, O_RDWR);
+ strcpy(SlaveName, name);
+}
+#else /* HAVE__GETPTY */
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ char **p;
+ int i,j;
+ char MasterName[DEVICELEN];
+
+#ifdef HAVE_DEV_PTMX
+ char *pn;
+ void (*s)();
+
+ extern char *ptsname(int);
+ extern int unlockpt(int);
+ extern int grantpt(int);
+
+ if((i = open("/dev/ptmx", O_RDWR, 0)) != -1) {
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(i) != -1) {
+ signal(SIGCHLD, s);
+ if(unlockpt(i) != -1) {
+ if((pn = ptsname(i)) != NULL) {
+ if((j = open(pn, O_RDWR, 0)) != -1) {
+#if defined I_PUSH
+ if(ioctl(j, I_PUSH, "ptem") != -1) {
+ if(ioctl(j, I_PUSH, "ldterm") != -1) {
+#endif
+ *master = i;
+ *slave = j;
+ strcpy(SlaveName, pn);
+ return;
+#if defined I_PUSH
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ close(i);
+ }
+ rb_raise(rb_eRuntimeError, "Cannot get Master/Slave device");
+#else
+ for (p = deviceNo; *p != NULL; p++) {
+ sprintf(MasterName ,MasterDevice,*p);
+ if ((i = open(MasterName,O_RDWR,0)) >= 0) {
+ *master = i;
+ sprintf(SlaveName ,SlaveDevice,*p);
+ if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
+ *slave = j;
+ chown(SlaveName, getuid(), getgid());
+ chmod(SlaveName, 0622);
+ return;
+ }
+ close(i);
+ }
+ }
+ rb_raise(rb_eRuntimeError, "Cannot get %s\n", SlaveDevice);
+#endif
+}
+#endif /* HAVE__GETPTY */
+#endif /* HAVE_OPENPTY */
+
+static void
+freeDevice()
+{
+ chmod(SlaveName, 0666);
+ chown(SlaveName, 0, 0);
+}
+
+/* ruby function: getpty */
+static VALUE
+pty_getpty(self, shell)
+ VALUE self, shell;
+{
+ VALUE res;
+ struct pty_info info;
+ OpenFile *wfptr,*rfptr;
+ NEWOBJ(rport, struct RFile);
+ NEWOBJ(wport, struct RFile);
+
+ if (n_pty == MAX_PTY+1) {
+ rb_raise(rb_eRuntimeError, "Too many ptys are open");
+ }
+
+ OBJSETUP(rport, rb_cFile, T_FILE);
+ MakeOpenFile(rport, rfptr);
+
+ OBJSETUP(wport, rb_cFile, T_FILE);
+ MakeOpenFile(wport, wfptr);
+
+ establishShell(RSTRING(shell)->ptr,&info);
+
+ rfptr->mode = rb_io_mode_flags("r");
+ rfptr->f = fdopen(info.fd, "r");
+ rfptr->path = strdup(RSTRING(shell)->ptr);
+
+ wfptr->mode = rb_io_mode_flags("w");
+ wfptr->f = fdopen(dup(info.fd), "w");
+ wfptr->path = strdup(RSTRING(shell)->ptr);
+
+ res = rb_ary_new2(2);
+ rb_ary_store(res,0,(VALUE)rport);
+ rb_ary_store(res,1,(VALUE)wport);
+ rb_ary_store(res,2,INT2FIX(info.child_pid));
+
+ if (rb_iterator_p()) {
+ rb_yield((VALUE)res);
+ reset_signal_action();
+ return Qnil;
+ }
+ else {
+ return (VALUE)res;
+ }
+}
+
+/* ruby function: protect_signal */
+static VALUE
+pty_protect(self)
+ VALUE self;
+{
+ reset_signal_action();
+ rb_yield(Qnil);
+ set_signal_action(chld_changed);
+ return self;
+}
+
+static VALUE
+pty_reset_signal(self)
+ VALUE self;
+{
+ reset_signal_action();
+ return self;
+}
+
+static VALUE cPTY;
+
+void
+Init_pty()
+{
+ cPTY = rb_define_module("PTY");
+ rb_define_module_function(cPTY,"getpty",pty_getpty,1);
+ rb_define_module_function(cPTY,"spawn",pty_getpty,1);
+ rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
+ rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
+}
diff --git a/ext/pty/script.rb b/ext/pty/script.rb
new file mode 100644
index 0000000000..6aaafec061
--- /dev/null
+++ b/ext/pty/script.rb
@@ -0,0 +1,38 @@
+require 'pty'
+
+if ARGV.size == 0 then
+ ofile = "typescript"
+else
+ ofile = ARGV[0]
+end
+
+logfile = File.open(ofile,"a")
+
+system "stty -echo raw lnext ^_"
+
+PTY.spawn("/bin/csh") do
+ |r_pty,w_pty,pid|
+
+ Thread.new do
+ while true
+ w_pty.print STDIN.getc.chr
+ w_pty.flush
+ end
+ end
+
+ begin
+ while true
+ c = r_pty.getc
+ next if c.nil?
+ print c.chr
+ STDOUT.flush
+ logfile.print c.chr
+ end
+ rescue
+ # print $@,':',$!,"\n"
+ logfile.close
+ end
+end
+
+system "stty echo -raw lnext ^v"
+
diff --git a/ext/pty/shl.rb b/ext/pty/shl.rb
new file mode 100644
index 0000000000..0c04a2735c
--- /dev/null
+++ b/ext/pty/shl.rb
@@ -0,0 +1,96 @@
+#
+# old-fashioned 'shl' like program
+# by A. Ito
+#
+# commands:
+# c creates new shell
+# C-z suspends shell
+# p lists all shell
+# 0,1,... choose shell
+# q quit
+
+require 'pty'
+
+$shells = []
+$n_shells = 0
+
+$r_pty = nil
+$w_pty = nil
+
+def writer
+ PTY.protect_signal do
+ system "stty -echo raw"
+ end
+ begin
+ while true
+ c = STDIN.getc
+ if c == 26 then # C-z
+ $reader.raise(nil)
+ return 'Suspend'
+ end
+ $w_pty.print c.chr
+ $w_pty.flush
+ end
+ rescue
+ $reader.raise(nil)
+ return 'Exit'
+ ensure
+ PTY.protect_signal do
+ system "stty echo -raw"
+ end
+ end
+end
+
+$reader = Thread.new {
+ while true
+ begin
+ next if $r_pty.nil?
+ c = $r_pty.getc
+ if c.nil? then
+ Thread.stop
+ end
+ print c.chr
+ STDOUT.flush
+ rescue
+ Thread.stop
+ end
+ end
+}
+
+# $reader.raise(nil)
+
+
+while true
+ print ">> "
+ STDOUT.flush
+ case gets
+ when /^c/i
+ $shells[$n_shells] = PTY.spawn("/bin/csh")
+ $r_pty,$w_pty = $shells[$n_shells]
+ $n_shells += 1
+ $reader.run
+ if writer == 'Exit'
+ $n_shells -= 1
+ $shells[$n_shells] = nil
+ end
+ when /^p/i
+ for i in 0..$n_shells
+ unless $shells[i].nil?
+ print i,"\n"
+ end
+ end
+ when /^([0-9]+)/
+ n = $1.to_i
+ if $shells[n].nil?
+ print "\##{i} doesn't exist\n"
+ else
+ $r_pty,$w_pty = $shells[n]
+ $reader.run
+ if writer == 'Exit' then
+ $shells[n] = nil
+ end
+ end
+ when /^q/i
+ exit
+ end
+end
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index e55233eb20..3dd9c0fc1e 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -1,6 +1,9 @@
require "mkmf"
+dir_config("readline")
+have_library("user32", nil) if /cygwin/ === PLATFORM
have_library("termcap", "tgetnum")
+have_library("curses", "tgetnum")
if have_header("readline/readline.h") and
have_header("readline/history.h") and
have_library("readline", "readline")
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 9e471195e6..02b29796af 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -19,13 +19,14 @@ static int
readline_event()
{
CHECK_INTS;
-#ifdef USE_THREAD
rb_thread_schedule();
-#endif
}
static VALUE
-readline_readline(int argc, VALUE *argv, VALUE self)
+readline_readline(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
VALUE tmp, add_hist, result;
char *prompt = NULL;
@@ -47,7 +48,9 @@ readline_readline(int argc, VALUE *argv, VALUE self)
}
static VALUE
-readline_s_set_completion_proc(VALUE self, VALUE proc)
+readline_s_set_completion_proc(self, proc)
+ VALUE self;
+ VALUE proc;
{
if (!rb_respond_to(proc, rb_intern("call")))
rb_raise(rb_eArgError, "argument have to respond to `call'");
@@ -55,25 +58,32 @@ readline_s_set_completion_proc(VALUE self, VALUE proc)
}
static VALUE
-readline_s_get_completion_proc(VALUE self)
+readline_s_get_completion_proc(self)
+ VALUE self;
{
return rb_iv_get(mReadline, COMPLETION_PROC);
}
static VALUE
-readline_s_set_completion_case_fold(VALUE self, VALUE val)
+readline_s_set_completion_case_fold(self, val)
+ VALUE self;
+ VALUE val;
{
return rb_iv_set(mReadline, COMPLETION_CASE_FOLD, val);
}
static VALUE
-readline_s_get_completion_case_fold(VALUE self)
+readline_s_get_completion_case_fold(self)
+ VALUE self;
{
return rb_iv_get(mReadline, COMPLETION_CASE_FOLD);
}
static char **
-readline_attempted_completion_function(char *text, int start, int end)
+readline_attempted_completion_function(text, start, end)
+ char *text;
+ int start;
+ int end;
{
VALUE proc, ary, temp;
char **result;
@@ -81,6 +91,8 @@ readline_attempted_completion_function(char *text, int start, int end)
int i, matches;
proc = rb_iv_get(mReadline, COMPLETION_PROC);
+ if (NIL_P(proc))
+ return NULL;
rl_attempted_completion_over = 1;
case_fold = RTEST(rb_iv_get(mReadline, COMPLETION_CASE_FOLD));
ary = rb_funcall(proc, rb_intern("call"), 1, rb_str_new2(text));
@@ -133,27 +145,32 @@ readline_attempted_completion_function(char *text, int start, int end)
}
static VALUE
-readline_s_vi_editing_mode(VALUE self)
+readline_s_vi_editing_mode(self)
+ VALUE self;
{
- rl_vi_editing_mode();
+ rl_vi_editing_mode(1,0);
return Qnil;
}
static VALUE
-readline_s_emacs_editing_mode(VALUE self)
+readline_s_emacs_editing_mode(self)
+ VALUE self;
{
- rl_emacs_editing_mode();
+ rl_emacs_editing_mode(1,0);
return Qnil;
}
static VALUE
-hist_to_s(VALUE self)
+hist_to_s(self)
+ VALUE self;
{
return rb_str_new2("HISTORY");
}
static VALUE
-hist_get(VALUE self, VALUE index)
+hist_get(self, index)
+ VALUE self;
+ VALUE index;
{
HISTORY_STATE *state;
int i;
@@ -167,7 +184,10 @@ hist_get(VALUE self, VALUE index)
}
static VALUE
-hist_set(VALUE self, VALUE index, VALUE str)
+hist_set(self, index, str)
+ VALUE self;
+ VALUE index;
+ VALUE str;
{
HISTORY_STATE *state;
int i;
@@ -182,15 +202,19 @@ hist_set(VALUE self, VALUE index, VALUE str)
}
static VALUE
-hist_push(VALUE self, VALUE str)
+hist_push(self, str)
+ VALUE self;
+ VALUE str;
{
add_history(STR2CSTR(str));
return self;
}
static VALUE
-hist_push_method(int argc, VALUE *argv,
- VALUE self)
+hist_push_method(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
VALUE str;
@@ -202,7 +226,8 @@ hist_push_method(int argc, VALUE *argv,
}
static VALUE
-hist_pop(VALUE self)
+hist_pop(self)
+ VALUE self;
{
HISTORY_STATE *state;
HIST_ENTRY *entry;
@@ -217,7 +242,8 @@ hist_pop(VALUE self)
}
static VALUE
-hist_shift(VALUE self)
+hist_shift(self)
+ VALUE self;
{
HISTORY_STATE *state;
HIST_ENTRY *entry;
@@ -232,7 +258,8 @@ hist_shift(VALUE self)
}
static VALUE
-hist_each(VALUE self)
+hist_each(self)
+ VALUE self;
{
HISTORY_STATE *state;
int i;
@@ -241,11 +268,12 @@ hist_each(VALUE self)
for (i = 0; i < state->length; i++) {
rb_yield(rb_str_new2(state->entries[i]->line));
}
- return Qnil;
+ return self;
}
static VALUE
-hist_length(VALUE self)
+hist_length(self)
+ VALUE self;
{
HISTORY_STATE *state;
@@ -254,7 +282,8 @@ hist_length(VALUE self)
}
static VALUE
-hist_empty_p(VALUE self)
+hist_empty_p(self)
+ VALUE self;
{
HISTORY_STATE *state;
@@ -266,7 +295,9 @@ hist_empty_p(VALUE self)
}
static VALUE
-hist_delete_at(VALUE self, VALUE index)
+hist_delete_at(self, index)
+ VALUE self;
+ VALUE index;
{
HISTORY_STATE *state;
HIST_ENTRY *entry;
@@ -282,7 +313,9 @@ hist_delete_at(VALUE self, VALUE index)
}
static VALUE
-filename_completion_proc_call(VALUE self, VALUE str)
+filename_completion_proc_call(self, str)
+ VALUE self;
+ VALUE str;
{
VALUE result;
char **matches;
@@ -307,7 +340,9 @@ filename_completion_proc_call(VALUE self, VALUE str)
}
static VALUE
-username_completion_proc_call(VALUE self, VALUE str)
+username_completion_proc_call(self, str)
+ VALUE self;
+ VALUE str;
{
VALUE result;
char **matches;
@@ -332,7 +367,7 @@ username_completion_proc_call(VALUE self, VALUE str)
}
void
-Init_readline(void)
+Init_readline()
{
VALUE histary, fcomp, ucomp;
diff --git a/ext/sdbm/MANIFEST b/ext/sdbm/MANIFEST
new file mode 100644
index 0000000000..d0ed99ba77
--- /dev/null
+++ b/ext/sdbm/MANIFEST
@@ -0,0 +1,5 @@
+MANIFEST
+_sdbm.c
+extconf.rb
+init.c
+sdbm.h
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
new file mode 100644
index 0000000000..a07cc55f6b
--- /dev/null
+++ b/ext/sdbm/_sdbm.c
@@ -0,0 +1,977 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * core routines
+ */
+
+#ifndef lint
+/*char sdbm_rcsid[] = "$Id$";*/
+#endif
+
+#include "sdbm.h"
+#include "config.h"
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#define BYTESIZ 8
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef BSD42
+#define SEEK_SET L_SET
+#define memset(s,c,n) bzero(s, n) /* only when c is zero */
+#define memcpy(s1,s2,n) bcopy(s2, s1, n)
+#define memcmp(s1,s2,n) bcmp(s1,s2,n)
+#endif
+
+/*
+ * important tuning parms (hah)
+ */
+
+#define SEEDUPS /* always detect duplicates */
+#define BADMESS /* generate a message for worst case:
+ cannot make room after SPLTMAX splits */
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
+
+#ifdef BIG_E
+#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
+#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
+#else
+#define GET_SHORT(p, i) ((p)[i])
+#define PUT_SHORT(p, i, s) ((p)[i] = (s))
+#endif
+
+/*#include "pair.h"*/
+static int fitpair proto((char *, int));
+static void putpair proto((char *, datum, datum));
+static datum getpair proto((char *, datum));
+static int delpair proto((char *, datum));
+static int chkpage proto((char *));
+static datum getnkey proto((char *, int));
+static void splpage proto((char *, char *, long));
+#ifdef SEEDUPS
+static int duppair proto((char *, datum));
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef MSDOS
+#include <io.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef BSD42
+#include <sys/file.h>
+#else
+#include <fcntl.h>
+/*#include <memory.h>*/
+#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include <errno.h>
+#ifndef EPERM
+#define EPERM EACCES
+#endif
+#include <string.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * externals
+ */
+#ifndef sun
+#ifndef MSDOS
+extern int errno;
+#endif
+#endif
+
+/*
+ * forward
+ */
+static int getdbit proto((DBM *, long));
+static int setdbit proto((DBM *, long));
+static int getpage proto((DBM *, long));
+static datum getnext proto((DBM *));
+static int makroom proto((DBM *, long, int));
+
+/*
+ * useful macros
+ */
+#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+#define ioerr(db) ((db)->flags |= DBM_IOERR)
+
+#define OFF_PAG(off) (long) (off) * PBLKSIZ
+#define OFF_DIR(off) (long) (off) * DBLKSIZ
+
+static long masks[] = {
+ 000000000000L, 000000000001L, 000000000003L,
+ 000000000007L, 000000000017L, 000000000037L,
+ 000000000077L, 000000000177L, 000000000377L,
+ 000000000777L, 000000001777L, 000000003777L,
+ 000000007777L, 000000017777L, 000000037777L,
+ 000000077777L, 000000177777L, 000000377777L,
+ 000000777777L, 000001777777L, 000003777777L,
+ 000007777777L, 000017777777L, 000037777777L,
+ 000077777777L, 000177777777L, 000377777777L,
+ 000777777777L, 001777777777L, 003777777777L,
+ 007777777777L, 017777777777L
+};
+
+datum nullitem = {NULL, 0};
+
+DBM *
+sdbm_open(file, flags, mode)
+register char *file;
+register int flags;
+register int mode;
+{
+ register DBM *db;
+ register char *dirname;
+ register char *pagname;
+ register int n;
+
+ if (file == NULL || !*file)
+ return errno = EINVAL, (DBM *) NULL;
+/*
+ * need space for two seperate filenames
+ */
+ n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
+
+ if ((dirname = malloc((unsigned) n)) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+/*
+ * build the file names
+ */
+ dirname = strcat(strcpy(dirname, file), DIRFEXT);
+ pagname = strcpy(dirname + strlen(dirname) + 1, file);
+ pagname = strcat(pagname, PAGFEXT);
+
+ db = sdbm_prep(dirname, pagname, flags, mode);
+ free((char *) dirname);
+ return db;
+}
+
+DBM *
+sdbm_prep(dirname, pagname, flags, mode)
+char *dirname;
+char *pagname;
+int flags;
+int mode;
+{
+ register DBM *db;
+ struct stat dstat;
+
+ if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+
+ db->flags = 0;
+ db->hmask = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+/*
+ * adjust user flags so that WRONLY becomes RDWR,
+ * as required by this package. Also set our internal
+ * flag for RDONLY.
+ */
+ if (flags & O_WRONLY)
+ flags = (flags & ~O_WRONLY) | O_RDWR;
+ if (flags & O_RDONLY)
+ db->flags = DBM_RDONLY;
+/*
+ * open the files in sequence, and stat the dirfile.
+ * If we fail anywhere, undo everything, return NULL.
+ */
+#ifdef MSDOS
+ flags |= O_BINARY;
+#endif
+ if ((db->pagf = open(pagname, flags, mode)) > -1) {
+ if ((db->dirf = open(dirname, flags, mode)) > -1) {
+/*
+ * need the dirfile size to establish max bit number.
+ */
+ if (fstat(db->dirf, &dstat) == 0) {
+/*
+ * zero size: either a fresh database, or one with a single,
+ * unsplit data page: dirpage is all zeros.
+ */
+ db->dirbno = (!dstat.st_size) ? 0 : -1;
+ db->pagbno = -1;
+ db->maxbno = dstat.st_size * (long) BYTESIZ;
+
+ (void) memset(db->pagbuf, 0, PBLKSIZ);
+ (void) memset(db->dirbuf, 0, DBLKSIZ);
+ /*
+ * success
+ */
+ return db;
+ }
+ (void) close(db->dirf);
+ }
+ (void) close(db->pagf);
+ }
+ free((char *) db);
+ return (DBM *) NULL;
+}
+
+void
+sdbm_close(db)
+register DBM *db;
+{
+ if (db == NULL)
+ errno = EINVAL;
+ else {
+ (void) close(db->dirf);
+ (void) close(db->pagf);
+ free((char *) db);
+ }
+}
+
+datum
+sdbm_fetch(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, nullitem;
+
+ if (getpage(db, exhash(key)))
+ return getpair(db->pagbuf, key);
+
+ return ioerr(db), nullitem;
+}
+
+int
+sdbm_delete(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ if (getpage(db, exhash(key))) {
+ if (!delpair(db->pagbuf, key))
+ return -1;
+/*
+ * update the page file
+ */
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+int
+sdbm_store(db, key, val, flags)
+register DBM *db;
+datum key;
+datum val;
+int flags;
+{
+ int need;
+ register long hash;
+
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ need = key.dsize + val.dsize;
+/*
+ * is the pair too big (or too small) for this database ??
+ */
+ if (need < 0 || need > PAIRMAX)
+ return errno = EINVAL, -1;
+
+ if (getpage(db, (hash = exhash(key)))) {
+/*
+ * if we need to replace, delete the key/data pair
+ * first. If it is not there, ignore.
+ */
+ if (flags == DBM_REPLACE)
+ (void) delpair(db->pagbuf, key);
+#ifdef SEEDUPS
+ else if (duppair(db->pagbuf, key))
+ return 1;
+#endif
+/*
+ * if we do not have enough room, we have to split.
+ */
+ if (!fitpair(db->pagbuf, need))
+ if (!makroom(db, hash, need))
+ return ioerr(db), -1;
+/*
+ * we have enough room or split is successful. insert the key,
+ * and update the page file.
+ */
+ (void) putpair(db->pagbuf, key, val);
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+ /*
+ * success
+ */
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static int
+makroom(db, hash, need)
+register DBM *db;
+long hash;
+int need;
+{
+ long newp;
+ char twin[PBLKSIZ];
+#ifdef MSDOS
+ char zer[PBLKSIZ];
+ long oldtail;
+#endif
+ char *pag = db->pagbuf;
+ char *new = twin;
+ register int smax = SPLTMAX;
+
+ do {
+/*
+ * split the current page
+ */
+ (void) splpage(pag, new, db->hmask + 1);
+/*
+ * address of the new page
+ */
+ newp = (hash & db->hmask) | (db->hmask + 1);
+ debug(("newp: %ld\n", newp));
+/*
+ * write delay, read avoidence/cache shuffle:
+ * select the page for incoming pair: if key is to go to the new page,
+ * write out the previous one, and copy the new one over, thus making
+ * it the current page. If not, simply write the new page, and we are
+ * still looking at the page of interest. current page is not updated
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
+ */
+
+#ifdef MSDOS
+ /*
+ * Fill hole with 0 if made it.
+ * (hole is NOT read as 0)
+ */
+ oldtail = lseek(db->pagf, 0L, SEEK_END);
+ memset(zer, 0, PBLKSIZ);
+ while (OFF_PAG(newp) > oldtail) {
+ if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
+ write(db->pagf, zer, PBLKSIZ) < 0) {
+
+ return 0;
+ }
+ oldtail += PBLKSIZ;
+ }
+#endif
+
+ if (hash & (db->hmask + 1)) {
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ db->pagbno = newp;
+ (void) memcpy(pag, new, PBLKSIZ);
+ }
+ else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
+ || write(db->pagf, new, PBLKSIZ) < 0)
+ return 0;
+
+ if (!setdbit(db, db->curbit))
+ return 0;
+/*
+ * see if we have enough room now
+ */
+ if (fitpair(pag, need))
+ return 1;
+/*
+ * try again... update curbit and hmask as getpage would have
+ * done. because of our update of the current page, we do not
+ * need to read in anything. BUT we have to write the current
+ * [deferred] page out, as the window of failure is too great.
+ */
+ db->curbit = 2 * db->curbit +
+ ((hash & (db->hmask + 1)) ? 2 : 1);
+ db->hmask |= (db->hmask + 1);
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+
+ } while (--smax);
+/*
+ * if we are here, this is real bad news. After SPLTMAX splits,
+ * we still cannot fit the key. say goodnight.
+ */
+#ifdef BADMESS
+ (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+ return 0;
+
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+datum
+sdbm_firstkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+/*
+ * start at page 0
+ */
+ (void) memset(db->pagbuf, 0, PBLKSIZ);
+ if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), nullitem;
+ db->pagbno = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+
+ return getnext(db);
+}
+
+datum
+sdbm_nextkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+ return getnext(db);
+}
+
+/*
+ * all important binary trie traversal
+ */
+static int
+getpage(db, hash)
+register DBM *db;
+register long hash;
+{
+ register int hbit;
+ register long dbit;
+ register long pagb;
+
+ dbit = 0;
+ hbit = 0;
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
+
+ debug(("dbit: %d...", dbit));
+
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+/*
+ * see if the block we need is already in memory.
+ * note: this lookaside cache has about 10% hit rate.
+ */
+ if (pagb != db->pagbno) {
+/*
+ * note: here, we assume a "hole" is read as 0s.
+ * if not, must zero pagbuf first.
+ */
+ (void) memset(db->pagbuf, 0, PBLKSIZ);
+
+ if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ if (!chkpage(db->pagbuf)) {
+ return 0;
+ }
+ db->pagbno = pagb;
+
+ debug(("pag read: %d\n", pagb));
+ }
+ return 1;
+}
+
+static int
+getdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
+}
+
+static int
+setdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
+
+ if (dbit >= db->maxbno)
+ db->maxbno += (long) DBLKSIZ * BYTESIZ;
+
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * getnext - get the next key in the page, and if done with
+ * the page, try the next page in sequence
+ */
+static datum
+getnext(db)
+register DBM *db;
+{
+ datum key;
+
+ for (;;) {
+ db->keyptr++;
+ key = getnkey(db->pagbuf, db->keyptr);
+ if (key.dptr != NULL)
+ return key;
+/*
+ * we either run out, or there is nothing on this page..
+ * try the next one... If we lost our position on the
+ * file, we will have to seek.
+ */
+ db->keyptr = 0;
+ if (db->pagbno != db->blkptr++)
+ if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
+ break;
+ db->pagbno = db->blkptr;
+ if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
+ break;
+ if (!chkpage(db->pagbuf)) {
+ break;
+ }
+ }
+
+ return ioerr(db), nullitem;
+}
+
+/* pair.c */
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * page-level routines
+ */
+
+#ifndef lint
+/*char pair_rcsid[] = "$Id$";*/
+#endif
+
+#ifndef BSD42
+/*#include <memory.h>*/
+#endif
+
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/*
+ * forward
+ */
+static int seepair proto((char *, int, char *, int));
+
+/*
+ * page format:
+ * +------------------------------+
+ * ino | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | - - - ----> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * calculating the offsets for free area: if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+static int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+ register int n;
+ register int off;
+ register int free;
+ register short *ino = (short *) pag;
+
+ off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
+ free = off - (n + 1) * sizeof(short);
+ need += 2 * sizeof(short);
+
+ debug(("free %d need %d\n", free, need));
+
+ return need <= free;
+}
+
+static void
+putpair(pag, key, val)
+char *pag;
+datum key;
+datum val;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
+/*
+ * enter the key first
+ */
+ off -= key.dsize;
+ if (key.dsize)
+ (void) memcpy(pag + off, key.dptr, key.dsize);
+ PUT_SHORT(ino,n + 1,off);
+/*
+ * now the data
+ */
+ off -= val.dsize;
+ if (val.dsize)
+ (void) memcpy(pag + off, val.dptr, val.dsize);
+ PUT_SHORT(ino,n + 2,off);
+/*
+ * adjust item count
+ */
+ PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
+}
+
+static datum
+getpair(pag, key)
+char *pag;
+datum key;
+{
+ register int i;
+ register int n;
+ datum val;
+ register short *ino = (short *) pag;
+
+ if ((n = GET_SHORT(ino,0)) == 0)
+ return nullitem;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return nullitem;
+
+ val.dptr = pag + GET_SHORT(ino,i + 1);
+ val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
+ return val;
+}
+
+#ifdef SEEDUPS
+static int
+duppair(pag, key)
+char *pag;
+datum key;
+{
+ register short *ino = (short *) pag;
+ return GET_SHORT(ino,0) > 0 &&
+ seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
+}
+#endif
+
+static datum
+getnkey(pag, num)
+char *pag;
+int num;
+{
+ datum key;
+ register int off;
+ register short *ino = (short *) pag;
+
+ num = num * 2 - 1;
+ if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
+ return nullitem;
+
+ off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
+
+ key.dptr = pag + GET_SHORT(ino,num);
+ key.dsize = off - GET_SHORT(ino,num);
+
+ return key;
+}
+
+static int
+delpair(pag, key)
+char *pag;
+datum key;
+{
+ register int n;
+ register int i;
+ register short *ino = (short *) pag;
+
+ if ((n = GET_SHORT(ino,0)) == 0)
+ return 0;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+ if (i < n - 1) {
+ register int m;
+ register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
+ register char *src = pag + GET_SHORT(ino,i + 1);
+ register int zoo = dst - src;
+
+ debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+ m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
+#ifdef DUFF
+#define MOVB *--dst = *--src
+
+ if (m > 0) {
+ register int loop = (m + 8 - 1) >> 3;
+
+ switch (m & (8 - 1)) {
+ case 0: do {
+ MOVB; case 7: MOVB;
+ case 6: MOVB; case 5: MOVB;
+ case 4: MOVB; case 3: MOVB;
+ case 2: MOVB; case 1: MOVB;
+ } while (--loop);
+ }
+ }
+#else
+#ifdef MEMMOVE
+ memmove(dst, src, m);
+#else
+ while (m--)
+ *--dst = *--src;
+#endif
+#endif
+/*
+ * adjust offset index up
+ */
+ while (i < n - 1) {
+ PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
+ i++;
+ }
+ }
+ PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
+ return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+ register int i;
+ register int off = PBLKSIZ;
+ register short *ino = (short *) pag;
+
+ for (i = 1; i < n; i += 2) {
+ if (siz == off - GET_SHORT(ino,i) &&
+ memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
+ return i;
+ off = GET_SHORT(ino,i + 1);
+ }
+ return 0;
+}
+
+static void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+ datum key;
+ datum val;
+
+ register int n;
+ register int off = PBLKSIZ;
+ char cur[PBLKSIZ];
+ register short *ino = (short *) cur;
+
+ (void) memcpy(cur, pag, PBLKSIZ);
+ (void) memset(pag, 0, PBLKSIZ);
+ (void) memset(new, 0, PBLKSIZ);
+
+ n = GET_SHORT(ino,0);
+ for (ino++; n > 0; ino += 2) {
+ key.dptr = cur + GET_SHORT(ino,0);
+ key.dsize = off - GET_SHORT(ino,0);
+ val.dptr = cur + GET_SHORT(ino,1);
+ val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+ (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+ off = GET_SHORT(ino,1);
+ n -= 2;
+ }
+
+ debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
+ ((short *) new)[0] / 2,
+ ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity:
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+static int
+chkpage(pag)
+char *pag;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (n > 0) {
+ off = PBLKSIZ;
+ for (ino++; n > 0; ino += 2) {
+ if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
+ GET_SHORT(ino,1) > GET_SHORT(ino,0))
+ return 0;
+ off = GET_SHORT(ino,1);
+ n -= 2;
+ }
+ }
+ return 1;
+}
+
+/* hash.c */
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599 nice.
+ * 65587 even better.
+ */
+long
+sdbm_hash(str, len)
+register char *str;
+register int len;
+{
+ register unsigned long n = 0;
+
+#ifdef DUFF
+
+#define HASHC n = *str++ + 65599 * n
+
+ if (len > 0) {
+ register int loop = (len + 8 - 1) >> 3;
+
+ switch(len & (8 - 1)) {
+ case 0: do {
+ HASHC; case 7: HASHC;
+ case 6: HASHC; case 5: HASHC;
+ case 4: HASHC; case 3: HASHC;
+ case 2: HASHC; case 1: HASHC;
+ } while (--loop);
+ }
+
+ }
+#else
+ while (len--)
+ n = ((*str++) & 255) + 65587L * n;
+#endif
+ return n;
+}
diff --git a/ext/sdbm/extconf.rb b/ext/sdbm/extconf.rb
new file mode 100644
index 0000000000..cc6c8cefd1
--- /dev/null
+++ b/ext/sdbm/extconf.rb
@@ -0,0 +1,3 @@
+require 'mkmf'
+
+create_makefile("sdbm")
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
new file mode 100644
index 0000000000..5ebffcb9fd
--- /dev/null
+++ b/ext/sdbm/init.c
@@ -0,0 +1,584 @@
+/************************************************
+
+ sdbminit.c -
+
+ $Author$
+ $Date$
+ created at: Fri May 7 08:34:24 JST 1999
+
+ Copyright (C) 1995-1998 Yukihiro Matsumoto
+
+************************************************/
+
+#include "ruby.h"
+
+#include "sdbm.h"
+#include <fcntl.h>
+#include <errno.h>
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
+
+VALUE cSDBM;
+
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
+static void
+closed_sdbm()
+{
+ rb_raise(rb_eRuntimeError, "closed SDBM file");
+}
+
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closed_sdbm();\
+}
+
+static void
+free_sdbm(dbmp)
+ struct dbmdata *dbmp;
+{
+
+ if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm);
+ free(dbmp);
+}
+
+static VALUE
+fsdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE file, vmode;
+ DBM *dbm;
+ struct dbmdata *dbmp;
+ int mode;
+ VALUE obj;
+
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ else if (NIL_P(vmode)) {
+ mode = -1; /* return nil if DB not exist */
+ }
+ else {
+ mode = NUM2INT(vmode);
+ }
+ Check_SafeStr(file);
+
+ dbm = 0;
+ if (mode >= 0)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
+ if (!dbm)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR, mode);
+ if (!dbm)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDONLY, mode);
+
+ if (!dbm) {
+ if (mode == -1) return Qnil;
+ rb_sys_fail(RSTRING(file)->ptr);
+ }
+
+ obj = Data_Make_Struct(klass,struct dbmdata,0,free_sdbm,dbmp);
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
+
+ return obj;
+}
+
+static VALUE
+fsdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_dbm == 0) closed_sdbm();
+ sdbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
+
+static VALUE
+fsdbm_fetch(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ value = sdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ return Qnil;
+ }
+ return rb_tainted_str_new(value.dptr, value.dsize);
+}
+
+static VALUE
+fsdbm_indexes(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE new;
+ int i;
+
+ new = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, fsdbm_fetch(obj, argv[i]));
+ }
+
+ return new;
+}
+
+static VALUE
+fsdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ rb_secure(4);
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ value = sdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ if (rb_iterator_p()) rb_yield(keystr);
+ return Qnil;
+ }
+
+ if (sdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_shift(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ key = sdbm_firstkey(dbm);
+ if (!key.dptr) return Qnil;
+ val = sdbm_fetch(dbm, key);
+ sdbm_delete(dbm, key);
+
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ return rb_assoc_new(keystr, valstr);
+}
+
+static VALUE
+fsdbm_delete_if(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
+ }
+ }
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_clear(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
+ }
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_invert(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+ VALUE hash = rb_hash_new();
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_hash_aset(hash, valstr, keystr);
+ }
+ return obj;
+}
+
+static VALUE
+each_pair(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
+}
+
+static VALUE fsdbm_store _((VALUE,VALUE,VALUE));
+
+static VALUE
+update_i(pair, dbm)
+ VALUE pair, dbm;
+{
+ Check_Type(pair, T_ARRAY);
+ if (RARRAY(pair)->len < 2) {
+ rb_raise(rb_eArgError, "pair must be [key, value]");
+ }
+ fsdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
+ return Qnil;
+}
+
+static VALUE
+fsdbm_update(obj, other)
+ VALUE obj, other;
+{
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fsdbm_replace(obj, other)
+ VALUE obj, other;
+{
+ fsdbm_clear(obj);
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fsdbm_store(obj, keystr, valstr)
+ VALUE obj, keystr, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ if (valstr == Qnil) {
+ fsdbm_delete(obj, keystr);
+ return Qnil;
+ }
+
+ rb_secure(4);
+ keystr = rb_obj_as_string(keystr);
+
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ if (NIL_P(valstr)) return fsdbm_delete(obj, keystr);
+
+ valstr = rb_obj_as_string(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ dbmp->di_size = -1;
+ dbm = dbmp->di_dbm;
+ if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
+#ifdef HAVE_DBM_CLAERERR
+ sdbm_clearerr(dbm);
+#endif
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eRuntimeError, "sdbm_store failed");
+ }
+
+ return valstr;
+}
+
+static VALUE
+fsdbm_length(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ int i = 0;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ i++;
+ }
+ dbmp->di_size = i;
+
+ return INT2FIX(i);
+}
+
+static VALUE
+fsdbm_empty_p(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ int i = 0;
+
+ Data_Get_Struct(obj, struct dbmdata, dbmp);
+ if (dbmp->di_size < 0) {
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ i++;
+ }
+ }
+ else {
+ i = dbmp->di_size;
+ }
+ if (i == 0) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_each_value(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_each_key(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_each_pair(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ struct dbmdata *dbmp;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_yield(rb_assoc_new(keystr, valstr));
+ }
+
+ return obj;
+}
+
+static VALUE
+fsdbm_keys(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fsdbm_values(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fsdbm_has_key(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ val = sdbm_fetch(dbm, key);
+ if (val.dptr) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_has_value(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ Check_Type(valstr, T_STRING);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_to_a(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize)));
+ }
+
+ return ary;
+}
+
+void
+Init_sdbm()
+{
+ cSDBM = rb_define_class("SDBM", rb_cObject);
+ rb_include_module(cSDBM, rb_mEnumerable);
+
+ rb_define_singleton_method(cSDBM, "open", fsdbm_s_open, -1);
+ rb_define_singleton_method(cSDBM, "new", fsdbm_s_open, -1);
+ rb_define_method(cSDBM, "close", fsdbm_close, 0);
+ rb_define_method(cSDBM, "[]", fsdbm_fetch, 1);
+ rb_define_method(cSDBM, "[]=", fsdbm_store, 2);
+ rb_define_method(cSDBM, "indexes", fsdbm_indexes, -1);
+ rb_define_method(cSDBM, "indices", fsdbm_indexes, -1);
+ rb_define_method(cSDBM, "length", fsdbm_length, 0);
+ rb_define_alias(cSDBM, "size", "length");
+ rb_define_method(cSDBM, "empty?", fsdbm_empty_p, 0);
+ rb_define_method(cSDBM, "each", fsdbm_each_pair, 0);
+ rb_define_method(cSDBM, "each_value", fsdbm_each_value, 0);
+ rb_define_method(cSDBM, "each_key", fsdbm_each_key, 0);
+ rb_define_method(cSDBM, "each_pair", fsdbm_each_pair, 0);
+ rb_define_method(cSDBM, "keys", fsdbm_keys, 0);
+ rb_define_method(cSDBM, "values", fsdbm_values, 0);
+ rb_define_method(cSDBM, "shift", fsdbm_shift, 1);
+ rb_define_method(cSDBM, "delete", fsdbm_delete, 1);
+ rb_define_method(cSDBM, "delete_if", fsdbm_delete_if, 0);
+ rb_define_method(cSDBM, "clear", fsdbm_clear, 0);
+ rb_define_method(cSDBM,"invert", fsdbm_invert, 0);
+ rb_define_method(cSDBM,"update", fsdbm_update, 1);
+ rb_define_method(cSDBM,"replace", fsdbm_replace, 1);
+
+ rb_define_method(cSDBM, "include?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "has_key?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "has_value?", fsdbm_has_value, 1);
+ rb_define_method(cSDBM, "key?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "value?", fsdbm_has_value, 1);
+
+ rb_define_method(cSDBM, "to_a", fsdbm_to_a, 0);
+}
diff --git a/ext/sdbm/sdbm.h b/ext/sdbm/sdbm.h
new file mode 100644
index 0000000000..ce8f54c4d4
--- /dev/null
+++ b/ext/sdbm/sdbm.h
@@ -0,0 +1,84 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ */
+#ifndef _SDBM_H_
+#define _SDBM_H_
+
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
+#define SPLTMAX 10 /* maximum allowed splits */
+ /* for a single insertion */
+#define DIRFEXT ".dir"
+#define PAGFEXT ".pag"
+
+typedef struct {
+ int dirf; /* directory file descriptor */
+ int pagf; /* page file descriptor */
+ int flags; /* status/error flags, see below */
+ long maxbno; /* size of dirfile in bits */
+ long curbit; /* current bit number */
+ long hmask; /* current hash mask */
+ long blkptr; /* current block for nextkey */
+ int keyptr; /* current key for nextkey */
+ long blkno; /* current page to read/write */
+ long pagbno; /* current page in pagbuf */
+ char pagbuf[PBLKSIZ]; /* page file block buffer */
+ long dirbno; /* current block in dirbuf */
+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
+} DBM;
+
+#define DBM_RDONLY 0x1 /* data base open read-only */
+#define DBM_IOERR 0x2 /* data base I/O error */
+
+/*
+ * utility macros
+ */
+#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
+#define sdbm_error(db) ((db)->flags & DBM_IOERR)
+
+#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
+
+#define sdbm_dirfno(db) ((db)->dirf)
+#define sdbm_pagfno(db) ((db)->pagf)
+
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+extern datum nullitem;
+
+#if defined(__STDC__) || defined(MSDOS)
+#define proto(p) p
+#else
+#define proto(p) ()
+#endif
+
+/*
+ * flags to sdbm_store
+ */
+#define DBM_INSERT 0
+#define DBM_REPLACE 1
+
+/*
+ * ndbm interface
+ */
+extern DBM *sdbm_open proto((char *, int, int));
+extern void sdbm_close proto((DBM *));
+extern datum sdbm_fetch proto((DBM *, datum));
+extern int sdbm_delete proto((DBM *, datum));
+extern int sdbm_store proto((DBM *, datum, datum, int));
+extern datum sdbm_firstkey proto((DBM *));
+extern datum sdbm_nextkey proto((DBM *));
+
+/*
+ * other
+ */
+extern DBM *sdbm_prep proto((char *, char *, int, int));
+extern long sdbm_hash proto((char *, int));
+
+#endif /* _SDBM_H_ */
diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST
index d41d9e0b69..616d459d92 100644
--- a/ext/socket/MANIFEST
+++ b/ext/socket/MANIFEST
@@ -1,4 +1,8 @@
MANIFEST
+addrinfo.h
depend
extconf.rb
+getaddrinfo.c
+getnameinfo.c
+sockport.h
socket.c
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
new file mode 100644
index 0000000000..74fae207b9
--- /dev/null
+++ b/ext/socket/addrinfo.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ADDR_INFO_H
+#define ADDR_INFO_H
+#ifndef HAVE_GETADDRINFO
+
+/* special compatibility hack */
+#undef EAI_ADDRFAMILY
+#undef EAI_AGAIN
+#undef EAI_BADFLAGS
+#undef EAI_FAIL
+#undef EAI_FAMILY
+#undef EAI_MEMORY
+#undef EAI_NODATA
+#undef EAI_NONAME
+#undef EAI_SERVICE
+#undef EAI_SOCKTYPE
+#undef EAI_SYSTEM
+#undef EAI_BADHINTS
+#undef EAI_PROTOCOL
+#undef EAI_MAX
+
+#undef AI_PASSIVE
+#undef AI_CANONNAME
+#undef AI_NUMERICHOST
+#undef AI_ALL
+#undef AI_ADDRCONFIG
+#undef AI_V4MAPPED
+#undef AI_DEFAULT
+
+#undef NI_NOFQDN
+#undef NI_NUMERICHOST
+#undef NI_NAMEREQD
+#undef NI_NUMERICSERV
+#undef NI_DGRAM
+
+#define addrinfo addrinfo__compat
+#define getaddrinfo getaddrinfo__compat
+#define getnameinfo getnameinfo__compat
+#define freehostent freehostent__compat
+#define freeaddrinfo freeaddrinfo__compat
+
+#ifndef __P
+# ifdef HAVE_PROTOTYPES
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif
+#endif
+
+/* special compatibility hack -- end*/
+
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_MAX 14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define AI_PASSIVE 0x00000001 /* get address to use bind() */
+#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
+#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
+#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+
+#ifdef NT
+#define IN_EXPERIMENTAL(x) 0
+#define IN_LOOPBACKNET 0
+#endif
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+extern int getaddrinfo __P((
+ const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res));
+
+extern int getnameinfo __P((
+ const struct sockaddr *sa,
+ size_t salen,
+ char *host,
+ size_t hostlen,
+ char *serv,
+ size_t servlen,
+ int flags));
+
+extern void freehostent __P((struct hostent *));
+extern void freeaddrent __P((struct addrinfo *));
+extern char *gai_strerror __P((int));
+
+/* In case there is no definition of offsetof() provided - though any proper
+Standard C system should have one. */
+
+#ifndef offsetof
+#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
+#endif
+
+#endif
+#endif
diff --git a/ext/socket/depend b/ext/socket/depend
index 6e8c3b7d97..cca6d4e62a 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -1 +1,3 @@
-socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h
+socket.o : socket.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
+getnameinfo.o: getnameinfo.c $(topdir)/config.h addrinfo.h sockport.h
+getaddrinfo.o: getaddrinfo.c $(topdir)/config.h addrinfo.h sockport.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 449d5a2785..da1a2a6b05 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -1,27 +1,276 @@
require 'mkmf'
-$LDFLAGS = "-L/usr/local/lib" if File.directory?("/usr/local/lib")
+$LDFLAGS += " -L/usr/local/lib" if File.directory?("/usr/local/lib")
+$CFLAGS += " -Dss_family=__ss_family -Dss_len=__ss_len"
+
case PLATFORM
when /mswin32/
test_func = "WSACleanup"
have_library("wsock32", "WSACleanup")
-when /cygwin32/
+when /cygwin/
+ $LDFLAGS << " -L/usr/lib" if File.directory?("/usr/lib")
+ $CFLAGS << " -I/usr/include"
test_func = "socket"
+ have_library("bind", "gethostbyaddr")
when /beos/
test_func = "socket"
have_library("net", "socket")
+when /i386-os2_emx/
+ test_func = "socket"
+ have_library("socket", "socket")
else
test_func = "socket"
have_library("nsl", "t_open")
have_library("socket", "socket")
end
+
+$ipv6 = false
+if enable_config("ipv6", false)
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <sys/socket.h>
+main()
+{
+ socket(AF_INET6, SOCK_STREAM, 0);
+}
+EOF
+ $CFLAGS+=" -DENABLE_IPV6"
+ $ipv6 = true
+ end
+end
+
+$ipv6type = nil
+$ipv6lib = nil
+$ipv6libdir = nil
+if $ipv6
+ if egrep_cpp("yes", <<EOF)
+#include <netinet/in.h>
+#ifdef IPV6_INRIA_VERSION
+yes
+#endif
+EOF
+ $ipv6type = "inria"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <netinet/in.h>
+#ifdef __KAME__
+yes
+#endif
+EOF
+ $ipv6type = "kame"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif File.directory? "/usr/inet6"
+ $ipv6type = "linux"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/inet6/lib"
+ $CFLAGS="-DINET6 -I/usr/inet6/include "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <sys/param.h>
+#ifdef _TOSHIBA_INET6
+yes
+#endif
+EOF
+ $ipv6type = "toshiba"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include </usr/local/v6/include/sys/v6config.h>
+#ifdef __V6D__
+yes
+#endif
+EOF
+ $ipv6type = "v6d"
+ $ipv6lib="v6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 -I/usr/local/v6/include "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <sys/param.h>
+#ifdef _ZETA_MINAMI_INET6
+yes
+#endif
+EOF
+ $ipv6type = "zeta"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ end
+
+ if $ipv6lib
+ if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a"
+ $LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib"
+ else
+ print <<EOS
+
+Fatal: no #$ipv6lib library found. cannot continue.
+You need to fetch lib#{$ipv6lib}.a from appropriate
+ipv6 kit and compile beforehand.
+EOS
+ exit
+ end
+ end
+end
+
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main()
+{
+ struct sockaddr_in sin;
+
+ sin.sin_len;
+ return 0;
+}
+EOF
+ $CFLAGS="-DHAVE_SIN_LEN "+$CFLAGS
+end
+
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main()
+{
+ struct sockaddr sa;
+
+ sa.sa_len;
+ return 0;
+}
+EOF
+ $CFLAGS="-DHAVE_SA_LEN "+$CFLAGS
+end
+
+have_header("sys/sysctl.h")
+
+$getaddr_info_ok = false
+if try_run(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+main()
+{
+ int passive, gaierr, inet4 = 0, inet6 = 0;
+ struct addrinfo hints, *ai, *aitop;
+ char straddr[INET6_ADDRSTRLEN], strport[16];
+
+ for (passive = 0; passive <= 1; passive++) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = passive ? AI_PASSIVE : 0;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
+ (void)gai_strerror(gaierr);
+ goto bad;
+ }
+ for (ai = aitop; ai; ai = ai->ai_next) {
+ if (ai->ai_addr == NULL ||
+ ai->ai_addrlen == 0 ||
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ straddr, sizeof(straddr), strport, sizeof(strport),
+ NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+ goto bad;
+ }
+ if (strcmp(strport, "54321") != 0) {
+ goto bad;
+ }
+ switch (ai->ai_family) {
+ case AF_INET:
+ if (passive) {
+ if (strcmp(straddr, "0.0.0.0") != 0) {
+ goto bad;
+ }
+ } else {
+ if (strcmp(straddr, "127.0.0.1") != 0) {
+ goto bad;
+ }
+ }
+ inet4++;
+ break;
+ case AF_INET6:
+ if (passive) {
+ if (strcmp(straddr, "::") != 0) {
+ goto bad;
+ }
+ } else {
+ if (strcmp(straddr, "::1") != 0) {
+ goto bad;
+ }
+ }
+ inet6++;
+ break;
+ case AF_UNSPEC:
+ goto bad;
+ break;
+ default:
+ /* another family support? */
+ break;
+ }
+ }
+ }
+
+ if (inet6 != 2 || inet4 != 2)
+ goto bad;
+
+ if (aitop)
+ freeaddrinfo(aitop);
+ exit(0);
+
+ bad:
+ if (aitop)
+ freeaddrinfo(aitop);
+ exit(1);
+}
+EOF
+ $getaddr_info_ok = true
+end
+if $ipv6 and not $getaddr_info_ok
+ print <<EOS
+
+Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
+But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
+you cannot compile IPv6 socket classes with broken these functions.
+EOS
+ exit
+end
+
+
+$objs = ["socket.#{$OBJEXT}"]
+
+if $getaddr_info_ok and have_func("getaddrinfo") and have_func("getnameinfo")
+ have_getaddrinfo = true
+end
+
+if have_getaddrinfo
+ $CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
+else
+ $CFLAGS="-I. "+$CFLAGS
+ $objs += ["getaddrinfo.#{$OBJEXT}"]
+ $objs += ["getnameinfo.#{$OBJEXT}"]
+ have_func("inet_ntop") or have_func("inet_ntoa")
+ have_func("inet_pton") or have_func("inet_aton")
+ have_header("arpa/nameser.h")
+ have_header("resolv.h")
+end
+
have_header("sys/un.h")
+
if have_func(test_func)
- have_func("inet_aton")
have_func("hsterror")
unless have_func("gethostname")
have_func("uname")
end
- if ENV["SOCKS_SERVER"] # test if SOCKSsocket needed
+ if ENV["SOCKS_SERVER"] or enable_config("socks", false)
if have_library("socks", "Rconnect")
$CFLAGS="-DSOCKS"
end
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
new file mode 100644
index 0000000000..c71a56ca80
--- /dev/null
+++ b/ext/socket/getaddrinfo.c
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked.
+ * - Return values. There are nonstandard return values defined and used
+ * in the source code. This is because RFC2133 is silent about which error
+ * code must be returned for which situation.
+ * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
+ */
+
+#include <sys/types.h>
+#ifndef NT
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifndef NT
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#if defined(HAVE_ARPA_NAMESER_H)
+#include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+#if defined(HAVE_RESOLV_H)
+#include <resolv.h>
+#endif
+#include <unistd.h>
+#else
+#include <winsock2.h>
+#include <io.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "addrinfo.h"
+#include "sockport.h"
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+#ifdef FAITH
+static int translate = NO;
+static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
+#endif
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback},
+ {0, 0, 0, 0, NULL, NULL},
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+
+static int get_name __P((const char *, struct afd *,
+ struct addrinfo **, char *, struct addrinfo *,
+ int));
+static int get_addr __P((const char *, int, struct addrinfo **,
+ struct addrinfo *, int));
+static int str_isnumber __P((const char *));
+
+static char *ai_errlist[] = {
+ "success.",
+ "address family for hostname not supported.", /* EAI_ADDRFAMILY */
+ "temporary failure in name resolution.", /* EAI_AGAIN */
+ "invalid value for ai_flags.", /* EAI_BADFLAGS */
+ "non-recoverable failure in name resolution.", /* EAI_FAIL */
+ "ai_family not supported.", /* EAI_FAMILY */
+ "memory allocation failure.", /* EAI_MEMORY */
+ "no address associated with hostname.", /* EAI_NODATA */
+ "hostname nor servname provided, or not known.",/* EAI_NONAME */
+ "servname not supported for ai_socktype.", /* EAI_SERVICE */
+ "ai_socktype not supported.", /* EAI_SOCKTYPE */
+ "system error returned in errno.", /* EAI_SYSTEM */
+ "invalid value for hints.", /* EAI_BADHINTS */
+ "resolved protocol is unknown.", /* EAI_PROTOCOL */
+ "unknown error.", /* EAI_MAX */
+};
+
+#define GET_CANONNAME(ai, str) \
+if (pai->ai_flags & AI_CANONNAME) {\
+ if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
+ strcpy((ai)->ai_canonname, (str));\
+ } else {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+}
+
+#define GET_AI(ai, afd, addr, port) {\
+ char *p;\
+ if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
+ ((afd)->a_socklen)))\
+ == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+ memcpy(ai, pai, sizeof(struct addrinfo));\
+ (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
+ memset((ai)->ai_addr, 0, (afd)->a_socklen);\
+ SET_SA_LEN((ai)->ai_addr, (ai)->ai_addrlen = (afd)->a_socklen);\
+ (ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
+ ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
+ p = (char *)((ai)->ai_addr);\
+ memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
+}
+
+#define ERR(err) { error = (err); goto bad; }
+
+char *
+gai_strerror(ecode)
+ int ecode;
+{
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return ai_errlist[ecode];
+}
+
+void
+freeaddrinfo(ai)
+ struct addrinfo *ai;
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
+}
+
+static int
+str_isnumber(p)
+ const char *p;
+{
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
+}
+
+#ifndef HAVE_INET_PTON
+
+static int
+inet_pton(af, hostname, pton)
+ int af;
+ const char *hostname;
+ void *pton;
+{
+ struct in_addr in;
+
+#ifdef HAVE_INET_ATON
+ if (!inet_aton(hostname, &in))
+ return 0;
+#else
+ int d1, d2, d3, d4;
+ char ch;
+
+ if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ in.s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ }
+ else {
+ return 0;
+ }
+#endif
+ memcpy(pton, &in, sizeof(in));
+ return 1;
+}
+#endif
+
+int
+getaddrinfo(hostname, servname, hints, res)
+ const char *hostname, *servname;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo sentinel;
+ struct addrinfo *top = NULL;
+ struct addrinfo *cur;
+ int i, error = 0;
+ char pton[PTON_MAX];
+ struct addrinfo ai;
+ struct addrinfo *pai;
+ u_short port;
+
+#ifdef FAITH
+ static int firsttime = 1;
+
+ if (firsttime) {
+ /* translator hack */
+ {
+ char *q = getenv("GAI");
+ if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
+ translate = YES;
+ }
+ firsttime = 0;
+ }
+#endif
+
+ /* initialize file static vars */
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+ port = ANY;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+ switch (pai->ai_socktype) {
+ case ANY:
+ switch (pai->ai_protocol) {
+ case ANY:
+ break;
+ case IPPROTO_UDP:
+ pai->ai_socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ pai->ai_socktype = SOCK_STREAM;
+ break;
+ default:
+ pai->ai_socktype = SOCK_RAW;
+ break;
+ }
+ break;
+ case SOCK_RAW:
+ break;
+ case SOCK_DGRAM:
+ if (pai->ai_protocol != IPPROTO_UDP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ if (pai->ai_protocol != IPPROTO_TCP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_TCP;
+ break;
+ default:
+ ERR(EAI_SOCKTYPE);
+ break;
+ }
+ }
+
+ /*
+ * service port
+ */
+ if (servname) {
+ if (str_isnumber(servname)) {
+ if (pai->ai_socktype == ANY) {
+ /* caller accept *ANY* socktype */
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ }
+ port = htons((unsigned short)atoi(servname));
+ } else {
+ struct servent *sp;
+ char *proto;
+
+ proto = NULL;
+ switch (pai->ai_socktype) {
+ case ANY:
+ proto = NULL;
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ fprintf(stderr, "panic!\n");
+ break;
+ }
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ ERR(EAI_SERVICE);
+ port = sp->s_port;
+ if (pai->ai_socktype == ANY)
+ if (strcmp(sp->s_proto, "udp") == 0) {
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(sp->s_proto, "tcp") == 0) {
+ pai->ai_socktype = SOCK_STREAM;
+ pai->ai_protocol = IPPROTO_TCP;
+ } else
+ ERR(EAI_PROTOCOL); /*xxx*/
+ }
+ }
+
+ /*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+ if (hostname == NULL) {
+ struct afd *afd;
+ int s;
+
+ for (afd = &afdl[0]; afd->a_af; afd++) {
+ if (!(pai->ai_family == PF_UNSPEC
+ || pai->ai_family == afd->a_af)) {
+ continue;
+ }
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afd->a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+ close(s);
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany, port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback,
+ port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ }
+ cur = cur->ai_next;
+ }
+ top = sentinel.ai_next;
+ if (top)
+ goto good;
+ else
+ ERR(EAI_FAMILY);
+ }
+
+ /* hostname as numeric name */
+ for (i = 0; afdl[i].a_af; i++) {
+ if (inet_pton(afdl[i].a_af, hostname, pton)) {
+ u_long v4a;
+#ifdef INET6
+ u_char pfx;
+#endif
+
+ switch (afdl[i].a_af) {
+ case AF_INET:
+ v4a = ((struct in_addr *)pton)->s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ pai->ai_flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ pfx = ((struct in6_addr *)pton)->s6_addr8[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afdl[i].a_af ||
+ pai->ai_family == PF_UNSPEC) {
+ if (! (pai->ai_flags & AI_CANONNAME)) {
+ GET_AI(top, &afdl[i], pton, port);
+ goto good;
+ }
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks strange
+ * that we do addr->name translation here.
+ */
+ get_name(pton, &afdl[i], &top, pton, pai, port);
+ goto good;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ }
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ /* hostname as alphabetical name */
+ error = get_addr(hostname, pai->ai_family, &top, pai, port);
+ if (error == 0) {
+ if (top) {
+ good:
+ *res = top;
+ return SUCCESS;
+ } else
+ error = EAI_FAIL;
+ }
+ free:
+ if (top)
+ freeaddrinfo(top);
+ bad:
+ *res = NULL;
+ return error;
+}
+
+static int
+get_name(addr, afd, res, numaddr, pai, port0)
+ const char *addr;
+ struct afd *afd;
+ struct addrinfo **res;
+ char *numaddr;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
+#ifdef INET6
+ int h_error;
+#endif
+
+#ifdef INET6
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+ hp = gethostbyaddr(addr, afd->a_addrlen, AF_INET);
+#endif
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ GET_AI(cur, afd, hp->h_addr_list[0], port);
+ GET_CANONNAME(cur, hp->h_name);
+ } else
+ GET_AI(cur, afd, numaddr, port);
+
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ *res = cur;
+ return SUCCESS;
+ free:
+ if (cur)
+ freeaddrinfo(cur);
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ /* bad: */
+ *res = NULL;
+ return error;
+}
+
+static int
+get_addr(hostname, af, res, pai, port0)
+ const char *hostname;
+ int af;
+ struct addrinfo **res;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct addrinfo sentinel;
+ struct hostent *hp;
+ struct addrinfo *top, *cur;
+ struct afd *afd;
+ int i, error = 0, h_error;
+ char *ap;
+#ifndef INET6
+#ifndef NT
+ extern int h_errno;
+#endif
+#endif
+
+ top = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+#ifdef INET6
+ if (af == AF_UNSPEC) {
+ hp = getipnodebyname(hostname, AF_INET6,
+ AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
+ } else
+ hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
+#else
+ hp = gethostbyname(hostname);
+ h_error = h_errno;
+#endif
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ goto bad;
+ }
+
+ if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
+ (hp->h_addr_list[0] == NULL))
+ ERR(EAI_FAIL);
+
+ for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ afd = &afdl[N_INET6];
+ break;
+#endif
+#ifndef INET6
+ default: /* AF_UNSPEC */
+#endif
+ case AF_INET:
+ afd = &afdl[N_INET];
+ break;
+#ifdef INET6
+ default: /* AF_UNSPEC */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ ap += sizeof(struct in6_addr) -
+ sizeof(struct in_addr);
+ afd = &afdl[N_INET];
+ } else
+ afd = &afdl[N_INET6];
+ break;
+#endif
+ }
+#ifdef FAITH
+ if (translate && afd->a_af == AF_INET) {
+ struct in6_addr *in6;
+
+ GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
+ in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
+ memcpy(&in6->s6_addr32[0], &faith_prefix,
+ sizeof(struct in6_addr) - sizeof(struct in_addr));
+ memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
+ } else
+#endif /* FAITH */
+ GET_AI(cur->ai_next, afd, ap, port);
+ if (cur == &sentinel) {
+ top = cur->ai_next;
+ GET_CANONNAME(top, hp->h_name);
+ }
+ cur = cur->ai_next;
+ }
+#ifdef INET6
+ freehostent(hp);
+#endif
+ *res = top;
+ return SUCCESS;
+ free:
+ if (top)
+ freeaddrinfo(top);
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ bad:
+ *res = NULL;
+ return error;
+}
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
new file mode 100644
index 0000000000..abadd8f442
--- /dev/null
+++ b/ext/socket/getnameinfo.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - Return values. There seems to be no standard for return value (RFC2133)
+ * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ */
+
+#include <sys/types.h>
+#ifndef NT
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#if defined(HAVE_ARPA_NAMESER_H)
+#include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+#if defined(HAVE_RESOLV_H)
+#include <resolv.h>
+#endif
+#endif
+#ifdef NT
+#include <winsock2.h>
+#include <stdio.h>
+#define snprintf _snprintf
+#endif
+
+#include <string.h>
+#include <stddef.h>
+
+#include "config.h"
+#include "addrinfo.h"
+#include "sockport.h"
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0, 0},
+};
+
+#define ENI_NOSOCKET 0
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+
+#ifndef HAVE_INET_NTOP
+static const char *
+inet_ntop(af, addr, numaddr, numaddr_len)
+ int af;
+ const void *addr;
+ char *numaddr;
+ size_t numaddr_len;
+{
+#ifdef HAVE_INET_NTOA
+ struct in_addr in;
+ memcpy(&in.s_addr, addr, sizeof(in.s_addr));
+ snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
+#else
+ unsigned long x = ntohl(*(unsigned long*)addr);
+ snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+#endif
+ return numaddr;
+}
+#endif
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, len, i;
+ char *addr, *p;
+ u_long v4a;
+#ifdef INET6
+ u_char pfx;
+#endif
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+#ifndef NT
+ extern int h_errno;
+#endif
+
+ if (sa == NULL)
+ return ENI_NOSOCKET;
+
+ len = SA_LEN(sa);
+ if (len != salen) return ENI_SALEN;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
+
+ found:
+ if (len != afd->a_socklen) return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /* what we should do? */
+ } else if (flags & NI_NUMERICSERV) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlen(numserv) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, numserv);
+ } else {
+ sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlen(sp->s_name) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else
+ return ENI_NOSERVNAME;
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags |= NI_NUMERICHOST;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ flags |= NI_NUMERICHOST;
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /* what should we do? */
+ } else if (flags & NI_NUMERICHOST) {
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ } else {
+#ifdef INET6
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ h_error = h_errno;
+#endif
+
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) > hostlen) {
+#ifdef INET6
+ freehostent(hp);
+#endif
+ return ENI_MEMORY;
+ }
+ strcpy(host, hp->h_name);
+#ifdef INET6
+ freehostent(hp);
+#endif
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ return SUCCESS;
+}
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index e9bdbc9e8c..93a8aacce3 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -30,7 +30,7 @@ extern int rb_thread_select(int, fd_set*, fd_set*, fd_set*, struct timeval*); /*
# include <GUSI.h>
#endif
-#if defined(USE_THREAD) && defined(HAVE_FCNTL)
+#if defined(HAVE_FCNTL)
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -41,44 +41,58 @@ extern int rb_thread_select(int, fd_set*, fd_set*, fd_set*, struct timeval*); /*
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
+#ifndef HAVE_GETADDRINFO
+# include "addrinfo.h"
+#endif
+#include "sockport.h"
+
+static int do_not_reverse_lookup = 0;
VALUE rb_cBasicSocket;
-VALUE rb_cIPsocket;
-VALUE rb_cTCPsocket;
-VALUE rb_cTCPserver;
-VALUE rb_cUDPsocket;
+VALUE rb_cIPSocket;
+VALUE rb_cTCPSocket;
+VALUE rb_cTCPServer;
+VALUE rb_cUDPSocket;
#ifdef AF_UNIX
-VALUE rb_cUNIXsocket;
-VALUE rb_cUNIXserver;
+VALUE rb_cUNIXSocket;
+VALUE rb_cUNIXServer;
#endif
VALUE rb_cSocket;
static VALUE rb_eSocket;
#ifdef SOCKS
-VALUE rb_cSOCKSsocket;
+VALUE rb_cSOCKSSocket;
void SOCKSinit();
int Rconnect();
#endif
-char *strdup();
-
#define INET_CLIENT 0
#define INET_SERVER 1
#define INET_SOCKS 2
+#ifndef INET6
+# undef ss_family
+# define sockaddr_storage sockaddr
+# define ss_family sa_family
+#endif
+
#ifdef NT
static void
sock_finalize(fptr)
OpenFile *fptr;
{
SOCKET s;
+ extern int errno;
if (!fptr->f) return;
- s = fileno(fptr->f);
- free(fptr->f);
- if (fptr->f2) free(fptr->f2);
+
+ myfdclose(fptr->f);
+ if(fptr->f2) myfdclose(fptr->f);
+/*
+ s = get_osfhandle(fileno(fptr->f));
closesocket(s);
+*/
}
#endif
@@ -96,11 +110,12 @@ sock_new(class, fd)
fp->f = rb_fdopen(fd, "r");
#ifdef NT
fp->finalize = sock_finalize;
+#else
+ fd = dup(fd);
#endif
fp->f2 = rb_fdopen(fd, "w");
fp->mode = FMODE_READWRITE;
rb_io_unbuffered(fp);
- rb_obj_call_init((VALUE)sock);
return (VALUE)sock;
}
@@ -140,11 +155,11 @@ bsock_close_read(sock)
rb_secure(4);
GetOpenFile(sock, fptr);
+ shutdown(fileno(fptr->f), 0);
if (fptr->f2 == 0) {
return rb_io_close(sock);
}
- if (shutdown(fileno(fptr->f), 0) == -1)
- rb_sys_fail(0);
+ rb_thread_fd_close(fileno(fptr->f));
fptr->mode &= ~FMODE_READABLE;
#ifdef NT
free(fptr->f);
@@ -168,8 +183,7 @@ bsock_close_write(sock)
if (fptr->f2 == 0) {
return rb_io_close(sock);
}
- if (shutdown(fileno(fptr->f), 1) == -1)
- rb_sys_fail(0);
+ shutdown(fileno(fptr->f2), 1);
fptr->mode &= ~FMODE_WRITABLE;
#ifdef NT
free(fptr->f2);
@@ -290,9 +304,7 @@ bsock_send(argc, argv, sock)
f = GetWriteFile(fptr);
fd = fileno(f);
retry:
-#ifdef USE_THREAD
rb_thread_fd_writable(fd);
-#endif
m = rb_str2cstr(msg, &mlen);
if (RTEST(to)) {
t = rb_str2cstr(to, &tlen);
@@ -305,13 +317,13 @@ bsock_send(argc, argv, sock)
if (n < 0) {
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
+ rb_thread_fd_writable(fd);
goto retry;
}
rb_sys_fail("send(2)");
@@ -319,16 +331,16 @@ bsock_send(argc, argv, sock)
return INT2FIX(n);
}
-static VALUE ipaddr _((struct sockaddr_in*));
+static VALUE ipaddr _((struct sockaddr *));
#ifdef HAVE_SYS_UN_H
-static VALUE unixaddr _((struct sockaddr_un*));
+static VALUE unixaddr _((struct sockaddr_un *));
#endif
enum sock_recv_type {
RECV_RECV, /* BasicSocket#recv(no from) */
- RECV_TCP, /* TCPsocket#recvfrom */
- RECV_UDP, /* UDPsocket#recvfrom */
- RECV_UNIX, /* UNIXsocket#recvfrom */
+ RECV_TCP, /* TCPSocket#recvfrom */
+ RECV_UDP, /* UDPSocket#recvfrom */
+ RECV_UNIX, /* UNIXSocket#recvfrom */
RECV_SOCKET, /* Socket#recvfrom */
};
@@ -355,9 +367,7 @@ s_recv(sock, argc, argv, from)
GetOpenFile(sock, fptr);
fd = fileno(fptr->f);
-#ifdef USE_THREAD
rb_thread_wait_fd(fd);
-#endif
TRAP_BEG;
retry:
RSTRING(str)->len = recvfrom(fd, RSTRING(str)->ptr, RSTRING(str)->len, flags,
@@ -367,13 +377,14 @@ s_recv(sock, argc, argv, from)
if (RSTRING(str)->len < 0) {
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
+ rb_thread_wait_fd(fd);
goto retry;
}
rb_sys_fail("recvfrom(2)");
@@ -383,17 +394,13 @@ s_recv(sock, argc, argv, from)
case RECV_RECV:
return (VALUE)str;
case RECV_TCP:
+ case RECV_UDP:
+#if 0
if (alen != sizeof(struct sockaddr_in)) {
rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
- return rb_assoc_new(str, ipaddr((struct sockaddr_in *)buf));
- case RECV_UDP:
- {
- VALUE addr = ipaddr((struct sockaddr_in *)buf);
-
- return rb_assoc_new(str, rb_assoc_new(RARRAY(addr)->ptr[2],
- RARRAY(addr)->ptr[1]));
- }
+#endif
+ return rb_assoc_new(str, ipaddr((struct sockaddr *)buf));
#ifdef HAVE_SYS_UN_H
case RECV_UNIX:
return rb_assoc_new(str, unixaddr((struct sockaddr_un *)buf));
@@ -413,106 +420,206 @@ bsock_recv(argc, argv, sock)
}
static VALUE
-mkipaddr(x)
- unsigned long x;
+bsock_do_not_rev_lookup()
{
- char buf[16];
-
- x = ntohl(x);
- sprintf(buf, "%d.%d.%d.%d",
- (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
- (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
- return rb_str_new2(buf);
+ return do_not_reverse_lookup?Qtrue:Qfalse;
}
static VALUE
-ipaddr(sockaddr)
- struct sockaddr_in *sockaddr;
+bsock_do_not_rev_lookup_set(self, val)
{
- VALUE family, port, addr1, addr2;
- VALUE ary;
- struct hostent *hostent;
+ do_not_reverse_lookup = RTEST(val);
+ return val;
+}
- family = rb_str_new2("AF_INET");
- hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
- sizeof(sockaddr->sin_addr),
- AF_INET);
- addr1 = 0;
- if (hostent) {
- addr1 = rb_str_new2(hostent->h_name);
+static void
+mkipaddr0(addr, buf, len)
+ struct sockaddr *addr;
+ char *buf;
+ size_t len;
+{
+ int error;
+
+ error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0,
+ NI_NUMERICHOST);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
}
- addr2 = mkipaddr(sockaddr->sin_addr.s_addr);
- if (!addr1) addr1 = addr2;
+}
- port = INT2FIX(ntohs(sockaddr->sin_port));
- ary = rb_ary_new3(4, family, port, addr1, addr2);
+static VALUE
+mkipaddr(addr)
+ struct sockaddr *addr;
+{
+ char buf[1024];
- return ary;
+ mkipaddr0(addr, buf, sizeof(buf));
+ return rb_str_new2(buf);
}
-#ifndef HAVE_INET_ATON
-static unsigned long
-inet_aton(host, inp)
- char *host;
- struct in_addr *inp;
+static void
+mkinetaddr(host, buf, len)
+ long host;
+ char *buf;
+ size_t len;
{
- int d1, d2, d3, d4;
- char ch;
+ struct sockaddr_in sin;
+
+ MEMZERO(&sin, struct sockaddr_in, 1);
+ sin.sin_family = AF_INET;
+ SET_SIN_LEN(&sin, sizeof(sin));
+ sin.sin_addr.s_addr = host;
+ mkipaddr0((struct sockaddr *)&sin, buf, len);
+}
+
+static struct addrinfo*
+ip_addrsetup(host, port)
+ VALUE host, port;
+{
+ struct addrinfo hints, *res;
+ char *hostp, *portp;
+ int error;
+ char hbuf[1024], pbuf[16];
+
+ if (NIL_P(host)) {
+ hostp = NULL;
+ }
+ else if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ long i = NUM2LONG(host);
- if (sscanf(host, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
- 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
- 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
- inp->s_addr = htonl(
- ((long) d1 << 24) | ((long) d2 << 16) |
- ((long) d3 << 8) | ((long) d4 << 0));
- return 1;
+ mkinetaddr(htonl(i), hbuf, sizeof(hbuf));
}
- return 0;
+ else {
+ char *name = STR2CSTR(host);
+
+ if (*name == 0) {
+ mkinetaddr(INADDR_ANY, hbuf, sizeof(hbuf));
+ }
+ else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
+ mkinetaddr(INADDR_BROADCAST, hbuf, sizeof(hbuf));
+ }
+ else {
+ strcpy(hbuf, name);
+ }
+ }
+ hostp = hbuf;
+ if (NIL_P(port)) {
+ portp = 0;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
+ portp = pbuf;
+ }
+ else {
+ portp = STR2CSTR(port);
+ }
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ error = getaddrinfo(hostp, portp, &hints, &res);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+
+ return res;
}
-#endif
static void
setipaddr(name, addr)
- char *name;
- struct sockaddr_in *addr;
+ VALUE name;
+ struct sockaddr *addr;
{
- struct hostent *hp;
+ struct addrinfo *res = ip_addrsetup(name, Qnil);
- if (name[0] == 0) {
- addr->sin_addr.s_addr = INADDR_ANY;
+ /* just take the first one */
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+}
+
+static VALUE
+ipaddr(sockaddr)
+ struct sockaddr *sockaddr;
+{
+ VALUE family, port, addr1, addr2;
+ VALUE ary;
+ int error;
+ char hbuf[1024], pbuf[1024];
+
+ switch (sockaddr->sa_family) {
+ case AF_INET:
+ family = rb_str_new2("AF_INET");
+ break;
+#ifdef INET6
+ case AF_INET6:
+ family = rb_str_new2("AF_INET6");
+ break;
+#endif
+ default:
+ family = 0;
+ break;
}
- else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
- addr->sin_addr.s_addr = INADDR_BROADCAST;
+ if (!do_not_reverse_lookup) {
+ error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
+ NULL, 0, 0);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+ addr1 = rb_str_new2(hbuf);
}
- else if (inet_aton(name, &addr->sin_addr) != 0) {
- /* ok to set addr->sin_addr */
+ error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
}
- else {
- hp = gethostbyname(name);
- if (!hp) {
-#ifdef HAVE_HSTRERROR
- extern int h_errno;
- rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
-#else
- rb_raise(rb_eSocket, "host not found");
-#endif
+ addr2 = rb_str_new2(hbuf);
+ if (do_not_reverse_lookup) {
+ addr1 = addr2;
+ }
+ port = INT2FIX(atoi(pbuf));
+ ary = rb_ary_new3(4, family, port, addr1, addr2);
+
+ return ary;
+}
+
+static void
+thread_write_select(fd)
+ int fd;
+{
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ rb_thread_select(fd+1, 0, &fds, 0, 0);
+}
+
+static int
+ruby_socket(domain, type, proto)
+ int domain, type, proto;
+{
+ int fd;
+
+ fd = socket(domain, type, proto);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = socket(domain, type, proto);
}
- memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
}
+ return fd;
}
-#if defined(USE_THREAD) && defined(HAVE_FCNTL)
static int
-thread_connect(fd, sockaddr, len, type)
+ruby_connect(fd, sockaddr, len, socks)
int fd;
struct sockaddr *sockaddr;
int len;
- int type;
+ int socks;
{
int status;
int mode;
- fd_set fds;
+#if defined(HAVE_FCNTL)
mode = fcntl(fd, F_GETFL, 0);
#ifdef O_NDELAY
@@ -525,9 +632,11 @@ thread_connect(fd, sockaddr, len, type)
#endif
#endif
fcntl(fd, F_SETFL, mode|NONBLOCKING);
+#endif /* HAVE_FCNTL */
+
for (;;) {
#ifdef SOCKS
- if (type == INET_SOCKS) {
+ if (socks) {
status = Rconnect(fd, sockaddr, len);
}
else
@@ -537,151 +646,107 @@ thread_connect(fd, sockaddr, len, type)
}
if (status < 0) {
switch (errno) {
+ case EAGAIN:
#ifdef EINPROGRESS
case EINPROGRESS:
-#ifdef EAGAIN
- case EAGAIN:
#endif
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- rb_thread_select(fd+1, 0, &fds, 0, 0);
+ thread_write_select(fd);
continue;
-#endif
#ifdef EISCONN
case EISCONN:
-#endif
-#ifdef EALREADY
- case EALREADY:
-#endif
-#if defined(EISCONN) || defined(EALREADY)
status = 0;
errno = 0;
break;
#endif
}
}
+#ifdef HAVE_FCNTL
mode &= ~NONBLOCKING;
fcntl(fd, F_SETFL, mode);
+#endif
return status;
}
}
-#endif
static VALUE
open_inet(class, h, serv, type)
VALUE class, h, serv;
int type;
{
- char *host;
- struct hostent *hostent, _hostent;
- struct servent *servent, _servent;
- struct protoent *protoent;
- struct sockaddr_in sockaddr;
+ struct addrinfo hints, *res, *res0;
int fd, status;
- int hostaddr, hostaddrPtr[2];
- int servport;
char *syscall;
+ char pbuf[1024], *portp;
+ char *host;
+ int error;
if (h) {
Check_SafeStr(h);
host = RSTRING(h)->ptr;
- hostent = gethostbyname(host);
- if (hostent == NULL) {
- if (!inet_aton(host, &sockaddr.sin_addr)) {
- if (type == INET_SERVER && !strlen(host))
- hostaddr = INADDR_ANY;
- else {
-#ifdef HAVE_HSTRERROR
- extern int h_errno;
- rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
-#else
- rb_raise(rb_eSocket, "host not found");
-#endif
- }
- }
- hostaddr = sockaddr.sin_addr.s_addr;
- _hostent.h_addr_list = (char **)hostaddrPtr;
- _hostent.h_addr_list[0] = (char *)&hostaddr;
- _hostent.h_addr_list[1] = NULL;
- _hostent.h_length = sizeof(hostaddr);
- _hostent.h_addrtype = AF_INET;
- hostent = &_hostent;
- }
- }
- servent = NULL;
- if (FIXNUM_P(serv)) {
- servport = FIX2UINT(serv);
- goto setup_servent;
- }
- servent = getservbyname(STR2CSTR(serv), "tcp");
- if (servent == NULL) {
- char *s = STR2CSTR(serv);
- char *end;
-
- servport = strtoul(s, &end, 0);
- if (*end != '\0') {
- rb_raise(rb_eSocket, "no such servce %s", s);
- }
- setup_servent:
- _servent.s_port = htons(servport);
- _servent.s_proto = "tcp";
- servent = &_servent;
}
-#ifdef __BEOS__
- fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-#else
- protoent = getprotobyname(servent->s_proto);
- if (protoent == NULL) {
- rb_raise(rb_eSocket, "no such proto %s", servent->s_proto);
+ else {
+ host = NULL;
}
-
- fd = socket(AF_INET, SOCK_STREAM, protoent->p_proto);
-#endif
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin_family = AF_INET;
- if (h) {
- memcpy((char *)&(sockaddr.sin_addr.s_addr),
- (char *) hostent->h_addr_list[0],
- (size_t) hostent->h_length);
+ if (FIXNUM_P(serv)) {
+ snprintf(pbuf, sizeof(pbuf), "%d", FIX2UINT(serv));
+ portp = pbuf;
}
else {
- sockaddr.sin_addr.s_addr = INADDR_ANY;
+ strcpy(pbuf, STR2CSTR(serv));
+ portp = pbuf;
}
- sockaddr.sin_port = servent->s_port;
-
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
if (type == INET_SERVER) {
- status = 1;
- setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&status,sizeof(status));
- status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
- syscall = "bind(2)";
+ hints.ai_flags = AI_PASSIVE;
}
- else {
-#if defined(USE_THREAD) && defined(HAVE_FCNTL)
- status = thread_connect(fd, (struct sockaddr*)&sockaddr,
- sizeof(sockaddr), type);
-#else
-#ifdef SOCKS
- if (type == INET_SOCKS) {
- status = Rconnect(fd, &sockaddr, sizeof(sockaddr));
+ error = getaddrinfo(host, portp, &hints, &res0);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+
+ fd = -1;
+ for (res = res0; res; res = res->ai_next) {
+ status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+ syscall = "socket(2)";
+ fd = status;
+ if (fd < 0) {
+ continue;
}
- else
-#endif
- {
- status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ if (type == INET_SERVER) {
+ status = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&status, sizeof(status));
+ status = bind(fd, res->ai_addr, res->ai_addrlen);
+ syscall = "bind(2)";
+ }
+ else {
+ status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
+ (type == INET_SOCKS));
+ syscall = "connect(2)";
}
-#endif
- syscall = "connect(2)";
- }
+ if (status < 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ } else
+ break;
+ }
if (status < 0) {
- close(fd);
+ if (fd >= 0)
+ close(fd);
+ freeaddrinfo(res0);
rb_sys_fail(syscall);
}
- if (type == INET_SERVER) listen(fd, 5);
+
+ if (type == INET_SERVER)
+ listen(fd, 5);
/* create new instance */
+ freeaddrinfo(res0);
return sock_new(class, fd);
}
@@ -710,24 +775,60 @@ socks_s_open(class, host, serv)
}
#endif
+/*
+ * NOTE: using gethostbyname() against AF_INET6 is a bad idea, as it
+ * does not initialize sin_flowinfo nor sin_scope_id properly.
+ */
static VALUE
tcp_s_gethostbyname(obj, host)
VALUE obj, host;
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
struct hostent *h;
char **pch;
VALUE ary, names;
- setipaddr(STR2CSTR(host), &addr);
- h = gethostbyaddr((char *)&addr.sin_addr,
- sizeof(addr.sin_addr),
- AF_INET);
+ if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ long i = NUM2LONG(host);
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ MEMZERO(sin, struct sockaddr_in, 1);
+ sin->sin_family = AF_INET;
+ SET_SIN_LEN(sin, sizeof(*sin));
+ sin->sin_addr.s_addr = htonl(i);
+ }
+ else {
+ setipaddr(host, &addr);
+ }
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ h = gethostbyaddr((char *)&sin->sin_addr,
+ sizeof(sin->sin_addr),
+ sin->sin_family);
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&addr;
+ h = gethostbyaddr((char *)&sin6->sin6_addr,
+ sizeof(sin6->sin6_addr),
+ sin6->sin6_family);
+ break;
+ }
+#endif
+ default:
+ h = NULL;
+ }
if (h == NULL) {
-#ifdef HAVE_HSTRERROR
+#ifdef HAVE_HSTERROR
extern int h_errno;
- rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
+ rb_raise(rb_eSocket, "%s", (char *)hsterror(h_errno));
#else
rb_raise(rb_eSocket, "host not found");
#endif
@@ -739,15 +840,45 @@ tcp_s_gethostbyname(obj, host)
for (pch = h->h_aliases; *pch; pch++) {
rb_ary_push(names, rb_str_new2(*pch));
}
- rb_ary_push(ary, NUM2INT(h->h_addrtype));
+ rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
- memcpy((char *) &addr.sin_addr, *pch, h->h_length);
- rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr));
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in sin;
+ MEMZERO(&sin, struct sockaddr_in, 1);
+ sin.sin_family = AF_INET;
+ SET_SIN_LEN(&sin, sizeof(sin));
+ memcpy((char *) &sin.sin_addr, *pch, h->h_length);
+ h = gethostbyaddr((char *)&sin.sin_addr,
+ sizeof(sin.sin_addr),
+ sin.sin_family);
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&sin));
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6;
+ MEMZERO(&sin6, struct sockaddr_in6, 1);
+ sin6.sin6_family = AF_INET;
+ sin6.sin6_len = sizeof(sin6);
+ memcpy((char *) &sin6.sin6_addr, *pch, h->h_length);
+ h = gethostbyaddr((char *)&sin6.sin6_addr,
+ sizeof(sin6.sin6_addr),
+ sin6.sin6_family);
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&sin6));
+ break;
+ }
+#endif
+ default:
+ h = NULL;
+ }
}
#else
memcpy((char *)&addr.sin_addr, h->h_addr, h->h_length);
- rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr));
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&addr));
#endif
return ary;
@@ -777,22 +908,21 @@ s_accept(class, fd, sockaddr, len)
int fd2;
retry:
-#ifdef USE_THREAD
rb_thread_wait_fd(fd);
-#endif
TRAP_BEG;
fd2 = accept(fd, sockaddr, len);
TRAP_END;
if (fd2 < 0) {
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
+ rb_thread_wait_fd(fd);
goto retry;
}
rb_sys_fail(0);
@@ -805,12 +935,12 @@ tcp_accept(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in from;
+ struct sockaddr_storage from;
int fromlen;
GetOpenFile(sock, fptr);
- fromlen = sizeof(struct sockaddr_in);
- return s_accept(rb_cTCPsocket, fileno(fptr->f),
+ fromlen = sizeof(from);
+ return s_accept(rb_cTCPSocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
@@ -836,10 +966,12 @@ open_unix(class, path, server)
OpenFile *fptr;
Check_SafeStr(path);
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) rb_sys_fail("socket(2)");
+ fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2)");
+ }
- memset(&sockaddr, 0, sizeof(sockaddr));
+ MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
strncpy(sockaddr.sun_path, path->ptr, sizeof(sockaddr.sun_path)-1);
sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0';
@@ -848,7 +980,7 @@ open_unix(class, path, server)
status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
}
else {
- status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ status = ruby_connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr), 0);
}
if (status < 0) {
@@ -871,14 +1003,14 @@ ip_addr(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
int len = sizeof addr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail("getsockname(2)");
- return ipaddr(&addr);
+ return ipaddr((struct sockaddr *)&addr);
}
static VALUE
@@ -886,106 +1018,67 @@ ip_peeraddr(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
int len = sizeof addr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail("getpeername(2)");
- return ipaddr(&addr);
+ return ipaddr((struct sockaddr *)&addr);
}
static VALUE
ip_s_getaddress(obj, host)
VALUE obj, host;
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
- if (rb_obj_is_kind_of(host, rb_cInteger)) {
- int i = NUM2INT(host);
- addr.sin_addr.s_addr = htonl(i);
- }
- else {
- setipaddr(STR2CSTR(host), &addr);
- }
-
- return mkipaddr(addr.sin_addr.s_addr);
+ setipaddr(host, &addr);
+ return mkipaddr((struct sockaddr *)&addr);
}
static VALUE
-udp_s_open(class)
+udp_s_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
VALUE class;
{
- return sock_new(class, socket(AF_INET, SOCK_DGRAM, 0));
-}
+ VALUE arg;
+ int socktype = AF_INET;
+ int fd;
-static void
-udp_addrsetup(host, port, addr)
- VALUE host, port;
- struct sockaddr_in *addr;
-{
- memset(addr, 0, sizeof(struct sockaddr_in));
- addr->sin_family = AF_INET;
- if (NIL_P(host)) {
- addr->sin_addr.s_addr = INADDR_ANY;
- }
- else if (rb_obj_is_kind_of(host, rb_cInteger)) {
- int i = NUM2INT(host);
- addr->sin_addr.s_addr = htonl(i);
- }
- else {
- setipaddr(STR2CSTR(host), addr);
+ if (rb_scan_args(argc, argv, "01", &arg) == 1) {
+ socktype = NUM2INT(arg);
}
- if (FIXNUM_P(port)) {
- addr->sin_port = htons(FIX2INT(port));
+ fd = ruby_socket(socktype, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2) - udp");
}
- else {
- struct servent *servent;
- servent = getservbyname(STR2CSTR(port), "udp");
- if (servent) {
- addr->sin_port = servent->s_port;
- }
- else {
- char *s = STR2CSTR(port);
- char *end;
- int portno;
-
- portno = strtoul(s, &end, 0);
- if (*end != '\0') {
- rb_raise(rb_eSocket, "no such servce %s", s);
- }
- addr->sin_port = htons(port);
- }
- }
+ return sock_new(class, fd);
}
static VALUE
udp_connect(sock, host, port)
VALUE sock, host, port;
{
- struct sockaddr_in addr;
OpenFile *fptr;
+ int fd;
+ struct addrinfo *res0, *res;
- udp_addrsetup(host, port, &addr);
GetOpenFile(sock, fptr);
- retry:
- if (connect(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) {
- switch (errno) {
- case EINTR:
- case EWOULDBLOCK:
-#if EAGAIN != EWOULDBLOCK
- case EAGAIN:
-#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
- goto retry;
+ fd = fileno(fptr->f);
+ res0 = ip_addrsetup(host, port);
+ for (res = res0; res; res = res->ai_next) {
+ if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
+ freeaddrinfo(res0);
+ return INT2FIX(0);
}
- rb_sys_fail("connect(2)");
}
+ freeaddrinfo(res0);
+ rb_sys_fail("connect(2)");
return INT2FIX(0);
}
@@ -993,14 +1086,20 @@ static VALUE
udp_bind(sock, host, port)
VALUE sock, host, port;
{
- struct sockaddr_in addr;
OpenFile *fptr;
+ struct addrinfo *res0, *res;
- udp_addrsetup(host, port, &addr);
GetOpenFile(sock, fptr);
- if (bind(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) {
- rb_sys_fail("bind(2)");
+ res0 = ip_addrsetup(host, port);
+ for (res = res0; res; res = res->ai_next) {
+ if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
+ continue;
+ }
+ freeaddrinfo(res0);
+ return INT2FIX(0);
}
+ freeaddrinfo(res0);
+ rb_sys_fail("bind(2)");
return INT2FIX(0);
}
@@ -1011,39 +1110,45 @@ udp_send(argc, argv, sock)
VALUE sock;
{
VALUE mesg, flags, host, port;
- struct sockaddr_in addr;
OpenFile *fptr;
FILE *f;
int n;
char *m;
int mlen;
+ struct addrinfo *res0, *res;
if (argc == 2) {
return bsock_send(argc, argv, sock);
}
rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
- udp_addrsetup(host, port, &addr);
GetOpenFile(sock, fptr);
+ res0 = ip_addrsetup(host, port);
f = GetWriteFile(fptr);
m = rb_str2cstr(mesg, &mlen);
+ for (res = res0; res; res = res->ai_next) {
retry:
- n = sendto(fileno(f), m, mlen, NUM2INT(flags),
- (struct sockaddr*)&addr, sizeof(addr));
- if (n < 0) {
+ n = sendto(fileno(f), m, mlen, NUM2INT(flags), res->ai_addr,
+ res->ai_addrlen);
+ if (n >= 0) {
+ freeaddrinfo(res0);
+ return INT2FIX(n);
+ }
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
+ thread_write_select(fileno(f));
goto retry;
}
- rb_sys_fail("sendto(2)");
}
+ freeaddrinfo(res0);
+ rb_sys_fail("sendto(2)");
return INT2FIX(n);
}
@@ -1107,7 +1212,7 @@ unix_accept(sock)
GetOpenFile(sock, fptr);
fromlen = sizeof(struct sockaddr_un);
- return s_accept(rb_cUNIXsocket, fileno(fptr->f),
+ return s_accept(rb_cUNIXSocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
@@ -1242,7 +1347,7 @@ sock_s_open(class, domain, type, protocol)
int d, t;
setup_domain_and_type(domain, &d, type, &t);
- fd = socket(d, t, NUM2INT(protocol));
+ fd = ruby_socket(d, t, NUM2INT(protocol));
if (fd < 0) rb_sys_fail("socket(2)");
return sock_new(class, fd);
@@ -1259,12 +1364,18 @@ static VALUE
sock_s_socketpair(class, domain, type, protocol)
VALUE class, domain, type, protocol;
{
-#if !defined(NT) && !defined(__BEOS__)
+#if !defined(NT) && !defined(__BEOS__) && !defined(__EMX__)
int d, t, sp[2];
setup_domain_and_type(domain, &d, type, &t);
- if (socketpair(d, t, NUM2INT(protocol), sp) < 0)
+ again:
+ if (socketpair(d, t, NUM2INT(protocol), sp) < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ goto again;
+ }
rb_sys_fail("socketpair(2)");
+ }
return rb_assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
#else
@@ -1277,24 +1388,14 @@ sock_connect(sock, addr)
VALUE sock, addr;
{
OpenFile *fptr;
+ int fd;
Check_Type(addr, T_STRING);
rb_str_modify(addr);
GetOpenFile(sock, fptr);
- retry:
- if (connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) {
- switch (errno) {
- case EINTR:
- case EWOULDBLOCK:
-#if EAGAIN != EWOULDBLOCK
- case EAGAIN:
-#endif
-#ifdef USE_THREAD
- rb_thread_schedule();
-#endif
- goto retry;
- }
+ fd = fileno(fptr->f);
+ if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
rb_sys_fail("connect(2)");
}
@@ -1344,7 +1445,7 @@ sock_accept(sock)
VALUE sock;
{
OpenFile *fptr;
- VALUE addr, sock2;
+ VALUE sock2;
char buf[1024];
int len = sizeof buf;
@@ -1401,7 +1502,7 @@ mkhostent(h)
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
- rb_raise(rb_eSocket, (char *)hstrerror(h_errno));
+ rb_raise(rb_eSocket, "%s", (char *)hstrerror(h_errno));
#else
rb_raise(rb_eSocket, "host not found");
#endif
@@ -1413,7 +1514,7 @@ mkhostent(h)
for (pch = h->h_aliases; *pch; pch++) {
rb_ary_push(names, rb_str_new2(*pch));
}
- rb_ary_push(ary, NUM2INT(h->h_addrtype));
+ rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
rb_ary_push(ary, rb_str_new(*pch, h->h_length));
@@ -1426,22 +1527,73 @@ mkhostent(h)
}
static VALUE
+mkaddrinfo(res0)
+ struct addrinfo *res0;
+{
+ VALUE base, ary;
+ struct addrinfo *res;
+
+ if (res0 == NULL) {
+ rb_raise(rb_eSocket, "host not found");
+ }
+ base = rb_ary_new();
+ for (res = res0; res; res = res->ai_next) {
+ ary = ipaddr(res->ai_addr);
+ rb_ary_push(ary, INT2FIX(res->ai_family));
+ rb_ary_push(ary, INT2FIX(res->ai_socktype));
+ rb_ary_push(ary, INT2FIX(res->ai_protocol));
+ rb_ary_push(base, ary);
+ }
+ return base;
+}
+
+/*
+ * NOTE: using gethostbyname() against AF_INET6 is a bad idea, as it
+ * does not initialize sin_flowinfo nor sin_scope_id properly.
+ */
+static VALUE
sock_s_gethostbyname(obj, host)
VALUE obj, host;
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
struct hostent *h;
if (rb_obj_is_kind_of(host, rb_cInteger)) {
- int i = NUM2INT(host);
- addr.sin_addr.s_addr = htonl(i);
+ long i = NUM2LONG(host);
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ MEMZERO(sin, struct sockaddr_in, 1);
+ sin->sin_family = AF_INET;
+ SET_SIN_LEN(sin, sizeof(*sin));
+ sin->sin_addr.s_addr = htonl(i);
}
else {
- setipaddr(STR2CSTR(host), &addr);
+ setipaddr(host, (struct sockaddr *)&addr);
+ }
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ h = gethostbyaddr((char *)&sin->sin_addr,
+ sizeof(sin->sin_addr),
+ sin->sin_family);
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&addr;
+ h = gethostbyaddr((char *)&sin6->sin6_addr,
+ sizeof(sin6->sin6_addr),
+ sin6->sin6_family);
+ break;
+ }
+#endif
+ default:
+ h = NULL;
}
- h = gethostbyaddr((char *)&addr.sin_addr,
- sizeof(addr.sin_addr),
- AF_INET);
return mkhostent(h);
}
@@ -1502,10 +1654,172 @@ sock_s_getservbyaname(argc, argv)
return INT2FIX(port);
}
+static VALUE
+sock_s_getaddrinfo(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE host, port, family, socktype, protocol, flags, ret;
+ char hbuf[1024], pbuf[1024];
+ char *hptr, *pptr;
+ struct addrinfo hints, *res;
+ int error;
+
+ host = port = family = socktype = protocol = flags = Qnil;
+ rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol,
+ &flags);
+ if (NIL_P(host)) {
+ hptr = NULL;
+ }
+ else {
+ strncpy(hbuf, STR2CSTR(host), sizeof(hbuf));
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ hptr = hbuf;
+ }
+ if (NIL_P(port)) {
+ pptr = NULL;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
+ pptr = pbuf;
+ }
+ else {
+ strncpy(pbuf, STR2CSTR(port), sizeof(pbuf));
+ pbuf[sizeof(pbuf) - 1] = '\0';
+ pptr = pbuf;
+ }
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (!NIL_P(family)) {
+ hints.ai_family = NUM2INT(family);
+ }
+ else {
+ hints.ai_family = PF_UNSPEC;
+ }
+ if (!NIL_P(socktype)) {
+ hints.ai_socktype = NUM2INT(socktype);
+ }
+ if (!NIL_P(protocol)) {
+ hints.ai_protocol = NUM2INT(protocol);
+ }
+ if (!NIL_P(flags)) {
+ hints.ai_flags = NUM2INT(flags);
+ }
+ error = getaddrinfo(hptr, pptr, &hints, &res);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+
+ ret = mkaddrinfo(res);
+ freeaddrinfo(res);
+ return ret;
+}
+
+static VALUE
+sock_s_getnameinfo(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE sa, af, host, port, flags;
+ static char hbuf[1024], pbuf[1024];
+ char *hptr, *pptr;
+ int fl;
+ struct addrinfo hints, *res = NULL;
+ int error;
+ struct sockaddr_storage ss;
+ struct sockaddr *sap;
+
+ sa = flags = Qnil;
+ rb_scan_args(argc, argv, "11", &sa, &flags);
+
+ if (TYPE(sa) == T_STRING) {
+ if (sizeof(ss) < RSTRING(sa)->len) {
+ rb_raise(rb_eTypeError, "sockaddr length too big");
+ }
+ memcpy(&ss, RSTRING(sa)->ptr, RSTRING(sa)->len);
+ if (RSTRING(sa)->len != SA_LEN((struct sockaddr *)&ss)) {
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
+ sap = (struct sockaddr *)&ss;
+ }
+ else if (TYPE(sa) == T_ARRAY) {
+ if (RARRAY(sa)->len == 3) {
+ af = RARRAY(sa)->ptr[0];
+ port = RARRAY(sa)->ptr[1];
+ host = RARRAY(sa)->ptr[2];
+ }
+ else if (RARRAY(sa)->len >= 4) {
+ af = RARRAY(sa)->ptr[0];
+ port = RARRAY(sa)->ptr[1];
+ host = RARRAY(sa)->ptr[3];
+ if (NIL_P(host)) {
+ host = RARRAY(sa)->ptr[2];
+ }
+ }
+ if (NIL_P(host)) {
+ hptr = NULL;
+ }
+ else {
+ strncpy(hbuf, STR2CSTR(host), sizeof(hbuf));
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ hptr = hbuf;
+ }
+ if (NIL_P(port)) {
+ strcpy(pbuf, "0");
+ pptr = NULL;
+ }
+ else if (!NIL_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%d", NUM2INT(port));
+ pptr = pbuf;
+ }
+ else {
+ strncpy(pbuf, STR2CSTR(port), sizeof(pbuf));
+ pbuf[sizeof(pbuf) - 1] = '\0';
+ pptr = pbuf;
+ }
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (strcmp(STR2CSTR(af), "AF_INET") == 0) {
+ hints.ai_family = PF_INET;
+ }
+#ifdef INET6
+ else if (strcmp(STR2CSTR(af), "AF_INET6") == 0) {
+ hints.ai_family = PF_INET6;
+ }
+#endif
+ else {
+ hints.ai_family = PF_UNSPEC;
+ }
+ error = getaddrinfo(hptr, pptr, &hints, &res);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+ sap = res->ai_addr;
+ }
+ else {
+ rb_raise(rb_eTypeError, "expecting String or Array");
+ }
+
+ fl = 0;
+ if (!NIL_P(flags)) {
+ fl = NUM2INT(flags);
+ }
+
+ gotsap:
+ error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), fl);
+ if (error) {
+ rb_raise(rb_eSocket, "%s", gai_strerror(error));
+ }
+ if (res)
+ freeaddrinfo(res);
+
+ return rb_ary_new3(2, rb_str_new2(hbuf), rb_str_new2(pbuf));
+}
+
static VALUE mConst;
static void
-sock_rb_define_const(name, value)
+sock_define_const(name, value)
char *name;
int value;
{
@@ -1513,6 +1827,7 @@ sock_rb_define_const(name, value)
rb_define_const(mConst, name, INT2FIX(value));
}
+void
Init_socket()
{
rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
@@ -1520,6 +1835,12 @@ Init_socket()
rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
rb_undef_method(CLASS_OF(rb_cBasicSocket), "new");
rb_undef_method(CLASS_OF(rb_cBasicSocket), "open");
+
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
+ bsock_do_not_rev_lookup, 0);
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
+ bsock_do_not_rev_lookup_set, 1);
+
rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
@@ -1530,49 +1851,56 @@ Init_socket()
rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
- rb_cIPsocket = rb_define_class("IPsocket", rb_cBasicSocket);
- rb_define_method(rb_cIPsocket, "addr", ip_addr, 0);
- rb_define_method(rb_cIPsocket, "peeraddr", ip_peeraddr, 0);
- rb_define_singleton_method(rb_cIPsocket, "getaddress", ip_s_getaddress, 1);
+ rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
+ rb_define_global_const("IPsocket", rb_cIPSocket);
+ rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
+ rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
+ rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
- rb_cTCPsocket = rb_define_class("TCPsocket", rb_cIPsocket);
- rb_define_singleton_method(rb_cTCPsocket, "open", tcp_s_open, 2);
- rb_define_singleton_method(rb_cTCPsocket, "new", tcp_s_open, 2);
- rb_define_singleton_method(rb_cTCPsocket, "gethostbyname", tcp_s_gethostbyname, 1);
- rb_define_method(rb_cTCPsocket, "recvfrom", tcp_recvfrom, -1);
+ rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
+ rb_define_global_const("TCPsocket", rb_cTCPSocket);
+ rb_define_singleton_method(rb_cTCPSocket, "open", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPSocket, "new", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
+ rb_define_method(rb_cTCPSocket, "recvfrom", tcp_recvfrom, -1);
#ifdef SOCKS
- rb_cSOCKSsocket = rb_define_class("SOCKSsocket", rb_cTCPsocket);
- rb_define_singleton_method(rb_cSOCKSsocket, "open", socks_s_open, 2);
- rb_define_singleton_method(rb_cSOCKSsocket, "new", socks_s_open, 2);
-#endif
-
- rb_cTCPserver = rb_define_class("TCPserver", rb_cTCPsocket);
- rb_define_singleton_method(rb_cTCPserver, "open", tcp_svr_s_open, -1);
- rb_define_singleton_method(rb_cTCPserver, "new", tcp_svr_s_open, -1);
- rb_define_method(rb_cTCPserver, "accept", tcp_accept, 0);
-
- rb_cUDPsocket = rb_define_class("UDPsocket", rb_cIPsocket);
- rb_define_singleton_method(rb_cUDPsocket, "open", udp_s_open, 0);
- rb_define_singleton_method(rb_cUDPsocket, "new", udp_s_open, 0);
- rb_define_method(rb_cUDPsocket, "connect", udp_connect, 2);
- rb_define_method(rb_cUDPsocket, "bind", udp_bind, 2);
- rb_define_method(rb_cUDPsocket, "send", udp_send, -1);
- rb_define_method(rb_cUDPsocket, "recvfrom", udp_recvfrom, -1);
+ rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
+ rb_define_global_const("SOCKSsocket", rb_cSOCKSSocket);
+ rb_define_singleton_method(rb_cSOCKSSocket, "open", socks_s_open, 2);
+ rb_define_singleton_method(rb_cSOCKSSocket, "new", socks_s_open, 2);
+#endif
+
+ rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
+ rb_define_global_const("TCPserver", rb_cTCPServer);
+ rb_define_singleton_method(rb_cTCPServer, "open", tcp_svr_s_open, -1);
+ rb_define_singleton_method(rb_cTCPServer, "new", tcp_svr_s_open, -1);
+ rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
+
+ rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
+ rb_define_global_const("UDPsocket", rb_cUDPSocket);
+ rb_define_singleton_method(rb_cUDPSocket, "open", udp_s_open, -1);
+ rb_define_singleton_method(rb_cUDPSocket, "new", udp_s_open, -1);
+ rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
+ rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
+ rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
+ rb_define_method(rb_cUDPSocket, "recvfrom", udp_recvfrom, -1);
#ifdef HAVE_SYS_UN_H
- rb_cUNIXsocket = rb_define_class("UNIXsocket", rb_cBasicSocket);
- rb_define_singleton_method(rb_cUNIXsocket, "open", unix_s_sock_open, 1);
- rb_define_singleton_method(rb_cUNIXsocket, "new", unix_s_sock_open, 1);
- rb_define_method(rb_cUNIXsocket, "path", unix_path, 0);
- rb_define_method(rb_cUNIXsocket, "addr", unix_addr, 0);
- rb_define_method(rb_cUNIXsocket, "peeraddr", unix_peeraddr, 0);
- rb_define_method(rb_cUNIXsocket, "recvfrom", unix_recvfrom, -1);
-
- rb_cUNIXserver = rb_define_class("UNIXserver", rb_cUNIXsocket);
- rb_define_singleton_method(rb_cUNIXserver, "open", unix_svr_s_open, 1);
- rb_define_singleton_method(rb_cUNIXserver, "new", unix_svr_s_open, 1);
- rb_define_method(rb_cUNIXserver, "accept", unix_accept, 0);
+ rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
+ rb_define_global_const("UNIXsocket", rb_cUNIXSocket);
+ rb_define_singleton_method(rb_cUNIXSocket, "open", unix_s_sock_open, 1);
+ rb_define_singleton_method(rb_cUNIXSocket, "new", unix_s_sock_open, 1);
+ rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
+ rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
+ rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
+ rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
+
+ rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
+ rb_define_global_const("UNIXserver", rb_cUNIXServer);
+ rb_define_singleton_method(rb_cUNIXServer, "open", unix_svr_s_open, 1);
+ rb_define_singleton_method(rb_cUNIXServer, "new", unix_svr_s_open, 1);
+ rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
#endif
rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
@@ -1593,152 +1921,255 @@ Init_socket()
rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
+ rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
+ rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
/* constants */
mConst = rb_define_module_under(rb_cSocket, "Constants");
- sock_rb_define_const("SOCK_STREAM", SOCK_STREAM);
- sock_rb_define_const("SOCK_DGRAM", SOCK_DGRAM);
+ sock_define_const("SOCK_STREAM", SOCK_STREAM);
+ sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
#ifdef SOCK_RAW
- sock_rb_define_const("SOCK_RAW", SOCK_RAW);
+ sock_define_const("SOCK_RAW", SOCK_RAW);
#endif
#ifdef SOCK_RDM
- sock_rb_define_const("SOCK_RDM", SOCK_RDM);
+ sock_define_const("SOCK_RDM", SOCK_RDM);
#endif
#ifdef SOCK_SEQPACKET
- sock_rb_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
+ sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET);
#endif
#ifdef SOCK_PACKET
- sock_rb_define_const("SOCK_PACKET", SOCK_PACKET);
+ sock_define_const("SOCK_PACKET", SOCK_PACKET);
#endif
- sock_rb_define_const("AF_INET", AF_INET);
+ sock_define_const("AF_INET", AF_INET);
#ifdef PF_INET
- sock_rb_define_const("PF_INET", PF_INET);
+ sock_define_const("PF_INET", PF_INET);
#endif
#ifdef AF_UNIX
- sock_rb_define_const("AF_UNIX", AF_UNIX);
- sock_rb_define_const("PF_UNIX", PF_UNIX);
+ sock_define_const("AF_UNIX", AF_UNIX);
+ sock_define_const("PF_UNIX", PF_UNIX);
#endif
#ifdef AF_AX25
- sock_rb_define_const("AF_AX25", AF_AX25);
- sock_rb_define_const("PF_AX25", PF_AX25);
+ sock_define_const("AF_AX25", AF_AX25);
+ sock_define_const("PF_AX25", PF_AX25);
#endif
#ifdef AF_IPX
- sock_rb_define_const("AF_IPX", AF_IPX);
- sock_rb_define_const("PF_IPX", PF_IPX);
+ sock_define_const("AF_IPX", AF_IPX);
+ sock_define_const("PF_IPX", PF_IPX);
#endif
#ifdef AF_APPLETALK
- sock_rb_define_const("AF_APPLETALK", AF_APPLETALK);
- sock_rb_define_const("PF_APPLETALK", PF_APPLETALK);
+ sock_define_const("AF_APPLETALK", AF_APPLETALK);
+ sock_define_const("PF_APPLETALK", PF_APPLETALK);
+#endif
+#ifdef AF_UNSPEC
+ sock_define_const("AF_UNSPEC", AF_UNSPEC);
+ sock_define_const("PF_UNSPEC", PF_UNSPEC);
+#endif
+#ifdef AF_INET6
+ sock_define_const("AF_INET6", AF_INET6);
+#endif
+#ifdef PF_INET6
+ sock_define_const("PF_INET6", PF_INET6);
#endif
- sock_rb_define_const("MSG_OOB", MSG_OOB);
+ sock_define_const("MSG_OOB", MSG_OOB);
#ifdef MSG_PEEK
- sock_rb_define_const("MSG_PEEK", MSG_PEEK);
+ sock_define_const("MSG_PEEK", MSG_PEEK);
#endif
#ifdef MSG_DONTROUTE
- sock_rb_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
+ sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
#endif
- sock_rb_define_const("SOL_SOCKET", SOL_SOCKET);
+ sock_define_const("SOL_SOCKET", SOL_SOCKET);
#ifdef SOL_IP
- sock_rb_define_const("SOL_IP", SOL_IP);
+ sock_define_const("SOL_IP", SOL_IP);
#endif
#ifdef SOL_IPX
- sock_rb_define_const("SOL_IPX", SOL_IPX);
+ sock_define_const("SOL_IPX", SOL_IPX);
#endif
#ifdef SOL_AX25
- sock_rb_define_const("SOL_AX25", SOL_AX25);
+ sock_define_const("SOL_AX25", SOL_AX25);
#endif
#ifdef SOL_ATALK
- sock_rb_define_const("SOL_ATALK", SOL_ATALK);
+ sock_define_const("SOL_ATALK", SOL_ATALK);
#endif
#ifdef SOL_TCP
- sock_rb_define_const("SOL_TCP", SOL_TCP);
+ sock_define_const("SOL_TCP", SOL_TCP);
#endif
#ifdef SOL_UDP
- sock_rb_define_const("SOL_UDP", SOL_UDP);
+ sock_define_const("SOL_UDP", SOL_UDP);
#endif
#ifdef SO_DEBUG
- sock_rb_define_const("SO_DEBUG", SO_DEBUG);
+ sock_define_const("SO_DEBUG", SO_DEBUG);
#endif
- sock_rb_define_const("SO_REUSEADDR", SO_REUSEADDR);
+ sock_define_const("SO_REUSEADDR", SO_REUSEADDR);
#ifdef SO_TYPE
- sock_rb_define_const("SO_TYPE", SO_TYPE);
+ sock_define_const("SO_TYPE", SO_TYPE);
#endif
#ifdef SO_ERROR
- sock_rb_define_const("SO_ERROR", SO_ERROR);
+ sock_define_const("SO_ERROR", SO_ERROR);
#endif
#ifdef SO_DONTROUTE
- sock_rb_define_const("SO_DONTROUTE", SO_DONTROUTE);
+ sock_define_const("SO_DONTROUTE", SO_DONTROUTE);
#endif
#ifdef SO_BROADCAST
- sock_rb_define_const("SO_BROADCAST", SO_BROADCAST);
+ sock_define_const("SO_BROADCAST", SO_BROADCAST);
#endif
#ifdef SO_SNDBUF
- sock_rb_define_const("SO_SNDBUF", SO_SNDBUF);
+ sock_define_const("SO_SNDBUF", SO_SNDBUF);
#endif
#ifdef SO_RCVBUF
- sock_rb_define_const("SO_RCVBUF", SO_RCVBUF);
+ sock_define_const("SO_RCVBUF", SO_RCVBUF);
#endif
#ifdef SO_KEEPALIVE
- sock_rb_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
+ sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
#endif
#ifdef SO_OOBINLINE
- sock_rb_define_const("SO_OOBINLINE", SO_OOBINLINE);
+ sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
#endif
#ifdef SO_NO_CHECK
- sock_rb_define_const("SO_NO_CHECK", SO_NO_CHECK);
+ sock_define_const("SO_NO_CHECK", SO_NO_CHECK);
#endif
#ifdef SO_PRIORITY
- sock_rb_define_const("SO_PRIORITY", SO_PRIORITY);
+ sock_define_const("SO_PRIORITY", SO_PRIORITY);
#endif
#ifdef SO_LINGER
- sock_rb_define_const("SO_LINGER", SO_LINGER);
+ sock_define_const("SO_LINGER", SO_LINGER);
#endif
#ifdef SOPRI_INTERACTIVE
- sock_rb_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
+ sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
#endif
#ifdef SOPRI_NORMAL
- sock_rb_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
+ sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL);
#endif
#ifdef SOPRI_BACKGROUND
- sock_rb_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
+ sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND);
#endif
#ifdef IP_MULTICAST_IF
- sock_rb_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
+ sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF);
#endif
#ifdef IP_MULTICAST_TTL
- sock_rb_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
+ sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL);
#endif
#ifdef IP_MULTICAST_LOOP
- sock_rb_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
+ sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP);
#endif
#ifdef IP_ADD_MEMBERSHIP
- sock_rb_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
+ sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP);
#endif
#ifdef IP_DEFAULT_MULTICAST_TTL
- sock_rb_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
+ sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL);
#endif
#ifdef IP_DEFAULT_MULTICAST_LOOP
- sock_rb_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
+ sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP);
#endif
#ifdef IP_MAX_MEMBERSHIPS
- sock_rb_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
+ sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
#endif
#ifdef IPX_TYPE
- sock_rb_define_const("IPX_TYPE", IPX_TYPE);
+ sock_define_const("IPX_TYPE", IPX_TYPE);
#endif
#ifdef TCP_NODELAY
- sock_rb_define_const("TCP_NODELAY", TCP_NODELAY);
+ sock_define_const("TCP_NODELAY", TCP_NODELAY);
#endif
#ifdef TCP_MAXSEG
- sock_rb_define_const("TCP_MAXSEG", TCP_MAXSEG);
+ sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
+#endif
+
+#ifdef EAI_ADDRFAMILY
+ sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY);
+#endif
+#ifdef EAI_AGAIN
+ sock_define_const("EAI_AGAIN", EAI_AGAIN);
+#endif
+#ifdef EAI_BADFLAGS
+ sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS);
+#endif
+#ifdef EAI_FAIL
+ sock_define_const("EAI_FAIL", EAI_FAIL);
+#endif
+#ifdef EAI_FAMILY
+ sock_define_const("EAI_FAMILY", EAI_FAMILY);
+#endif
+#ifdef EAI_MEMORY
+ sock_define_const("EAI_MEMORY", EAI_MEMORY);
+#endif
+#ifdef EAI_NODATA
+ sock_define_const("EAI_NODATA", EAI_NODATA);
+#endif
+#ifdef EAI_NONAME
+ sock_define_const("EAI_NONAME", EAI_NONAME);
+#endif
+#ifdef EAI_SERVICE
+ sock_define_const("EAI_SERVICE", EAI_SERVICE);
+#endif
+#ifdef EAI_SOCKTYPE
+ sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE);
+#endif
+#ifdef EAI_SYSTEM
+ sock_define_const("EAI_SYSTEM", EAI_SYSTEM);
+#endif
+#ifdef EAI_BADHINTS
+ sock_define_const("EAI_BADHINTS", EAI_BADHINTS);
+#endif
+#ifdef EAI_PROTOCOL
+ sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL);
+#endif
+#ifdef EAI_MAX
+ sock_define_const("EAI_MAX", EAI_MAX);
+#endif
+#ifdef AI_PASSIVE
+ sock_define_const("AI_PASSIVE", AI_PASSIVE);
+#endif
+#ifdef AI_CANONNAME
+ sock_define_const("AI_CANONNAME", AI_CANONNAME);
+#endif
+#ifdef AI_NUMERICHOST
+ sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST);
+#endif
+#ifdef AI_MASK
+ sock_define_const("AI_MASK", AI_MASK);
+#endif
+#ifdef AI_ALL
+ sock_define_const("AI_ALL", AI_ALL);
+#endif
+#ifdef AI_V4MAPPED_CFG
+ sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG);
+#endif
+#ifdef AI_ADDRCONFIG
+ sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG);
+#endif
+#ifdef AI_V4MAPPED
+ sock_define_const("AI_V4MAPPED", AI_V4MAPPED);
+#endif
+#ifdef AI_DEFAULT
+ sock_define_const("AI_DEFAULT", AI_DEFAULT);
+#endif
+#ifdef NI_MAXHOST
+ sock_define_const("NI_MAXHOST", NI_MAXHOST);
+#endif
+#ifdef NI_MAXSERV
+ sock_define_const("NI_MAXSERV", NI_MAXSERV);
+#endif
+#ifdef NI_NOFQDN
+ sock_define_const("NI_NOFQDN", NI_NOFQDN);
+#endif
+#ifdef NI_NUMERICHOST
+ sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST);
+#endif
+#ifdef NI_NAMEREQD
+ sock_define_const("NI_NAMEREQD", NI_NAMEREQD);
+#endif
+#ifdef NI_NUMERICSERV
+ sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV);
+#endif
+#ifdef NI_DGRAM
+ sock_define_const("NI_DGRAM", NI_DGRAM);
#endif
}
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
new file mode 100644
index 0000000000..99bec91a1a
--- /dev/null
+++ b/ext/socket/sockport.h
@@ -0,0 +1,43 @@
+/************************************************
+
+ sockport.h -
+
+ $Author$
+ $Date$
+ created at: Fri Apr 30 23:19:34 JST 1999
+
+************************************************/
+
+#ifndef SOCKPORT_H
+#define SOCKPORT_H
+
+#ifndef SA_LEN
+# ifdef HAVE_SA_LEN
+# define SA_LEN(sa) (sa)->sa_len
+# else
+# ifdef INET6
+# define SA_LEN(sa) \
+ (((sa)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
+ : sizeof(struct sockaddr))
+# else
+ /* by tradition, sizeof(struct sockaddr) covers most of the sockaddrs */
+# define SA_LEN(sa) (sizeof(struct sockaddr))
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SA_LEN
+# define SET_SA_LEN(sa, len) (sa)->sa_len = (len)
+#else
+# define SET_SA_LEN(sa, len) (len)
+#endif
+
+#ifdef HAVE_SIN_LEN
+# define SIN_LEN(si) (si)->sin_len
+# define SET_SIN_LEN(si,len) (si)->sin_len = (len)
+#else
+# define SIN_LEN(si) sizeof(struct sockaddr_in)
+# define SET_SIN_LEN(si,len) (len)
+#endif
+
+#endif
diff --git a/ext/tcltklib/depend b/ext/tcltklib/depend
index 71d9f20537..e91f9dacbf 100644
--- a/ext/tcltklib/depend
+++ b/ext/tcltklib/depend
@@ -1 +1 @@
-tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+tcltklib.o: tcltklib.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb
index e34e549ca0..e1086855ba 100644
--- a/ext/tcltklib/extconf.rb
+++ b/ext/tcltklib/extconf.rb
@@ -7,79 +7,41 @@ have_library("socket", "socket")
have_library("dl", "dlopen")
have_library("m", "log")
-$includes = []
-def search_header(include, *path)
- pwd = Dir.getwd
- begin
- for i in path.sort!.reverse!
- dir = Dir[i]
- for path in dir.sort!.reverse!
- next unless File.directory? path
- Dir.chdir path
- files = Dir[include]
- if files.size > 0
- unless $includes.include? path
- $includes << path
- end
- return
- end
- end
- end
- ensure
- Dir.chdir pwd
- end
-end
+dir_config("tk")
+dir_config("tcl")
+dir_config("X11")
-search_header("tcl.h",
- "/usr/include/tcl{,8*,7*}",
- "/usr/include",
- "/usr/local/include/tcl{,8*,7*}",
- "/usr/local/include")
-search_header("tk.h",
- "/usr/include/tk{,8*,4*}",
- "/usr/include",
- "/usr/local/include/tk{,8*,4*}",
- "/usr/local/include")
-search_header("X11/Xlib.h",
- "/usr/include/X11*",
- "/usr/include",
- "/usr/openwin/include",
- "/usr/X11*/include")
+tklib = with_config("tklib")
+tcllib = with_config("tcllib")
-$CFLAGS = $includes.collect{|path| "-I" + path}.join(" ")
+def find_tcl(tcllib)
+ paths = ["/usr/local/lib", "/usr/pkg"]
+ func = "Tcl_FindExecutable"
+ if tcllib
+ find_library(tcllib, func, *paths)
+ else
+ find_library("tcl", func, *paths) or
+ find_library("tcl8.0", func, *paths) or
+ find_library("tcl7.6", func, *paths)
+ end
+end
-$libraries = []
-def search_lib(file, func, *path)
- for i in path.reverse!
- dir = Dir[i]
- for path in dir.sort!.reverse!
- $LDFLAGS = $libraries.collect{|p| "-L" + p}.join(" ") + " -L" + path
- files = Dir[path+"/"+file]
- if files.size > 0
- for lib in files.sort!.reverse!
- lib = File::basename(lib)
- lib.sub!(/^lib/, '')
- lib.sub!(/\.(a|so)$/, '')
- if have_library(lib, func)
- unless $libraries.include? path
- $libraries << path
- end
- return true
- end
- end
- end
- end
+def find_tk(tklib)
+ paths = ["/usr/local/lib", "/usr/pkg"]
+ func = "Tk_Init"
+ if tklib
+ find_library(tklib, func, *paths)
+ else
+ find_library("tk", func, *paths) or
+ find_library("tk8.0", func, *paths) or
+ find_library("tk4.2", func, *paths)
end
- return false;
end
if have_header("tcl.h") && have_header("tk.h") &&
- search_lib("libX11.{so,a}", "XOpenDisplay",
- "/usr/lib", "/usr/openwin/lib", "/usr/X11*/lib") &&
- search_lib("libtcl{8*,7*,}.{so,a}", "Tcl_FindExecutable",
- "/usr/lib", "/usr/local/lib") &&
- search_lib("libtk{8*,4*,}.{so,a}", "Tk_Init",
- "/usr/lib", "/usr/local/lib")
- $LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ")
+ (/mswin32/ =~ RUBY_PLATFORM || find_library("X11", "XOpenDisplay",
+ "/usr/X11/lib", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
+ find_tcl(tcllib) &&
+ find_tk(tklib)
create_makefile("tcltklib")
end
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
index 625fe61ccc..314246869e 100644
--- a/ext/tcltklib/tcltklib.c
+++ b/ext/tcltklib/tcltklib.c
@@ -4,22 +4,22 @@
* Oct. 24, 1997 Y. Matsumoto
*/
-#include "ruby.h"
-#include "rubysig.h"
#include <stdio.h>
#include <string.h>
#include <tcl.h>
#include <tk.h>
+#include "ruby.h"
+#include "rubysig.h"
#ifdef __MACOS__
# include <tkMac.h>
# include <Quickdraw.h>
#endif
-/* for rb_debug */
+/* for ruby_debug */
-#define DUMP1(ARG1) if (rb_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
-#define DUMP2(ARG1, ARG2) if (rb_debug) { fprintf(stderr, "tcltklib: ");\
+#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
+#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
/*
#define DUMP1(ARG1)
@@ -27,8 +27,10 @@ fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
*/
/* for callback break & continue */
-VALUE eTkCallbackBreak;
-VALUE eTkCallbackContinue;
+static VALUE eTkCallbackBreak;
+static VALUE eTkCallbackContinue;
+
+static VALUE ip_invoke_real _((int, VALUE*, VALUE));
/* from tkAppInit.c */
@@ -42,51 +44,61 @@ int *tclDummyMathPtr = (int *) matherr;
/*---- module TclTkLib ----*/
+struct invoke_queue {
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+ int done;
+ VALUE result;
+ VALUE thread;
+ struct invoke_queue *next;
+};
+
+static struct invoke_queue *iqueue;
+static VALUE main_thread;
+
/* Tk_ThreadTimer */
-typedef struct {
- Tcl_TimerToken token;
- int flag;
-} Tk_TimerData;
+static Tcl_TimerToken timer_token;
/* timer callback */
-void _timer_for_tcl (ClientData clientData)
+static void
+_timer_for_tcl(clientData)
+ ClientData clientData;
{
- Tk_TimerData *timer = (Tk_TimerData*)clientData;
+ struct invoke_queue *q, *tmp;
+ VALUE thread;
- timer->flag = 0;
- CHECK_INTS;
-#ifdef USE_THREAD
- if (!rb_thread_critical) rb_thread_schedule();
-#endif
+ Tk_DeleteTimerHandler(timer_token);
+ timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
+ (ClientData)0);
- timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
- (ClientData)timer);
- timer->flag = 1;
+ CHECK_INTS;
+ q = iqueue;
+ while (q) {
+ tmp = q;
+ q = q->next;
+ if (!tmp->done) {
+ tmp->done = 1;
+ tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj);
+ thread = tmp->thread;
+ tmp = tmp->next;
+ rb_thread_run(thread);
+ }
+ }
+ rb_thread_schedule();
}
/* execute Tk_MainLoop */
static VALUE
-lib_mainloop(VALUE self)
+lib_mainloop(self)
+ VALUE self;
{
- Tk_TimerData *timer;
-
- timer = (Tk_TimerData *) ckalloc(sizeof(Tk_TimerData));
- timer->flag = 0;
- timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
- (ClientData)timer);
- timer->flag = 1;
-
+ timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
+ (ClientData)0);
DUMP1("start Tk_Mainloop");
- while (Tk_GetNumMainWindows() > 0) {
- Tcl_DoOneEvent(0);
- }
+ Tk_MainLoop();
DUMP1("stop Tk_Mainloop");
-
-#ifdef USE_THREAD
- if (timer->flag) {
- Tk_DeleteTimerHandler(timer->token);
- }
-#endif
+ Tk_DeleteTimerHandler(timer_token);
return Qnil;
}
@@ -99,7 +111,9 @@ struct tcltkip {
/* Tcl command `ruby' */
static VALUE
-ip_eval_rescue(VALUE *failed, VALUE einfo)
+ip_eval_rescue(failed, einfo)
+ VALUE *failed;
+ VALUE einfo;
{
*failed = einfo;
return Qnil;
@@ -107,10 +121,17 @@ ip_eval_rescue(VALUE *failed, VALUE einfo)
static int
#if TCL_MAJOR_VERSION >= 8
-ip_ruby(ClientData clientData, Tcl_Interp *interp,
- int argc, Tcl_Obj *CONST argv[])
+ip_ruby(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ Tcl_Obj *CONST argv[];
#else
-ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
+ip_ruby(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
#endif
{
VALUE res;
@@ -143,11 +164,11 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
VALUE eclass = CLASS_OF(failed);
Tcl_AppendResult(interp, STR2CSTR(failed), (char*)NULL);
if (eclass == eTkCallbackBreak) {
- return TCL_BREAK;
+ return TCL_BREAK;
} else if (eclass == eTkCallbackContinue) {
- return TCL_CONTINUE;
+ return TCL_CONTINUE;
} else {
- return TCL_ERROR;
+ return TCL_ERROR;
}
}
@@ -167,7 +188,8 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
/* destroy interpreter */
static void
-ip_free(struct tcltkip *ptr)
+ip_free(ptr)
+ struct tcltkip *ptr;
{
DUMP1("Tcl_DeleteInterp");
Tcl_DeleteInterp(ptr->ip);
@@ -176,7 +198,8 @@ ip_free(struct tcltkip *ptr)
/* create and initialize interpreter */
static VALUE
-ip_new(VALUE self)
+ip_new(self)
+ VALUE self;
{
struct tcltkip *ptr; /* tcltkip data struct */
VALUE obj; /* newly created object */
@@ -192,11 +215,11 @@ ip_new(VALUE self)
/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "Tcl_Init");
+ rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, "Tk_Init");
+ rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
@@ -218,7 +241,9 @@ ip_new(VALUE self)
/* eval string in tcl by Tcl_Eval() */
static VALUE
-ip_eval(VALUE self, VALUE str)
+ip_eval(self, str)
+ VALUE self;
+ VALUE str;
{
char *s;
char *buf; /* Tcl_Eval requires re-writable string region */
@@ -234,7 +259,7 @@ ip_eval(VALUE self, VALUE str)
DUMP2("Tcl_Eval(%s)", buf);
ptr->return_value = Tcl_Eval(ptr->ip, buf);
if (ptr->return_value == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, ptr->ip->result);
+ rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP2("(TCL_Eval result) %d", ptr->return_value);
@@ -244,76 +269,77 @@ ip_eval(VALUE self, VALUE str)
static VALUE
-ip_toUTF8(VALUE self, VALUE str, VALUE encodename)
+ip_toUTF8(self, str, encodename)
+ VALUE self;
+ VALUE str;
+ VALUE encodename;
{
-#ifndef TCL_UTF_MAX
- return str;
-#else
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- struct tcltkip *ptr;
- char *buff1,*buff2;
-
- Data_Get_Struct(self,struct tcltkip, ptr);
- interp = ptr->ip;
-
- encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
- buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
- strcpy(buff1,STR2CSTR(str));
-
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- Tcl_ExternalToUtfDString(encoding,buff1,strlen(buff1),&dstr);
- buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
- strcpy(buff2,Tcl_DStringValue(&dstr));
-
- Tcl_FreeEncoding(encoding);
- Tcl_DStringFree(&dstr);
-
- return rb_str_new2(buff2);
+#ifdef TCL_UTF_MAX
+ Tcl_Interp *interp;
+ Tcl_Encoding encoding;
+ Tcl_DString dstr;
+ struct tcltkip *ptr;
+ char *buf;
+
+ Data_Get_Struct(self,struct tcltkip, ptr);
+ interp = ptr->ip;
+
+ encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
+ buf = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
+ strcpy(buf,STR2CSTR(str));
+
+ Tcl_DStringInit(&dstr);
+ Tcl_DStringFree(&dstr);
+ Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr);
+ str = rb_str_new2(Tcl_DStringValue(&dstr));
+
+ Tcl_FreeEncoding(encoding);
+ Tcl_DStringFree(&dstr);
#endif
+ return str;
}
static VALUE
-ip_fromUTF8(VALUE self, VALUE str, VALUE encodename)
+ip_fromUTF8(self, str, encodename)
+ VALUE self;
+ VALUE str;
+ VALUE encodename;
{
-#ifndef TCL_UTF_MAX
- return str;
-#else
- Tcl_Interp *interp;
- Tcl_Encoding encoding;
- Tcl_DString dstr;
- struct tcltkip *ptr;
- char *buff1,*buff2;
+#ifdef TCL_UTF_MAX
+ Tcl_Interp *interp;
+ Tcl_Encoding encoding;
+ Tcl_DString dstr;
+ struct tcltkip *ptr;
+ char *buf;
- Data_Get_Struct(self,struct tcltkip, ptr);
- interp = ptr->ip;
+ Data_Get_Struct(self,struct tcltkip, ptr);
+ interp = ptr->ip;
- encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
- buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
- strcpy(buff1,STR2CSTR(str));
+ encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename));
+ buf = ALLOCA_N(char,strlen(STR2CSTR(str))+1);
+ strcpy(buf,STR2CSTR(str));
- Tcl_DStringInit(&dstr);
- Tcl_DStringFree(&dstr);
- Tcl_UtfToExternalDString(encoding,buff1,strlen(buff1),&dstr);
- buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1);
- strcpy(buff2,Tcl_DStringValue(&dstr));
+ Tcl_DStringInit(&dstr);
+ Tcl_DStringFree(&dstr);
+ Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr);
+ str = rb_str_new2(Tcl_DStringValue(&dstr));
- Tcl_FreeEncoding(encoding);
- Tcl_DStringFree(&dstr);
+ Tcl_FreeEncoding(encoding);
+ Tcl_DStringFree(&dstr);
- return rb_str_new2(buff2);
#endif
+ return str;
}
static VALUE
-ip_invoke(int argc, VALUE *argv, VALUE obj)
+ip_invoke_real(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
struct tcltkip *ptr; /* tcltkip data struct */
int i;
- int object = 0;
Tcl_CmdInfo info;
char *cmd;
char **av = (char **)NULL;
@@ -332,63 +358,115 @@ ip_invoke(int argc, VALUE *argv, VALUE obj)
if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
rb_raise(rb_eNameError, "invalid command name `%s'", cmd);
}
-#if TCL_MAJOR_VERSION >= 8
- object = info.isNativeObjectProc;
-#endif
/* memory allocation for arguments of this command */
- if (object) {
#if TCL_MAJOR_VERSION >= 8
- /* object interface */
- ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
- for (i = 0; i < argc; ++i) {
- char *s = STR2CSTR(argv[i]);
- ov[i] = Tcl_NewStringObj(s, strlen(s));
- }
- ov[argc] = (Tcl_Obj *)NULL;
+ if (info.isNativeObjectProc) {
+ /* object interface */
+ ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
+ for (i = 0; i < argc; ++i) {
+ char *s = STR2CSTR(argv[i]);
+ ov[i] = Tcl_NewStringObj(s, strlen(s));
+ Tcl_IncrRefCount(ov[i]);
+ }
+ ov[argc] = (Tcl_Obj *)NULL;
+ }
+ else
#endif
- } else {
+ {
/* string interface */
- av = (char **)ALLOCA_N(char *, argc+1);
- for (i = 0; i < argc; ++i) {
- char *s = STR2CSTR(argv[i]);
-
- av[i] = ALLOCA_N(char, strlen(s)+1);
- strcpy(av[i], s);
- }
- av[argc] = (char *)NULL;
+ av = (char **)ALLOCA_N(char *, argc+1);
+ for (i = 0; i < argc; ++i) {
+ char *s = STR2CSTR(argv[i]);
+
+ av[i] = ALLOCA_N(char, strlen(s)+1);
+ strcpy(av[i], s);
+ }
+ av[argc] = (char *)NULL;
}
Tcl_ResetResult(ptr->ip);
/* Invoke the C procedure */
- if (object) {
#if TCL_MAJOR_VERSION >= 8
- int dummy;
- ptr->return_value = (*info.objProc)(info.objClientData,
- ptr->ip, argc, ov);
-
- /* get the string value from the result object */
- resultPtr = Tcl_GetObjResult(ptr->ip);
- Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
- TCL_VOLATILE);
+ if (info.isNativeObjectProc) {
+ int dummy;
+ ptr->return_value = (*info.objProc)(info.objClientData,
+ ptr->ip, argc, ov);
+
+ /* get the string value from the result object */
+ resultPtr = Tcl_GetObjResult(ptr->ip);
+ Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
+ TCL_VOLATILE);
+
+ for (i=0; i<argc; i++) {
+ Tcl_DecrRefCount(ov[i]);
+ }
+ }
+ else
#endif
- } else {
- ptr->return_value = (*info.proc)(info.clientData,
- ptr->ip, argc, av);
+ {
+ ptr->return_value = (*info.proc)(info.clientData,
+ ptr->ip, argc, av);
}
if (ptr->return_value == TCL_ERROR) {
- rb_raise(rb_eRuntimeError, ptr->ip->result);
+ rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
/* pass back the result (as string) */
- return(rb_str_new2(ptr->ip->result));
+ return rb_str_new2(ptr->ip->result);
+}
+
+static VALUE
+ip_invoke(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ struct invoke_queue *tmp, *p;
+ VALUE result = rb_thread_current();
+
+ if (result == main_thread) {
+ return ip_invoke_real(argc, argv, obj);
+ }
+ tmp = ALLOC(struct invoke_queue);
+ tmp->obj = obj;
+ tmp->argc = argc;
+ tmp->argv = ALLOC_N(VALUE, argc);
+ MEMCPY(tmp->argv, argv, VALUE, argc);
+ tmp->thread = result;
+ tmp->done = 0;
+
+ tmp->next = iqueue;
+ iqueue = tmp;
+
+ rb_thread_stop();
+ result = tmp->result;
+ if (iqueue == tmp) {
+ iqueue = tmp->next;
+ free(tmp->argv);
+ free(tmp);
+ return result;
+ }
+
+ p = iqueue;
+ while (p->next) {
+ if (p->next == tmp) {
+ p->next = tmp->next;
+ free(tmp->argv);
+ free(tmp);
+ break;
+ }
+ p = p->next;
+ }
+ return result;
}
/* get return code from Tcl_Eval() */
static VALUE
-ip_retval(VALUE self)
+ip_retval(self)
+ VALUE self;
{
struct tcltkip *ptr; /* tcltkip data struct */
@@ -402,13 +480,14 @@ ip_retval(VALUE self)
static void
_macinit()
{
- tcl_macQdPtr = &qd; /* setup QuickDraw globals */
- Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
+ tcl_macQdPtr = &qd; /* setup QuickDraw globals */
+ Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
}
#endif
/*---- initialization ----*/
-void Init_tcltklib()
+void
+Init_tcltklib()
{
extern VALUE rb_argv0; /* the argv[0] */
@@ -428,6 +507,7 @@ void Init_tcltklib()
rb_define_method(ip, "_return_value", ip_retval, 0);
rb_define_method(ip, "mainloop", lib_mainloop, 0);
+ main_thread = rb_thread_current();
#ifdef __MACOS__
_macinit();
#endif
diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST
new file mode 100644
index 0000000000..9689186bf0
--- /dev/null
+++ b/ext/tk/MANIFEST
@@ -0,0 +1,25 @@
+MANIFEST
+extconf.rb
+depend
+tkutil.c
+lib/tk.rb
+lib/tkafter.rb
+lib/tkbgerror.rb
+lib/tkcanvas.rb
+lib/tkclass.rb
+lib/tkdialog.rb
+lib/tkentry.rb
+lib/tkfont.rb
+lib/tkmenubar.rb
+lib/tkmngfocus.rb
+lib/tkpalette.rb
+lib/tkscrollbox.rb
+lib/tktext.rb
+lib/tkvirtevent.rb
+sample/tkbiff.rb
+sample/tkbrowse.rb
+sample/tkdialog.rb
+sample/tkfrom.rb
+sample/tkhello.rb
+sample/tkline.rb
+sample/tktimer.rb
diff --git a/ext/tk/depend b/ext/tk/depend
new file mode 100644
index 0000000000..fd63e230f0
--- /dev/null
+++ b/ext/tk/depend
@@ -0,0 +1 @@
+tkutil.o: tkutil.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
new file mode 100644
index 0000000000..f769b06e30
--- /dev/null
+++ b/ext/tk/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile("tkutil")
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
new file mode 100644
index 0000000000..2b4b504b0a
--- /dev/null
+++ b/ext/tk/lib/tk.rb
@@ -0,0 +1,2495 @@
+#
+# tk.rb - Tk interface modue using tcltklib
+# $Date$
+# by Yukihiro Matsumoto <matz@netlab.co.jp>
+
+# use Shigehiro's tcltklib
+require "tcltklib"
+require "tkutil"
+
+module TkComm
+ None = Object.new
+ def None.to_s
+ 'None'
+ end
+
+ Tk_CMDTBL = {}
+ Tk_WINDOWS = {}
+
+ def error_at
+ frames = caller()
+ frames.delete_if do |c|
+ c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
+ end
+ frames
+ end
+ private :error_at
+
+ def _genobj_for_tkwidget(path)
+ return TkRoot.new if path == '.'
+
+ begin
+ tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
+ rescue
+ return path
+ end
+
+ ruby_class = TkClassBind::WidgetClassNameTBL[tk_class]
+ gen_class_name = ruby_class.name + 'GeneratedOnTk'
+ unless Object.const_defined? gen_class_name
+ eval "class #{gen_class_name}<#{ruby_class.name}
+ def initialize(path)
+ @path=path
+ Tk_WINDOWS[@path] = self
+ end
+ end"
+ end
+ eval "#{gen_class_name}.new('#{path}')"
+ end
+
+ def tk_tcl2ruby(val)
+ if val =~ /^rb_out (c\d+)/
+ return Tk_CMDTBL[$1]
+ end
+ if val.include? ?\s
+ return val.split.collect{|v| tk_tcl2ruby(v)}
+ end
+ case val
+ when /^@font/
+ TkFont.get_obj(val)
+ when /^-?\d+$/
+ val.to_i
+ when /^\./
+ Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
+ when / /
+ val.split.collect{|elt|
+ tk_tcl2ruby(elt)
+ }
+ when /^-?\d+\.\d*$/
+ val.to_f
+ else
+ val
+ end
+ end
+
+ def tk_split_list(str)
+ return [] if str == ""
+ idx = str.index('{')
+ return tk_tcl2ruby(str) unless idx
+
+ list = tk_tcl2ruby(str[0,idx])
+ list = [] if list == ""
+ str = str[idx+1..-1]
+ i = -1
+ brace = 1
+ str.each_byte {|c|
+ i += 1
+ brace += 1 if c == ?{
+ brace -= 1 if c == ?}
+ break if brace == 0
+ }
+ if str[0, i] == ' '
+ list.push ' '
+ else
+ list.push tk_split_list(str[0, i])
+ end
+ list += tk_split_list(str[i+1..-1])
+ list
+ end
+
+ def tk_split_simplelist(str)
+ return [] if str == ""
+ idx = str.index('{')
+ return str.split unless idx
+
+ list = str[0,idx].split
+ str = str[idx+1..-1]
+ i = -1
+ brace = 1
+ str.each_byte {|c|
+ i += 1
+ brace += 1 if c == ?{
+ brace -= 1 if c == ?}
+ break if brace == 0
+ }
+ if i == 0
+ list.push ''
+ elsif str[0, i] == ' '
+ list.push ' '
+ else
+ list.push str[0..i-1]
+ end
+ list += tk_split_simplelist(str[i+1..-1])
+ list
+ end
+ private :tk_tcl2ruby, :tk_split_list, :tk_split_simplelist
+
+ def hash_kv(keys)
+ conf = []
+ if keys and keys != None
+ for k, v in keys
+ conf.push("-#{k}")
+ conf.push(v)
+ end
+ end
+ conf
+ end
+ private :hash_kv
+
+ def array2tk_list(ary)
+ ary.collect{|e|
+ if e.kind_of? Array
+ "{#{array2tk_list(e)}}"
+ elsif e.kind_of? Hash
+ "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
+ else
+ s = _get_eval_string(e)
+ (s.index(/\s/))? "{#{s}}": s
+ end
+ }.join(" ")
+ end
+ private :array2tk_list
+
+ def bool(val)
+ case val
+ when "1", 1, 'yes', 'true'
+ TRUE
+ else
+ FALSE
+ end
+ end
+ def number(val)
+ case val
+ when /^-?\d+$/
+ val.to_i
+ when /^-?\d+\.\d*$/
+ val.to_f
+ else
+ val
+ end
+ end
+ def string(val)
+ if val == "{}"
+ ''
+ elsif val[0] == ?{
+ val[1..-2]
+ else
+ val
+ end
+ end
+ def list(val)
+ tk_split_list(val).to_a
+ end
+ def window(val)
+ Tk_WINDOWS[val]
+ end
+ def procedure(val)
+ if val =~ /^rb_out (c\d+)/
+ Tk_CMDTBL[$1]
+ else
+ nil
+ end
+ end
+ private :bool, :number, :string, :list, :window, :procedure
+
+ def _get_eval_string(str)
+ return nil if str == None
+ if str.kind_of?(Hash)
+ str = hash_kv(str).join(" ")
+ elsif str.kind_of?(Array)
+ str = array2tk_list(str)
+ elsif str.kind_of?(Proc)
+ str = install_cmd(str)
+ elsif str == nil
+ str = ""
+ elsif str == false
+ str = "0"
+ elsif str == true
+ str = "1"
+ elsif (str.respond_to?(:to_eval))
+ str = str.to_eval()
+ else
+ str = str.to_s()
+ end
+ return str
+ end
+ private :_get_eval_string
+
+ Tk_IDs = [0, 0] # [0]-cmdid, [1]-winid
+ def _curr_cmd_id
+ id = format("c%.4d", Tk_IDs[0])
+ end
+ def _next_cmd_id
+ id = _curr_cmd_id
+ Tk_IDs[0] += 1
+ id
+ end
+ def install_cmd(cmd)
+ return '' if cmd == ''
+ id = _next_cmd_id
+ Tk_CMDTBL[id] = cmd
+ @cmdtbl = [] unless @cmdtbl
+ @cmdtbl.push id
+ return format("rb_out %s", id);
+ end
+ def uninstall_cmd(id)
+ id = $1 if /rb_out (c\d+)/
+ Tk_CMDTBL[id] = nil
+ end
+ private :install_cmd, :uninstall_cmd
+
+ def install_win(ppath)
+ id = format("w%.4d", Tk_IDs[1])
+ Tk_IDs[1] += 1
+ if !ppath or ppath == "."
+ @path = format(".%s", id);
+ else
+ @path = format("%s.%s", ppath, id)
+ end
+ Tk_WINDOWS[@path] = self
+ end
+
+ def uninstall_win()
+ Tk_WINDOWS[@path] = nil
+ end
+
+ class Event
+ def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy)
+ @serial = seq
+ @num = b
+ @focus = (f == 1)
+ @height = h
+ @keycode = k
+ @state = s
+ @time = t
+ @width = w
+ @x = x
+ @y = y
+ @char = aa
+ @send_event = (ee == 1)
+ @keysym = kk
+ @keysym_num = nn
+ @type = tt
+ @widget = ww
+ @x_root = xx
+ @y_root = yy
+ end
+ attr :serial
+ attr :num
+ attr :focus
+ attr :height
+ attr :keycode
+ attr :state
+ attr :time
+ attr :width
+ attr :x
+ attr :y
+ attr :char
+ attr :send_event
+ attr :keysym
+ attr :keysym_num
+ attr :type
+ attr :widget
+ attr :x_root
+ attr :y_root
+ end
+
+ def install_bind(cmd, args=nil)
+ if args
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, *arg
+ })
+ id + " " + args
+ else
+ id = install_cmd(proc{|arg|
+ TkUtil.eval_cmd cmd, Event.new(*arg)
+ })
+ id + ' %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y'
+ end
+ end
+
+ def tk_event_sequence(context)
+ if context.kind_of? TkVirtualEvent
+ context = context.path
+ end
+ if context.kind_of? Array
+ context = context.collect{|ev|
+ if context.kind_of? TkVirtualEvent
+ ev.path
+ else
+ ev
+ end
+ }.join("><")
+ end
+ if /,/ =~ context
+ context = context.split(/\s*,\s*/).join("><")
+ else
+ context
+ end
+ end
+
+ def _bind_core(mode, path, context, cmd, args=nil)
+ id = install_bind(cmd, args)
+ begin
+ tk_call 'bind', path, "<#{tk_event_sequence(context)}>", mode + id
+ rescue
+ uninstall_cmd(id)
+ fail
+ end
+ end
+
+ def _bind(path, context, cmd, args=nil)
+ _bind_core('', path, context, cmd, args)
+ end
+
+ def _bind_append(path, context, cmd, args=nil)
+ _bind_core('+', path, context, cmd, args)
+ end
+ private :install_bind, :tk_event_sequence, :_bind_core, :_bind, :_bind_append
+
+ def bind_all(context, cmd=Proc.new, args=nil)
+ _bind 'all', context, cmd, args
+ end
+
+ def bind_append_all(context, cmd=Proc.new, args=nil)
+ _bind_append 'all', context, cmd, args
+ end
+
+ def bind(tagOrClass, context, cmd=Proc.new, args=nil)
+ _bind tagOrClass, context, cmd, args
+ end
+
+ def bind_append(tagOrClass, context, cmd=Proc.new, args=nil)
+ _bind_append tagOrClass, context, cmd, args
+ end
+
+ def _bindinfo(tagOrClass, context=nil)
+ if context
+ (tk_call('bind', tagOrClass,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_call 'bind', tagOrClass).collect{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def bindinfo(tagOrClass, context=nil)
+ _bindinfo tagOrClass, context
+ end
+
+ def pack(*args)
+ TkPack.configure *args
+ end
+
+ def grid(*args)
+ TkGrid.configure *args
+ end
+
+ def update(idle=nil)
+ if idle
+ tk_call 'update', 'idletasks'
+ else
+ tk_call 'update'
+ end
+ end
+
+end
+
+module TkCore
+ include TkComm
+ extend TkComm
+
+ INTERP = TclTkIp.new
+
+ INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {return -code $st $ret} {return $ret}")
+
+ def callback_break
+ raise TkCallbackBreak, "Tk callback returns 'break' status"
+ end
+
+ def callback_continue
+ raise TkCallbackContinue, "Tk callback returns 'continue' status"
+ end
+
+ def after(ms, cmd=Proc.new)
+ myid = _curr_cmd_id
+ cmdid = install_cmd(cmd)
+ tk_call("after",ms,cmdid)
+ return
+ if false #defined? Thread
+ Thread.start do
+ ms = Float(ms)/1000
+ ms = 10 if ms == 0
+ sleep ms/1000
+ cmd.call
+ end
+ else
+ cmdid = install_cmd(cmd)
+ tk_call("after",ms,cmdid)
+ end
+ end
+
+ def TkCore.callback(arg)
+ arg = Array(tk_split_list(arg))
+ _get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
+ end
+
+ def appname(name=None)
+ tk_call('tk', 'appname', name)
+ end
+
+ def appsend(interp, async, *args)
+ if async
+ tk_call('send', '-async', '--', interp, *args)
+ else
+ tk_call('send', '--', interp, *args)
+ end
+ end
+
+ def rb_appsend(interp, async, *args)
+ args = args.filter{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
+ args.push(').to_s"')
+ appsend(interp, async, 'ruby "(', *args)
+ end
+
+ def appsend_displayof(interp, win, async, *args)
+ win = '.' if win == nil
+ if async
+ tk_call('send', '-async', '-displayof', win, '--', interp, *args)
+ else
+ tk_call('send', '-displayor', win, '--', interp, *args)
+ end
+ end
+
+ def rb_appsend_displayof(interp, win, async, *args)
+ args = args.filter{|c| _get_eval_string(c).gsub(/[][$"]/, '\\\\\&')}
+ args.push(').to_s"')
+ appsend_displayof(interp, win, async, 'ruby "(', *args)
+ end
+
+ def info(*args)
+ tk_call('info', *args)
+ end
+
+ def mainloop
+ TclTkLib.mainloop
+ end
+
+ def event_generate(window, context, keys=nil)
+ window = window.path if window.kind_of? TkObject
+ if keys
+ tk_call('event', 'generate', window,
+ "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ else
+ tk_call('event', 'generate', window, "<#{tk_event_sequence(context)}>")
+ end
+ end
+
+ def messageBox(keys)
+ tk_call 'tk_messageBox', *hash_kv(keys)
+ end
+
+ def getOpenFile(keys)
+ tk_call 'tk_getOpenFile', *hash_kv(keys)
+ end
+
+ def getSaveFile(keys)
+ tk_call 'tk_getSaveFile', *hash_kv(keys)
+ end
+
+ def chooseColor(keys)
+ tk_call 'tk_chooseColor', *hash_kv(keys)
+ end
+
+ def tk_call(*args)
+ print args.join(" "), "\n" if $DEBUG
+ args.filter {|x|_get_eval_string(x)}
+ args.compact!
+ args.flatten!
+ begin
+ res = INTERP._invoke(*args)
+ rescue NameError
+ err = $!
+ begin
+ args.unshift "unknown"
+ res = INTERP._invoke(*args)
+ rescue
+ raise unless /^invalid command/ =~ $!
+ raise err
+ end
+ end
+ if INTERP._return_value() != 0
+ fail RuntimeError, res, error_at
+ end
+ print "==> ", res, "\n" if $DEBUG
+ return res
+ end
+end
+
+module Tk
+ include TkCore
+ extend Tk
+
+ TCL_VERSION = INTERP._invoke("info", "tclversion")
+ TK_VERSION = INTERP._invoke("set", "tk_version")
+ JAPANIZED_TK = (INTERP._invoke("info", "commands", "kanji") != "")
+
+ def root
+ TkRoot.new
+ end
+
+ def bell
+ tk_call 'bell'
+ end
+
+ def Tk.focus(display=nil)
+ if display == nil
+ r = tk_call('focus')
+ else
+ r = tk_call('focus', '-displayof', display)
+ end
+ tk_tcl2ruby(r)
+ end
+
+ def Tk.focus_lastfor(win)
+ tk_tcl2ruby(tk_call('focus', '-lastfor', win))
+ end
+
+ def toUTF8(str,encoding)
+ INTERP._toUTF8(str,encoding)
+ end
+
+ def fromUTF8(str,encoding)
+ INTERP._fromUTF8(str,encoding)
+ end
+
+ module Scrollable
+ def xscrollcommand(cmd=Proc.new)
+ configure_cmd 'xscrollcommand', cmd
+ end
+ def yscrollcommand(cmd=Proc.new)
+ configure_cmd 'yscrollcommand', cmd
+ end
+ end
+
+ module Wm
+ include TkComm
+ def aspect(*args)
+ w = window(tk_call('wm', 'grid', path, *args))
+ w.split.collect{|s|s.to_i} if args.length == 0
+ end
+ def client(name=None)
+ tk_call 'wm', 'client', path, name
+ end
+ def colormapwindows(*args)
+ list(tk_call('wm', 'colormapwindows', path, *args))
+ end
+ def wm_command(value=None)
+ string(tk_call('wm', 'command', path, value))
+ end
+ def deiconify
+ tk_call 'wm', 'deiconify', path
+ end
+ def focusmodel(*args)
+ tk_call 'wm', 'focusmodel', path, *args
+ end
+ def frame
+ tk_call 'wm', 'frame', path
+ end
+ def geometry(*args)
+ list(tk_call('wm', 'geometry', path, *args))
+ end
+ def grid(*args)
+ w = tk_call('wm', 'grid', path, *args)
+ list(w) if args.size == 0
+ end
+ def group(*args)
+ tk_call 'wm', 'group', path, *args
+ end
+ def iconbitmap(*args)
+ tk_call 'wm', 'iconbitmap', path, *args
+ end
+ def iconify
+ tk_call 'wm', 'iconify', path
+ end
+ def iconmask(*args)
+ tk_call 'wm', 'iconmask', path, *args
+ end
+ def iconname(*args)
+ tk_call 'wm', 'iconname', path, *args
+ end
+ def iconposition(*args)
+ w = tk_call('wm', 'iconposition', path, *args)
+ list(w) if args.size == 0
+ end
+ def iconwindow(*args)
+ w = tk_call('wm', 'iconwindow', path, *args)
+ window(w) if args.size == 0
+ end
+ def maxsize(*args)
+ w = tk_call('wm', 'maxsize', path, *args)
+ list(w) if not args.size == 0
+ end
+ def minsize(*args)
+ w = tk_call('wm', 'minsize', path, *args)
+ list(w) if args.size == 0
+ end
+ def overrideredirect(bool=None)
+ if bool == None
+ bool(tk_call('wm', 'overrideredirect', path))
+ else
+ tk_call 'wm', 'overrideredirect', path, bool
+ end
+ end
+ def positionfrom(*args)
+ tk_call 'wm', 'positionfrom', path, *args
+ end
+ def protocol(name=nil, cmd=nil)
+ if cmd
+ tk_call('wm', 'protocol', path, name, cmd)
+ elsif name
+ result = tk_call('wm', 'protocol', path, name)
+ (result == "")? nil : tk_tcl2ruby(result)
+ else
+ tk_split_simplelist(tk_call('wm', 'protocol', path))
+ end
+ end
+ def resizable(*args)
+ w = tk_call('wm', 'resizable', path, *args)
+ if args.length == 0
+ list(w).collect{|e| bool(e)}
+ end
+ end
+ def sizefrom(*args)
+ list(tk_call('wm', 'sizefrom', path, *args))
+ end
+ def state
+ tk_call 'wm', 'state', path
+ end
+ def title(*args)
+ tk_call 'wm', 'title', path, *args
+ end
+ def transient(*args)
+ tk_call 'wm', 'transient', path, *args
+ end
+ def withdraw
+ tk_call 'wm', 'withdraw', path
+ end
+ end
+end
+
+class TkVariable
+ include Tk
+ extend TkCore
+
+ TkVar_CB_TBL = {}
+ Tk_VARIABLE_ID = ["v00000"]
+
+ INTERP._invoke("proc", "rb_var", "args", "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
+
+ def TkVariable.callback(args)
+ name1,name2,op = tk_split_list(args)
+ if TkVar_CB_TBL[name1]
+ _get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
+ else
+ ''
+ end
+ end
+
+ def initialize(val="")
+ @id = Tk_VARIABLE_ID[0]
+ Tk_VARIABLE_ID[0] = Tk_VARIABLE_ID[0].succ
+ if val == []
+ INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)',
+ @id, @id, @id))
+ elsif val.kind_of?(Array)
+ a = []
+ val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
+ s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ elsif val.kind_of?(Hash)
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; array set %s %s', @id, @id, s))
+ else
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ end
+ end
+
+ def wait
+ INTERP._eval("tkwait variable #{@id}")
+ end
+
+ def id
+ @id
+ end
+
+ def value
+ begin
+ INTERP._eval(format('global %s; set %s', @id, @id))
+ rescue
+ if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
+ raise
+ else
+ Hash[*tk_split_simplelist(INTERP._eval(format('global %s; array get %s',
+ @id, @id)))]
+ end
+ end
+ end
+
+ def value=(val)
+ begin
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ rescue
+ if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
+ raise
+ else
+ if val == []
+ INTERP._eval(format('global %s; unset %s; set %s(0) 0; unset %s(0)',
+ @id, @id, @id, @id))
+ elsif val.kind_of?(Array)
+ a = []
+ val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))}
+ s = '"' + a.join(" ").gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ elsif val.kind_of?(Hash)
+ s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\
+ .gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; unset %s; array set %s %s',
+ @id, @id, @id, s))
+ else
+ raise
+ end
+ end
+ end
+ end
+
+ def [](index)
+ INTERP._eval(format('global %s; set %s(%s)',
+ @id, @id, _get_eval_string(index)))
+ end
+
+ def []=(index,val)
+ INTERP._eval(format('global %s; set %s(%s) %s', @id, @id,
+ _get_eval_string(index), _get_eval_string(val)))
+ end
+
+ def to_i
+ Integer(number(value))
+ end
+
+ def to_f
+ Float(number(value))
+ end
+
+ def to_s
+ String(string(value))
+ end
+
+ def inspect
+ format "<TkVariable: %s>", @id
+ end
+
+ def ==(other)
+ case other
+ when TkVariable
+ self.equal(self)
+ when String
+ self.to_s == other
+ when Integer
+ self.to_i == other
+ when Float
+ self.to_f == other
+ when Array
+ self.to_a == other
+ else
+ false
+ end
+ end
+
+ def to_a
+ list(value)
+ end
+
+ def to_eval
+ @id
+ end
+
+ def unset(elem=nil)
+ if elem
+ INTERP._eval(format('global %s; unset %s(%s)',
+ @id, @id, tk_tcl2ruby(elem)))
+ else
+ INTERP._eval(format('global %s; unset %s', @id, @id))
+ end
+ end
+ alias remove unset
+
+ def trace_callback(elem, op)
+ if @trace_var.kind_of? Array
+ @trace_var.each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ if elem.kind_of? String
+ if @trace_elem[elem].kind_of? Array
+ @trace_elem[elem].each{|m,e| e.call(self,elem,op) if m.index(op)}
+ end
+ end
+ end
+
+ def trace(opts, cmd)
+ @trace_var = [] if @trace_var == nil
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ @trace_var.unshift([opts,cmd])
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ else
+ newopts = @trace_opts.dup
+ opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_element(elem, opts, cmd)
+ @trace_elem = {} if @trace_elem == nil
+ @trace_elem[elem] = [] if @trace_elem[elem] == nil
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ @trace_elem[elem].unshift([opts,cmd])
+ if @trace_opts == nil
+ TkVar_CB_TBL[@id] = self
+ @trace_opts = opts
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ else
+ newopts = @trace_opts.dup
+ opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_vinfo
+ return [] unless @trace_var
+ @trace_var.dup
+ end
+ def trace_vinfo_for_element(elem)
+ return [] unless @trace_elem
+ return [] unless @trace_elem[elem]
+ @trace_elem[elem].dup
+ end
+
+ def trace_vdelete(opts,cmd)
+ return unless @trace_var.kind_of? Array
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ idx = -1
+ newopts = ''
+ @trace_var.each_with_index{|i,e|
+ if idx < 0 && e[0] == opts && e[1] == cmd
+ idx = i
+ next
+ end
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ if idx >= 0
+ @trace_var.delete_at(idx)
+ else
+ return
+ end
+
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ }
+
+ newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ if @trace_opts != ''
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+
+ def trace_vdelete_for_element(elem,opts,cmd)
+ return unless @trace_elem.kind_of? Hash
+ return unless @trace_elem[elem].kind_of? Array
+ opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+ idx = -1
+ @trace_elem[elem].each_with_index{|i,e|
+ if idx < 0 && e[0] == opts && e[1] == cmd
+ idx = i
+ next
+ end
+ }
+ if idx >= 0
+ @trace_elem[elem].delete_at(idx)
+ else
+ return
+ end
+
+ newopts = ''
+ @trace_var.each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
+ }
+ }
+
+ newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
+ if newopts != @trace_opts
+ Tk.tk_call('trace', 'vdelete', @id, @trace_opts, 'rb_var')
+ @trace_opts.replace(newopts)
+ if @trace_opts != ''
+ Tk.tk_call('trace', 'variable', @id, @trace_opts, 'rb_var')
+ end
+ end
+ end
+end
+
+class TkVarAccess<TkVariable
+ def initialize(varname, val=nil)
+ @id = varname
+ if val
+ s = '"' + _get_eval_string(val).gsub(/[][$"]/, '\\\\\&') + '"'
+ INTERP._eval(format('global %s; set %s %s', @id, @id, s))
+ end
+ end
+end
+
+module TkSelection
+ include Tk
+ extend Tk
+ def clear(win=Tk.root)
+ tk_call 'selection', 'clear', win.path
+ end
+ def get(type=None)
+ tk_call 'selection', 'get', type
+ end
+ def TkSelection.handle(win, func, type=None, format=None)
+ id = install_cmd(func)
+ tk_call 'selection', 'handle', win.path, id, type, format
+ end
+ def handle(func, type=None, format=None)
+ TkSelection.handle self, func, type, format
+ end
+ def TkSelection.own(win, func=None)
+ id = install_cmd(func)
+ tk_call 'selection', 'own', win.path, id
+ end
+ def own(func=None)
+ TkSelection.own self, func
+ end
+
+ module_function :clear, :get
+end
+
+module TkKinput
+ include Tk
+ extend Tk
+
+ def TkKinput.start(window, style=None)
+ tk_call 'kinput_start', window.path, style
+ end
+ def kinput_start(style=None)
+ TkKinput.start(self, style)
+ end
+
+ def TkKinput.send_spot(window)
+ tk_call 'kinput_send_spot', window.path
+ end
+ def kinput_send_spot
+ TkKinput.send_spot(self)
+ end
+
+ def TkKinput.input_start(window, keys=nil)
+ tk_call 'kanjiInput', 'start', window.path, *hash_kv(keys)
+ end
+ def kanji_input_start(keys=nil)
+ TkKinput.input_start(self, keys)
+ end
+
+ def TkKinput.attribute_config(window, slot, value=None)
+ if slot.kind_of? Hash
+ tk_call 'kanjiInput', 'attribute', window.path, *hash_kv(slot)
+ else
+ tk_call 'kanjiInput', 'attribute', window.path, "-#{slot}", value
+ end
+ end
+ def kinput_attribute_config(slot, value=None)
+ TkKinput.attribute_config(self, slot, value)
+ end
+
+ def TkKinput.attribute_info(window, slot=nil)
+ if slot
+ conf = tk_split_list(tk_call('kanjiInput', 'attribute',
+ window.path, "-#{slot}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call('kanjiInput', 'attribute',
+ window.path)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+ def kinput_attribute_info(slot=nil)
+ TkKinput.attribute_info(self, slot)
+ end
+
+ def TkKinput.input_end(window)
+ tk_call 'kanjiInput', 'end', window.path
+ end
+ def kanji_input_end
+ TkKinput.input_end(self)
+ end
+end
+
+module TkWinfo
+ include Tk
+ extend Tk
+ def TkWinfo.atom(name)
+ tk_call 'winfo', name
+ end
+ def winfo_atom(name)
+ TkWinfo.atom name
+ end
+ def TkWinfo.atomname(id)
+ tk_call 'winfo', id
+ end
+ def winfo_atomname(id)
+ TkWinfo.atomname id
+ end
+ def TkWinfo.cells(window)
+ number(tk_call('winfo', window.path))
+ end
+ def winfo_cells
+ TkWinfo.cells self
+ end
+ def TkWinfo.children(window)
+ c = tk_call('winfo', 'children', window.path)
+ list(c)
+ end
+ def winfo_children
+ TkWinfo.children self
+ end
+ def TkWinfo.classname(window)
+ tk_call 'winfo', 'class', window.path
+ end
+ def winfo_classname
+ TkWinfo.classname self
+ end
+ def TkWinfo.containing(rootX, rootY)
+ path = tk_call('winfo', 'containing', rootX, rootY)
+ window(path)
+ end
+ def winfo_containing(x, y)
+ TkWinfo.containing x, y
+ end
+ def TkWinfo.depth(window)
+ number(tk_call('winfo', 'depth', window.path))
+ end
+ def winfo_depth
+ TkWinfo.depth self
+ end
+ def TkWinfo.exist?(window)
+ bool(tk_call('winfo', 'exists', window.path))
+ end
+ def winfo_exist?
+ TkWinfo.exist? self
+ end
+ def TkWinfo.fpixels(window, number)
+ number(tk_call('winfo', 'fpixels', window.path, number))
+ end
+ def winfo_fpixels(number)
+ TkWinfo.fpixels self, number
+ end
+ def TkWinfo.geometry(window)
+ list(tk_call('winfo', 'geometry', window.path))
+ end
+ def winfo_geometry
+ TkWinfo.geometry self
+ end
+ def TkWinfo.height(window)
+ number(tk_call('winfo', 'height', window.path))
+ end
+ def winfo_height
+ TkWinfo.height self
+ end
+ def TkWinfo.id(window)
+ number(tk_call('winfo', 'id', window.path))
+ end
+ def winfo_id
+ TkWinfo.id self
+ end
+ def TkWinfo.interps(window=nil)
+ if window
+ tk_split_simplelist(tk_call('winfo', '-displayof', window.path,
+ 'interps'))
+ else
+ tk_split_simplelist(tk_call('winfo', 'interps'))
+ end
+ end
+ def winfo_interps
+ TkWinfo.interps self
+ end
+ def TkWinfo.mapped?(window)
+ bool(tk_call('winfo', 'ismapped', window.path))
+ end
+ def winfo_mapped?
+ TkWinfo.mapped? self
+ end
+ def TkWinfo.appname(window)
+ bool(tk_call('winfo', 'name', window.path))
+ end
+ def winfo_appname
+ TkWinfo.appname self
+ end
+ def TkWinfo.parent(window)
+ window(tk_call('winfo', 'parent', window.path))
+ end
+ def winfo_parent
+ TkWinfo.parent self
+ end
+ def TkWinfo.widget(id)
+ window(tk_call('winfo', 'pathname', id))
+ end
+ def winfo_widget(id)
+ TkWinfo.widget id
+ end
+ def TkWinfo.pixels(window, number)
+ number(tk_call('winfo', 'pixels', window.path, number))
+ end
+ def winfo_pixels(number)
+ TkWinfo.pixels self, number
+ end
+ def TkWinfo.reqheight(window)
+ number(tk_call('winfo', 'reqheight', window.path))
+ end
+ def winfo_reqheight
+ TkWinfo.reqheight self
+ end
+ def TkWinfo.reqwidth(window)
+ number(tk_call('winfo', 'reqwidth', window.path))
+ end
+ def winfo_reqwidth
+ TkWinfo.reqwidth self
+ end
+ def TkWinfo.rgb(window, color)
+ list(tk_call('winfo', 'rgb', window.path, color))
+ end
+ def winfo_rgb(color)
+ TkWinfo.rgb self, color
+ end
+ def TkWinfo.rootx(window)
+ number(tk_call('winfo', 'rootx', window.path))
+ end
+ def winfo_rootx
+ TkWinfo.rootx self
+ end
+ def TkWinfo.rooty(window)
+ number(tk_call('winfo', 'rooty', window.path))
+ end
+ def winfo_rooty
+ TkWinfo.rooty self
+ end
+ def TkWinfo.screen(window)
+ tk_call 'winfo', 'screen', window.path
+ end
+ def winfo_screen
+ TkWinfo.screen self
+ end
+ def TkWinfo.screencells(window)
+ number(tk_call('winfo', 'screencells', window.path))
+ end
+ def winfo_screencells
+ TkWinfo.screencells self
+ end
+ def TkWinfo.screendepth(window)
+ number(tk_call('winfo', 'screendepth', window.path))
+ end
+ def winfo_screendepth
+ TkWinfo.screendepth self
+ end
+ def TkWinfo.screenheight (window)
+ number(tk_call('winfo', 'screenheight', window.path))
+ end
+ def winfo_screenheight
+ TkWinfo.screenheight self
+ end
+ def TkWinfo.screenmmheight(window)
+ number(tk_call('winfo', 'screenmmheight', window.path))
+ end
+ def winfo_screenmmheight
+ TkWinfo.screenmmheight self
+ end
+ def TkWinfo.screenmmwidth(window)
+ number(tk_call('winfo', 'screenmmwidth', window.path))
+ end
+ def winfo_screenmmwidth
+ TkWinfo.screenmmwidth self
+ end
+ def TkWinfo.screenvisual(window)
+ tk_call 'winfo', 'screenvisual', window.path
+ end
+ def winfo_screenvisual
+ TkWinfo.screenvisual self
+ end
+ def TkWinfo.screenwidth(window)
+ number(tk_call('winfo', 'screenwidth', window.path))
+ end
+ def winfo_screenwidth
+ TkWinfo.screenwidth self
+ end
+ def TkWinfo.toplevel(window)
+ window(tk_call('winfo', 'toplevel', window.path))
+ end
+ def winfo_toplevel
+ TkWinfo.toplevel self
+ end
+ def TkWinfo.visual(window)
+ tk_call 'winfo', 'visual', window.path
+ end
+ def winfo_visual
+ TkWinfo.visual self
+ end
+ def TkWinfo.vrootheigh(window)
+ number(tk_call('winfo', 'vrootheight', window.path))
+ end
+ def winfo_vrootheight
+ TkWinfo.vrootheight self
+ end
+ def TkWinfo.vrootwidth(window)
+ number(tk_call('winfo', 'vrootwidth', window.path))
+ end
+ def winfo_vrootwidth
+ TkWinfo.vrootwidth self
+ end
+ def TkWinfo.vrootx(window)
+ number(tk_call('winfo', 'vrootx', window.path))
+ end
+ def winfo_vrootx
+ TkWinfo.vrootx self
+ end
+ def TkWinfo.vrooty(window)
+ number(tk_call('winfo', 'vrooty', window.path))
+ end
+ def winfo_vrooty
+ TkWinfo.vrooty self
+ end
+ def TkWinfo.width(window)
+ number(tk_call('winfo', 'width', window.path))
+ end
+ def winfo_width
+ TkWinfo.width self
+ end
+ def TkWinfo.x(window)
+ number(tk_call('winfo', 'x', window.path))
+ end
+ def winfo_x
+ TkWinfo.x self
+ end
+ def TkWinfo.y(window)
+ number(tk_call('winfo', 'y', window.path))
+ end
+ def winfo_y
+ TkWinfo.y self
+ end
+ def TkWinfo.viewable(window)
+ bool(tk_call 'winfo', 'viewable', window.path)
+ end
+ def winfo_viewable
+ TkWinfo.viewable self
+ end
+ def TkWinfo.pointerx(window)
+ number(tk_call('winfo', 'pointerx', window.path))
+ end
+ def winfo_pointerx
+ TkWinfo.pointerx self
+ end
+ def TkWinfo.pointery(window)
+ number(tk_call('winfo', 'pointery', window.path))
+ end
+ def winfo_pointery
+ TkWinfo.pointery self
+ end
+ def TkWinfo.pointerxy(window)
+ list(tk_call('winfo', 'pointerxy', window.path))
+ end
+ def winfo_pointerxy
+ TkWinfo.pointerxy self
+ end
+end
+
+module TkPack
+ include Tk
+ extend Tk
+ def configure(win, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ end
+ wins = [win.epath]
+ for i in args
+ wins.push i.epath
+ end
+ tk_call "pack", 'configure', *(wins+hash_kv(keys))
+ end
+
+ def forget(*args)
+ tk_call 'pack', 'forget' *args
+ end
+
+ def propagate(master, bool=None)
+ bool(tk_call('pack', 'propagate', master.epath, bool))
+ end
+ module_function :configure, :forget, :propagate
+end
+
+module TkGrid
+ include Tk
+ extend Tk
+
+ def bbox(*args)
+ list(tk_call('grid', 'bbox', *args))
+ end
+
+ def configure(widget, *args)
+ if args[-1].kind_of?(Hash)
+ keys = args.pop
+ end
+ wins = [widget.epath]
+ for i in args
+ wins.push i.epath
+ end
+ tk_call "grid", 'configure', *(wins+hash_kv(keys))
+ end
+
+ def columnconfigure(master, index, args)
+ tk_call "grid", 'columnconfigure', master, index, *hash_kv(args)
+ end
+
+ def rowconfigure(master, index, args)
+ tk_call "grid", 'rowconfigure', master, index, *hash_kv(args)
+ end
+
+ def add(widget, *args)
+ configure(widget, *args)
+ end
+
+ def forget(*args)
+ tk_call 'grid', 'forget', *args
+ end
+
+ def info(slave)
+ list(tk_call('grid', 'info', slave))
+ end
+
+ def location(master, x, y)
+ list(tk_call('grid', 'location', master, x, y))
+ end
+
+ def propagate(master, bool=None)
+ bool(tk_call('grid', 'propagate', master.epath, bool))
+ end
+
+ def remove(*args)
+ tk_call 'grid', 'remove', *args
+ end
+
+ def size(master)
+ tk_call 'grid', 'size', master
+ end
+
+ def slaves(args)
+ list(tk_call('grid', 'slaves', *hash_kv(args)))
+ end
+
+ module_function :bbox, :forget, :propagate, :info
+ module_function :remove, :size, :slaves, :location
+ module_function :configure, :columnconfigure, :rowconfigure
+end
+
+module TkOption
+ include Tk
+ extend Tk
+ def add pat, value, pri=None
+ tk_call 'option', 'add', pat, value, pri
+ end
+ def clear
+ tk_call 'option', 'clear'
+ end
+ def get win, name, klass
+ tk_call 'option', 'get', win ,name, klass
+ end
+ def readfile file, pri=None
+ tk_call 'option', 'readfile', file, pri
+ end
+ module_function :add, :clear, :get, :readfile
+end
+
+module TkTreatFont
+ def font_configinfo
+ ret = TkFont.used_on(self.path)
+ if ret == nil
+ ret = TkFont.init_widget_font(self.path, self.path, 'configure')
+ end
+ ret
+ end
+ alias fontobj font_configinfo
+
+ def font_configure(slot)
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(self.path, self.path,'configure',slot)
+ else
+ latinfont_configure(fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latinfont_configure(ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latinfont_configure(ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjifont_configure(knj) if knj
+ end
+
+ tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latinfont_configure(ltn, keys=nil)
+ fobj = fontobj
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val}
+ if keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciifont_configure latinfont_configure
+
+ def kanjifont_configure(knj, keys=nil)
+ fobj = fontobj
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val}
+ if keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(cond)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def font_copy(window, tag=nil)
+ if tag
+ window.tagfontobj(tag).configinfo.each{|key,value|
+ fontobj.configure(key,value)
+ }
+ fontobj.replace(window.tagfontobj(tag).latin_font,
+ window.tagfontobj(tag).kanji_font)
+ else
+ window.fontobj.configinfo.each{|key,value|
+ fontobj.configure(key,value)
+ }
+ fontobj.replace(window.fontobj.latin_font, window.fontobj.kanji_font)
+ end
+ end
+
+ def latinfont_copy(window, tag=nil)
+ if tag
+ fontobj.latin_replace(window.tagfontobj(tag).latin_font)
+ else
+ fontobj.latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciifont_copy latinfont_copy
+
+ def kanjifont_copy(window, tag=nil)
+ if tag
+ fontobj.kanji_replace(window.tagfontobj(tag).kanji_font)
+ else
+ fontobj.kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkObject<TkKernel
+ include Tk
+ include TkTreatFont
+
+ def path
+ return @path
+ end
+
+ def epath
+ return @path
+ end
+
+ def to_eval
+ @path
+ end
+
+ def tk_send(cmd, *rest)
+ tk_call path, cmd, *rest
+ end
+ private :tk_send
+
+ def method_missing(id, *args)
+ name = id.id2name
+ case args.length
+ when 1
+ configure name, args[0]
+ when 0
+ begin
+ cget name
+ rescue
+ fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
+ end
+ else
+ fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
+ end
+ end
+
+ def [](id)
+ cget id
+ end
+
+ def []=(id, val)
+ configure id, val
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call path, 'cget', "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ if (slot['font'] || slot['kanjifont'] ||
+ slot['latinfont'] || slot['asciifont'] )
+ font_configure(slot.dup)
+ else
+ tk_call path, 'configure', *hash_kv(slot)
+ end
+
+ else
+ if (slot == 'font' || slot == 'kanjifont' ||
+ slot == 'latinfont' || slot == 'asciifont')
+ if value == None
+ fontobj
+ else
+ font_configure({slot=>value})
+ end
+ else
+ tk_call path, 'configure', "-#{slot}", value
+ end
+ end
+ end
+
+ def configure_cmd(slot, value)
+ configure slot, install_cmd(value)
+ end
+
+ def configinfo(slot = nil)
+ if slot == 'font' || slot == 'kanjifont'
+ fontobj
+ else
+ if slot
+ conf = tk_split_list(tk_send('configure', "-#{slot}") )
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ ret = tk_split_list(tk_send('configure') ).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ if ret.assoc('font')
+ ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
+ ret.push(['font', fontobj])
+ else
+ ret
+ end
+ end
+ end
+ end
+
+ def bind(context, cmd=Proc.new, args=nil)
+ _bind path, context, cmd, args
+ end
+
+ def bind_append(context, cmd=Proc.new, args=nil)
+ _bind_append path, context, cmd, args
+ end
+
+ def bindinfo(context=nil)
+ _bindinfo path, context
+ end
+
+ def event_generate(context, keys=nil)
+ if keys
+ tk_call('event', 'generate', path,
+ "<#{tk_event_sequence(context)}>", *hash_kv(keys))
+ else
+ tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
+ end
+ end
+
+ def tk_trace_variable(v)
+ unless v.kind_of?(TkVariable)
+ fail ArgumentError, format("requires TkVariable given %s", v.type)
+ end
+ v
+ end
+ private :tk_trace_variable
+
+ def destroy
+ tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
+ end
+end
+
+module TkClassBind
+ WidgetClassNameTBL = {}
+
+ def TkClassBind.name2class(name)
+ WidgetClassNameTBL[name]
+ end
+
+ def bind(context, cmd=Proc.new, args=nil)
+ Tk.bind to_eval, context, cmd, args
+ end
+
+ def bind_append(context, cmd=Proc.new, args=nil)
+ Tk.bind_append to_eval, context, cmd, args
+ end
+
+ def bindinfo(context=nil)
+ Tk.bindinfo to_eval, context
+ end
+end
+
+class TkWindow<TkObject
+ extend TkClassBind
+
+ def initialize(parent=nil, keys=nil)
+ install_win(if parent then parent.path end)
+ create_self
+ if keys
+ # tk_call @path, 'configure', *hash_kv(keys)
+ configure(keys)
+ end
+ end
+
+ def create_self
+ end
+ private :create_self
+
+ def pack(keys = nil)
+ tk_call 'pack', epath, *hash_kv(keys)
+ self
+ end
+
+ def unpack(keys = nil)
+ tk_call 'pack', 'forget', epath
+ self
+ end
+
+ def grid(keys = nil)
+ tk_call 'grid', epath, *hash_kv(keys)
+ self
+ end
+
+ def ungrid(keys = nil)
+ tk_call 'grid', 'forget', epath
+ self
+ end
+
+ def place(keys = nil)
+ tk_call 'place', epath, *hash_kv(keys)
+ self
+ end
+
+ def unplace(keys = nil)
+ tk_call 'place', 'forget', epath, *hash_kv(keys)
+ self
+ end
+ alias place_forget unplace
+
+ def place_config(keys)
+ tk_call "place", 'configure', epath, *hash_kv(keys)
+ end
+
+ def place_info()
+ ilist = list(tk_call('place', 'info', epath))
+ info = {}
+ while key = ilist.shift
+ info[key[1..-1]] = ilist.shift
+ end
+ return info
+ end
+
+ def pack_slaves()
+ list(tk_call('pack', 'slaves', epath))
+ end
+
+ def pack_info()
+ ilist = list(tk_call('pack', 'info', epath))
+ info = {}
+ while key = ilist.shift
+ info[key[1..-1]] = ilist.shift
+ end
+ return info
+ end
+
+ def place_slaves()
+ list(tk_call('place', 'slaves', epath))
+ end
+
+ def focus(force=false)
+ if force
+ tk_call 'focus', '-force', path
+ else
+ tk_call 'focus', path
+ end
+ self
+ end
+
+ def grab(*args)
+ if !args or args.length == 0
+ tk_call 'grab', 'set', path
+ elsif args.length == 1
+ case args[0]
+ when 'global'
+ tk_call 'grab', 'set', '-global', path
+ else
+ val = tk_call('grab', args[0], path)
+ end
+ case args[0]
+ when 'current'
+ return window(val)
+ when 'status'
+ return val
+ end
+ else
+ fail ArgumentError, 'wrong # of args'
+ end
+ end
+
+ def lower(below=None)
+ tk_call 'lower', path, below
+ self
+ end
+ def raise(above=None)
+ tk_call 'raise', path, above
+ self
+ end
+
+ def command(cmd=Proc.new)
+ configure_cmd 'command', cmd
+ end
+
+ def colormodel model=None
+ tk_call 'tk', 'colormodel', path, model
+ self
+ end
+
+ def destroy
+ tk_call 'destroy', path
+ if @cmdtbl
+ for id in @cmdtbl
+ uninstall_cmd id
+ end
+ end
+ uninstall_win
+ end
+
+ def wait_visibility
+ tk_call 'tkwait', 'visibility', path
+ end
+ alias wait wait_visibility
+
+ def wait_destroy
+ tk_call 'tkwait', 'window', path
+ end
+
+ def bindtags(taglist=nil)
+ if taglist
+ fail unless taglist.kind_of? Array
+ tk_call('bindtags', path, taglist)
+ else
+ tk_split_list(tk_call('bindtags', path)).collect{|tag|
+ if tag == nil
+ '.'
+ elsif tag.kind_of?(String) && (cls = TkClassBind.name2class(tag))
+ cls
+ else
+ tag
+ end
+ }
+ end
+ end
+end
+
+class TkRoot<TkWindow
+ include Wm
+ ROOT = []
+ def TkRoot.new
+ return ROOT[0] if ROOT[0]
+ new = super
+ ROOT[0] = new
+ Tk_WINDOWS["."] = new
+ end
+
+ WidgetClassName = 'Tk'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ @path = '.'
+ end
+ def path
+ "."
+ end
+end
+
+class TkToplevel<TkWindow
+ include Wm
+
+ WidgetClassName = 'Toplevel'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def initialize(parent=nil, screen=nil, classname=nil, keys=nil)
+ if screen.kind_of? Hash
+ keys = screen.dup
+ else
+ @screen = screen
+ end
+ @classname = classname
+ if keys.kind_of? Hash
+ keys = keys.dup
+ if keys['classname']
+ @classname = keys['classname']
+ keys['classname'] = nil
+ end
+ if keys['colormap']
+ @colormap = keys['colormap']
+ keys['colormap'] = nil
+ end
+ if keys['container']
+ @classname = keys['container']
+ keys['classname'] = nil
+ end
+ if keys['screen']
+ @screen = keys['screen']
+ keys['screen'] = nil
+ end
+ if keys['use']
+ @use = keys['use']
+ keys['use'] = nil
+ end
+ if keys['visual']
+ @screen = keys['visual']
+ keys['visual'] = nil
+ end
+ end
+ super(parent, keys)
+ end
+
+ def create_self
+ s = []
+ s.push << "-class" << @classname if @classname
+ s.push << "-colormap" << @colormap if @colormap
+ s.push << "-container" << @container if @container
+ s.push << "-screen" << @screen if @screen
+ s.push << "-use" << @use if @use
+ s.push << "-visual" << @visual if @visual
+ tk_call 'toplevel', @path, *s
+ end
+
+ def specific_class
+ @classname
+ end
+end
+
+class TkFrame<TkWindow
+ WidgetClassName = 'Frame'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def initialize(parent=nil, keys=nil)
+ if keys.kind_of? Hash
+ keys = keys.dup
+ if keys['classname']
+ @classname = keys['classname']
+ keys['classname'] = nil
+ end
+ if keys['colormap']
+ @colormap = keys['colormap']
+ keys['colormap'] = nil
+ end
+ if keys['container']
+ @classname = keys['container']
+ keys['classname'] = nil
+ end
+ if keys['visual']
+ @screen = keys['visual']
+ keys['visual'] = nil
+ end
+ end
+ super(parent, keys)
+ end
+
+ def create_self
+ s = []
+ s.push << "-class" << @classname if @classname
+ s.push << "-colormap" << @colormap if @colormap
+ s.push << "-container" << @container if @container
+ s.push << "-visual" << @visual if @visual
+ tk_call 'frame', @path, *s
+ end
+end
+
+class TkLabel<TkWindow
+ WidgetClassName = 'Label'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'label', @path
+ end
+ def textvariable(v)
+ configure 'textvariable', tk_trace_variable(v)
+ end
+end
+
+class TkButton<TkLabel
+ TkClassBind::WidgetClassNameTBL['Button'] = self
+ def TkButton.to_eval
+ 'Button'
+ end
+ def create_self
+ tk_call 'button', @path
+ end
+ def invoke
+ tk_send 'invoke'
+ end
+ def flash
+ tk_send 'flash'
+ end
+end
+
+class TkRadioButton<TkButton
+ TkClassBind::WidgetClassNameTBL['Radiobutton'] = self
+ def TkRadioButton.to_eval
+ 'Radiobutton'
+ end
+ def create_self
+ tk_call 'radiobutton', @path
+ end
+ def deselect
+ tk_send 'deselect'
+ end
+ def select
+ tk_send 'select'
+ end
+ def variable(v)
+ configure 'variable', tk_trace_variable(v)
+ end
+end
+
+class TkCheckButton<TkRadioButton
+ TkClassBind::WidgetClassNameTBL['Checkbutton'] = self
+ def TkCheckButton.to_eval
+ 'Checkbutton'
+ end
+ def create_self
+ tk_call 'checkbutton', @path
+ end
+ def toggle
+ tk_send 'toggle'
+ end
+end
+
+class TkMessage<TkLabel
+ TkClassBind::WidgetClassNameTBL['Message'] = self
+ def TkMessage.to_eval
+ 'Message'
+ end
+ def create_self
+ tk_call 'message', @path
+ end
+end
+
+class TkScale<TkWindow
+ WidgetClassName = 'Scale'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'scale', path
+ end
+
+ def get
+ number(tk_send('get'))
+ end
+
+ def set(val)
+ tk_send "set", val
+ end
+
+ def value
+ get
+ end
+
+ def value= (val)
+ set val
+ end
+end
+
+class TkScrollbar<TkWindow
+ WidgetClassName = 'Scrollbar'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'scrollbar', path
+ end
+
+ def delta(deltax=None, deltay=None)
+ number(tk_send('delta', deltax, deltay))
+ end
+
+ def fraction(x=None, y=None)
+ number(tk_send('fraction', x, y))
+ end
+
+ def identify(x=None, y=None)
+ tk_send('fraction', x, y)
+ end
+
+ def get
+ ary1 = tk_send('get').split
+ ary2 = []
+ for i in ary1
+ ary2.push number(i)
+ end
+ ary2
+ end
+
+ def set(first, last)
+ tk_send "set", first, last
+ end
+end
+
+class TkTextWin<TkWindow
+ def create_self
+ raise TypeError, "TkTextWin is abstract class"
+ end
+
+ def bbox(index)
+ tk_send 'bbox', index
+ end
+ def delete(first, last=None)
+ tk_send 'delete', first, last
+ end
+ def get(*index)
+ tk_send 'get', *index
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def insert(index, chars, *args)
+ tk_send 'insert', index, chars, *args
+ end
+ def scan_mark(x, y)
+ tk_send 'scan', 'mark', x, y
+ end
+ def scan_dragto(x, y)
+ tk_send 'scan', 'dragto', x, y
+ end
+ def see(index)
+ tk_send 'see', index
+ end
+end
+
+class TkListbox<TkTextWin
+ TkClassBind::WidgetClassNameTBL['Listbox'] = self
+ def TkListbox.to_eval
+ 'Listbox'
+ end
+ def create_self
+ tk_call 'listbox', path
+ end
+
+ def activate(y)
+ tk_send 'activate', y
+ end
+ def curselection
+ list(tk_send('curselection'))
+ end
+ def nearest(y)
+ tk_send('nearest', y).to_i
+ end
+ def size(y)
+ tk_send('size').to_i
+ end
+ def selection_anchor(index)
+ tk_send 'selection', 'anchor', index
+ end
+ def selection_clear(first, last=None)
+ tk_send 'selection', 'clear', first, last
+ end
+ def selection_includes
+ bool(tk_send('selection', 'includes'))
+ end
+ def selection_set(first, last=None)
+ tk_send 'selection', 'set', first, last
+ end
+ def xview(cmd, *more)
+ v = tk_send('xview', cmd, *more)
+ v.to_i if more.size == 0
+ end
+ def yview(cmd, *more)
+ v = tk_send('yview', cmd, *more)
+ v.to_i if more.size == 0
+ end
+end
+
+module TkTreatMenuEntryFont
+ def tagfont_configinfo(index)
+ pathname = self.path + ';' + index
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'entryconfigure', index)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(index, slot)
+ pathname = self.path + ';' + index
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'entryconfigure',index,slot)
+ else
+ latintagfont_configure(index, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(index, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(index, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(index, knj) if knj
+ end
+
+ tk_call(self.path, 'entryconfigure', index, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(index, ltn, keys=nil)
+ fobj = tagfontobj(index)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(index, knj, keys=nil)
+ fobj = tagfontobj(index)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(index, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(index).configure(key,value)
+ }
+ tagfontobj(index).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(wintag).configinfo.each{|key,value|
+ tagfontobj(index).configure(key,value)
+ }
+ tagfontobj(index).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(index, window, wintag=nil)
+ if wintag
+ tagfontobj(index).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(index).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(index, window, wintag=nil)
+ if wintag
+ tagfontobj(index).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(index).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkMenu<TkWindow
+ include TkTreatMenuEntryFont
+
+ WidgetClassName = 'Menu'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ def create_self
+ tk_call 'menu', path
+ end
+ def activate(index)
+ tk_send 'activate', index
+ end
+ def add(type, keys=nil)
+ tk_send 'add', type, *hash_kv(keys)
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def invoke(index)
+ tk_send 'invoke', index
+ end
+ def insert(index, type, keys=nil)
+ tk_send 'add', index, type, *hash_kv(keys)
+ end
+ def delete(index, last=None)
+ tk_send 'delete', index, last
+ end
+ def post(x, y)
+ tk_send 'post', x, y
+ end
+ def postcascade(index)
+ tk_send 'postcascade', index
+ end
+ def postcommand(cmd=Proc.new)
+ configure_cmd 'postcommand', cmd
+ end
+ def menutype(index)
+ tk_send 'type', index
+ end
+ def unpost
+ tk_send 'unpost'
+ end
+ def yposition(index)
+ number(tk_send('yposition', index))
+ end
+ def entrycget(index, key)
+ tk_tcl2ruby tk_send 'entrycget', index, "-#{key}"
+ end
+ def entryconfigure(index, key, val=None)
+ if key.kind_of? Hash
+ if (key['font'] || key['kanjifont'] ||
+ key['latinfont'] || key['asciifont'])
+ tagfont_configure(index, key.dup)
+ else
+ tk_send 'entryconfigure', index, *hash_kv(key)
+ end
+
+ else
+ if (key == 'font' || key == 'kanjifont' ||
+ key == 'latinfont' || key == 'asciifont' )
+ tagfont_configure({key=>val})
+ else
+ tk_call 'entryconfigure', index, "-#{key}", val
+ end
+ end
+ end
+
+ def entryconfiginfo(index, key=nil)
+ if key
+ conf = tk_split_list(tk_send('entryconfigure',index,"-#{key}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send('entryconfigure', index)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+end
+
+class TkMenubutton<TkLabel
+ TkClassBind::WidgetClassNameTBL['Menubutton'] = self
+ def TkMenubutton.to_eval
+ 'Menubutton'
+ end
+ def create_self
+ tk_call 'menubutton', path
+ end
+end
+
+module TkComposite
+ include Tk
+ extend Tk
+
+ def initialize(parent=nil, *args)
+ @frame = TkFrame.new(parent)
+ @path = @epath = @frame.path
+ initialize_composite(*args)
+ end
+
+ def epath
+ @epath
+ end
+
+ def initialize_composite(*args) end
+ private :initialize_composite
+
+ def delegate(option, *wins)
+ unless @delegates
+ @delegates = {}
+ @delegates['DEFAULT'] = @frame
+ end
+ if @delegates[option].kind_of?(Array)
+ for i in wins
+ @delegates[option].push(i)
+ end
+ else
+ @delegates[option] = wins
+ end
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ slot.each{|slot,value| configure slot, value}
+ else
+ if @delegates and @delegates[slot]
+ for i in @delegates[slot]
+ if not i
+ i = @delegates['DEFALUT']
+ redo
+ else
+ last = i.configure(slot, value)
+ end
+ end
+ last
+ else
+ super
+ end
+ end
+ end
+end
+
+module TkClipboard
+ include Tk
+ extend Tk
+
+ def clear
+ tk_call 'clipboard', 'clear'
+ end
+ def get
+ begin
+ tk_call 'selection', 'get', '-selection', 'CLIPBOARD'
+ rescue
+ ''
+ end
+ end
+ def set(data)
+ clear
+ append(data)
+ end
+ def append(data)
+ tk_call 'clipboard', 'append', data
+ end
+
+ module_function :clear, :set, :get, :append
+end
+
+autoload :TkCanvas, 'tkcanvas'
+autoload :TkImage, 'tkcanvas'
+autoload :TkBitmapImage, 'tkcanvas'
+autoload :TkPhotoImage, 'tkcanvas'
+autoload :TkEntry, 'tkentry'
+autoload :TkText, 'tktext'
+autoload :TkDialog, 'tkdialog'
+autoload :TkMenubar, 'tkmenubar'
+autoload :TkAfter, 'tkafter'
+autoload :TkPalette, 'tkpalette'
+autoload :TkFont, 'tkfont'
+autoload :TkVirtualEvent, 'tkvirtevent'
diff --git a/ext/tk/lib/tkafter.rb b/ext/tk/lib/tkafter.rb
new file mode 100644
index 0000000000..be2e50ff3a
--- /dev/null
+++ b/ext/tk/lib/tkafter.rb
@@ -0,0 +1,296 @@
+#
+# tkafter.rb : methods for Tcl/Tk after command
+# 1998/07/02 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkAfter
+ include TkCore
+ extend TkCore
+
+ Tk_CBID = [0]
+ Tk_CBTBL = {}
+
+ INTERP._invoke("proc", "rb_after", "args", "ruby [format \"TkAfter.callback %%Q!%s!\" $args]")
+
+ ###############################
+ # class methods
+ ###############################
+ def TkAfter.callback(arg)
+ @after_id = nil
+ arg = Array(tk_split_list(arg))
+ obj_id = arg.shift
+ ex_obj = Tk_CBTBL[obj_id]
+ return nil if ex_obj == nil; # canceled
+ _get_eval_string(ex_obj.do_callback(*arg))
+ end
+
+ def TkAfter.info
+ tk_call('after', 'info').split(' ').filter{|id|
+ ret = Tk_CBTBL.find{|key,val| val.after_id == id}
+ (ret == nil)? id: ret[1]
+ }
+ end
+
+ ###############################
+ # instance methods
+ ###############################
+ def do_callback(*args)
+ @in_callback = true
+ ret = @current_proc.call(*args)
+ if @set_next
+ set_next_callback(*args)
+ else
+ @set_next = true
+ end
+ @in_callback = false
+ ret
+ end
+
+ def set_callback(sleep, args=nil)
+ @after_script = "rb_after #{@id} #{_get_eval_string(args)}"
+ @after_id = tk_call('after', sleep, @after_script)
+ @current_script = [sleep, @after_script]
+ end
+
+ def set_next_callback(*args)
+ if @running == false || @proc_max == 0 || @do_loop == 0
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ if @current_pos >= @proc_max
+ if @do_loop < 0 || (@do_loop -= 1) > 0
+ @current_pos = 0
+ else
+ Tk_CBTBL[@id] = nil ;# for GC
+ @running = false
+ return
+ end
+ end
+
+ @current_args = args
+
+ if @sleep_time.kind_of? Proc
+ sleep = @sleep_time.call(*args)
+ else
+ sleep = @sleep_time
+ end
+ @current_sleep = sleep
+
+ cmd, *cmd_args = @loop_proc[@current_pos]
+ @current_pos += 1
+ @current_proc = cmd
+
+ if cmd_args[0].kind_of? Proc
+ #c = cmd_args.shift
+ #cb_args = c.call(*(cmd_args + args))
+ cb_args = cmd_args[0].call(*args)
+ else
+ cb_args = cmd_args
+ end
+
+ set_callback(sleep, cb_args)
+ end
+
+ def initialize(*args)
+ @id = format("a%.4d", Tk_CBID[0])
+ Tk_CBID[0] += 1
+
+ @set_next = true
+
+ @init_sleep = 0
+ @init_proc = nil
+ @init_args = []
+
+ @current_script = []
+ @current_proc = nil
+ @current_args = nil
+
+ @sleep_time = 0
+ @current_sleep = 0
+ @loop_exec = 0
+ @do_loop = 0
+ @loop_proc = []
+ @proc_max = 0
+ @current_pos = 0
+
+ @after_id = nil
+ @after_script = nil
+
+ set_procs(*args) if args != []
+
+ @running = false
+ end
+
+ attr :after_id
+ attr :after_script
+ attr :current_proc
+ attr :current_sleep
+
+ attr_accessor :loop_exec
+
+ def get_procs
+ [@init_sleep, @init_proc, @init_args, @sleep_time, @loop_exec, @loop_proc]
+ end
+
+ def current_status
+ [@running, @current_sleep, @current_proc, @current_args, @do_loop]
+ end
+
+ def running?
+ @running
+ end
+
+ def loop_rest
+ @do_loop
+ end
+
+ def loop_rest=(rest)
+ @do_loop = rest
+ end
+
+ def set_procs(interval, loop_exec, *procs)
+ if !interval == 'idle' \
+ && !interval.kind_of?(Integer) && !interval.kind_of?(Proc)
+ fail format("%s need to be Integer or Proc", interval.inspect)
+ end
+ @sleep_time = interval
+
+ @loop_proc = []
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+ @current_pos = 0
+
+ @do_loop = 0
+ if loop_exec
+ if loop_exec.kind_of?(Integer) && loop_exec < 0
+ @loop_exec = -1
+ elsif loop_exec == nil || loop_exec == false || loop_exec == 0
+ @loop_exec = 1
+ else
+ if not loop_exec.kind_of?(Integer)
+ fail format("%s need to be Integer", loop_exec.inspect)
+ end
+ @loop_exec = loop_exec
+ end
+ @do_loop = @loop_exec
+ end
+
+ self
+ end
+
+ def add_procs(*procs)
+ procs.each{|e|
+ if e.kind_of? Proc
+ @loop_proc.push([e])
+ else
+ @loop_proc.push(e)
+ end
+ }
+ @proc_max = @loop_proc.size
+
+ self
+ end
+
+ def set_start_proc(sleep, init_proc, *init_args)
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ @init_proc = init_proc
+ @init_args = init_args
+ self
+ end
+
+ def start(*init_args)
+ return nil if @running
+
+ Tk_CBTBL[@id] = self
+ @do_loop = @loop_exec
+ @current_pos = 0
+
+ argc = init_args.size
+ if argc > 0
+ sleep = init_args.shift
+ if !sleep == 'idle' && !sleep.kind_of?(Integer)
+ fail format("%s need to be Integer", sleep.inspect)
+ end
+ @init_sleep = sleep
+ end
+ @init_proc = init_args.shift if argc > 1
+ @init_args = init_args if argc > 0
+
+ @current_sleep = @init_sleep
+ @running = true
+ if @init_proc
+ if not @init_proc.kind_of? Proc
+ fail format("%s need to be Proc", @init_proc.inspect)
+ end
+ @current_proc = @init_proc
+ set_callback(sleep, @init_args)
+ @set_next = false if @in_callback
+ else
+ set_next_callback(*@init_args)
+ end
+
+ self
+ end
+
+ def restart(*restart_args)
+ cancel if @running
+ if restart_args == []
+ start(@init_sleep, @init_proc, *@init_args)
+ else
+ start(*restart_args)
+ end
+ end
+
+ def cancel
+ @running = false
+ tk_call 'after', 'cancel', @after_id if @after_id
+ @after_id = nil
+ Tk_CBTBL[@id] = nil ;# for GC
+ self
+ end
+ alias stop cancel
+
+ def continue(wait=nil)
+ sleep, cmd = @current_script
+ return nil if cmd == nil || @running == true
+ if wait
+ if not wait.kind_of? Integer
+ fail format("%s need to be Integer", wait.inspect)
+ end
+ sleep = wait
+ end
+ Tk_CBTBL[@id] = self
+ @running = true
+ @after_id = tk_call('after', sleep, cmd)
+ self
+ end
+
+ def skip
+ return nil if @running == false
+ cancel
+ Tk_CBTBL[@id] = self
+ @running = true
+ set_next_callback(@current_args)
+ self
+ end
+
+ def info
+ if @after_id
+ inf = tk_split_list(tk_call('after', 'info', @after_id))
+ [Tk_CBTBL[inf[0][1]], inf[1]]
+ else
+ nil
+ end
+ end
+end
diff --git a/ext/tk/lib/tkbgerror.rb b/ext/tk/lib/tkbgerror.rb
new file mode 100644
index 0000000000..8022077a3f
--- /dev/null
+++ b/ext/tk/lib/tkbgerror.rb
@@ -0,0 +1,17 @@
+#
+# tkbgerror -- bgerror ( tkerror ) module
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkBgError
+ extend Tk
+
+ def bgerror(message)
+ tk_call 'bgerror', message
+ end
+ alias tkerror bgerror
+ alias show bgerror
+
+ module_function :bgerror, :tkerror, :show
+end
diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb
new file mode 100644
index 0000000000..1cf24eeb7b
--- /dev/null
+++ b/ext/tk/lib/tkcanvas.rb
@@ -0,0 +1,829 @@
+#
+# tkcanvas.rb - Tk canvas classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+# $Date$
+# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+
+require "tk"
+require 'tkfont'
+
+module TkTreatCItemFont
+ def tagfont_configinfo(tagOrId)
+ if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
+ pathname = self.path + ';' + tagOrId.id.to_s
+ else
+ pathname = self.path + ';' + tagOrId.to_s
+ end
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'itemconfigure', tagOrId)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(tagOrId, slot)
+ if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag)
+ pathname = self.path + ';' + tagOrId.id.to_s
+ else
+ pathname = self.path + ';' + tagOrId.to_s
+ end
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'itemconfigure',tagOrId,slot)
+ else
+ latintagfont_configure(tagOrId, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(tagOrId, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(tagOrId, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(tagOrId, knj) if knj
+ end
+
+ tk_call(self.path, 'itemconfigure', tagOrId, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(tagOrId, ltn, keys=nil)
+ fobj = tagfontobj(tagOrId)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(tagOrId, knj, keys=nil)
+ fobj = tagfontobj(tagOrId)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(tagOrId).configure(key,value)
+ }
+ tagfontobj(tagOrId).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(tagOrId).configinfo.each{|key,value|
+ tagfontobj(tagOrId).configure(key,value)
+ }
+ tagfontobj(tagOrId).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ tagfontobj(tagOrId).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(tagOrId, window, wintag=nil)
+ if wintag
+ tagfontobj(tagOrId).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkCanvas<TkWindow
+ include TkTreatCItemFont
+
+ WidgetClassName = 'Canvas'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'canvas', path
+ end
+
+ def tagid(tag)
+ if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag)
+ tag.id
+ else
+ tag
+ end
+ end
+ private :tagid
+
+ def addtag(tag, mode, *args)
+ tk_send 'addtag', tagid(tag), mode, *args
+ end
+ def addtag_above(tagOrId, target)
+ addtag(tagOrId, 'above', tagid(target))
+ end
+ def addtag_all(tagOrId)
+ addtag(tagOrId, 'all')
+ end
+ def addtag_below(tagOrId, target)
+ addtag(tagOrId, 'below', tagid(target))
+ end
+ def addtag_closest(tagOrId, x, y, halo=None, start=None)
+ addtag(tagOrId, 'closest', x, y, halo, start)
+ end
+ def addtag_enclosed(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'enclosed', x1, y1, x2, y2)
+ end
+ def addtag_overlapping(tagOrId, x1, y1, x2, y2)
+ addtag(tagOrId, 'overlapping', x1, y1, x2, y2)
+ end
+ def addtag_withtag(tagOrId, tag)
+ addtag(tagOrId, 'withtag', tagid(tag))
+ end
+
+ def bbox(tagOrId, *tags)
+ list(tk_send('bbox', tagid(tagOrId), *tags))
+ end
+
+ def itembind(tag, context, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ begin
+ tk_send 'bind', tagid(tag), "<#{tk_event_sequence(context)}>", id
+ rescue
+ uninstall_cmd(cmd)
+ fail
+ end
+ # @cmdtbl.push id
+ end
+
+ def itembindinfo(tag, context=nil)
+ if context
+ (tk_send('bind', tagid(tag),
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_send 'bind', tagid(tag)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def canvasx(x, *args)
+ tk_tcl2ruby(tk_send 'canvasx', x, *args)
+ end
+ def canvasy(y, *args)
+ tk_tcl2ruby(tk_send 'canvasy', y, *args)
+ end
+
+ def coords(tag, *args)
+ if args == []
+ tk_split_list(tk_send('coords', tagid(tag)))
+ else
+ tk_send('coords', tagid(tag), *args)
+ end
+ end
+
+ def dchars(tag, first, last=None)
+ tk_send 'dchars', tagid(tag), first, last
+ end
+
+ def delete(*args)
+ tk_send 'delete', *args
+ end
+ alias remove delete
+
+ def dtag(tag, tag_to_del=None)
+ tk_send 'dtag', tagid(tag), tag_to_del
+ end
+
+ def find(mode, *args)
+ list(tk_send 'find', mode, *args).filter{|id|
+ TkcItem.id2obj(id)
+ }
+ end
+ def find_above(target)
+ find('above', tagid(target))
+ end
+ def find_all
+ find('all')
+ end
+ def find_below(target)
+ find('below', tagid(target))
+ end
+ def find_closest(x, y, halo=None, start=None)
+ find('closest', x, y, halo, start)
+ end
+ def find_enclosed(x1, y1, x2, y2)
+ find('enclosed', x1, y1, x2, y2)
+ end
+ def find_overlapping(x1, y1, x2, y2)
+ find('overlapping', x1, y1, x2, y2)
+ end
+ def find_withtag(tag)
+ find('withtag', tag)
+ end
+
+ def itemfocus(tagOrId=nil)
+ if tagOrId
+ tk_send 'focus', tagid(tagOrId)
+ else
+ ret = tk_send('focus')
+ if ret == ""
+ nil
+ else
+ TkcItem.id2obj(ret)
+ end
+ end
+ end
+
+ def gettags(tagOrId)
+ list(tk_send('gettags', tagid(tagOrId))).collect{|tag|
+ TkcTag.id2obj(tag)
+ }
+ end
+
+ def icursor(tagOrId, index)
+ tk_send 'icursor', tagid(tagOrId), index
+ end
+
+ def index(tagOrId, index)
+ tk_send 'index', tagid(tagOrId), index
+ end
+
+ def insert(tagOrId, index, string)
+ tk_send 'insert', tagid(tagOrId), index, string
+ end
+
+ def itemcget(tagOrId, option)
+ tk_tcl2ruby tk_send 'itemcget', tagid(tagOrId), "-#{option}"
+ end
+
+ def itemconfigure(tagOrId, key, value=None)
+ if key.kind_of? Hash
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tagOrId, key.dup)
+ else
+ tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
+ end
+
+ else
+ if ( key == 'font' || key == 'kanjifont' \
+ || key == 'latinfont' || key == 'asciifont' )
+ tagfont_configure(tagid(tagOrId), {key=>value})
+ else
+ tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
+ end
+ end
+ end
+# def itemconfigure(tagOrId, key, value=None)
+# if key.kind_of? Hash
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key)
+# else
+# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
+# end
+# end
+# def itemconfigure(tagOrId, keys)
+# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys)
+# end
+
+ def itemconfiginfo(tagOrId, key=nil)
+ if key
+ conf = tk_split_list(tk_send 'itemconfigure', tagid(tagOrId), "-#{key}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send 'itemconfigure', tagid(tagOrId)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+
+ def lower(tag, below=None)
+ tk_send 'lower', tagid(tag), below
+ end
+
+ def move(tag, x, y)
+ tk_send 'move', tagid(tag), x, y
+ end
+
+ def postscript(keys)
+ tk_send "postscript", *hash_kv(keys)
+ end
+
+ def raise(tag, above=None)
+ tk_send 'raise', tagid(tag), above
+ end
+
+ def scale(tag, x, y, xs, ys)
+ tk_send 'scale', tagid(tag), x, y, xs, ys
+ end
+
+ def scan_mark(x, y)
+ tk_send 'scan', 'mark', x, y
+ end
+ def scan_dragto(x, y)
+ tk_send 'scan', 'dragto', x, y
+ end
+
+ def select(mode, *args)
+ tk_send 'select', mode, *args
+ end
+ def select_adjust(tagOrId, index)
+ select('adjust', tagid(tagOrId), index)
+ end
+ def select_clear
+ select('clear')
+ end
+ def select_from(tagOrId, index)
+ select('from', tagid(tagOrId), index)
+ end
+ def select_item
+ select('item')
+ end
+ def select_to(tagOrId, index)
+ select('to', tagid(tagOrId), index)
+ end
+
+ def itemtype(tag)
+ TkcItem.type2class(tk_send 'type', tagid(tag))
+ end
+
+ def xview(*index)
+ tk_send 'xview', *index
+ end
+ def yview(*index)
+ tk_send 'yview', *index
+ end
+end
+
+module TkcTagAccess
+ include TkComm
+ include TkTreatTagFont
+
+ def addtag(tag)
+ @c.addtag(tag, 'with', @id)
+ end
+
+ def bbox
+ @c.bbox(@id)
+ end
+
+ def bind(seq, cmd=Proc.new, args=nil)
+ @c.itembind @id, seq, cmd, args
+ end
+
+ def bindinfo(seq=nil)
+ @c.itembindinfo @id, seq
+ end
+
+ def cget(option)
+ @c.itemcget @id, option
+ end
+
+ def configure(key, value=None)
+ @c.itemconfigure @id, key, value
+ end
+# def configure(keys)
+# @c.itemconfigure @id, keys
+# end
+
+ def configinfo(key=nil)
+ @c.itemconfiginfo @id, key
+ end
+
+ def coords(*args)
+ @c.coords @id, *args
+ end
+
+ def dchars(first, last=None)
+ @c.dchars @id, first, last
+ end
+
+ def dtag(tag_to_del=None)
+ @c.dtag @id, tag_to_del
+ end
+
+ def find
+ @c.find 'withtag', @id
+ end
+ alias list find
+
+ def focus
+ @c.itemfocus @id
+ end
+
+ def gettags
+ @c.gettags @id
+ end
+
+ def icursor(index)
+ @c.icursor @id, index
+ end
+
+ def index(index)
+ @c.index @id, index
+ end
+
+ def insert(beforethis, string)
+ @c.insert @id, beforethis, string
+ end
+
+ def lower(belowthis=None)
+ @c.lower @id, belowthis
+ end
+
+ def move(xamount, yamount)
+ @c.move @id, xamount, yamount
+ end
+
+ def raise(abovethis=None)
+ @c.raise @id, abovethis
+ end
+
+ def scale(xorigin, yorigin, xscale, yscale)
+ @c.scale @id, xorigin, yorigin, xscale, yscale
+ end
+
+ def select_adjust(index)
+ @c.select('adjust', @id, index)
+ end
+ def select_from(index)
+ @c.select('from', @id, index)
+ end
+ def select_to(index)
+ @c.select('to', @id, index)
+ end
+
+ def itemtype
+ @c.itemtype @id
+ end
+end
+
+class TkcTag<TkObject
+ include TkcTagAccess
+
+ CTagID_TBL = {}
+
+ def TkcTag.id2obj(id)
+ CTagID_TBL[id]? CTagID_TBL[id]: id
+ end
+
+ $tk_canvas_tag = 'ctag0000'
+ def initialize(parent, mode=nil, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = $tk_canvas_tag
+ CTagID_TBL[@id] = self
+ $tk_canvas_tag = $tk_canvas_tag.succ
+ if mode
+ tk_call @c.path, "addtag", @id, mode, *args
+ end
+ end
+ def id
+ return @id
+ end
+
+ def delete
+ @c.delete @id
+ CTagID_TBL[@id] = nil
+ end
+ alias remove delete
+ alias destroy delete
+
+ def set_to_above(target)
+ @c.addtag_above(@id, target)
+ end
+ alias above set_to_above
+
+ def set_to_all
+ @c.addtag_all(@id)
+ end
+ alias all set_to_all
+
+ def set_to_below(target)
+ @c.addtag_below(@id, target)
+ end
+ alias below set_to_below
+
+ def set_to_closest(x, y, halo=None, start=None)
+ @c.addtag_closest(@id, x, y, halo, start)
+ end
+ alias closest set_to_closest
+
+ def set_to_enclosed(x1, y1, x2, y2)
+ @c.addtag_enclosest(@id, x1, y1, x2, y2)
+ end
+ alias enclosed set_to_enclosed
+
+ def set_to_overlapping(x1, y1, x2, y2)
+ @c.addtag_overlapping(@id, x1, y1, x2, y2)
+ end
+ alias overlapping set_to_overlapping
+
+ def set_to_withtag(target)
+ @c.addtag_withtag(@id, target)
+ end
+ alias withtag set_to_withtag
+end
+
+class TkcTagAll<TkcTag
+ def initialize(parent)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = 'all'
+ CTagID_TBL[@id] = self
+ end
+end
+
+class TkcTagCurrent<TkcTag
+ def initialize(parent)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = 'current'
+ CTagID_TBL[@id] = self
+ end
+end
+
+class TkcGroup<TkcTag
+ $tk_group_id = 'tkg00000'
+ def create_self(parent, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @c = parent
+ @path = @id = $tk_group_id
+ CTagID_TBL[@id] = self
+ $tk_group_id = $tk_group_id.succ
+ add(*args) if args != []
+ end
+
+ def include(*tags)
+ for i in tags
+ i.addtag @id
+ end
+ end
+
+ def exclude(*tags)
+ for i in tags
+ i.delete @id
+ end
+ end
+end
+
+
+class TkcItem<TkObject
+ include TkcTagAccess
+
+ CItemTypeToClass = {}
+ CItemID_TBL = {}
+
+ def TkcItem.type2class(type)
+ CItemTypeToClass[type]
+ end
+
+ def TkcItem.id2obj(id)
+ CItemID_TBL[id]? CItemID_TBL[id]: id
+ end
+
+ def initialize(parent, *args)
+ if not parent.kind_of?(TkCanvas)
+ fail format("%s need to be TkCanvas", parent.inspect)
+ end
+ @parent = @c = parent
+ @path = parent.path
+ if args[-1].kind_of? Hash
+ keys = args.pop
+ end
+ @id = create_self(*args).to_i ;# 'canvas item id' is integer number
+ CItemID_TBL[@id] = self
+ if keys
+ # tk_call @path, 'itemconfigure', @id, *hash_kv(keys)
+ configure(keys) if keys
+ end
+ end
+ def create_self(*args); end
+ private :create_self
+ def id
+ return @id
+ end
+
+ def delete
+ @c.delete @id
+ CItemID_TBL[@id] = nil
+ end
+ alias remove delete
+ alias destroy delete
+end
+
+class TkcArc<TkcItem
+ CItemTypeToClass['arc'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'arc', *args)
+ end
+end
+class TkcBitmap<TkcItem
+ CItemTypeToClass['bitmap'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'bitmap', *args)
+ end
+end
+class TkcImage<TkcItem
+ CItemTypeToClass['image'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'image', *args)
+ end
+end
+class TkcLine<TkcItem
+ CItemTypeToClass['line'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'line', *args)
+ end
+end
+class TkcOval<TkcItem
+ CItemTypeToClass['oval'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'oval', *args)
+ end
+end
+class TkcPolygon<TkcItem
+ CItemTypeToClass['polygon'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'polygon', *args)
+ end
+end
+class TkcRectangle<TkcItem
+ CItemTypeToClass['rectangle'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'rectangle', *args)
+ end
+end
+class TkcText<TkcItem
+ CItemTypeToClass['text'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'text', *args)
+ end
+end
+class TkcWindow<TkcItem
+ CItemTypeToClass['window'] = self
+ def create_self(*args)
+ tk_call(@path, 'create', 'window', *args)
+ end
+end
+
+class TkImage<TkObject
+ include Tk
+
+ Tk_IMGTBL = {}
+
+ $tk_image_id = 'i00000'
+ def initialize(keys=nil)
+ @path = $tk_image_id
+ $tk_image_id = $tk_image_id.succ
+ tk_call 'image', 'create', @type, @path, *hash_kv(keys)
+ Tk_IMGTBL[@path] = self
+ end
+
+ def delete
+ Tk_IMGTBL[@id] = nil if @id
+ tk_call('image', 'delete', @path)
+ end
+ def height
+ number(tk_call('image', 'height', @path))
+ end
+ def itemtype
+ tk_call('image', 'type', @path)
+ end
+ def width
+ number(tk_call('image', 'width', @path))
+ end
+
+ def TkImage.names
+ Tk.tk_call('image', 'names').split.filter{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
+ end
+
+ def TkImage.types
+ Tk.tk_call('image', 'types').split
+ end
+end
+
+class TkBitmapImage<TkImage
+ def initialize(*args)
+ @type = 'bitmap'
+ super
+ end
+end
+
+class TkPhotoImage<TkImage
+ def initialize(*args)
+ @type = 'photo'
+ super
+ end
+
+ def blank
+ tk_send 'blank'
+ end
+
+ def cget(option)
+ tk_tcl2ruby tk_send 'cget', option
+ end
+
+ def copy(source, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'copy', source, *args
+ end
+
+ def get(x, y)
+ tk_send 'get', x, y
+ end
+
+ def put(data, *to)
+ if to == []
+ tk_send 'put', data
+ else
+ tk_send 'put', data, '-to', *to
+ end
+ end
+
+ def read(file, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'read', file, *args
+ end
+
+ def redither
+ tk_send 'redither'
+ end
+
+ def write(file, *opts)
+ args = opts.collect{|term|
+ if term.kind_of?(String) && term.include?(?\s)
+ term.split
+ else
+ term
+ end
+ }.flatten
+
+ tk_send 'write', file, *args
+ end
+end
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
new file mode 100644
index 0000000000..0b33d4ec8b
--- /dev/null
+++ b/ext/tk/lib/tkclass.rb
@@ -0,0 +1,38 @@
+#
+# tkclass.rb - Tk classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require "tk"
+
+TopLevel = TkToplevel
+Frame = TkFrame
+Label = TkLabel
+Button = TkButton
+Radiobutton = TkRadioButton
+Checkbutton = TkCheckButton
+Message = TkMessage
+Entry = TkEntry
+Text = TkText
+Scale = TkScale
+Scrollbar = TkScrollbar
+Listbox = TkListbox
+Menu = TkMenu
+Menubutton = TkMenubutton
+Canvas = TkCanvas
+Arc = TkcArc
+Bitmap = TkcBitmap
+Line = TkcLine
+Oval = TkcOval
+Polygon = TkcPolygon
+Rectangle = TkcRectangle
+TextItem = TkcText
+WindowItem = TkcWindow
+Selection = TkSelection
+Winfo = TkWinfo
+Pack = TkPack
+Variable = TkVariable
+
+def Mainloop
+ Tk.mainloop
+end
diff --git a/ext/tk/lib/tkdialog.rb b/ext/tk/lib/tkdialog.rb
new file mode 100644
index 0000000000..1133db6ae9
--- /dev/null
+++ b/ext/tk/lib/tkdialog.rb
@@ -0,0 +1,141 @@
+require "tk"
+
+class TkDialog < TkWindow
+ extend Tk
+
+ # initialize tk_dialog
+ def initialize(keys = nil)
+ super()
+ @var = TkVariable.new
+ id = @var.id
+
+ @title = title
+
+ @message = message
+ @message_config = message_config
+
+ @bitmap = bitmap
+ @bitmap_config = message_config
+
+ @default_button = default_button
+
+ @buttons = buttons
+ @button_configs = proc{|num| button_configs num}
+
+ if keys.kind_of? Hash
+ @title = keys['title'] if keys['title']
+ @message = keys['message'] if keys['message']
+ @bitmap = keys['bitmap'] if keys['bitmap']
+ @default_button = keys['default'] if keys['default']
+ @buttons = keys['buttons'] if keys['buttons']
+
+ @command = keys['prev_command']
+
+ @message_config = keys['message_config'] if keys['message_config']
+ @bitmap_config = keys['bitmap_config'] if keys['bitmap_config']
+ @button_configs = keys['button_configs'] if keys['button_configs']
+ end
+
+ if @title.include? ?\s
+ @title = '{' + @title + '}'
+ end
+
+ @buttons = tk_split_list(@buttons) if @buttons.kind_of? String
+ @buttons = @buttons.collect{|s|
+ if s.kind_of? Array
+ s = s.join(' ')
+ end
+ if s.include? ?\s
+ '{' + s + '}'
+ else
+ s
+ end
+ }
+
+ config = ""
+ if @message_config.kind_of? Hash
+ config << format("%s.msg configure %s\n",
+ @path, hash_kv(@message_config).join(' '))
+ end
+ if @bitmap_config.kind_of? Hash
+ config << format("%s.msg configure %s\n",
+ @path, hash_kv(@bitmap_config).join(' '))
+ end
+ if @button_configs.kind_of? Proc
+ @buttons.each_index{|i|
+ if (c = @button_configs.call(i)).kind_of? Hash
+ config << format("%s.button%s configure %s\n",
+ @path, i, hash_kv(c).join(' '))
+ end
+ }
+ end
+ config = 'after idle {' + config + '};' if config != ""
+
+ if @command.kind_of? Proc
+ @command.call(self)
+ end
+
+ INTERP._eval('eval {global '+id+';'+config+
+ 'set '+id+' [tk_dialog '+
+ @path+" "+@title+" {#{@message}} "+@bitmap+" "+
+ String(@default_button)+" "+@buttons.join(' ')+']}')
+ end
+ def value
+ return @var.value.to_i
+ end
+ ######################################################
+ # #
+ # these methods must be overridden for each dialog #
+ # #
+ ######################################################
+ def title
+ return "DIALOG"
+ end
+ def message
+ return "MESSAGE"
+ end
+ def message_config
+ return nil
+ end
+ def bitmap
+ return "info"
+ end
+ def bitmap_config
+ return nil
+ end
+ def default_button
+ return 0
+ end
+ def buttons
+ #return "BUTTON1 BUTTON2"
+ return ["BUTTON1", "BUTTON2"]
+ end
+ def button_configs(num)
+ return nil
+ end
+end
+
+#
+# dialog for warning
+#
+class TkWarning < TkDialog
+ def initialize(mes)
+ @mes = mes
+ super()
+ end
+ def message
+ return @mes
+ end
+ def title
+ return "WARNING";
+ end
+ def bitmap
+ return "warning";
+ end
+ def default_button
+ return 0;
+ end
+ def buttons
+ return "OK";
+ end
+end
diff --git a/ext/tk/lib/tkentry.rb b/ext/tk/lib/tkentry.rb
new file mode 100644
index 0000000000..b834c455c6
--- /dev/null
+++ b/ext/tk/lib/tkentry.rb
@@ -0,0 +1,73 @@
+#
+# tkentry.rb - Tk entry classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+
+class TkEntry<TkLabel
+ WidgetClassName = 'Entry'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+
+ def create_self
+ tk_call 'entry', @path
+ end
+ def scrollcommand(cmd)
+ configure 'scrollcommand', cmd
+ end
+
+ def delete(s, e=None)
+ tk_send 'delete', s, e
+ end
+
+ def cursor
+ tk_send 'index', 'insert'
+ end
+ def cursor=(index)
+ tk_send 'icursor', index
+ end
+ def index(index)
+ number(tk_send('index', index))
+ end
+ def insert(pos,text)
+ tk_send 'insert', pos, text
+ end
+ def mark(pos)
+ tk_send 'scan', 'mark', pos
+ end
+ def dragto(pos)
+ tk_send 'scan', 'dragto', pos
+ end
+ def selection_adjust(index)
+ tk_send 'selection', 'adjust', index
+ end
+ def selection_clear
+ tk_send 'selection', 'clear', 'end'
+ end
+ def selection_from(index)
+ tk_send 'selection', 'from', index
+ end
+ def selection_present()
+ tk_send('selection', 'present') == 1
+ end
+ def selection_range(s, e)
+ tk_send 'selection', 'range', s, e
+ end
+ def selection_to(index)
+ tk_send 'selection', 'to', index
+ end
+ def xview(*index)
+ tk_send 'xview', *index
+ end
+
+ def value
+ tk_send 'get'
+ end
+ def value= (val)
+ tk_send 'delete', 0, 'end'
+ tk_send 'insert', 0, val
+ end
+end
diff --git a/ext/tk/lib/tkfont.rb b/ext/tk/lib/tkfont.rb
new file mode 100644
index 0000000000..c680d166e7
--- /dev/null
+++ b/ext/tk/lib/tkfont.rb
@@ -0,0 +1,953 @@
+#
+# tkfont.rb - the class to treat fonts on Ruby/Tk
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+
+class TkFont
+ include Tk
+ extend TkCore
+
+ Tk_FontID = [0]
+ Tk_FontNameTBL = {}
+ Tk_FontUseTBL = {}
+
+ DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
+
+ ###################################
+ # class methods
+ ###################################
+ def TkFont.families(window=nil)
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ ['fixed']
+
+ when /^8\.*/
+ if window
+ tk_split_simplelist(tk_call('font', 'families', '-displayof', window))
+ else
+ tk_split_simplelist(tk_call('font', 'families'))
+ end
+ end
+ end
+
+ def TkFont.names
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ r = ['fixed']
+ r += ['a14', 'k14'] if JAPANIZED_TK
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ r | []
+
+ when /^8\.*/
+ tk_split_simplelist(tk_call('font', 'names'))
+
+ end
+ end
+
+ def TkFont.create_copy(font)
+ keys = {}
+ font.configure.each{|key,value| keys[key] = value }
+ new_font = TkFont.new(font.latin_font, font.kanji_font, keys)
+ end
+
+ def TkFont.get_obj(name)
+ if name =~ /^(@font[0-9]+)(|c|l|k)$/
+ Tk_FontNameTBL[$1]
+ else
+ nil
+ end
+ end
+
+ def TkFont.init_widget_font(path, *args)
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ conf = tk_split_simplelist(tk_call(*args)).
+ find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}.
+ collect{|prop| tk_split_simplelist(prop)}
+ if font_inf = conf.assoc('-font')
+ ltn = font_inf[4]
+ ltn = nil if ltn == []
+ else
+ #ltn = nil
+ raise RuntimeError, "unknown option '-font'"
+ end
+ if font_inf = conf.assoc('-kanjifont')
+ knj = font_inf[4]
+ knj = nil if knj == []
+ else
+ knj = nil
+ end
+ TkFont.new(ltn, knj).call_font_configure(path, *(args + [{}]))
+
+ when /^8\.*/
+ font_prop = tk_split_simplelist(tk_call(*args)).find{|prop|
+ prop[0..5] == '-font '
+ }
+ unless font_prop
+ raise RuntimeError, "unknown option '-font'"
+ end
+ fnt = tk_split_simplelist(font_prop)[4]
+ if fnt == ""
+ TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
+ else
+ begin
+ compound = Hash[*list(tk_call('font', 'configure',
+ fnt))].collect{|key,value|
+ [key[1..-1], value]
+ }.assoc('compound')[1]
+ rescue
+ compound = []
+ end
+ if compound == []
+ TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
+ .call_font_configure(path, *(args + [{}]))
+ else
+ TkFont.new(compound[0], compound[1]) \
+ .call_font_configure(path, *(args + [{}]))
+ end
+ end
+ end
+ end
+
+ def TkFont.used_on(path=nil)
+ if path
+ Tk_FontUseTBL[path]
+ else
+ Tk_FontUseTBL.values | []
+ end
+ end
+
+ ###################################
+ private
+ ###################################
+ def initialize(ltn=nil, knj=nil, keys=nil)
+ @id = format("@font%.4d", Tk_FontID[0])
+ Tk_FontID[0] += 1
+ Tk_FontNameTBL[@id] = self
+
+ ltn = DEFAULT_LATIN_FONT_NAME unless ltn
+ create_latinfont(ltn)
+
+ knj = DEFAULT_KANJI_FONT_NAME unless knj
+ create_kanjifont(knj)
+
+ create_compoundfont(keys)
+ end
+
+ def _get_font_info_from_hash(font)
+ foundry = (info = font['foundry'] .to_s)? info: '*'
+ family = (info = font['family'] .to_s)? info: '*'
+ weight = (info = font['weight'] .to_s)? info: '*'
+ slant = (info = font['slant'] .to_s)? info: '*'
+ swidth = (info = font['swidth'] .to_s)? info: '*'
+ adstyle = (info = font['adstyle'] .to_s)? info: '*'
+ pixels = (info = font['pixels'] .to_s)? info: '*'
+ points = (info = font['points'] .to_s)? info: '*'
+ resx = (info = font['resx'] .to_s)? info: '*'
+ resy = (info = font['resy'] .to_s)? info: '*'
+ space = (info = font['space'] .to_s)? info: '*'
+ avgWidth = (info = font['avgWidth'].to_s)? info: '*'
+ charset = (info = font['charset'] .to_s)? info: '*'
+ encoding = (info = font['encoding'].to_s)? info: '*'
+
+ [foundry, family, weight, slant, swidth, adstyle,
+ pixels, points, resx, resy, space, avgWidth, charset, encoding]
+ end
+
+ def create_latinfont_tk4x(font)
+ if font.kind_of? Hash
+ @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+
+ elsif font.kind_of? TkFont
+ @latinfont = font.latin_font
+
+ else
+ @latinfont = font
+
+ end
+ end
+
+ def create_kanjifont_tk4x(font)
+ unless JAPANIZED_TK
+ @kanjifont = ""
+ return
+ end
+
+ if font.kind_of? Hash
+ @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-'
+
+ elsif font.kind_of? Array
+ finfo = {}
+ finfo['family'] = font[0].to_s
+ if font[1]
+ fsize = font[1].to_s
+ if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/
+ if $1 == '-'
+ finfo['pixels'] = $2
+ else
+ finfo['points'] = $2
+ end
+ else
+ finfo['points'] = '13'
+ end
+ end
+ font[2..-1].each{|style|
+ case (style)
+ when 'normal'
+ finfo['weight'] = style
+ when 'bold'
+ finfo['weight'] = style
+ when 'roman'
+ finfo['slant'] = 'r'
+ when 'italic'
+ finfo['slant'] = 'i'
+ end
+ }
+
+ @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-'
+ elsif font.kind_of? TkFont
+ @kanjifont = font.kanji_font
+ else
+ @kanjifont = font
+ end
+ end
+
+ def create_compoundfont_tk4x(keys)
+ if JAPANIZED_TK
+ @compoundfont = [[@latinfont], [@kanjifont]]
+ @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
+ else
+ @compoundfont = @latinfont
+ @fontslot = {'font'=>@latinfont}
+ end
+ end
+
+ def create_latinfont_tk8x(font)
+ @latinfont = @id + 'l'
+
+ if JAPANIZED_TK
+ if font.kind_of? Hash
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font))
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @latinfont, '-copy', font.latin_font)
+ else
+ tk_call('font', 'create', @latinfont, '-copy', font)
+ end
+ else
+ if font.kind_of? Hash
+ tk_call('font', 'create', @latinfont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.latin_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @latinfont, *hash_kv(keys))
+ end
+ end
+ end
+
+ def create_kanjifont_tk80(font)
+ unless JAPANIZED_TK
+ @kanjifont = ""
+ return
+ end
+
+ @kanjifont = @id + 'k'
+
+ if font.kind_of? Hash
+ if font['charset']
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ tk_call('font', 'create', @kanjifont,
+ '-charset', 'jisx0208.1983', *hash_kv(font))
+ end
+ elsif font.kind_of? Array
+ tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font))
+ tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983')
+
+ elsif font.kind_of? TkFont
+ tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font)
+ else
+ tk_call('font', 'create', @kanjifont, '-copy', font,
+ '-charset', 'jisx0208.1983')
+ end
+ end
+
+ def create_kanjifont_tk81(font)
+ @kanjifont = @id + 'k'
+
+ if font.kind_of? Hash
+ tk_call('font', 'create', @kanjifont, *hash_kv(font))
+ else
+ keys = {}
+ if font.kind_of? Array
+ actual_core(array2tk_list(font)).each{|key,val| keys[key] = val}
+ elsif font.kind_of? TkFont
+ actual_core(font.kanji_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(font).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'create', @kanjifont, *hash_kv(keys))
+ end
+
+ keys = {}
+ actual_core(@kanjifont).each{|key,val| keys[key] = val}
+ begin
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ rescue
+ end
+ end
+
+ def create_compoundfont_tk80(keys)
+ @compoundfont = @id + 'c'
+ if JAPANIZED_TK
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'create', @compoundfont,
+ '-compound', [@latinfont, @kanjifont], *hash_kv(keys))
+ else
+ tk_call('font', 'create', @compoundfont)
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ end
+
+ def create_compoundfont_tk81(keys)
+ @compoundfont = @id + 'c'
+ tk_call('font', 'create', @compoundfont)
+
+ latinkeys = {}
+ begin
+ actual_core(@latinfont).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys {}
+ end
+ if latinkeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ end
+
+ kanjikeys = {}
+ begin
+ actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val}
+ rescue
+ kanjikeys {}
+ end
+ if kanjikeys != {}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys))
+ end
+
+ @fontslot = {'font'=>@compoundfont}
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+
+ def actual_core_tk4x(font, window=nil, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ [['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
+ ['underline',[]], ['overstrike',[]], ['charset',[]],
+ ['pointadjust',[]]]
+ end
+ end
+
+ def actual_core_tk8x(font, window=nil, option=nil)
+ if option == 'compound'
+ ""
+ elsif option
+ if window
+ tk_call('font', 'actual', font, "-#{option}")
+ else
+ tk_call('font', 'actual', font, "-displayof", window, "-#{option}")
+ end
+ else
+ l = tk_split_simplelist(if window
+ tk_call('font', 'actual', font,
+ "-displayof", window)
+ else
+ tk_call('font', 'actual', font)
+ end)
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ r.push [key[1..-1], l.shift]
+ end
+ end
+ r
+ end
+ end
+
+ def configure_core_tk4x(font, slot, value=None)
+ ""
+ end
+
+ def configinfo_core_tk4x(font, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ [['family',[]], ['size',[]], ['weight',[]], ['slant',[]],
+ ['underline',[]], ['overstrike',[]], ['charset',[]],
+ ['pointadjust',[]]]
+ end
+ end
+
+ def configure_core_tk8x(font, slot, value=None)
+ if slot.kind_of? Hash
+ tk_call 'font', 'configure', font, *hash_kv(slot)
+ else
+ tk_call 'font', 'configure', font, "-#{slot}", value
+ end
+ end
+
+ def configinfo_core_tk8x(font, option=nil)
+ if option == 'compound'
+ ""
+ elsif option
+ tk_call('font', 'configure', font, "-#{option}")
+ else
+ l = tk_split_simplelist(tk_call('font', 'configure', font))
+ r = []
+ while key=l.shift
+ if key == '-compound'
+ l.shift
+ else
+ r.push [key[1..-1], l.shift]
+ end
+ end
+ r
+ end
+ end
+
+ def delete_core_tk4x
+ Tk_FontNameTBL[@id] = nil
+ Tk_FontUseTBL.delete_if{|key,value| value == self}
+ end
+
+ def delete_core_tk8x
+ begin
+ tk_call('font', 'delete', @latinfont)
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @kanjifont)
+ rescue
+ end
+ begin
+ tk_call('font', 'delete', @compoundfont)
+ rescue
+ end
+ Tk_FontNameTBL[@id] = nil
+ Tk_FontUseTBL.delete_if{|key,value| value == self}
+ end
+
+ def latin_replace_core_tk4x(ltn)
+ create_latinfont_tk4x(ltn)
+ @compoundfont[0] = [@latinfont] if JAPANIZED_TK
+ @fontslot['font'] = @latinfont
+ Tk_FontUseTBL.dup.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag = w.split(';')
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'font'=>@latinfont})
+ if winobj.kind_of? TkText
+ tk_call(win, 'tag', 'configure', tag, '-font', @latinfont)
+ elsif winobj.kind_of? TkCanvas
+ tk_call(win, 'itemconfigure', tag, '-font', @latinfont)
+ elsif winobj.kind_of? TkMenu
+ tk_call(win, 'entryconfigure', tag, '-font', @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('font'=>@latinfont)
+ tk_call(w, 'configure', '-font', @latinfont)
+ end
+ rescue
+ Tk_FontUseTBL[w] = nil
+ end
+ end
+ }
+ self
+ end
+
+ def kanji_replace_core_tk4x(knj)
+ return self unless JAPANIZED_TK
+
+ create_kanjifont_tk4x(knj)
+ @compoundfont[1] = [@kanjifont]
+ @fontslot['kanjifont'] = @kanjifont
+ Tk_FontUseTBL.dup.each{|w, fobj|
+ if self == fobj
+ begin
+ if w.include?(';')
+ win, tag = w.split(';')
+ winobj = tk_tcl2ruby(win)
+# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
+ if winobj.kind_of? TkText
+ tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont)
+ elsif winobj.kind_of? TkCanvas
+ tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont)
+ elsif winobj.kind_of? TkMenu
+ tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont)
+ else
+ raise RuntimeError, "unknown widget type"
+ end
+ else
+# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont)
+ tk_call(w, 'configure', '-kanjifont', @kanjifont)
+ end
+ rescue
+ Tk_FontUseTBL[w] = nil
+ end
+ end
+ }
+ self
+ end
+
+ def latin_replace_core_tk8x(ltn)
+ begin
+ tk_call('font', 'delete', @latinfont)
+ rescue
+ end
+ create_latinfont(ltn)
+ self
+ end
+
+ def kanji_replace_core_tk80(knj)
+ return self unless JAPANIZED_TK
+
+ begin
+ tk_call('font', 'delete', @kanjifont)
+ rescue
+ end
+ create_kanjifont(knj)
+ self
+ end
+
+ def kanji_replace_core_tk81(knj)
+ if font.kind_of? Hash
+ tk_call('font', 'configure', @compoundfont, *hash_kv(knj))
+ else
+ keys = {}
+ if knj.kind_of? Array
+ actual_core(array2tk_list(knj)).each{|key,val| keys[key] = val}
+ elsif knj.kind_of? TkFont
+ actual_core(knj.latin_font).each{|key,val| keys[key] = val}
+ else
+ actual_core(knj).each{|key,val| keys[key] = val}
+ end
+ tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
+ end
+ self
+ end
+
+ def measure_core_tk4x(window, text)
+ 0
+ end
+
+ def measure_core_tk8x(window, text)
+ if window
+ number(tk_call('font', 'measure', @compoundfont,
+ '-displayof', window, text))
+ else
+ number(tk_call('font', 'measure', @compoundfont, text))
+ end
+ end
+
+ def metrics_core_tk4x(font, window, option=nil)
+ # dummy
+ if option
+ ""
+ else
+ [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]]
+ end
+ end
+
+ def metrics_core_tk8x(font, window, option=nil)
+ if option
+ if window
+ number(tk_call('font', 'metrics', font, "-#{option}"))
+ else
+ number(tk_call('font', 'metrics', font,
+ "-displayof", window, "-#{option}"))
+ end
+ else
+ l = tk_split_list(if window
+ tk_call('font','metrics',font,"-displayof",window)
+ else
+ tk_call('font','metrics',font)
+ end)
+ r = []
+ while key=l.shift
+ r.push [key[1..-1], l.shift.to_i]
+ end
+ r
+ end
+ end
+
+ ###################################
+ # private alias
+ ###################################
+ case (Tk::TK_VERSION)
+ when /^4\.*/
+ alias create_latinfont create_latinfont_tk4x
+ alias create_kanjifont create_kanjifont_tk4x
+ alias create_compoundfont create_compoundfont_tk4x
+ alias actual_core actual_core_tk4x
+ alias configure_core configure_core_tk4x
+ alias configinfo_core configinfo_core_tk4x
+ alias delete_core delete_core_tk4x
+ alias latin_replace_core latin_replace_core_tk4x
+ alias kanji_replace_core kanji_replace_core_tk4x
+ alias measure_core measure_core_tk4x
+ alias metrics_core metrics_core_tk4x
+
+ when /^8\.0/
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk80
+ alias create_compoundfont create_compoundfont_tk80
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk80
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ when /^8\.1/
+ alias create_latinfont create_latinfont_tk8x
+ alias create_kanjifont create_kanjifont_tk81
+ alias create_compoundfont create_compoundfont_tk81
+ alias actual_core actual_core_tk8x
+ alias configure_core configure_core_tk8x
+ alias configinfo_core configinfo_core_tk8x
+ alias delete_core delete_core_tk8x
+ alias latin_replace_core latin_replace_core_tk8x
+ alias kanji_replace_core kanji_replace_core_tk81
+ alias measure_core measure_core_tk8x
+ alias metrics_core metrics_core_tk8x
+
+ end
+
+ ###################################
+ public
+ ###################################
+ def call_font_configure(path, *args)
+ args += hash_kv(args.pop.update(@fontslot))
+ tk_call *args
+ Tk_FontUseTBL[path] = self
+ self
+ end
+
+ def used
+ ret = []
+ Tk_FontUseTBL.each{|key,value|
+ if key.include?(';')
+ win, tag = key.split(';')
+ winobj = tk_tcl2ruby(win)
+ if winobj.kind_of? TkText
+ ret.push([winobj, winobj.tagid2obj(tag)])
+ elsif winobj.kind_of? TkCanvas
+ if (tagobj = TkcTag.id2obj(tag)).kind_of? TkcTag
+ ret.push([winobj, tagobj])
+ elsif (tagobj = TkcItem.id2obj(tag)).kind_of? TkcItem
+ ret.push([winobj, tagobj])
+ else
+ ret.push([winobj, tag])
+ end
+ elsif winobj.kind_of? TkMenu
+ ret.push([winobj, tag])
+ else
+ ret.push([win, tag])
+ end
+ else
+ ret.push(tk_tcl2ruby(key)) if value == self
+ end
+ }
+ ret
+ end
+
+ def id
+ @id
+ end
+
+ def to_eval
+ font
+ end
+
+ def font
+ @compoundfont
+ end
+
+ def latin_font
+ @latinfont
+ end
+
+ def kanji_font
+ @kanjifont
+ end
+
+ def actual(option=nil)
+ actual_core(@compoundfont, nil, option)
+ end
+
+ def actual_displayof(window, option=nil)
+ window = '.' unless window
+ actual_core(@compoundfont, window, option)
+ end
+
+ def latin_actual(option=nil)
+ actual_core(@latinfont, nil, option)
+ end
+
+ def latin_actual_displayof(window, option=nil)
+ window = '.' unless window
+ actual_core(@latinfont, window, option)
+ end
+
+ def kanji_actual(option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ actual_core(@kanjifont, nil, option)
+ else
+ actual_core_tk4x(nil, nil, option)
+ end
+ end
+
+ def kanji_actual_displayof(window, option=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ window = '.' unless window
+ actual_core(@kanjifont, window, option)
+ else
+ actual_core_tk4x(nil, window, option)
+ end
+ end
+
+ def [](slot)
+ configinfo slot
+ end
+
+ def []=(slot, val)
+ configure slot, val
+ end
+
+ def configure(slot, value=None)
+ configure_core(@compoundfont, slot, value)
+ end
+
+ def configinfo(slot=nil)
+ configinfo_core(@compoundfont, slot)
+ end
+
+ def delete
+ delete_core
+ end
+
+ def latin_configure(slot, value=None)
+ if JAPANIZED_TK
+ configure_core(@latinfont, slot, value)
+ else
+ configure(slot, value)
+ end
+ end
+
+ def latin_configinfo(slot=nil)
+ if JAPANIZED_TK
+ configinfo_core(@latinfont, slot)
+ else
+ configure(slot, value)
+ end
+ end
+
+ def kanji_configure(slot, value=None)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ configure_core(@kanjifont, slot, value)
+ configure('size'=>configinfo('size')) # to reflect new configuration
+ else
+ #""
+ configure(slot, value)
+ end
+ end
+
+ def kanji_configinfo(slot=nil)
+ #if JAPANIZED_TK
+ if @kanjifont != ""
+ configinfo_core(@kanjifont, slot)
+ else
+ #[]
+ configinfo(slot)
+ end
+ end
+
+ def replace(ltn, knj)
+ latin_replace(ltn)
+ kanji_replace(knj)
+ self
+ end
+
+ def latin_replace(ltn)
+ latin_replace_core(ltn)
+ reset_pointadjust
+ end
+
+ def kanji_replace(knj)
+ kanji_replace_core(knj)
+ reset_pointadjust
+ end
+
+ def measure(text)
+ measure_core(nil, text)
+ end
+
+ def measure_displayof(window, text)
+ window = '.' unless window
+ measure_core(window, text)
+ end
+
+ def metrics(option=nil)
+ metrics_core(@compoundfont, nil, option)
+ end
+
+ def metrics_displayof(window, option=nil)
+ window = '.' unless window
+ metrics_core(@compoundfont, window, option)
+ end
+
+ def latin_metrics(option=nil)
+ metrics_core(@latinfont, nil, option)
+ end
+
+ def latin_metrics_displayof(window, option=nil)
+ window = '.' unless window
+ metrics_core(@latinfont, window, option)
+ end
+
+ def kanji_metrics(option=nil)
+ if JAPANIZED_TK
+ metrics_core(@kanjifont, nil, option)
+ else
+ metrics_core_tk4x(nil, nil, option)
+ end
+ end
+
+ def kanji_metrics_displayof(window, option=nil)
+ if JAPANIZED_TK
+ window = '.' unless window
+ metrics_core(@kanjifont, window, option)
+ else
+ metrics_core_tk4x(nil, window, option)
+ end
+ end
+
+ def reset_pointadjust
+ begin
+ if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
+ kanji_actual.assoc('size')[1].to_f )
+ end
+ rescue
+ end
+ self
+ end
+
+ ###################################
+ # public alias
+ ###################################
+ alias ascii_font latin_font
+ alias create_asciifont create_latinfont
+ alias ascii_actual latin_actual
+ alias ascii_actual_displayof latin_actual_displayof
+ alias ascii_configure latin_configure
+ alias ascii_configinfo latin_configinfo
+ alias ascii_replace latin_replace
+ alias ascii_metrics latin_metrics
+
+end
+
+module TkTreatTagFont
+ def font_configinfo
+ @parent.tagfont_configinfo(@id)
+ end
+ alias font font_configinfo
+
+ def font_configure(slot)
+ @parent.tagfont_configure(@id, slot)
+ end
+
+ def latinfont_configure(ltn, keys=nil)
+ @parent.latintagfont_configure(@id, ltn, keys)
+ end
+ alias asciifont_configure latinfont_configure
+
+ def kanjifont_configure(knj, keys=nil)
+ @parent.kanjitagfont_configure(@id, ltn, keys)
+ end
+
+ def font_copy(window, wintag=nil)
+ @parent.tagfont_copy(@id, window, wintag)
+ end
+
+ def latinfont_copy(window, wintag=nil)
+ @parent.latintagfont_copy(@id, window, wintag)
+ end
+ alias asciifont_copy latinfont_copy
+
+ def kanjifont_copy(window, wintag=nil)
+ @parent.kanjitagfont_copy(@id, window, wintag)
+ end
+end
diff --git a/ext/tk/lib/tkmenubar.rb b/ext/tk/lib/tkmenubar.rb
new file mode 100644
index 0000000000..441f3f5c03
--- /dev/null
+++ b/ext/tk/lib/tkmenubar.rb
@@ -0,0 +1,137 @@
+#
+# tkmenubar.rb
+#
+# Copyright (C) 1998 maeda shugo. All rights reserved.
+# This file can be distributed under the terms of the Ruby.
+
+# Usage:
+#
+# menu_spec = [
+# [['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]],
+# [['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]]
+# ]
+# menubar = TkMenubar.new(nil, menu_spec,
+# 'tearoff'=>false,
+# 'foreground'=>'grey40',
+# 'activeforeground'=>'red',
+# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+#
+#
+# OR
+#
+#
+# menubar = TkMenubar.new
+# menubar.add_menu([['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]])
+# menubar.add_menu([['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]])
+# menubar.configure('tearoff', false)
+# menubar.configure('foreground', 'grey40')
+# menubar.configure('activeforeground', 'red')
+# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+
+# The format of the menu_spec is:
+# [
+# [
+# [button text, underline, accelerator],
+# [menu label, command, underline, accelerator],
+# '---', # separator
+# ...
+# ],
+# ...
+# ]
+
+# underline and accelerator are optional parameters.
+# Hashes are OK instead of Arrays.
+
+# To use add_menu, configuration must be done by calling configure after
+# adding all menus by add_menu, not by the constructor arguments.
+
+require "tk"
+
+class TkMenubar<TkFrame
+
+ include TkComposite
+
+ def initialize(parent = nil, spec = nil, options = nil)
+ super(parent, options)
+
+ @menus = []
+
+ if spec
+ for menu_info in spec
+ add_menu(menu_info)
+ end
+ end
+
+ if options
+ for key, value in options
+ configure(key, value)
+ end
+ end
+ end
+
+ def add_menu(menu_info)
+ btn_info = menu_info.shift
+ mbtn = TkMenubutton.new(@frame)
+
+ if btn_info.kind_of?(Hash)
+ for key, value in btn_info
+ mbtn.configure(key, value)
+ end
+ elsif btn_info.kind_of?(Array)
+ mbtn.configure('text', btn_info[0]) if btn_info[0]
+ mbtn.configure('underline', btn_info[1]) if btn_info[1]
+ mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
+ else
+ mbtn.configure('text', btn_info)
+ end
+
+ menu = TkMenu.new(mbtn)
+
+ for item_info in menu_info
+ if item_info.kind_of?(Hash)
+ menu.add('command', item_info)
+ elsif item_info.kind_of?(Array)
+ options = {}
+ options['label'] = item_info[0] if item_info[0]
+ options['command'] = item_info[1] if item_info[1]
+ options['underline'] = item_info[2] if item_info[2]
+ options['accelerator'] = item_info[3] if item_info[3]
+ menu.add('command', options)
+ elsif /^-+$/ =~ item_info
+ menu.add('sep')
+ else
+ menu.add('command', 'label' => item_info)
+ end
+ end
+
+ mbtn.menu(menu)
+ @menus.push([mbtn, menu])
+ delegate('tearoff', menu)
+ delegate('foreground', mbtn, menu)
+ delegate('background', mbtn, menu)
+ delegate('disabledforeground', mbtn, menu)
+ delegate('activeforeground', mbtn, menu)
+ delegate('activebackground', mbtn, menu)
+ delegate('font', mbtn, menu)
+ delegate('kanjifont', mbtn, menu)
+ mbtn.pack('side' => 'left')
+ end
+
+ def [](index)
+ return @menus[index]
+ end
+end
diff --git a/ext/tk/lib/tkmngfocus.rb b/ext/tk/lib/tkmngfocus.rb
new file mode 100644
index 0000000000..921fb646e7
--- /dev/null
+++ b/ext/tk/lib/tkmngfocus.rb
@@ -0,0 +1,27 @@
+#
+# tkmngfocus.rb : methods for Tcl/Tk standard library 'focus.tcl'
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkManageFocus
+ extend Tk
+
+ def TkManageFocus.followsMouse
+ tk_call 'tk_focusFollowsMouse'
+ end
+
+ def TkManageFocus.next(window)
+ tk_call 'tk_focusNext', window
+ end
+ def focusNext
+ TkManageFocus.next(self)
+ end
+
+ def TkManageFocus.prev(window)
+ tk_call 'tk_focusPrev', window
+ end
+ def focusPrev
+ TkManageFocus.prev(self)
+ end
+end
diff --git a/ext/tk/lib/tkpalette.rb b/ext/tk/lib/tkpalette.rb
new file mode 100644
index 0000000000..a2dc7c87cb
--- /dev/null
+++ b/ext/tk/lib/tkpalette.rb
@@ -0,0 +1,48 @@
+#
+# tkpalette.rb : methods for Tcl/Tk standard library 'palette.tcl'
+# 1998/06/21 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+module TkPalette
+ include Tk
+ extend Tk
+
+ def TkPalette.set(*args)
+ args = args.to_a.flatten if args.kind_of? Hash
+ tk_call 'tk_setPalette', *args
+ end
+ def TkPalette.setPalette(*args)
+ TkPalette.set(*args)
+ end
+
+ def TkPalette.bisque
+ tk_call 'tk_bisque'
+ end
+
+ def TkPalette.darken(color, percent)
+ tk_call 'tkDarken', color, percent
+ end
+
+ def TkPalette.recolorTree(window, colors)
+ if not colors.kind_of?(Hash)
+ fail "2nd arg need to be Hash"
+ end
+
+ colors.each{|key, value|
+ begin
+ if window.cget(key) == tk_call('set', "tkPalette(#{key})")
+ window[key] = colors[key]
+ end
+ rescue
+ # ignore
+ end
+ }
+
+ TkWinfo.children(window).each{|w| TkPalette.recolorTree(w, colors)}
+ end
+
+ def recolorTree(colors)
+ TkPalette.recolorTree(self, colors)
+ end
+end
diff --git a/ext/tk/lib/tkscrollbox.rb b/ext/tk/lib/tkscrollbox.rb
new file mode 100644
index 0000000000..6236430491
--- /dev/null
+++ b/ext/tk/lib/tkscrollbox.rb
@@ -0,0 +1,29 @@
+#
+# tkscrollbox.rb - Tk Listbox with Scrollbar
+# as an example of Composite Widget
+# $Date$
+# by Yukihiro Matsumoto <matz@netlab.co.jp>
+
+require 'tk.rb'
+
+class TkScrollbox<TkListbox
+ include TkComposite
+ def initialize_composite(keys=nil)
+ list = TkListbox.new(@frame)
+ scroll = TkScrollbar.new(@frame)
+ @path = list.path
+
+ list.configure 'yscroll', scroll.path+" set"
+ list.pack 'side'=>'left','fill'=>'both','expand'=>'yes'
+ scroll.configure 'command', list.path+" yview"
+ scroll.pack 'side'=>'right','fill'=>'y'
+
+ delegate('DEFAULT', list)
+ delegate('foreground', list)
+ delegate('background', list, scroll)
+ delegate('borderwidth', @frame)
+ delegate('relief', @frame)
+
+ configure keys if keys
+ end
+end
diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb
new file mode 100644
index 0000000000..324af90f85
--- /dev/null
+++ b/ext/tk/lib/tktext.rb
@@ -0,0 +1,946 @@
+#
+# tktext.rb - Tk text classes
+# $Date$
+# by Yukihiro Matsumoto <matz@caelum.co.jp>
+
+require 'tk.rb'
+require 'tkfont'
+
+module TkTreatTextTagFont
+ def tagfont_configinfo(tag)
+ if tag.kind_of? TkTextTag
+ pathname = self.path + ';' + tag.id
+ else
+ pathname = self.path + ';' + tag
+ end
+ ret = TkFont.used_on(pathname)
+ if ret == nil
+ ret = TkFont.init_widget_font(pathname,
+ self.path, 'tag', 'configure', tag)
+ end
+ ret
+ end
+ alias tagfontobj tagfont_configinfo
+
+ def tagfont_configure(tag, slot)
+ if tag.kind_of? TkTextTag
+ pathname = self.path + ';' + tag.id
+ else
+ pathname = self.path + ';' + tag
+ end
+ if (fnt = slot['font'])
+ slot['font'] = nil
+ if fnt.kind_of? TkFont
+ return fnt.call_font_configure(pathname,
+ self.path,'tag','configure',tag,slot)
+ else
+ latintagfont_configure(tag, fnt) if fnt
+ end
+ end
+ if (ltn = slot['latinfont'])
+ slot['latinfont'] = nil
+ latintagfont_configure(tag, ltn) if ltn
+ end
+ if (ltn = slot['asciifont'])
+ slot['asciifont'] = nil
+ latintagfont_configure(tag, ltn) if ltn
+ end
+ if (knj = slot['kanjifont'])
+ slot['kanjifont'] = nil
+ kanjitagfont_configure(tag, knj) if knj
+ end
+
+ tk_call(self.path, 'tag', 'configure', tag, *hash_kv(slot)) if slot != {}
+ self
+ end
+
+ def latintagfont_configure(tag, ltn, keys=nil)
+ fobj = tagfontobj(tag)
+ if ltn.kind_of? TkFont
+ conf = {}
+ ltn.latin_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.latin_replace(ltn)
+ fobj.latin_configure(keys) if keys
+ elsif keys
+ fobj.latin_configure(conf.update(keys))
+ else
+ fobj.latin_configure(conf)
+ end
+ else
+ fobj.latin_replace(ltn)
+ end
+ end
+ alias asciitagfont_configure latintagfont_configure
+
+ def kanjitagfont_configure(tag, knj, keys=nil)
+ fobj = tagfontobj(tag)
+ if knj.kind_of? TkFont
+ conf = {}
+ knj.kanji_configinfo.each{|key,val| conf[key] = val if val != []}
+ if conf == {}
+ fobj.kanji_replace(knj)
+ fobj.kanji_configure(keys) if keys
+ elsif keys
+ fobj.kanji_configure(conf.update(keys))
+ else
+ fobj.kanji_configure(conf)
+ end
+ else
+ fobj.kanji_replace(knj)
+ end
+ end
+
+ def tagfont_copy(tag, window, wintag=nil)
+ if wintag
+ window.tagfontobj(wintag).configinfo.each{|key,value|
+ tagfontobj(tag).configure(key,value)
+ }
+ tagfontobj(tag).replace(window.tagfontobj(wintag).latin_font,
+ window.tagfontobj(wintag).kanji_font)
+ else
+ window.tagfont(wintag).configinfo.each{|key,value|
+ tagfontobj(tag).configure(key,value)
+ }
+ tagfontobj(tag).replace(window.fontobj.latin_font,
+ window.fontobj.kanji_font)
+ end
+ end
+
+ def latintagfont_copy(tag, window, wintag=nil)
+ if wintag
+ tagfontobj(tag).latin_replace(window.tagfontobj(wintag).latin_font)
+ else
+ tagfontobj(tag).latin_replace(window.fontobj.latin_font)
+ end
+ end
+ alias asciitagfont_copy latintagfont_copy
+
+ def kanjitagfont_copy(tag, window, wintag=nil)
+ if wintag
+ tagfontobj(tag).kanji_replace(window.tagfontobj(wintag).kanji_font)
+ else
+ tagfontobj(tag).kanji_replace(window.fontobj.kanji_font)
+ end
+ end
+end
+
+class TkText<TkTextWin
+ include TkTreatTextTagFont
+
+ WidgetClassName = 'Text'.freeze
+ TkClassBind::WidgetClassNameTBL[WidgetClassName] = self
+ def self.to_eval
+ WidgetClassName
+ end
+ include Scrollable
+ def create_self
+ tk_call 'text', @path
+ @tags = {}
+ end
+ def index(index)
+ tk_send 'index', index
+ end
+ def value
+ tk_send 'get', "1.0", "end - 1 char"
+ end
+ def value= (val)
+ tk_send 'delete', "1.0", 'end'
+ tk_send 'insert', "1.0", val
+ end
+ def _addcmd(cmd)
+ @cmdtbl.push cmd
+ end
+ def _addtag(name, obj)
+ @tags[name] = obj
+ end
+
+ def tagid2obj(tagid)
+ if not @tags[tagid]
+ tagid
+ else
+ @tags[tagid]
+ end
+ end
+
+ def tag_names(index=None)
+ tk_split_list(tk_send('tag', 'names', index)).collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+ def window_names
+ tk_send('window', 'names').collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+ def image_names
+ tk_send('image', 'names').collect{|elt|
+ tagid2obj(elt)
+ }
+ end
+
+ def set_insert(index)
+ tk_send 'mark', 'set', 'insert', index
+ end
+ def set_current(index)
+ tk_send 'mark', 'set', 'current', index
+ end
+
+ def insert(index, chars, *tags)
+ super index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')
+ end
+
+ def destroy
+ @tags.each_value do |t|
+ t.destroy
+ end
+ super
+ end
+
+ def backspace
+ self.delete 'insert'
+ end
+
+ def compare(idx1, op, idx2)
+ bool(tk_send('compare', idx1, op, idx2))
+ end
+
+ def debug
+ bool(tk_send('debug'))
+ end
+ def debug=(boolean)
+ tk_send 'debug', boolean
+ end
+
+ def bbox(index)
+ inf = tk_send('bbox', index)
+ (inf == "")? [0,0,0,0]: inf
+ end
+ def dlineinfo(index)
+ inf = tk_send('dlineinfo', index)
+ (inf == "")? [0,0,0,0,0]: inf
+ end
+
+ def yview(*what)
+ tk_send 'yview', *what
+ end
+ def yview_pickplace(*what)
+ tk_send 'yview', '-pickplace', *what
+ end
+
+ def xview(*what)
+ tk_send 'xview', *what
+ end
+ def xview_pickplace(*what)
+ tk_send 'xview', '-pickplace', *what
+ end
+
+ def tag_add(tag,index1,index2=None)
+ tk_send 'tag', 'add', tag, index1, index2
+ end
+
+ def _tag_bind_core(mode, tag, seq, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ tk_send 'tag', 'bind', tag, "<#{tk_event_sequence(seq)}>", mode + id
+ # _addcmd cmd
+ end
+ private :_tag_bind_core
+
+ def tag_bind(tag, seq, cmd=Proc.new, args=nil)
+ _tag_bind_core('', tag, seq, cmd, args=nil)
+ end
+
+ def tag_bind_append(tag, seq, cmd=Proc.new, args=nil)
+ _tag_bind_core('+', tag, seq, cmd, args=nil)
+ end
+
+ def tag_bindinfo(tag, context=nil)
+ if context
+ (tk_send('tag', 'bind', tag,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_send('tag', 'bind', tag)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def tag_cget(tag, key)
+ tk_tcl2ruby tk_call @path, 'tag', 'cget', tag, "-#{key}"
+ end
+
+ def tag_configure(tag, key, val=None)
+ if key.kind_of? Hash
+ if ( key['font'] || key['kanjifont'] \
+ || key['latinfont'] || key['asciifont'] )
+ tagfont_configure(tag, key.dup)
+ else
+ tk_send 'tag', 'configure', tag, *hash_kv(key)
+ end
+
+ else
+ if key == 'font' || key == 'kanjifont' ||
+ key == 'latinfont' || key == 'asciifont'
+ tagfont_configure({key=>val})
+ else
+ tk_send 'tag', 'configure', tag, "-#{key}", val
+ end
+ end
+ end
+
+ def tag_configinfo(tag, key=nil)
+ if key
+ conf = tk_split_list(tk_send('tag','configure',tag,"-#{key}"))
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_send('tag', 'configure', tag)).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+
+ def tag_raise(tag, above=None)
+ tk_send 'tag', 'raise', tag, above
+ end
+
+ def tag_lower(tag, below=None)
+ tk_send 'tag', 'lower', tag, below
+ end
+
+ def tag_remove(tag, *index)
+ tk_send 'tag', 'remove', tag, *index
+ end
+
+ def tag_ranges(tag)
+ l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
+ r = []
+ while key=l.shift
+ r.push [key, l.shift]
+ end
+ r
+ end
+
+ def tag_nextrange(tag, first, last=None)
+ tk_split_simplelist(tk_send('tag', 'nextrange', tag, first, last))
+ end
+
+ def tag_prevrange(tag, first, last=None)
+ tk_split_simplelist(tk_send('tag', 'prevrange', tag, first, last))
+ end
+
+ def search_with_length(pat,start,stop=None)
+ pat = pat.char if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'>=',stop)
+ txt = get(start,stop)
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(start + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(start + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get(start,'end - 1 char')
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(start + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(start + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.index(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def search(pat,start,stop=None)
+ search_with_length(pat,start,stop)[0]
+ end
+
+ def rsearch_with_length(pat,start,stop=None)
+ pat = pat.char if pat.kind_of? Integer
+ if stop != None
+ return ["", 0] if compare(start,'<=',stop)
+ txt = get(stop,start)
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index(stop + " + #{pos} chars"), pat.split('').length]
+ else
+ return [index(stop + " + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ else
+ txt = get('1.0',start)
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ txt = get('1.0','end - 1 char')
+ if (pos = txt.rindex(pat))
+ pos = txt[0..(pos-1)].split('').length if pos > 0
+ if pat.kind_of? String
+ return [index("1.0 + #{pos} chars"), pat.split('').length]
+ else
+ return [index("1.0 + #{pos} chars"), $&.split('').length]
+ end
+ else
+ return ["", 0]
+ end
+ end
+ end
+ end
+
+ def rsearch(pat,start,stop=None)
+ rsearch_with_length(pat,start,stop)[0]
+ end
+end
+
+class TkTextTag<TkObject
+ include TkTreatTagFont
+
+ $tk_text_tag = 'tag0000'
+ def initialize(parent, *args)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @parent = @t = parent
+ @path = @id = $tk_text_tag
+ $tk_text_tag = $tk_text_tag.succ
+ #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
+ if args != [] then
+ keys = args.pop
+ if keys.kind_of? Hash then
+ add(*args) if args != []
+ configure(keys)
+ else
+ args.push keys
+ add(*args)
+ end
+ end
+ @t._addtag id, self
+ end
+
+ def id
+ return @id
+ end
+
+ def first
+ @id + '.first'
+ end
+
+ def last
+ @id + '.last'
+ end
+
+ def add(*index)
+ tk_call @t.path, 'tag', 'add', @id, *index
+ end
+
+ def remove(*index)
+ tk_call @t.path, 'tag', 'remove', @id, *index
+ end
+
+ def ranges
+ l = tk_split_simplelist(tk_call(@t.path, 'tag', 'ranges', @id))
+ r = []
+ while key=l.shift
+ r.push [key, l.shift]
+ end
+ r
+ end
+
+ def nextrange(first, last=None)
+ tk_split_simplelist(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
+ end
+
+ def prevrange(first, last=None)
+ tk_split_simplelist(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
+ end
+
+ def [](key)
+ cget key
+ end
+
+ def []=(key,val)
+ configure key, val
+ end
+
+ def cget(key)
+ tk_tcl2ruby tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
+ end
+
+ def configure(key, val=None)
+ @t.tag_configure @id, key, val
+ end
+# def configure(key, val=None)
+# if key.kind_of? Hash
+# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
+# else
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
+# end
+# end
+# def configure(key, value)
+# if value == FALSE
+# value = "0"
+# elsif value.kind_of? Proc
+# value = install_cmd(value)
+# end
+# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
+# end
+
+ def configinfo(key=nil)
+ @t.tag_configinfo @id, key
+ end
+# def configinfo(key=nil)
+# if key
+# conf = tk_split_list(tk_call(@t.path, 'tag','configure',@id,"-#{key}"))
+# conf[0] = conf[0][1..-1]
+# conf
+# else
+# tk_split_list(tk_call(@t.path, 'tag', 'configure', @id)).collect{|conf|
+# conf[0] = conf[0][1..-1]
+# conf
+# }
+# end
+# end
+
+ def bind(seq, cmd=Proc.new, args=nil)
+ id = install_bind(cmd, args)
+ tk_call @t.path, 'tag', 'bind', @id, "<#{tk_event_sequence(seq)}>", id
+ # @t._addcmd cmd
+ end
+
+ def bindinfo(context=nil)
+ if context
+ (tk_call(@t.path, 'tag', 'bind', @id,
+ "<#{tk_event_sequence(context)}>")).collect{|cmdline|
+ if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ [Tk_CMDTBL[$1], $2]
+ else
+ cmdline
+ end
+ }
+ else
+ tk_split_list(tk_call(@t.path, 'tag', 'bind', @id)).filter{|seq|
+ seq[1..-2].gsub(/></,',')
+ }
+ end
+ end
+
+ def raise(above=None)
+ tk_call @t.path, 'tag', 'raise', @id, above
+ end
+
+ def lower(below=None)
+ tk_call @t.path, 'tag', 'lower', @id, below
+ end
+
+ def destroy
+ tk_call @t.path, 'tag', 'delete', @id
+ end
+end
+
+class TkTextTagSel<TkTextTag
+ def initialize(parent, keys=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'sel'
+ #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
+ configure(keys) if keys
+ @t._addtag id, self
+ end
+end
+
+class TkTextMark<TkObject
+ $tk_text_mark = 'mark0000'
+ def initialize(parent, index)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = $tk_text_mark
+ $tk_text_mark = $tk_text_mark.succ
+ tk_call @t.path, 'mark', 'set', @id, index
+ @t._addtag id, self
+ end
+ def id
+ return @id
+ end
+
+ def set(where)
+ tk_call @t.path, 'mark', 'set', @id, where
+ end
+
+ def unset
+ tk_call @t.path, 'mark', 'unset', @id
+ end
+ alias destroy unset
+
+ def gravity
+ tk_call @t.path, 'mark', 'gravity', @id
+ end
+
+ def gravity=(direction)
+ tk_call @t.path, 'mark', 'gravity', @id, direction
+ end
+end
+
+class TkTextMarkInsert<TkTextMark
+ def initialize(parent, index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'insert'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
+class TkTextMarkCurrent<TkTextMark
+ def initialize(parent,index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'current'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
+class TkTextMarkAnchor<TkTextMark
+ def initialize(parent,index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'anchor'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
+class TkTextWindow<TkObject
+ def initialize(parent, index, keys)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ if index == 'end'
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ elsif index.kind_of? TkTextMark
+ if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ @id = keys['window']
+ if keys['create']
+ @p_create = keys['create']
+ if @p_create.kind_of? Proc
+ keys['create'] = install_cmd(proc{@id = @p_create.call; @id.path})
+ end
+ end
+ tk_call @t.path, 'window', 'create', @index, *hash_kv(keys)
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call @t.path, 'window', 'cget', @index, "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ @id = slot['window'] if slot['window']
+ if slot['create']
+ self.create=value
+ slot['create']=nil
+ end
+ if slot.size > 0
+ tk_call @t.path, 'window', 'configure', @index, *hash_kv(slot)
+ end
+ else
+ @id = value if slot == 'window'
+ if slot == 'create'
+ self.create=value
+ else
+ tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value
+ end
+ end
+ end
+
+ def window
+ @id
+ end
+
+ def window=(value)
+ tk_call @t.path, 'window', 'configure', @index, '-window', value
+ @id = value
+ end
+
+ def create
+ @p_create
+ end
+
+ def create=(value)
+ @p_create = value
+ if @p_create.kind_of? Proc
+ value = install_cmd(proc{@id = @p_create.call})
+ end
+ tk_call @t.path, 'window', 'configure', @index, '-create', value
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ conf = tk_split_list(tk_call @t.path, 'window', 'configure',
+ @index, "-#{slot}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call @t.path, 'window', 'configure',
+ @index).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+
+ def _dump(type, *index)
+ str = tk_send('dump', type, *index)
+ result = []
+ sel = nil
+ i = 0
+ while i < str.size
+ # retrieve key
+ idx = str.index(/ /, i)
+ result.push str[i..(idx-1)]
+ i = idx + 1
+
+ # retrieve value
+ case result[-1]
+ when 'text'
+ if str[i] == ?{
+ # text formed as {...}
+ val, i = _retrieve_braced_text(str, i)
+ result.push val
+ else
+ # text which may contain backslahes
+ val, i = _retrieve_backslashed_text(str, i)
+ result.push val
+ end
+ else
+ idx = str.index(/ /, i)
+ val = str[i..(idx-1)]
+ case result[-1]
+ when 'mark'
+ case val
+ when 'insert'
+ result.push TkTextMarkInsert.new(self)
+ when 'current'
+ result.push TkTextMarkCurrent.new(self)
+ when 'anchor'
+ result.push TkTextMarkAnchor.new(self)
+ else
+ result.push tk_tcl2rb(val)
+ end
+ when 'tagon'
+ if val == 'sel'
+ if sel
+ result.push sel
+ else
+ result.push TkTextTagSel.new(self)
+ end
+ else
+ result.push tk_tcl2rb val
+ end
+ when 'tagoff'
+ result.push tk_tcl2rb sel
+ when 'window'
+ result.push tk_tcl2rb val
+ end
+ i = idx + 1
+ end
+
+ # retrieve index
+ idx = str.index(/ /, i)
+ if idx
+ result.push str[i..(idx-1)]
+ i = idx + 1
+ else
+ result.push str[i..-1]
+ break
+ end
+ end
+
+ kvis = []
+ until result.empty?
+ kvis.push [result.shift, result.shift, result.shift]
+ end
+ kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
+ end
+ private :_dump
+
+ def _retrieve_braced_text(str, i)
+ cnt = 0
+ idx = i
+ while idx < str.size
+ case str[idx]
+ when ?{
+ cnt += 1
+ when ?}
+ cnt -= 1
+ if cnt == 0
+ break
+ end
+ end
+ idx += 1
+ end
+ return str[i+1..idx-1], idx + 2
+ end
+ private :_retrieve_braced_text
+
+ def _retrieve_backslashed_text(str, i)
+ j = i
+ idx = nil
+ loop {
+ idx = str.index(/ /, j)
+ if str[idx-1] == ?\\
+ j += 1
+ else
+ break
+ end
+ }
+ val = str[i..(idx-1)]
+ val.gsub!(/\\( |\{|\})/, '\1')
+ return val, idx + 1
+ end
+ private :_retrieve_backslashed_text
+
+ def dump_all(*index)
+ _dump('-all', *index)
+ end
+ def dump_mark(*index)
+ _dump('-mark', *index)
+ end
+ def dump_tag(*index)
+ _dump('-tag', *index)
+ end
+ def dump_text(*index)
+ _dump('-text', *index)
+ end
+ def dump_window(*index)
+ _dump('-window', *index)
+ end
+end
+
+class TkTextImage<TkObject
+ def initialize(parent, index, keys)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ if index == 'end'
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ elsif index.kind_of? TkTextMark
+ if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
+ end
+ else
+ @path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
+ end
+ @path.gravity = 'left'
+ @index = @path.path
+ @id = tk_call(@t.path, 'image', 'create', @index, *hash_kv(keys))
+ end
+
+ def [](slot)
+ cget(slot)
+ end
+ def []=(slot, value)
+ configure(slot, value)
+ end
+
+ def cget(slot)
+ tk_tcl2ruby tk_call @t.path, 'image', 'cget', @index, "-#{slot}"
+ end
+
+ def configure(slot, value=None)
+ if slot.kind_of? Hash
+ tk_call @t.path, 'image', 'configure', @index, *hash_kv(slot)
+ else
+ tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
+ end
+ end
+# def configure(slot, value)
+# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
+# end
+
+ def image
+ tk_call @t.path, 'image', 'configure', @index, '-image'
+ end
+
+ def image=(value)
+ tk_call @t.path, 'image', 'configure', @index, '-image', value
+ end
+
+ def configinfo(slot = nil)
+ if slot
+ conf = tk_split_list(tk_call @t.path, 'image', 'configure',
+ @index, "-#{slot}")
+ conf[0] = conf[0][1..-1]
+ conf
+ else
+ tk_split_list(tk_call @t.path, 'image', 'configure',
+ @index).collect{|conf|
+ conf[0] = conf[0][1..-1]
+ conf
+ }
+ end
+ end
+end
diff --git a/ext/tk/lib/tkvirtevent.rb b/ext/tk/lib/tkvirtevent.rb
new file mode 100644
index 0000000000..0d100c2186
--- /dev/null
+++ b/ext/tk/lib/tkvirtevent.rb
@@ -0,0 +1,66 @@
+#
+# tkvirtevent.rb : treats virtual events
+# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
+#
+require 'tk'
+
+class TkVirtualEvent<TkObject
+ extend Tk
+
+ TkVirturlEventID = [0]
+ TkVirturlEventTBL = {}
+
+ def TkVirtualEvent.getobj(event)
+ obj = TkVirturlEventTBL[event]
+ obj ? obj : event
+ end
+
+ def TkVirtualEvent.info
+ tk_call('event', 'info').split(/\s+/).filter{|seq|
+ TkVirtualEvent.getobj(seq[1..-2])
+ }
+ end
+
+ def initialize(*sequences)
+ @path = @id = format("<VirtEvent%.4d>", TkVirturlEventID[0])
+ TkVirturlEventID[0] += 1
+ add(*sequences)
+ end
+
+ def add(*sequences)
+ if sequences != []
+ tk_call('event', 'add', "<#{@id}>",
+ *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
+ TkVirturlEventTBL[@id] = self
+ end
+ self
+ end
+
+ def delete(*sequences)
+ if sequences == []
+ tk_call('event', 'delete', "<#{@id}>")
+ TkVirturlEventTBL[@id] = nil
+ else
+ tk_call('event', 'delete', "<#{@id}>",
+ *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) )
+ TkVirturlEventTBL[@id] = nil if info == []
+ end
+ self
+ end
+
+ def info
+ tk_call('event', 'info', "<#{@id}>").split(/\s+/).filter{|seq|
+ l = seq.scan(/<*[^<>]+>*/).filter{|subseq|
+ case (subseq)
+ when /^<<[^<>]+>>$/
+ TkVirtualEvent.getobj(subseq[1..-2])
+ when /^<[^<>]+>$/
+ subseq[1..-2]
+ else
+ subseq.split('')
+ end
+ }.flatten
+ (l.size == 1) ? l[0] : l
+ }
+ end
+end
diff --git a/ext/tk/sample/tkbiff.rb b/ext/tk/sample/tkbiff.rb
new file mode 100644
index 0000000000..d2d7bf7beb
--- /dev/null
+++ b/ext/tk/sample/tkbiff.rb
@@ -0,0 +1,149 @@
+#! /usr/local/bin/ruby
+
+if ARGV[0] != '-d'
+ unless $DEBUG
+ exit if fork
+ end
+else
+ ARGV.shift
+end
+
+if ARGV.length == 0
+ if ENV['MAIL']
+ $spool = ENV['MAIL']
+ else
+ $spool = '/usr/spool/mail/' + ENV['USER']
+ end
+else
+ $spool = ARGV[0]
+end
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.kind_of?(IO)
+ f = open(f, "r")
+ me = super
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ next if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+require "tkscrollbox"
+
+$top = TkRoot.new
+$top.withdraw
+$list = TkScrollbox.new($top) {
+ relief 'raised'
+ width 80
+ height 8
+ setgrid 'yes'
+ pack
+}
+TkButton.new($top) {
+ text 'Dismiss'
+ command proc {$top.withdraw}
+ pack('fill'=>'both','expand'=>'yes')
+}
+$top.bind "Control-c", proc{exit}
+$top.bind "Control-q", proc{exit}
+$top.bind "space", proc{exit}
+
+$spool_size = 0
+$check_time = Time.now
+
+def check
+ $check_time = Time.now
+ size = File.size($spool)
+ if size and size != $spool_size
+ $spool_size = size
+ pop_up if size > 0
+ end
+ Tk.after 5000, proc{check}
+end
+
+if defined? Thread
+ Thread.start do
+ loop do
+ sleep 600
+ if Time.now - $check_time > 200
+ Tk.after 5000, proc{check}
+ end
+ end
+ end
+end
+
+def pop_up
+ outcount = 0;
+ $list.delete 0, 'end'
+ f = open($spool, "r")
+ while !f.eof?
+ mail = Mail.new(f)
+ date, from, subj = mail.header['Date'], mail.header['From'], mail.header['Subject']
+ next if !date
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" if ! from
+ subj = "(nil)" if ! subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ $list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ outcount += 1
+ end
+ f.close
+ if outcount == 0
+ $list.insert 'end', "You have no mail."
+ else
+ $list.see 'end'
+ end
+ $top.deiconify
+ Tk.after 2000, proc{$top.withdraw}
+end
+
+$list.insert 'end', "You have no mail."
+check
+Tk.after 2000, proc{$top.withdraw}
+begin
+ Tk.mainloop
+rescue
+ `echo #$! > /tmp/tkbiff`
+end
diff --git a/ext/tk/sample/tkbrowse.rb b/ext/tk/sample/tkbrowse.rb
new file mode 100644
index 0000000000..882f0a489b
--- /dev/null
+++ b/ext/tk/sample/tkbrowse.rb
@@ -0,0 +1,79 @@
+#!/usr/local/bin/ruby
+#
+# This script generates a directory browser, which lists the working
+# directory and allows you to open files or subdirectories by
+# double-clicking.
+
+# Create a scrollbar on the right side of the main window and a listbox
+# on the left side.
+
+require "tkscrollbox"
+
+# The procedure below is invoked to open a browser on a given file; if the
+# file is a directory then another instance of this program is invoked; if
+# the file is a regular file then the Mx editor is invoked to display
+# the file.
+
+$dirlist = {}
+
+def browsedir (dir)
+ if $dirlist.key? dir
+ $dirlist[dir]
+ else
+ top = if $dirlist.size > 0 then TkToplevel.new else nil end
+ list = TkScrollbox.new(top) {
+ relief 'raised'
+ width 20
+ height 20
+ setgrid 'yes'
+ pack
+ }
+ list.insert 'end', *`ls #{dir}`.split
+
+ # Set up bindings for the browser.
+
+ list.focus
+ list.bind "Control-q", proc{exit}
+ list.bind "Control-c", proc{exit}
+ list.bind "Control-p", proc{
+ print "selection <", TkSelection.get, ">\n"
+ }
+
+ list.bind "Double-Button-1", proc{
+ for i in TkSelection.get.split
+ print "clicked ", i, "\n"
+ browse dir, i
+ end
+ }
+ $dirlist[dir] = list
+ end
+end
+
+def browse (dir, file)
+ file="#{dir}/#{file}"
+ if File.directory? file
+ browsedir(file)
+ else
+ if File.file? file
+ if ENV['EDITOR']
+ system format("%s %s&", ENV['EDITOR'], file)
+ else
+ system "xedit #{file}&"
+ end
+ else
+ STDERR.print "\"#{file}\" isn't a directory or regular file"
+ end
+ end
+end
+
+# Fill the listbox with a list of all the files in the directory (run
+# the "ls" command to get that information).
+
+if ARGV.length>0
+ dir = ARGV[0]
+else
+ dir="."
+end
+
+browsedir(dir)
+Tk.mainloop
diff --git a/ext/tk/sample/tkdialog.rb b/ext/tk/sample/tkdialog.rb
new file mode 100644
index 0000000000..e83e16d0a8
--- /dev/null
+++ b/ext/tk/sample/tkdialog.rb
@@ -0,0 +1,62 @@
+#! /usr/local/bin/ruby
+require "tk"
+
+root = TkFrame.new
+top = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+msg = TkMessage.new(top) {
+ text "File main.c hasn't been saved to disk since \
+it was last modified. What should I do?"
+ justify 'center'
+ aspect 200
+ font '-Adobe-helvetica-medium-r-normal--*-240*'
+ pack('padx'=>5, 'pady'=>5, 'expand'=>'yes')
+}
+top.pack('fill'=>'both')
+root.pack
+
+bot = TkFrame.new(root) {
+ relief 'raised'
+ border 1
+}
+
+TkFrame.new(bot) { |left|
+ relief 'sunken'
+ border 1
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10, 'pady'=> 10)
+ TkButton.new(left) {
+ text "Save File"
+ command "quit 'save'"
+ pack('expand'=>'yes','padx'=>6,'pady'=> 6)
+ top.bind "Enter", proc{state 'active'}
+ msg.bind "Enter", proc{state 'active'}
+ bot.bind "Enter", proc{state 'active'}
+ top.bind "Leave", proc{state 'normal'}
+ msg.bind "Leave", proc{state 'normal'}
+ bot.bind "Leave", proc{state 'normal'}
+ Tk.root.bind "ButtonRelease-1", proc{quit 'save'}
+ Tk.root.bind "Return", proc{quit 'save'}
+ }
+}
+TkButton.new(bot) {
+ text "Quit Anyway"
+ command "quit 'quit'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+TkButton.new(bot) {
+ text "Return To Editor"
+ command "quit 'return'"
+ pack('side'=>'left', 'expand'=>'yes', 'padx'=>10)
+}
+bot.pack
+root.pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
+
+def quit(button)
+ print "aaa\n"
+ print "You pressed the \"#{button}\" button; bye-bye!\n"
+ exit
+end
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkfrom.rb b/ext/tk/sample/tkfrom.rb
new file mode 100644
index 0000000000..ba0e547799
--- /dev/null
+++ b/ext/tk/sample/tkfrom.rb
@@ -0,0 +1,132 @@
+#! /usr/local/bin/ruby
+
+require "parsedate"
+require "base64"
+
+include ParseDate
+
+class Mail
+ def Mail.new(f)
+ if !f.kind_of?(IO)
+ f = open(f, "r")
+ me = super(f)
+ f.close
+ else
+ me = super
+ end
+ return me
+ end
+
+ def initialize(f)
+ @header = {}
+ @body = []
+ while f.gets()
+ $_.chop!
+ next if /^From / # skip From-line
+ break if /^$/ # end of header
+ if /^(\S+):\s*(.*)/
+ @header[attr = $1.capitalize] = $2
+ elsif attr
+ sub(/^\s*/, '')
+ @header[attr] += "\n" + $_
+ end
+ end
+
+ return if ! $_
+
+ while f.gets()
+ break if /^From /
+ @body.push($_)
+ end
+ end
+
+ def header
+ return @header
+ end
+
+ def body
+ return @body
+ end
+
+end
+
+if ARGV.length == 0
+ if ENV['MAIL']
+ ARGV[0] = ENV['MAIL']
+ elsif ENV['USER']
+ ARGV[0] = '/usr/spool/mail/' + ENV['USER']
+ elsif ENV['LOGNAME']
+ ARGV[0] = '/usr/spool/mail/' + ENV['LOGNAME']
+ end
+end
+
+require "tk"
+list = scroll = nil
+TkFrame.new{|f|
+ list = TkListbox.new(f) {
+ yscroll proc{|idx|
+ scroll.set *idx
+ }
+ relief 'raised'
+# geometry "80x5"
+ width 80
+ height 5
+ setgrid 'yes'
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+ }
+ scroll = TkScrollbar.new(f) {
+ command proc{|idx|
+ list.yview *idx
+ }
+ pack('side'=>'right','fill'=>'y')
+ }
+ pack
+}
+root = Tk.root
+TkButton.new(root) {
+ text 'Dismiss'
+ command proc {exit}
+ pack('fill'=>'both','expand'=>'yes')
+}
+root.bind "Control-c", proc{exit}
+root.bind "Control-q", proc{exit}
+root.bind "space", proc{exit}
+
+$outcount = 0;
+for file in ARGV
+ next if File.exist?(file)
+ atime = File.atime(file)
+ mtime = File.mtime(file)
+ f = open(file, "r")
+ begin
+ until f.eof
+ mail = Mail.new(f)
+ date = mail.header['Date']
+ next unless date
+ from = mail.header['From']
+ subj = mail.header['Subject']
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" unless from
+ subj = "(nil)" unless subj
+ from = decode_b(from)
+ subj = decode_b(subj)
+ list.insert 'end', format('%-02d/%02d/%02d [%-28.28s] %s',y,m,d,from,subj)
+ $outcount += 1
+ end
+ ensure
+ f.close
+ File.utime(atime, mtime, file)
+ list.see 'end'
+ end
+end
+
+limit = 10000
+if $outcount == 0
+ list.insert 'end', "You have no mail."
+ limit = 2000
+end
+Tk.after limit, proc{
+ exit
+}
+Tk.mainloop
diff --git a/ext/tk/sample/tkhello.rb b/ext/tk/sample/tkhello.rb
new file mode 100644
index 0000000000..5188fe1c8c
--- /dev/null
+++ b/ext/tk/sample/tkhello.rb
@@ -0,0 +1,10 @@
+require "tk"
+
+TkButton.new(nil,
+ 'text' => 'hello',
+ 'command' => proc{print "hello\n"}).pack('fill'=>'x')
+TkButton.new(nil,
+ 'text' => 'quit',
+ 'command' => 'exit').pack('fill'=>'x')
+
+Tk.mainloop
diff --git a/ext/tk/sample/tkline.rb b/ext/tk/sample/tkline.rb
new file mode 100644
index 0000000000..2406b0749f
--- /dev/null
+++ b/ext/tk/sample/tkline.rb
@@ -0,0 +1,45 @@
+
+require "tkclass"
+
+$tkline_init = FALSE
+def start_random
+ return if $tkline_init
+ $tkline_init = TRUE
+ if defined? Thread
+ Thread.start do
+ loop do
+ sleep 2
+ Line.new($c, rand(400), rand(200), rand(400), rand(200))
+ end
+ end
+ end
+end
+
+$c = Canvas.new
+$c.pack
+$start_x = start_y = 0
+
+def do_press(x, y)
+ $start_x = x
+ $start_y = y
+ $current_line = Line.new($c, x, y, x, y)
+ start_random
+end
+def do_motion(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ end
+end
+
+def do_release(x, y)
+ if $current_line
+ $current_line.coords $start_x, $start_y, x, y
+ $current_line.fill 'black'
+ $current_line = nil
+ end
+end
+
+$c.bind("1", proc{|e| do_press e.x, e.y})
+$c.bind("B1-Motion", proc{|x, y| do_motion x, y}, "%x %y")
+$c.bind("ButtonRelease-1", proc{|x, y| do_release x, y}, "%x %y")
+Tk.mainloop
diff --git a/ext/tk/sample/tktimer.rb b/ext/tk/sample/tktimer.rb
new file mode 100644
index 0000000000..34377e2f39
--- /dev/null
+++ b/ext/tk/sample/tktimer.rb
@@ -0,0 +1,50 @@
+#!/usr/local/bin/ruby
+# This script generates a counter with start and stop buttons.
+
+require "tk"
+$label = TkLabel.new {
+ text '0.00'
+ relief 'raised'
+ width 10
+ pack('side'=>'bottom', 'fill'=>'both')
+}
+
+TkButton.new {
+ text 'Start'
+ command proc {
+ if $stopped
+ $stopped = FALSE
+ tick
+ end
+ }
+ pack('side'=>'left','fill'=>'both','expand'=>'yes')
+}
+TkButton.new {
+ text 'Stop'
+ command proc{
+ exit if $stopped
+ $stopped = TRUE
+ }
+ pack('side'=>'right','fill'=>'both','expand'=>'yes')
+}
+
+$seconds=0
+$hundredths=0
+$stopped=TRUE
+
+def tick
+ if $stopped then return end
+ Tk.after 50, proc{tick}
+ $hundredths+=5
+ if $hundredths >= 100
+ $hundredths=0
+ $seconds+=1
+ end
+ $label.text format("%d.%02d", $seconds, $hundredths)
+end
+
+root = Tk.root
+root.bind "Control-c", proc{root.destroy}
+root.bind "Control-q", proc{root.destroy}
+Tk.root.focus
+Tk.mainloop
diff --git a/ext/tk/tkutil.c b/ext/tk/tkutil.c
new file mode 100644
index 0000000000..9d4ca0a9d0
--- /dev/null
+++ b/ext/tk/tkutil.c
@@ -0,0 +1,45 @@
+/************************************************
+
+ tk.c -
+
+ $Author$
+ $Date$
+ created at: Fri Nov 3 00:47:54 JST 1995
+
+************************************************/
+
+#include "ruby.h"
+
+static VALUE
+tk_eval_cmd(argc, argv)
+ int argc;
+ VALUE argv[];
+{
+ VALUE cmd, rest;
+
+ rb_scan_args(argc, argv, "1*", &cmd, &rest);
+ return rb_eval_cmd(cmd, rest);
+}
+
+static VALUE
+tk_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = rb_class_new_instance(argc, argv, klass);
+
+ if (rb_iterator_p()) rb_obj_instance_eval(0, 0, obj);
+ return obj;
+}
+
+void
+Init_tkutil()
+{
+ VALUE mTK = rb_define_module("TkUtil");
+ VALUE cTK = rb_define_class("TkKernel", rb_cObject);
+
+ rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1);
+
+ rb_define_singleton_method(cTK, "new", tk_s_new, -1);
+}