summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--MANIFEST1
-rw-r--r--eval.c110
-rw-r--r--lib/tk.rb13
-rw-r--r--lib/tkmenubar.rb137
5 files changed, 198 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index f78f96e9fa..4b03cf9a12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
Wed Jan 21 01:43:42 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+ * eval.c (PUSH_FRAME): do not use ALLOCA_N(). crash on some
+ platforms (such as HP-UX or mswin32).
+
* regex.c (re_compile_pattern): too many pops for non register subexpr.
* parse.y (yylex): open parentheses after identifiers are argument
diff --git a/MANIFEST b/MANIFEST
index aa629eeb08..27bb946f50 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -120,6 +120,7 @@ lib/tkcanvas.rb
lib/tkclass.rb
lib/tkdialog.rb
lib/tkentry.rb
+lib/tkmenubar.rb
lib/tkscrollbox.rb
lib/tktext.rb
lib/tracer.rb
diff --git a/eval.c b/eval.c
index e4b5feb7f2..ace4cd18f2 100644
--- a/eval.c
+++ b/eval.c
@@ -283,15 +283,15 @@ static struct FRAME *top_frame;
static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
- struct FRAME *_frame = ALLOCA_N(struct FRAME,1);\
- _frame->prev = the_frame; \
- _frame->file = sourcefile; \
- _frame->line = sourceline; \
- _frame->iter = the_iter->iter; \
- _frame->cbase = the_frame->cbase; \
- the_frame = _frame; \
+ struct FRAME _frame; \
+ _frame.prev = the_frame; \
+ _frame.file = sourcefile; \
+ _frame.line = sourceline; \
+ _frame.iter = the_iter->iter; \
+ _frame.cbase = the_frame->cbase; \
+ the_frame = &_frame; \
-#define POP_FRAME() the_frame = _frame->prev; }
+#define POP_FRAME() the_frame = _frame.prev; }
struct BLOCK {
NODE *var;
@@ -310,29 +310,29 @@ struct BLOCK {
} *the_block;
#define PUSH_BLOCK(v,b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- _block->tag = prot_tag; \
- _block->var = v; \
- _block->body = b; \
- _block->self = self; \
- _block->frame = *the_frame; \
- _block->class = the_class; \
- _block->frame.file = sourcefile; \
- _block->frame.line = sourceline; \
- _block->scope = the_scope; \
- _block->d_vars = the_dyna_vars; \
- _block->prev = the_block; \
- _block->iter = the_iter->iter; \
- the_block = _block;
+ struct BLOCK _block; \
+ _block.tag = prot_tag; \
+ _block.var = v; \
+ _block.body = b; \
+ _block.self = self; \
+ _block.frame = *the_frame; \
+ _block.class = the_class; \
+ _block.frame.file = sourcefile; \
+ _block.frame.line = sourceline; \
+ _block.scope = the_scope; \
+ _block.d_vars = the_dyna_vars; \
+ _block.prev = the_block; \
+ _block.iter = the_iter->iter; \
+ the_block = &_block;
#define PUSH_BLOCK2(b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- *_block = *b; \
- _block->prev = the_block; \
- the_block = _block;
+ struct BLOCK _block; \
+ _block = *b; \
+ _block.prev = the_block; \
+ the_block = &_block;
#define POP_BLOCK() \
- the_block = the_block->prev; \
+ the_block = _block.prev; \
}
struct RVarmap *the_dyna_vars;
@@ -417,38 +417,26 @@ static struct iter {
the_iter = _iter.prev; \
}
-#ifdef C_ALLOCA
-/* need to protect retval in struct tag from GC. */
-#define tag_retval_dcl VALUE *dd_retval
-#define tag_retval_init VALUE _tag_retval = Qnil;\
- _tag->dd_retval = &_tag_retval;
-#define tag_retval dd_retval[0]
-#else
-#define tag_retval_dcl VALUE retval
-#define tag_retval_init _tag->retval = Qnil
-#define tag_retval retval
-#endif
-
static struct tag {
jmp_buf buf;
struct FRAME *frame;
struct iter *iter;
ID tag;
- tag_retval_dcl;
+ VALUE retval;
ID dst;
struct tag *prev;
} *prot_tag;
#define PUSH_TAG(ptag) { \
- struct tag *_tag = ALLOCA_N(struct tag,1);\
- tag_retval_init; \
- _tag->frame = the_frame; \
- _tag->iter = the_iter; \
- _tag->prev = prot_tag; \
- _tag->tag_retval = Qnil; \
- _tag->tag = ptag; \
- _tag->dst = 0; \
- prot_tag = _tag;
+ struct tag _tag; \
+ _tag.retval = Qnil; \
+ _tag.frame = the_frame; \
+ _tag.iter = the_iter; \
+ _tag.prev = prot_tag; \
+ _tag.retval = Qnil; \
+ _tag.tag = ptag; \
+ _tag.dst = 0; \
+ prot_tag = &_tag;
#define PROT_NONE 0
#define PROT_FUNC -1
@@ -463,7 +451,7 @@ static struct tag {
}
#define POP_TAG() \
- prot_tag = _tag->prev; \
+ prot_tag = _tag.prev; \
}
#define TAG_RETURN 0x1
@@ -1373,7 +1361,7 @@ call_trace_func(event, file, line, self, id)
prev = the_frame;
PUSH_FRAME();
- *the_frame = *_frame->prev;
+ *the_frame = *_frame.prev;
the_frame->prev = prev;
the_frame->line = sourceline = line;
@@ -1608,7 +1596,7 @@ rb_eval(self, node)
else if (the_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
}
}
POP_TAG();
@@ -2579,7 +2567,7 @@ f_raise(argc, argv)
}
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
+ *the_frame = *_frame.prev->prev;
rb_longjmp(TAG_RAISE, mesg, arg3);
POP_FRAME();
}
@@ -2806,7 +2794,7 @@ rb_iterate(it_proc, data1, bl_proc, data2)
if (the_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- retval = prot_tag->tag_retval;
+ retval = prot_tag->retval;
}
}
POP_TAG();
@@ -2979,7 +2967,7 @@ f_missing(argc, argv, obj)
sourcefile = file;
sourceline = line;
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
+ *the_frame = *_frame.prev->prev;
NameError(format,
rb_id2name(id),
@@ -3312,7 +3300,7 @@ rb_call(class, recv, mid, argc, argv, scope)
result = rb_eval(recv, body);
}
else if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
state = 0;
}
POP_VARS();
@@ -3655,8 +3643,8 @@ eval_under(under, self, src)
PUSH_CLASS();
the_class = under;
PUSH_FRAME();
- the_frame->last_func = _frame->last_func;
- the_frame->last_class = _frame->last_class;
+ the_frame->last_func = _frame.last_func;
+ the_frame->last_class = _frame.last_class;
the_frame->argc = 1;
the_frame->argv = &src;
the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase);
@@ -5741,7 +5729,7 @@ f_catch(dmy, tag)
val = rb_yield(tag);
}
else if (state == TAG_THROW && prot_tag->tag == prot_tag->dst) {
- val = prot_tag->tag_retval;
+ val = prot_tag->retval;
state = 0;
}
POP_TAG();
@@ -5765,7 +5753,7 @@ f_throw(argc, argv)
while (tt) {
if (tt->tag == t) {
tt->dst = t;
- tt->tag_retval = value;
+ tt->retval = value;
break;
}
#ifdef THREAD
@@ -5793,7 +5781,7 @@ return_value(val)
while (tt) {
if (tt->tag == PROT_FUNC) {
- tt->tag_retval = val;
+ tt->retval = val;
break;
}
#ifdef THREAD
diff --git a/lib/tk.rb b/lib/tk.rb
index 1a3ae2933d..8bb6c7f842 100644
--- a/lib/tk.rb
+++ b/lib/tk.rb
@@ -972,6 +972,7 @@ class TkRoot<TkWindow
return ROOT[0] if ROOT[0]
new = super
ROOT[0] = new
+ Tk_WINDOWS["."] = new
end
def create_self
@path = '.'
@@ -1229,12 +1230,12 @@ module TkComposite
@delegates = {}
@delegates['DEFAULT'] = @frame
end
- if option.kind_of?(String)
- @delegates[option] = wins
- else
- for i in option
- @delegates[i] = wins
+ if @delegates[option].kind_of?(Array)
+ for i in wins
+ @delegates[option].push(i)
end
+ else
+ @delegates[option] = wins
end
end
@@ -1261,3 +1262,5 @@ autoload :TkBitmapImage, 'tkcanvas'
autoload :TkPhotoImage, 'tkcanvas'
autoload :TkEntry, 'tkentry'
autoload :TkText, 'tktext'
+autoload :TkDialog, 'tkdialog'
+autoload :TkMenubar, 'tkmenubar'
diff --git a/lib/tkmenubar.rb b/lib/tkmenubar.rb
new file mode 100644
index 0000000000..441f3f5c03
--- /dev/null
+++ b/lib/tkmenubar.rb
@@ -0,0 +1,137 @@
+#
+# tkmenubar.rb
+#
+# Copyright (C) 1998 maeda shugo. All rights reserved.
+# This file can be distributed under the terms of the Ruby.
+
+# Usage:
+#
+# menu_spec = [
+# [['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]],
+# [['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]]
+# ]
+# menubar = TkMenubar.new(nil, menu_spec,
+# 'tearoff'=>false,
+# 'foreground'=>'grey40',
+# 'activeforeground'=>'red',
+# 'font'=>'-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+#
+#
+# OR
+#
+#
+# menubar = TkMenubar.new
+# menubar.add_menu([['File', 0],
+# ['Open', proc{puts('Open clicked')}, 0],
+# '---',
+# ['Quit', proc{exit}, 0]])
+# menubar.add_menu([['Edit', 0],
+# ['Cut', proc{puts('Cut clicked')}, 2],
+# ['Copy', proc{puts('Copy clicked')}, 0],
+# ['Paste', proc{puts('Paste clicked')}, 0]])
+# menubar.configure('tearoff', false)
+# menubar.configure('foreground', 'grey40')
+# menubar.configure('activeforeground', 'red')
+# menubar.configure('font', '-adobe-helvetica-bold-r-*--12-*-iso8859-1')
+# menubar.pack('side'=>'top', 'fill'=>'x')
+
+# The format of the menu_spec is:
+# [
+# [
+# [button text, underline, accelerator],
+# [menu label, command, underline, accelerator],
+# '---', # separator
+# ...
+# ],
+# ...
+# ]
+
+# underline and accelerator are optional parameters.
+# Hashes are OK instead of Arrays.
+
+# To use add_menu, configuration must be done by calling configure after
+# adding all menus by add_menu, not by the constructor arguments.
+
+require "tk"
+
+class TkMenubar<TkFrame
+
+ include TkComposite
+
+ def initialize(parent = nil, spec = nil, options = nil)
+ super(parent, options)
+
+ @menus = []
+
+ if spec
+ for menu_info in spec
+ add_menu(menu_info)
+ end
+ end
+
+ if options
+ for key, value in options
+ configure(key, value)
+ end
+ end
+ end
+
+ def add_menu(menu_info)
+ btn_info = menu_info.shift
+ mbtn = TkMenubutton.new(@frame)
+
+ if btn_info.kind_of?(Hash)
+ for key, value in btn_info
+ mbtn.configure(key, value)
+ end
+ elsif btn_info.kind_of?(Array)
+ mbtn.configure('text', btn_info[0]) if btn_info[0]
+ mbtn.configure('underline', btn_info[1]) if btn_info[1]
+ mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
+ else
+ mbtn.configure('text', btn_info)
+ end
+
+ menu = TkMenu.new(mbtn)
+
+ for item_info in menu_info
+ if item_info.kind_of?(Hash)
+ menu.add('command', item_info)
+ elsif item_info.kind_of?(Array)
+ options = {}
+ options['label'] = item_info[0] if item_info[0]
+ options['command'] = item_info[1] if item_info[1]
+ options['underline'] = item_info[2] if item_info[2]
+ options['accelerator'] = item_info[3] if item_info[3]
+ menu.add('command', options)
+ elsif /^-+$/ =~ item_info
+ menu.add('sep')
+ else
+ menu.add('command', 'label' => item_info)
+ end
+ end
+
+ mbtn.menu(menu)
+ @menus.push([mbtn, menu])
+ delegate('tearoff', menu)
+ delegate('foreground', mbtn, menu)
+ delegate('background', mbtn, menu)
+ delegate('disabledforeground', mbtn, menu)
+ delegate('activeforeground', mbtn, menu)
+ delegate('activebackground', mbtn, menu)
+ delegate('font', mbtn, menu)
+ delegate('kanjifont', mbtn, menu)
+ mbtn.pack('side' => 'left')
+ end
+
+ def [](index)
+ return @menus[index]
+ end
+end