summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-06-09 09:21:37 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-06-09 09:21:37 +0000
commitc1241cd2ed230573bb81b52173d6cd2bd91176f2 (patch)
treecaa3babd9a35b930814fffa9c8ebb3366d46dae8 /ext
parent17ae11ca25d210da8c7deeeee0f03fd1a09ee0b2 (diff)
thread bugs
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_3@482 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/extmk.rb.in31
-rw-r--r--ext/md5/md5init.c24
-rw-r--r--ext/pty/pty.c4
-rw-r--r--ext/readline/extconf.rb1
-rw-r--r--ext/socket/addrinfo.h3
-rw-r--r--ext/socket/depend4
-rw-r--r--ext/socket/extconf.rb9
-rw-r--r--ext/socket/getnameinfo.c28
-rw-r--r--ext/socket/socket.c46
-rw-r--r--ext/socket/sockport.h6
-rw-r--r--ext/tcltklib/tcltklib.c131
-rw-r--r--ext/tk/lib/tktext.rb165
12 files changed, 361 insertions, 91 deletions
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index c564b59b70..8090c2ab19 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -324,6 +324,19 @@ def create_makefile(target)
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
end
+ defflag = ''
+ if PLATFORM =~ /cygwin/ and not $static
+ if File.exist? target + ".def"
+ defflag = "--def=" + target + ".def"
+ end
+ if $libs
+ $libs = $libs + " @LIBRUBYARG@"
+ else
+ $libs = "@LIBRUBYARG@"
+ end
+ $DLDFLAGS = $DLDFLAGS + " -L" + $topdir
+ end
+
$srcdir = $top_srcdir + "/ext/" + $mdir
mfile = open("Makefile", "w")
mfile.printf "\
@@ -342,7 +355,7 @@ CC = @CC@
prefix = @prefix@
CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s
DLDFLAGS = #$DLDFLAGS #$LDFLAGS
-LDSHARED = @LDSHARED@
+LDSHARED = @LDSHARED@ #{defflag}
", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
mfile.printf "\
@@ -367,7 +380,7 @@ archdir = $(pkglibdir)/@arch@
$objs = []
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{|})})$/, "o")
$objs.push f
end
end
@@ -418,23 +431,21 @@ $(DLLIB): $(OBJS)
$(DLLIB): $(OBJS)
$(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
"
- elsif not SRC_EXT.detect{|ext| File.exist?(target + ext)}
- if PLATFORM == "m68k-human"
- mfile.printf "\
+ elsif PLATFORM == "m68k-human"
+ mfile.printf "\
$(DLLIB): $(OBJS)
ar cru $(DLLIB) $(OBJS)
"
- elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
- mfile.printf "\
+ elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
+ mfile.printf "\
$(DLLIB): $(OBJS)
cc -r $(CFLAGS) -o $(DLLIB) $(OBJS)
"
- else
- mfile.printf "\
+ else
+ mfile.printf "\
$(DLLIB): $(OBJS)
ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
"
- end
end
if File.exist?("depend")
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
index e95e135812..e63258f3f1 100644
--- a/ext/md5/md5init.c
+++ b/ext/md5/md5init.c
@@ -29,8 +29,9 @@ md5_update(obj, str)
Data_Get_Struct(obj, MD5_CTX, md5);
MD5Update(md5, str->ptr, str->len);
- return Qnil;
+ return obj;
}
+
static VALUE
md5_digest(obj)
VALUE obj;
@@ -46,6 +47,26 @@ md5_digest(obj)
}
static VALUE
+md5_hexdigest(obj)
+ VALUE obj;
+{
+ MD5_CTX *md5, ctx;
+ unsigned char digest[16];
+ char buf[35];
+ char *p = buf;
+ int i;
+
+ Data_Get_Struct(obj, MD5_CTX, md5);
+ ctx = *md5;
+ MD5Final(digest, &ctx);
+
+ for (i=0; i<16; i++) {
+ sprintf(buf+i*2, "%x", digest[i]);
+ }
+ return rb_str_new(buf, 32);
+}
+
+static VALUE
md5_clone(obj)
VALUE obj;
{
@@ -90,5 +111,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/pty/pty.c b/ext/pty/pty.c
index 0d3ba7f060..6462c3c7ca 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -19,6 +19,10 @@
#include <sys/stropts.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#define DEVICELEN 16
#if !defined(HAVE_OPENPTY)
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index 0bd11bb946..f532f8a21d 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -16,6 +16,7 @@ if readline_dir
$LDFLAGS = "-L#{readline_dir}"
end
+have_library("user32", nil) if /cygwin/ === PLATFORM
have_library("termcap", "tgetnum")
have_library("curses", "tgetnum")
if have_header("readline/readline.h") and
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
index 724f800c79..74fae207b9 100644
--- a/ext/socket/addrinfo.h
+++ b/ext/socket/addrinfo.h
@@ -27,6 +27,8 @@
* SUCH DAMAGE.
*/
+#ifndef ADDR_INFO_H
+#define ADDR_INFO_H
#ifndef HAVE_GETADDRINFO
/* special compatibility hack */
@@ -167,3 +169,4 @@ Standard C system should have one. */
#endif
#endif
+#endif
diff --git a/ext/socket/depend b/ext/socket/depend
index 09e851498e..df2f0c5d16 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -1,3 +1,3 @@
socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
-getaddrinfo.o: getaddrinfo.c addrinfo.h sockport.h
-getnameinfo.o: getnameinfo.c addrinfo.h sockport.h
+getnameinfo.o: getnameinfo.c $(hdrdir)/config.h addrinfo.h sockport.h
+getaddrinfo.o: getaddrinfo.c $(hdrdir)/config.h addrinfo.h sockport.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 37d8de5cbb..1e41c02261 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -6,8 +6,11 @@ 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")
@@ -252,8 +255,8 @@ if have_getaddrinfo
$CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
else
$CFLAGS="-I. "+$CFLAGS
- $objs += "getaddrinfo.o"
- $objs += "getnameinfo.o"
+ $objs += ["getaddrinfo.o"]
+ $objs += ["getnameinfo.o"]
have_func("inet_ntop") or have_func("inet_ntoa")
have_func("inet_pton") or have_func("inet_aton")
end
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index f4da5bbf7a..5af329225c 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -61,6 +61,12 @@
#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;
@@ -68,18 +74,18 @@ static struct afd {
int a_off;
} afdl [] = {
#ifdef INET6
- {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
- offsetof(struct sockaddr_in6, sin6_addr)},
+#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},
-};
-
-struct sockinet {
- u_char si_len;
- u_char si_family;
- u_short si_port;
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0, 0},
};
#define ENI_NOSOCKET 0
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index dda7eb06fc..0912ca9dd1 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -583,6 +583,21 @@ thread_write_select(fd)
}
static int
+ruby_socket(domain, type, proto)
+ int domain, type, proto;
+{
+ int fd;
+
+ fd = socket(domain, type, proto);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = socket(domain, type, proto);
+ }
+ }
+}
+
+static int
ruby_connect(fd, sockaddr, len, socks)
int fd;
struct sockaddr *sockaddr;
@@ -683,11 +698,12 @@ open_inet(class, h, serv, type)
fd = -1;
for (res = res0; res; res = res->ai_next) {
- status = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
syscall = "socket(2)";
fd = status;
- if (fd < 0)
+ if (fd < 0) {
continue;
+ }
if (type == INET_SERVER) {
status = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
@@ -939,8 +955,10 @@ 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)");
+ }
MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
@@ -1017,11 +1035,17 @@ udp_s_open(argc, argv, class)
{
VALUE arg;
int socktype = AF_INET;
+ int fd;
if (rb_scan_args(argc, argv, "01", &arg) == 1) {
socktype = NUM2INT(arg);
}
- return sock_new(class, socket(socktype, SOCK_DGRAM, 0));
+ fd = ruby_socket(socktype, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2) - udp");
+ }
+
+ return sock_new(class, fd);
}
static VALUE
@@ -1312,7 +1336,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);
@@ -1333,8 +1357,14 @@ sock_s_socketpair(class, domain, type, protocol)
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
@@ -1920,6 +1950,8 @@ Init_socket()
#endif
#ifdef AF_INET6
sock_define_const("AF_INET6", AF_INET6);
+#endif
+#ifdef PF_INET6
sock_define_const("PF_INET6", PF_INET6);
#endif
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
index 3a2007362f..99bec91a1a 100644
--- a/ext/socket/sockport.h
+++ b/ext/socket/sockport.h
@@ -1,6 +1,6 @@
/************************************************
- sockcomm.h -
+ sockport.h -
$Author$
$Date$
@@ -8,8 +8,8 @@
************************************************/
-#ifndef SOCKCOMM_H
-#define SOCKCOMM_H
+#ifndef SOCKPORT_H
+#define SOCKPORT_H
#ifndef SA_LEN
# ifdef HAVE_SA_LEN
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
index 5f6f9a0c02..6652b9409a 100644
--- a/ext/tcltklib/tcltklib.c
+++ b/ext/tcltklib/tcltklib.c
@@ -30,6 +30,8 @@ fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
static VALUE eTkCallbackBreak;
static VALUE eTkCallbackContinue;
+static VALUE ip_invoke_real _((int, VALUE*, VALUE));
+
/* from tkAppInit.c */
/*
@@ -42,55 +44,47 @@ int *tclDummyMathPtr = (int *) matherr;
/*---- module TclTkLib ----*/
-/* Tk_ThreadTimer */
-typedef struct {
- Tcl_TimerToken token;
- int flag;
-} Tk_TimerData;
-
-/* timer callback */
-static void
-_timer_for_tcl(clientData)
- ClientData clientData;
-{
- Tk_TimerData *timer = (Tk_TimerData*)clientData;
+static VALUE main_thread;
- timer->flag = 0;
- CHECK_INTS;
+struct invoke_queue {
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+ int done;
+ VALUE result;
+ VALUE thread;
+ struct invoke_queue *next;
+};
- if (timer->flag) {
- Tk_DeleteTimerHandler(timer->token);
- }
- timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
- (ClientData)timer);
- timer->flag = 1;
-}
+static struct invoke_queue *iqueue;
/* execute Tk_MainLoop */
static VALUE
lib_mainloop(self)
VALUE self;
{
- Tk_TimerData *timer;
-
- timer = (Tk_TimerData *)ALLOC(Tk_TimerData);
- timer->flag = 0;
- timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
- (ClientData)timer);
- timer->flag = 1;
+ struct invoke_queue *q, *tmp;
+ VALUE thread;
DUMP1("start Tk_Mainloop");
while (Tk_GetNumMainWindows() > 0) {
- Tcl_DoOneEvent(0);
+ Tcl_DoOneEvent(TCL_DONT_WAIT);
CHECK_INTS;
+ q = iqueue;
+ while (q) {
+ tmp = q;
+ q = q->next;
+ if (!tmp->done) {
+ tmp->done = 1;
+ tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj);
+ thread = tmp->thread;
+ tmp = tmp->next;
+ rb_thread_run(thread);
+ }
+ }
}
DUMP1("stop Tk_Mainloop");
- if (timer->flag) {
- Tk_DeleteTimerHandler(timer->token);
- }
- free(timer);
-
return Qnil;
}
@@ -206,11 +200,11 @@ ip_new(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,
@@ -324,14 +318,13 @@ ip_fromUTF8(self, str, encodename)
static VALUE
-ip_invoke(argc, argv, 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;
@@ -350,13 +343,10 @@ ip_invoke(argc, argv, 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
+ if (info.isNativeObjectProc) {
/* object interface */
ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
for (i = 0; i < argc; ++i) {
@@ -365,8 +355,10 @@ ip_invoke(argc, argv, obj)
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) {
@@ -381,8 +373,8 @@ ip_invoke(argc, argv, obj)
Tcl_ResetResult(ptr->ip);
/* Invoke the C procedure */
- if (object) {
#if TCL_MAJOR_VERSION >= 8
+ if (info.isNativeObjectProc) {
int dummy;
ptr->return_value = (*info.objProc)(info.objClientData,
ptr->ip, argc, ov);
@@ -395,9 +387,10 @@ ip_invoke(argc, argv, obj)
for (i=0; i<argc; i++) {
Tcl_DecrRefCount(ov[i]);
}
-#endif
}
- else {
+ else
+#endif
+ {
ptr->return_value = (*info.proc)(info.clientData,
ptr->ip, argc, av);
}
@@ -410,6 +403,51 @@ ip_invoke(argc, argv, obj)
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(self)
@@ -454,6 +492,7 @@ 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/lib/tktext.rb b/ext/tk/lib/tktext.rb
index 3dde30d60d..3d8e4fa405 100644
--- a/ext/tk/lib/tktext.rb
+++ b/ext/tk/lib/tktext.rb
@@ -285,8 +285,8 @@ class TkText<TkTextWin
end
else
- if ( key == 'font' || key == 'kanjifont' \
- || key == 'latinfont' || key == 'asciifont' )
+ if key == 'font' || key == 'kanjifont' ||
+ key == 'latinfont' || key == 'asciifont'
tagfont_configure({key=>val})
else
tk_send 'tag', 'configure', tag, "-#{key}", val
@@ -320,7 +320,7 @@ class TkText<TkTextWin
end
def tag_ranges(tag)
- l = tk_split_list(tk_send('tag', 'ranges', tag))
+ l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
r = []
while key=l.shift
r.push [key, l.shift]
@@ -329,11 +329,11 @@ class TkText<TkTextWin
end
def tag_nextrange(tag, first, last=None)
- tk_split_list(tk_send('tag', 'nextrange', tag, first, last))
+ tk_split_simplelist(tk_send('tag', 'nextrange', tag, first, last))
end
def tag_prevrange(tag, first, last=None)
- tk_split_list(tk_send('tag', 'prevrange', tag, first, last))
+ tk_split_simplelist(tk_send('tag', 'prevrange', tag, first, last))
end
def search_with_length(pat,start,stop=None)
@@ -437,9 +437,19 @@ class TkTextTag<TkObject
@path = @id = $tk_text_tag
$tk_text_tag = $tk_text_tag.succ
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
- configure(keys) if keys
+ if args != [] then
+ keys = args.pop
+ if keys.kind_of? Hash then
+ add(*args) if args != []
+ configure(keys)
+ else
+ args.push keys
+ add(*args)
+ end
+ end
@t._addtag id, self
end
+
def id
return @id
end
@@ -470,11 +480,11 @@ class TkTextTag<TkObject
end
def nextrange(first, last=None)
- tk_split_list(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
+ tk_split_simplelist(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
end
def prevrange(first, last=None)
- tk_split_list(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
+ tk_split_simplelist(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
end
def [](key)
@@ -631,6 +641,18 @@ class TkTextMarkCurrent<TkTextMark
end
end
+class TkTextMarkAnchor<TkTextMark
+ def initialize(parent,index=nil)
+ if not parent.kind_of?(TkText)
+ fail format("%s need to be TkText", parent.inspect)
+ end
+ @t = parent
+ @path = @id = 'anchor'
+ tk_call @t.path, 'mark', 'set', @id, index if index
+ @t._addtag id, self
+ end
+end
+
class TkTextWindow<TkObject
def initialize(parent, index, keys)
if not parent.kind_of?(TkText)
@@ -726,6 +748,133 @@ class TkTextWindow<TkObject
}
end
end
+
+ def _dump(type, *index)
+ str = tk_send('dump', type, *index)
+ result = []
+ sel = nil
+ i = 0
+ while i < str.size
+ # retrieve key
+ idx = str.index(/ /, i)
+ result.push str[i..(idx-1)]
+ i = idx + 1
+
+ # retrieve value
+ case result[-1]
+ when 'text'
+ if str[i] == ?{
+ # text formed as {...}
+ val, i = _retrieve_braced_text(str, i)
+ result.push val
+ else
+ # text which may contain backslahes
+ val, i = _retrieve_backslashed_text(str, i)
+ result.push val
+ end
+ else
+ idx = str.index(/ /, i)
+ val = str[i..(idx-1)]
+ case result[-1]
+ when 'mark'
+ case val
+ when 'insert'
+ result.push TkTextMarkInsert.new(self)
+ when 'current'
+ result.push TkTextMarkCurrent.new(self)
+ when 'anchor'
+ result.push TkTextMarkAnchor.new(self)
+ else
+ result.push tk_tcl2rb(val)
+ end
+ when 'tagon'
+ if val == 'sel'
+ if sel
+ result.push sel
+ else
+ result.push TkTextTagSel.new(self)
+ end
+ else
+ result.push tk_tcl2rb val
+ end
+ when 'tagoff'
+ result.push tk_tcl2rb sel
+ when 'window'
+ result.push tk_tcl2rb val
+ end
+ i = idx + 1
+ end
+
+ # retrieve index
+ idx = str.index(/ /, i)
+ if idx
+ result.push str[i..(idx-1)]
+ i = idx + 1
+ else
+ result.push str[i..-1]
+ break
+ end
+ end
+
+ kvis = []
+ until result.empty?
+ kvis.push [result.shift, result.shift, result.shift]
+ end
+ kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
+ end
+ private :_dump
+
+ def _retrieve_braced_text(str, i)
+ cnt = 0
+ idx = i
+ while idx < str.size
+ case str[idx]
+ when ?{
+ cnt += 1
+ when ?}
+ cnt -= 1
+ if cnt == 0
+ break
+ end
+ end
+ idx += 1
+ end
+ return str[i+1..idx-1], idx + 2
+ end
+ private :_retrieve_braced_text
+
+ def _retrieve_backslashed_text(str, i)
+ j = i
+ idx = nil
+ loop {
+ idx = str.index(/ /, j)
+ if str[idx-1] == ?\\
+ j += 1
+ else
+ break
+ end
+ }
+ val = str[i..(idx-1)]
+ val.gsub!(/\\( |\{|\})/, '\1')
+ return val, idx + 1
+ end
+ private :_retrieve_backslashed_text
+
+ def dump_all(*index)
+ _dump('-all', *index)
+ end
+ def dump_mark(*index)
+ _dump('-mark', *index)
+ end
+ def dump_tag(*index)
+ _dump('-tag', *index)
+ end
+ def dump_text(*index)
+ _dump('-text', *index)
+ end
+ def dump_window(*index)
+ _dump('-window', *index)
+ end
end
class TkTextImage<TkObject