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 +#include +#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 +#else +# ifdef HAVE_CURSES_COLR_CURSES_H +# include +# include # else # include # 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 +#endif #include #include #include @@ -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 similarity index 98% rename from ext/etc/etc.doc rename to 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 + $top_srcdir = File.expand_path($top_srcdir) end -$topdir = ".." -if $topdir !~ "^/" - # get absolute path - save = Dir.pwd - Dir.chdir $topdir - $topdir = Dir.pwd - Dir.chdir save -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_cpp - xsystem(format(CPP, $CFLAGS)) +def try_link(src, opt="") + begin + try_link0(src, opt) + ensure + system "rm -f conftest*" + end end -def install_rb(mfile) +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 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 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 +#include int main() { return 0; } -int t() { %s(); return 0; } -", func - cfile.close - - begin - if $libs - libs = "-l" + lib + " " + $libs - else - libs = "-l" + lib +int t() { #{func}(); return 0; } +SRC + unless r + r = try_link(<<"SRC", libs) +#include +#include +int main() { return 0; } +int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; } +SRC end - unless try_link(libs) - $lib_cache[lib] = 'no' - $cache_mod = TRUE - return FALSE - 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 + $lib_cache[lib] = 'no' + $cache_mod = true + return false end else - if $libs - libs = "-l" + lib + " " + $libs - else - libs = "-l" + lib - end + 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 +#include +int main() { return 0; } +int t() { #{func}(); return 0; } +SRC + unless r + r = try_link(<<"SRC", libs) +#include +#include +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 create_makefile(target) +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 - if $libs and "@DLEXT@" == "o" + $CFLAGS += idir if idir + $LDFLAGS += ldir if ldir +end + +def create_makefile(target) + $target = target + + 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" - end + if RUBY_PLATFORM =~ /beos/ + $libs = $libs + " -lruby" $DLDFLAGS = $DLDFLAGS + " -L" + $topdir end - $srcdir = $top_srcdir + "/ext/" + target + 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/" + $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 < /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 -#include -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 -#include -//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 +void Init_fcntl() { VALUE mFcntl = rb_define_module("Fcntl"); diff --git a/ext/marshal/MANIFEST b/ext/gdbm/MANIFEST similarity index 55% rename from ext/marshal/MANIFEST rename to 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 +#include +#include +#ifdef USE_CWGUSI +# include +#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; iptr; + 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 -#include - -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; ilen; 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; ilen; 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; ilen; 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; iptr[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; iptr[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; iptr[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(>k_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;iptr[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;iptr[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> (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;isymbol, 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; iptr[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 0) { - if (c > sizeof(long)) long_toobig((int)c); - x = 0; - for (i=0;i sizeof(long)) long_toobig((int)c); - x = -1; - for (i=0;ifp) { - 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; iptr[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 similarity index 83% rename from ext/md5/md5.doc rename to 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; @@ -45,11 +46,29 @@ md5_digest(obj) return rb_str_new(digest, 16); } +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= 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 similarity index 64% rename from ext/kconv/kconv.c rename to 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) -** 連絡先: (株)富士通研究所 ソフト3研 市川 至 -** (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#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 +#endif #if defined(MSDOS) || defined(__OS2__) #include @@ -126,10 +111,8 @@ static char *Patchlevel = #include #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 int file_out = FALSE; +static int add_cr = FALSE; +static int del_cr = FALSE; -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 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= *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,61 +462,163 @@ 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= *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; + } + } +} + +#ifndef PERL_XS +static void +noconvert(f) + FILE *f; +{ + int c; + + while ((c = getc(f)) != EOF) + putchar(c); +} +#endif + + +static void +kanji_convert(f) + FILE *f; +{ + int c1, c2; c2 = 0; - 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; - } - - 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; - } - if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) { estab_f = TRUE; iconv = oconv; } else if(input_f == SJIS_INPUT) { @@ -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) { @@ -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> 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' ';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 '@') @@ -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= 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 ** 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] +M1FERED"6GIAR(%-E8V]N9"!3=&%G92"8I9=Y($AI +M#28./ +>@Y*#DR!+:6=O=2"!18&'@D^"8(._@]:$081@A+X* +eofeof +#' + +example['euc'] = <<'eofeof'.unpack('u')[0] +M1FERI?*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 +MHCK>.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.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.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 +M5)!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(&-A5)!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(&-AB1./RD;*$)H5)! +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(&-AB1./RD;*$)HB1./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(&-AB1./RD;*$)HB1./RD[=ALH0@H;)$(T +603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`* +eofeof +#" + +example['mime.base64'] = <<'eofeof'.unpack('u')[0] +M9W-M5"])3&YG$I+-&=Q=4,S24LS9W%Q0E%:3TUI-39,,S0Q-&=S5T)1 +M43!+9VUA1%9O3T@*9S)+1%1O3'=K8C)1;$E+;V=Q2T-X24MG9W5M0W%*3EEG +<$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)$2P@1$5.34%22R`@7"`B36EN(&OF<&AEX0208 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 +#include +#include +#include +#include +#include +#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#else +#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +#endif +#include + +#include +#include + +#include +#ifdef HAVE_SYS_STROPTS_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#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 +#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 +#include +#ifdef MSDOS +#include +#endif +#include +#include +#ifdef BSD42 +#include +#else +#include +/*#include */ +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#include +#ifndef EPERM +#define EPERM EACCES +#endif +#include + +#ifdef __STDC__ +#include +#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 */ +#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 +#include +#ifdef USE_CWGUSI +# include +#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; iptr; + 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(< +#include +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", < +#ifdef IPV6_INRIA_VERSION +yes +#endif +EOF + $ipv6type = "inria" + $CFLAGS="-DINET6 "+$CFLAGS + elsif egrep_cpp("yes", < +#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", < +#ifdef _TOSHIBA_INET6 +yes +#endif +EOF + $ipv6type = "toshiba" + $ipv6lib="inet6" + $ipv6libdir="/usr/local/v6/lib" + $CFLAGS="-DINET6 "+$CFLAGS + elsif egrep_cpp("yes", < +#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", < +#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 < +#include +#include +#include +#include +int +main() +{ + struct sockaddr_in sin; + + sin.sin_len; + return 0; +} +EOF + $CFLAGS="-DHAVE_SIN_LEN "+$CFLAGS +end + + if try_link(< +#include +#include +#include +#include +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(< +#include +#include +#include +#include + +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 < +#ifndef NT +#include +#endif +#ifdef HAVE_SYSCTL_H +#include +#endif +#ifndef NT +#include +#include +#include +#if defined(HAVE_ARPA_NAMESER_H) +#include +#endif +#include +#if defined(HAVE_RESOLV_H) +#include +#endif +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include + +#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 +#ifndef NT +#include +#include +#include +#if defined(HAVE_ARPA_NAMESER_H) +#include +#endif +#include +#if defined(HAVE_RESOLV_H) +#include +#endif +#endif +#ifdef NT +#include +#include +#define snprintf _snprintf +#endif + +#include +#include + +#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 #endif -#if defined(USE_THREAD) && defined(HAVE_FCNTL) +#if defined(HAVE_FCNTL) #ifdef HAVE_SYS_SELECT_H #include #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]; + return do_not_reverse_lookup?Qtrue:Qfalse; +} - 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); +static VALUE +bsock_do_not_rev_lookup_set(self, val) +{ + do_not_reverse_lookup = RTEST(val); + return val; +} + +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)); + } +} + +static VALUE +mkipaddr(addr) + struct sockaddr *addr; +{ + char buf[1024]; + + mkipaddr0(addr, buf, sizeof(buf)); return rb_str_new2(buf); } +static void +mkinetaddr(host, buf, len) + long host; + char *buf; + size_t len; +{ + 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); + + mkinetaddr(htonl(i), hbuf, sizeof(hbuf)); + } + else { + char *name = STR2CSTR(host); + + if (*name == 0) { + mkinetaddr(INADDR_ANY, hbuf, sizeof(hbuf)); + } + else if (name[0] == '<' && strcmp(name, "") == 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; +} + +static void +setipaddr(name, addr) + VALUE name; + struct sockaddr *addr; +{ + struct addrinfo *res = ip_addrsetup(name, Qnil); + + /* just take the first one */ + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); +} + static VALUE ipaddr(sockaddr) - struct sockaddr_in *sockaddr; + struct sockaddr *sockaddr; { VALUE family, port, addr1, addr2; VALUE ary; - struct hostent *hostent; + int error; + char hbuf[1024], pbuf[1024]; - 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); + 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; } - addr2 = mkipaddr(sockaddr->sin_addr.s_addr); - if (!addr1) addr1 = addr2; - - port = INT2FIX(ntohs(sockaddr->sin_port)); + 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); + } + 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)); + } + 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; } -#ifndef HAVE_INET_ATON -static unsigned long -inet_aton(host, inp) - char *host; - struct in_addr *inp; -{ - int d1, d2, d3, d4; - char ch; - - 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; - } - return 0; -} -#endif - static void -setipaddr(name, addr) - char *name; - struct sockaddr_in *addr; +thread_write_select(fd) + int fd; { - struct hostent *hp; + fd_set fds; - if (name[0] == 0) { - addr->sin_addr.s_addr = INADDR_ANY; - } - else if (name[0] == '<' && strcmp(name, "") == 0) { - addr->sin_addr.s_addr = INADDR_BROADCAST; - } - else if (inet_aton(name, &addr->sin_addr) != 0) { - /* ok to set addr->sin_addr */ - } - 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 - } - memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length); - } + FD_ZERO(&fds); + FD_SET(fd, &fds); + rb_thread_select(fd+1, 0, &fds, 0, 0); } -#if defined(USE_THREAD) && defined(HAVE_FCNTL) static int -thread_connect(fd, sockaddr, len, type) +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); + } + } + return fd; +} + +static int +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; + else { + host = 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); - } - - 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); + 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)); - } - else -#endif - { - status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); - } -#endif - syscall = "connect(2)"; + 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; + } + 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)"; + } + + 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; + if (rb_scan_args(argc, argv, "01", &arg) == 1) { + socktype = NUM2INT(arg); } - else if (rb_obj_is_kind_of(host, rb_cInteger)) { - int i = NUM2INT(host); - addr->sin_addr.s_addr = htonl(i); + fd = ruby_socket(socktype, SOCK_DGRAM, 0); + if (fd < 0) { + rb_sys_fail("socket(2) - udp"); } - else { - setipaddr(STR2CSTR(host), addr); - } - if (FIXNUM_P(port)) { - addr->sin_port = htons(FIX2INT(port)); - } - 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)); @@ -1425,23 +1526,74 @@ mkhostent(h) return ary; } +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); + 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_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_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_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_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_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_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_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 +dir_config("tk") +dir_config("tcl") +dir_config("X11") + +tklib = with_config("tklib") +tcllib = with_config("tcllib") + +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 -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") - -$CFLAGS = $includes.collect{|path| "-I" + path}.join(" ") - -$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 #include #include #include +#include "ruby.h" +#include "rubysig.h" #ifdef __MACOS__ # include # include #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; + + Tk_DeleteTimerHandler(timer_token); + timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, + (ClientData)0); - timer->flag = 0; CHECK_INTS; -#ifdef USE_THREAD - if (!rb_thread_critical) rb_thread_schedule(); -#endif - - timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl, - (ClientData)timer); - timer->flag = 1; + 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; +#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_ExternalToUtfDString(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_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr); + str = rb_str_new2(Tcl_DStringValue(&dstr)); - Tcl_FreeEncoding(encoding); - Tcl_DStringFree(&dstr); - - return rb_str_new2(buff2); + 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 = (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[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); + 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); + /* 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; ireturn_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 + +# 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(/>", *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 "", @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 TkVarAccessvalue}) + 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 TkWindowval}) + 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 +# +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 +# +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 +# $Date$ +# by Hidetoshi Nagai + +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", 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(/>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 + +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 + +require 'tk.rb' + +class TkEntry@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 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 +# +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 +# +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 + +require 'tk.rb' + +class TkScrollbox'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 + +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", 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(/>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", 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(/> 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 +# +require 'tk' + +class TkVirtualEvent", 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); +}