tk-win 0.2.1-x86-mingw32 → 0.2.2-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +11 -10
- data/VERSION +1 -1
- data/lib/multi-tk.rb +3740 -0
- data/lib/remote-tk.rb +530 -0
- data/lib/tk/busy.rb +118 -0
- data/lib/tk/fontchooser.rb +176 -0
- data/lib/tkextlib/tcllib/README +135 -0
- data/lib/tkextlib/tcllib/calendar.rb +55 -0
- data/lib/tkextlib/tcllib/canvas_sqmap.rb +36 -0
- data/lib/tkextlib/tcllib/canvas_zoom.rb +21 -0
- data/lib/tkextlib/tcllib/chatwidget.rb +151 -0
- data/lib/tkextlib/tcllib/crosshair.rb +117 -0
- data/lib/tkextlib/tcllib/dateentry.rb +62 -0
- data/lib/tkextlib/tcllib/diagrams.rb +224 -0
- data/lib/tkextlib/tcllib/khim.rb +68 -0
- data/lib/tkextlib/tcllib/menuentry.rb +47 -0
- data/lib/tkextlib/tcllib/ntext.rb +146 -0
- data/lib/tkextlib/tcllib/scrolledwindow.rb +57 -0
- data/lib/tkextlib/tcllib/statusbar.rb +79 -0
- data/lib/tkextlib/tcllib/toolbar.rb +175 -0
- data/lib/tkextlib/tile/tspinbox.rb +107 -0
- data/lib/tkextlib/tkimg/README +26 -0
- data/tk-win.gemspec +26 -6
- metadata +27 -8
data/Rakefile
CHANGED
@@ -5,18 +5,19 @@ require 'rake'
|
|
5
5
|
begin
|
6
6
|
require 'jeweler'
|
7
7
|
Jeweler::Tasks.new do |gem|
|
8
|
-
gem.name
|
9
|
-
gem.summary
|
10
|
-
gem.description
|
11
|
-
gem.email
|
12
|
-
gem.homepage
|
13
|
-
gem.authors
|
14
|
-
|
8
|
+
gem.name = "tk-win"
|
9
|
+
gem.summary = %Q{RubyTk bindings for MS Windows RubyInstaller 1.9.1 bundled with binaries.}
|
10
|
+
gem.description = %Q{RubyTk bindings for windows bundled with tcltklib.so and tkutil.so for windows RubyInstaller 1.9.1}
|
11
|
+
gem.email = "elia.schito@gmail.com"
|
12
|
+
gem.homepage = "http://www.dumbo.ai.kyutech.ac.jp/nagai/RubyTk/?Ruby%2FTk-Kit"
|
13
|
+
gem.authors = ["Hidetoshi Nagai", "Elia Schito"]
|
14
|
+
|
15
15
|
gem.required_ruby_version = "~> 1.9.1"
|
16
|
-
gem.platform
|
17
|
-
gem.require_paths
|
18
|
-
gem.files
|
16
|
+
gem.platform = "x86-mingw32"
|
17
|
+
gem.require_paths += Dir["lib/#{gem.platform}"]
|
18
|
+
gem.files += Dir["lib/#{gem.platform}/*.so"]
|
19
19
|
|
20
|
+
gem.add_development_dependency "rspec", "~> 1.2.9"
|
20
21
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
21
22
|
end
|
22
23
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/lib/multi-tk.rb
ADDED
@@ -0,0 +1,3740 @@
|
|
1
|
+
#
|
2
|
+
# multi-tk.rb - supports multi Tk interpreters
|
3
|
+
# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
4
|
+
|
5
|
+
require 'tcltklib'
|
6
|
+
require 'tkutil'
|
7
|
+
require 'thread'
|
8
|
+
|
9
|
+
if defined? Tk
|
10
|
+
fail RuntimeError,"'multi-tk' library must be required before requiring 'tk'"
|
11
|
+
end
|
12
|
+
|
13
|
+
################################################
|
14
|
+
# ignore exception on the mainloop?
|
15
|
+
|
16
|
+
TclTkLib.mainloop_abort_on_exception = true
|
17
|
+
# TclTkLib.mainloop_abort_on_exception = false
|
18
|
+
# TclTkLib.mainloop_abort_on_exception = nil
|
19
|
+
|
20
|
+
|
21
|
+
################################################
|
22
|
+
# add ThreadGroup check to TclTkIp.new
|
23
|
+
class << TclTkIp
|
24
|
+
alias __new__ new
|
25
|
+
private :__new__
|
26
|
+
|
27
|
+
def new(*args)
|
28
|
+
if Thread.current.group != ThreadGroup::Default
|
29
|
+
raise SecurityError, 'only ThreadGroup::Default can call TclTkIp.new'
|
30
|
+
end
|
31
|
+
obj = __new__(*args)
|
32
|
+
obj.instance_eval{
|
33
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
34
|
+
@encoding ||= TkUtil.untrust([nil])
|
35
|
+
def @encoding.to_s; self.join(nil); end
|
36
|
+
}
|
37
|
+
obj
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
################################################
|
43
|
+
# use pseudo-toplevel feature of MultiTkIp ?
|
44
|
+
if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) ||
|
45
|
+
Use_PseudoToplevel_Feature_of_MultiTkIp)
|
46
|
+
module MultiTkIp_PseudoToplevel_Evaluable
|
47
|
+
#def pseudo_toplevel_eval(body = Proc.new)
|
48
|
+
# Thread.current[:TOPLEVEL] = self
|
49
|
+
# begin
|
50
|
+
# body.call
|
51
|
+
# ensure
|
52
|
+
# Thread.current[:TOPLEVEL] = nil
|
53
|
+
# end
|
54
|
+
#end
|
55
|
+
|
56
|
+
def pseudo_toplevel_evaluable?
|
57
|
+
@pseudo_toplevel_evaluable
|
58
|
+
end
|
59
|
+
|
60
|
+
def pseudo_toplevel_evaluable=(mode)
|
61
|
+
@pseudo_toplevel_evaluable = (mode)? true: false
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.extended(mod)
|
65
|
+
mod.__send__(:extend_object, mod)
|
66
|
+
mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Object
|
71
|
+
alias __method_missing_alias_for_MultiTkIp__ method_missing
|
72
|
+
private :__method_missing_alias_for_MultiTkIp__
|
73
|
+
|
74
|
+
def method_missing(id, *args)
|
75
|
+
begin
|
76
|
+
has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) &&
|
77
|
+
top.respond_to?(:pseudo_toplevel_evaluable?) &&
|
78
|
+
top.pseudo_toplevel_evaluable? &&
|
79
|
+
top.respond_to?(id)
|
80
|
+
rescue Exception => e
|
81
|
+
has_top = false
|
82
|
+
end
|
83
|
+
|
84
|
+
if has_top
|
85
|
+
top.__send__(id, *args)
|
86
|
+
else
|
87
|
+
__method_missing_alias_for_MultiTkIp__(id, *args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
# dummy
|
93
|
+
module MultiTkIp_PseudoToplevel_Evaluable
|
94
|
+
def pseudo_toplevel_evaluable?
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
################################################
|
101
|
+
# exceptiopn to treat the return value from IP
|
102
|
+
class MultiTkIp_OK < Exception
|
103
|
+
def self.send(thread, ret=nil)
|
104
|
+
thread.raise self.new(ret)
|
105
|
+
end
|
106
|
+
|
107
|
+
def initialize(ret=nil)
|
108
|
+
super('succeed')
|
109
|
+
@return_value = ret
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_reader :return_value
|
113
|
+
alias value return_value
|
114
|
+
end
|
115
|
+
MultiTkIp_OK.freeze
|
116
|
+
|
117
|
+
|
118
|
+
################################################
|
119
|
+
# methods for construction
|
120
|
+
class MultiTkIp
|
121
|
+
class Command_Queue < Queue
|
122
|
+
def initialize(interp)
|
123
|
+
@interp = interp
|
124
|
+
super()
|
125
|
+
end
|
126
|
+
|
127
|
+
def push(value)
|
128
|
+
if !@interp || @interp.deleted?
|
129
|
+
fail RuntimeError, "Tk interpreter is already deleted"
|
130
|
+
end
|
131
|
+
super(value)
|
132
|
+
end
|
133
|
+
alias << push
|
134
|
+
alias enq push
|
135
|
+
|
136
|
+
def close
|
137
|
+
@interp = nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
Command_Queue.freeze
|
141
|
+
|
142
|
+
BASE_DIR = File.dirname(__FILE__)
|
143
|
+
|
144
|
+
WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class
|
145
|
+
WITH_ENCODING = defined?(::Encoding.default_external)
|
146
|
+
#WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
|
147
|
+
|
148
|
+
(@@SLAVE_IP_ID = ['slave'.freeze, TkUtil.untrust('0')]).instance_eval{
|
149
|
+
@mutex = Mutex.new
|
150
|
+
def mutex; @mutex; end
|
151
|
+
freeze
|
152
|
+
}
|
153
|
+
|
154
|
+
@@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE)
|
155
|
+
|
156
|
+
@@INIT_IP_ENV = TkUtil.untrust([]) unless defined?(@@INIT_IP_ENV) # table of Procs
|
157
|
+
@@ADD_TK_PROCS = TkUtil.untrust([]) unless defined?(@@ADD_TK_PROCS) # table of [name, args, body]
|
158
|
+
|
159
|
+
@@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST)
|
160
|
+
|
161
|
+
unless defined?(@@TK_CMD_TBL)
|
162
|
+
@@TK_CMD_TBL = TkUtil.untrust(Object.new)
|
163
|
+
|
164
|
+
# @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
|
165
|
+
tbl_obj = TkUtil.untrust(Hash.new{|hash,key|
|
166
|
+
fail IndexError, "unknown command ID '#{key}'"
|
167
|
+
})
|
168
|
+
@@TK_CMD_TBL.instance_variable_set('@tbl', tbl_obj)
|
169
|
+
|
170
|
+
class << @@TK_CMD_TBL
|
171
|
+
allow = [
|
172
|
+
'__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id',
|
173
|
+
'[]', '[]=', 'delete', 'each', 'has_key?'
|
174
|
+
]
|
175
|
+
instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)}
|
176
|
+
|
177
|
+
def kind_of?(klass)
|
178
|
+
@tbl.kind_of?(klass)
|
179
|
+
end
|
180
|
+
|
181
|
+
def inspect
|
182
|
+
if Thread.current.group == ThreadGroup::Default
|
183
|
+
@tbl.inspect
|
184
|
+
else
|
185
|
+
ip = MultiTkIp.__getip
|
186
|
+
@tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def [](idx)
|
191
|
+
return unless (ent = @tbl[idx])
|
192
|
+
if Thread.current.group == ThreadGroup::Default
|
193
|
+
ent
|
194
|
+
elsif ent.respond_to?(:ip)
|
195
|
+
(ent.ip == MultiTkIp.__getip)? ent: nil
|
196
|
+
else
|
197
|
+
ent
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def []=(idx,val)
|
202
|
+
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
|
203
|
+
fail SecurityError,"cannot change the entried command"
|
204
|
+
end
|
205
|
+
@tbl[idx] = val
|
206
|
+
end
|
207
|
+
|
208
|
+
def delete(idx, &blk)
|
209
|
+
# if gets an entry, is permited to delete
|
210
|
+
if self[idx]
|
211
|
+
@tbl.delete(idx)
|
212
|
+
elsif blk
|
213
|
+
blk.call(idx)
|
214
|
+
else
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def each(&blk)
|
220
|
+
if Thread.current.group == ThreadGroup::Default
|
221
|
+
@tbl.each(&blk)
|
222
|
+
else
|
223
|
+
ip = MultiTkIp.__getip
|
224
|
+
@tbl.each{|idx, ent|
|
225
|
+
blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip
|
226
|
+
}
|
227
|
+
end
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
def has_key?(k)
|
232
|
+
@tbl.has_key?(k)
|
233
|
+
end
|
234
|
+
alias include? has_key?
|
235
|
+
alias key? has_key?
|
236
|
+
alias member? has_key?
|
237
|
+
end
|
238
|
+
|
239
|
+
@@TK_CMD_TBL.freeze
|
240
|
+
end
|
241
|
+
|
242
|
+
######################################
|
243
|
+
|
244
|
+
@@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){
|
245
|
+
def initialize(ip, cmd)
|
246
|
+
@ip = ip
|
247
|
+
@safe = safe = $SAFE
|
248
|
+
# @cmd = cmd
|
249
|
+
cmd = MultiTkIp._proc_on_safelevel(&cmd)
|
250
|
+
@cmd = proc{|*args| cmd.call(safe, *args)}
|
251
|
+
self.freeze
|
252
|
+
end
|
253
|
+
attr_reader :ip, :cmd
|
254
|
+
def inspect
|
255
|
+
cmd.inspect
|
256
|
+
end
|
257
|
+
def call(*args)
|
258
|
+
unless @ip.deleted?
|
259
|
+
current = Thread.current
|
260
|
+
backup_ip = current[:callback_ip]
|
261
|
+
current[:callback_ip] = @ip
|
262
|
+
begin
|
263
|
+
ret = @ip.cb_eval(@cmd, *args)
|
264
|
+
fail ret if ret.kind_of?(Exception)
|
265
|
+
ret
|
266
|
+
rescue TkCallbackBreak, TkCallbackContinue => e
|
267
|
+
fail e
|
268
|
+
rescue SecurityError => e
|
269
|
+
# in 'exit', 'exit!', and 'abort' : security error --> delete IP
|
270
|
+
if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
|
271
|
+
@ip.delete
|
272
|
+
elsif @ip.safe?
|
273
|
+
if @ip.respond_to?(:cb_error)
|
274
|
+
@ip.cb_error(e)
|
275
|
+
else
|
276
|
+
nil # ignore
|
277
|
+
end
|
278
|
+
else
|
279
|
+
fail e
|
280
|
+
end
|
281
|
+
rescue Exception => e
|
282
|
+
fail e if e.message =~ /^TkCallback/
|
283
|
+
|
284
|
+
if @ip.safe?
|
285
|
+
if @ip.respond_to?(:cb_error)
|
286
|
+
@ip.cb_error(e)
|
287
|
+
else
|
288
|
+
nil # ignore
|
289
|
+
end
|
290
|
+
else
|
291
|
+
fail e
|
292
|
+
end
|
293
|
+
ensure
|
294
|
+
current[:callback_ip] = backup_ip
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
}.freeze
|
299
|
+
|
300
|
+
######################################
|
301
|
+
|
302
|
+
def _keys2opts(src_keys)
|
303
|
+
return nil if src_keys == nil
|
304
|
+
keys = {}; src_keys.each{|k, v| keys[k.to_s] = v}
|
305
|
+
#keys.collect{|k,v| "-#{k} #{v}"}.join(' ')
|
306
|
+
keys.collect{|k,v| "-#{k} #{TclTkLib._conv_listelement(TkComm::_get_eval_string(v))}"}.join(' ')
|
307
|
+
end
|
308
|
+
private :_keys2opts
|
309
|
+
|
310
|
+
def _check_and_return(thread, exception, wait=0)
|
311
|
+
unless thread
|
312
|
+
unless exception.kind_of?(MultiTkIp_OK)
|
313
|
+
msg = "#{exception.class}: #{exception.message}"
|
314
|
+
|
315
|
+
if @interp.deleted?
|
316
|
+
warn("Warning (#{self}): " + msg)
|
317
|
+
return nil
|
318
|
+
end
|
319
|
+
|
320
|
+
if safe?
|
321
|
+
warn("Warning (#{self}): " + msg) if $DEBUG
|
322
|
+
return nil
|
323
|
+
end
|
324
|
+
|
325
|
+
begin
|
326
|
+
@interp._eval_without_enc(@interp._merge_tklist('bgerror', msg))
|
327
|
+
rescue Exception => e
|
328
|
+
warn("Warning (#{self}): " + msg)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
return nil
|
332
|
+
end
|
333
|
+
|
334
|
+
if wait == 0
|
335
|
+
# no wait
|
336
|
+
Thread.pass
|
337
|
+
if thread.stop?
|
338
|
+
thread.raise exception
|
339
|
+
end
|
340
|
+
return thread
|
341
|
+
end
|
342
|
+
|
343
|
+
# wait to stop the caller thread
|
344
|
+
wait.times{
|
345
|
+
if thread.stop?
|
346
|
+
# ready to send exception
|
347
|
+
thread.raise exception
|
348
|
+
return thread
|
349
|
+
end
|
350
|
+
|
351
|
+
# wait
|
352
|
+
Thread.pass
|
353
|
+
}
|
354
|
+
|
355
|
+
# unexpected error
|
356
|
+
thread.raise RuntimeError, "the thread may not wait for the return value"
|
357
|
+
return thread
|
358
|
+
end
|
359
|
+
|
360
|
+
######################################
|
361
|
+
|
362
|
+
def set_cb_error(cmd = Proc.new)
|
363
|
+
@cb_error_proc[0] = cmd
|
364
|
+
end
|
365
|
+
|
366
|
+
def cb_error(e)
|
367
|
+
if @cb_error_proc[0].respond_to?(:call)
|
368
|
+
@cb_error_proc[0].call(e)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
######################################
|
373
|
+
|
374
|
+
def set_safe_level(safe)
|
375
|
+
if safe > @safe_level[0]
|
376
|
+
@safe_level[0] = safe
|
377
|
+
@cmd_queue.enq([@system, 'set_safe_level', safe])
|
378
|
+
end
|
379
|
+
@safe_level[0]
|
380
|
+
end
|
381
|
+
def safe_level=(safe)
|
382
|
+
set_safe_level(safe)
|
383
|
+
end
|
384
|
+
def self.set_safe_level(safe)
|
385
|
+
__getip.set_safe_level(safe)
|
386
|
+
end
|
387
|
+
def self.safe_level=(safe)
|
388
|
+
self.set_safe_level(safe)
|
389
|
+
end
|
390
|
+
def safe_level
|
391
|
+
@safe_level[0]
|
392
|
+
end
|
393
|
+
def self.safe_level
|
394
|
+
__getip.safe_level
|
395
|
+
end
|
396
|
+
|
397
|
+
def wait_on_mainloop?
|
398
|
+
@wait_on_mainloop[0]
|
399
|
+
end
|
400
|
+
def wait_on_mainloop=(bool)
|
401
|
+
@wait_on_mainloop[0] = bool
|
402
|
+
end
|
403
|
+
|
404
|
+
def running_mainloop?
|
405
|
+
@wait_on_mainloop[1] > 0
|
406
|
+
end
|
407
|
+
|
408
|
+
def _destroy_slaves_of_slaveIP(ip)
|
409
|
+
unless ip.deleted?
|
410
|
+
# ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name|
|
411
|
+
ip._split_tklist(ip._invoke_without_enc('interp', 'slaves')).each{|name|
|
412
|
+
name = _fromUTF8(name)
|
413
|
+
begin
|
414
|
+
# ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}")
|
415
|
+
after_ids = ip._eval_without_enc("#{name} eval {after info}")
|
416
|
+
ip._eval_without_enc("#{name} eval {foreach i {#{after_ids}} {after cancel $i}}")
|
417
|
+
rescue Exception
|
418
|
+
end
|
419
|
+
begin
|
420
|
+
# ip._invoke('interp', 'eval', name, 'destroy', '.')
|
421
|
+
ip._invoke(name, 'eval', 'destroy', '.')
|
422
|
+
rescue Exception
|
423
|
+
end
|
424
|
+
|
425
|
+
# safe_base?
|
426
|
+
if ip._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
|
427
|
+
begin
|
428
|
+
ip._eval_without_enc("::safe::interpDelete #{name}")
|
429
|
+
rescue Exception
|
430
|
+
end
|
431
|
+
end
|
432
|
+
=begin
|
433
|
+
if ip._invoke('interp', 'exists', name) == '1'
|
434
|
+
begin
|
435
|
+
ip._invoke(name, 'eval', 'exit')
|
436
|
+
rescue Exception
|
437
|
+
end
|
438
|
+
end
|
439
|
+
=end
|
440
|
+
unless ip.deleted?
|
441
|
+
if ip._invoke('interp', 'exists', name) == '1'
|
442
|
+
begin
|
443
|
+
ip._invoke('interp', 'delete', name)
|
444
|
+
rescue Exception
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
}
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def _receiver_eval_proc_core(safe_level, thread, cmd, *args)
|
453
|
+
begin
|
454
|
+
#ret = proc{$SAFE = safe_level; cmd.call(*args)}.call
|
455
|
+
#ret = cmd.call(safe_level, *args)
|
456
|
+
normal_ret = false
|
457
|
+
ret = catch(:IRB_EXIT) do # IRB hack
|
458
|
+
retval = cmd.call(safe_level, *args)
|
459
|
+
normal_ret = true
|
460
|
+
retval
|
461
|
+
end
|
462
|
+
unless normal_ret
|
463
|
+
# catch IRB_EXIT
|
464
|
+
exit(ret)
|
465
|
+
end
|
466
|
+
ret
|
467
|
+
rescue SystemExit => e
|
468
|
+
# delete IP
|
469
|
+
unless @interp.deleted?
|
470
|
+
@slave_ip_tbl.each{|name, subip|
|
471
|
+
_destroy_slaves_of_slaveIP(subip)
|
472
|
+
begin
|
473
|
+
# subip._eval_without_enc("foreach i [after info] {after cancel $i}")
|
474
|
+
after_ids = subip._eval_without_enc("after info")
|
475
|
+
subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
476
|
+
rescue Exception
|
477
|
+
end
|
478
|
+
=begin
|
479
|
+
begin
|
480
|
+
subip._invoke('destroy', '.') unless subip.deleted?
|
481
|
+
rescue Exception
|
482
|
+
end
|
483
|
+
=end
|
484
|
+
# safe_base?
|
485
|
+
if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
|
486
|
+
begin
|
487
|
+
@interp._eval_without_enc("::safe::interpDelete #{name}")
|
488
|
+
rescue Exception
|
489
|
+
else
|
490
|
+
next if subip.deleted?
|
491
|
+
end
|
492
|
+
end
|
493
|
+
if subip.respond_to?(:safe_base?) && subip.safe_base? &&
|
494
|
+
!subip.deleted?
|
495
|
+
# do 'exit' to call the delete_hook procedure
|
496
|
+
begin
|
497
|
+
subip._eval_without_enc('exit')
|
498
|
+
rescue Exception
|
499
|
+
end
|
500
|
+
else
|
501
|
+
begin
|
502
|
+
subip.delete unless subip.deleted?
|
503
|
+
rescue Exception
|
504
|
+
end
|
505
|
+
end
|
506
|
+
}
|
507
|
+
|
508
|
+
begin
|
509
|
+
# @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
|
510
|
+
after_ids = @interp._eval_without_enc("after info")
|
511
|
+
@interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
512
|
+
rescue Exception
|
513
|
+
end
|
514
|
+
begin
|
515
|
+
@interp._invoke('destroy', '.') unless @interp.deleted?
|
516
|
+
rescue Exception
|
517
|
+
end
|
518
|
+
if @safe_base && !@interp.deleted?
|
519
|
+
# do 'exit' to call the delete_hook procedure
|
520
|
+
@interp._eval_without_enc('exit')
|
521
|
+
else
|
522
|
+
@interp.delete unless @interp.deleted?
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
|
527
|
+
_check_and_return(thread, MultiTkIp_OK.new($3 == 'exit'))
|
528
|
+
else
|
529
|
+
_check_and_return(thread, MultiTkIp_OK.new(nil))
|
530
|
+
end
|
531
|
+
|
532
|
+
# if master? && !safe? && allow_ruby_exit?
|
533
|
+
if !@interp.deleted? && master? && !safe? && allow_ruby_exit?
|
534
|
+
=begin
|
535
|
+
ObjectSpace.each_object(TclTkIp){|obj|
|
536
|
+
obj.delete unless obj.deleted?
|
537
|
+
}
|
538
|
+
=end
|
539
|
+
#exit(e.status)
|
540
|
+
fail e
|
541
|
+
end
|
542
|
+
# break
|
543
|
+
|
544
|
+
rescue SecurityError => e
|
545
|
+
# in 'exit', 'exit!', and 'abort' : security error --> delete IP
|
546
|
+
if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
|
547
|
+
ret = ($3 == 'exit')
|
548
|
+
unless @interp.deleted?
|
549
|
+
@slave_ip_tbl.each{|name, subip|
|
550
|
+
_destroy_slaves_of_slaveIP(subip)
|
551
|
+
begin
|
552
|
+
# subip._eval_without_enc("foreach i [after info] {after cancel $i}")
|
553
|
+
after_ids = subip._eval_without_enc("after info")
|
554
|
+
subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
555
|
+
rescue Exception
|
556
|
+
end
|
557
|
+
=begin
|
558
|
+
begin
|
559
|
+
subip._invoke('destroy', '.') unless subip.deleted?
|
560
|
+
rescue Exception
|
561
|
+
end
|
562
|
+
=end
|
563
|
+
# safe_base?
|
564
|
+
if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
|
565
|
+
begin
|
566
|
+
@interp._eval_without_enc("::safe::interpDelete #{name}")
|
567
|
+
rescue Exception
|
568
|
+
else
|
569
|
+
next if subip.deleted?
|
570
|
+
end
|
571
|
+
end
|
572
|
+
if subip.respond_to?(:safe_base?) && subip.safe_base? &&
|
573
|
+
!subip.deleted?
|
574
|
+
# do 'exit' to call the delete_hook procedure
|
575
|
+
begin
|
576
|
+
subip._eval_without_enc('exit')
|
577
|
+
rescue Exception
|
578
|
+
end
|
579
|
+
else
|
580
|
+
begin
|
581
|
+
subip.delete unless subip.deleted?
|
582
|
+
rescue Exception
|
583
|
+
end
|
584
|
+
end
|
585
|
+
}
|
586
|
+
|
587
|
+
begin
|
588
|
+
# @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
|
589
|
+
after_ids = @interp._eval_without_enc("after info")
|
590
|
+
@interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
591
|
+
rescue Exception
|
592
|
+
end
|
593
|
+
=begin
|
594
|
+
begin
|
595
|
+
@interp._invoke('destroy', '.') unless @interp.deleted?
|
596
|
+
rescue Exception
|
597
|
+
end
|
598
|
+
=end
|
599
|
+
if @safe_base && !@interp.deleted?
|
600
|
+
# do 'exit' to call the delete_hook procedure
|
601
|
+
@interp._eval_without_enc('exit')
|
602
|
+
else
|
603
|
+
@interp.delete unless @interp.deleted?
|
604
|
+
end
|
605
|
+
end
|
606
|
+
_check_and_return(thread, MultiTkIp_OK.new(ret))
|
607
|
+
# break
|
608
|
+
|
609
|
+
else
|
610
|
+
# raise security error
|
611
|
+
_check_and_return(thread, e)
|
612
|
+
end
|
613
|
+
|
614
|
+
rescue Exception => e
|
615
|
+
# raise exception
|
616
|
+
begin
|
617
|
+
bt = _toUTF8(e.backtrace.join("\n"))
|
618
|
+
if MultiTkIp::WITH_ENCODING
|
619
|
+
bt.force_encoding('utf-8')
|
620
|
+
else
|
621
|
+
bt.instance_variable_set(:@encoding, 'utf-8')
|
622
|
+
end
|
623
|
+
rescue Exception
|
624
|
+
bt = e.backtrace.join("\n")
|
625
|
+
end
|
626
|
+
begin
|
627
|
+
@interp._set_global_var('errorInfo', bt)
|
628
|
+
rescue Exception
|
629
|
+
end
|
630
|
+
_check_and_return(thread, e)
|
631
|
+
|
632
|
+
else
|
633
|
+
# no exception
|
634
|
+
_check_and_return(thread, MultiTkIp_OK.new(ret))
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
638
|
+
def _receiver_eval_proc(last_thread, safe_level, thread, cmd, *args)
|
639
|
+
if thread
|
640
|
+
Thread.new{
|
641
|
+
last_thread.join if last_thread
|
642
|
+
unless @interp.deleted?
|
643
|
+
_receiver_eval_proc_core(safe_level, thread, cmd, *args)
|
644
|
+
end
|
645
|
+
}
|
646
|
+
else
|
647
|
+
Thread.new{
|
648
|
+
unless @interp.deleted?
|
649
|
+
_receiver_eval_proc_core(safe_level, thread, cmd, *args)
|
650
|
+
end
|
651
|
+
}
|
652
|
+
last_thread
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
private :_receiver_eval_proc, :_receiver_eval_proc_core
|
657
|
+
|
658
|
+
def _receiver_mainloop(check_root)
|
659
|
+
if @evloop_thread[0] && @evloop_thread[0].alive?
|
660
|
+
@evloop_thread[0]
|
661
|
+
else
|
662
|
+
@evloop_thread[0] = Thread.new{
|
663
|
+
while !@interp.deleted?
|
664
|
+
#if check_root
|
665
|
+
# inf = @interp._invoke_without_enc('info', 'command', '.')
|
666
|
+
# break if !inf.kind_of?(String) || inf != '.'
|
667
|
+
#end
|
668
|
+
break if check_root && !@interp.has_mainwindow?
|
669
|
+
sleep 0.5
|
670
|
+
end
|
671
|
+
}
|
672
|
+
@evloop_thread[0]
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
def _create_receiver_and_watchdog(lvl = $SAFE)
|
677
|
+
lvl = $SAFE if lvl < $SAFE
|
678
|
+
|
679
|
+
# command-procedures receiver
|
680
|
+
receiver = Thread.new(lvl){|safe_level|
|
681
|
+
last_thread = {}
|
682
|
+
|
683
|
+
loop do
|
684
|
+
break if @interp.deleted?
|
685
|
+
thread, cmd, *args = @cmd_queue.deq
|
686
|
+
if thread == @system
|
687
|
+
# control command
|
688
|
+
case cmd
|
689
|
+
when 'set_safe_level'
|
690
|
+
begin
|
691
|
+
safe_level = args[0] if safe_level < args[0]
|
692
|
+
rescue Exception
|
693
|
+
end
|
694
|
+
when 'call_mainloop'
|
695
|
+
thread = args.shift
|
696
|
+
_check_and_return(thread,
|
697
|
+
MultiTkIp_OK.new(_receiver_mainloop(*args)))
|
698
|
+
else
|
699
|
+
# ignore
|
700
|
+
end
|
701
|
+
|
702
|
+
else
|
703
|
+
# procedure
|
704
|
+
last_thread[thread] = _receiver_eval_proc(last_thread[thread],
|
705
|
+
safe_level, thread,
|
706
|
+
cmd, *args)
|
707
|
+
end
|
708
|
+
end
|
709
|
+
}
|
710
|
+
|
711
|
+
# watchdog of receiver
|
712
|
+
watchdog = Thread.new{
|
713
|
+
begin
|
714
|
+
loop do
|
715
|
+
sleep 1
|
716
|
+
if @interp.deleted?
|
717
|
+
receiver.kill
|
718
|
+
@cmd_queue.close
|
719
|
+
end
|
720
|
+
break unless receiver.alive?
|
721
|
+
end
|
722
|
+
rescue Exception
|
723
|
+
# ignore all kind of Exception
|
724
|
+
end
|
725
|
+
|
726
|
+
# receiver is dead
|
727
|
+
retry_count = 3
|
728
|
+
loop do
|
729
|
+
Thread.pass
|
730
|
+
begin
|
731
|
+
thread, cmd, *args = @cmd_queue.deq(true) # non-block
|
732
|
+
rescue ThreadError
|
733
|
+
# queue is empty
|
734
|
+
retry_count -= 1
|
735
|
+
break if retry_count <= 0
|
736
|
+
sleep 0.5
|
737
|
+
retry
|
738
|
+
end
|
739
|
+
next unless thread
|
740
|
+
if thread.alive?
|
741
|
+
if @interp.deleted?
|
742
|
+
thread.raise RuntimeError, 'the interpreter is already deleted'
|
743
|
+
else
|
744
|
+
thread.raise RuntimeError,
|
745
|
+
'the interpreter no longer receives command procedures'
|
746
|
+
end
|
747
|
+
end
|
748
|
+
end
|
749
|
+
}
|
750
|
+
|
751
|
+
# return threads
|
752
|
+
[receiver, watchdog]
|
753
|
+
end
|
754
|
+
private :_check_and_return, :_create_receiver_and_watchdog
|
755
|
+
|
756
|
+
######################################
|
757
|
+
|
758
|
+
unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
|
759
|
+
### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
|
760
|
+
RUN_EVENTLOOP_ON_MAIN_THREAD = false
|
761
|
+
end
|
762
|
+
|
763
|
+
if self.const_defined? :DEFAULT_MASTER_NAME
|
764
|
+
name = DEFAULT_MASTER_NAME.to_s
|
765
|
+
else
|
766
|
+
name = nil
|
767
|
+
end
|
768
|
+
if self.const_defined?(:DEFAULT_MASTER_OPTS) &&
|
769
|
+
DEFAULT_MASTER_OPTS.kind_of?(Hash)
|
770
|
+
keys = DEFAULT_MASTER_OPTS
|
771
|
+
else
|
772
|
+
keys = {}
|
773
|
+
end
|
774
|
+
|
775
|
+
@@DEFAULT_MASTER = self.allocate
|
776
|
+
@@DEFAULT_MASTER.instance_eval{
|
777
|
+
@tk_windows = TkUtil.untrust({})
|
778
|
+
|
779
|
+
@tk_table_list = TkUtil.untrust([])
|
780
|
+
|
781
|
+
@slave_ip_tbl = TkUtil.untrust({})
|
782
|
+
|
783
|
+
@slave_ip_top = TkUtil.untrust({})
|
784
|
+
|
785
|
+
@evloop_thread = TkUtil.untrust([])
|
786
|
+
|
787
|
+
unless keys.kind_of? Hash
|
788
|
+
fail ArgumentError, "expecting a Hash object for the 2nd argument"
|
789
|
+
end
|
790
|
+
|
791
|
+
if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
|
792
|
+
@interp = TclTkIp.new(name, _keys2opts(keys))
|
793
|
+
else ### Ruby 1.9 !!!!!!!!!!!
|
794
|
+
@interp_thread = Thread.new{
|
795
|
+
current = Thread.current
|
796
|
+
begin
|
797
|
+
current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys))
|
798
|
+
rescue e
|
799
|
+
current[:interp] = e
|
800
|
+
raise e
|
801
|
+
end
|
802
|
+
#sleep
|
803
|
+
current[:mutex] = mutex = Mutex.new
|
804
|
+
current[:root_check] = cond_var = ConditionVariable.new
|
805
|
+
|
806
|
+
status = [nil]
|
807
|
+
def status.value
|
808
|
+
self[0]
|
809
|
+
end
|
810
|
+
def status.value=(val)
|
811
|
+
self[0] = val
|
812
|
+
end
|
813
|
+
current[:status] = status
|
814
|
+
|
815
|
+
begin
|
816
|
+
begin
|
817
|
+
#TclTkLib.mainloop_abort_on_exception = false
|
818
|
+
#Thread.current[:status].value = TclTkLib.mainloop(true)
|
819
|
+
interp.mainloop_abort_on_exception = true
|
820
|
+
current[:status].value = interp.mainloop(true)
|
821
|
+
rescue SystemExit=>e
|
822
|
+
current[:status].value = e
|
823
|
+
rescue Exception=>e
|
824
|
+
current[:status].value = e
|
825
|
+
retry if interp.has_mainwindow?
|
826
|
+
ensure
|
827
|
+
mutex.synchronize{ cond_var.broadcast }
|
828
|
+
end
|
829
|
+
|
830
|
+
#Thread.current[:status].value = TclTkLib.mainloop(false)
|
831
|
+
current[:status].value = interp.mainloop(false)
|
832
|
+
|
833
|
+
ensure
|
834
|
+
# interp must be deleted before the thread for interp is dead.
|
835
|
+
# If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler
|
836
|
+
# deleted by the wrong thread.
|
837
|
+
interp.delete
|
838
|
+
end
|
839
|
+
}
|
840
|
+
until @interp_thread[:interp]
|
841
|
+
Thread.pass
|
842
|
+
end
|
843
|
+
# INTERP_THREAD.run
|
844
|
+
@interp = @interp_thread[:interp]
|
845
|
+
|
846
|
+
def self.mainloop(check_root = true)
|
847
|
+
begin
|
848
|
+
TclTkLib.set_eventloop_window_mode(true)
|
849
|
+
@interp_thread.value
|
850
|
+
ensure
|
851
|
+
TclTkLib.set_eventloop_window_mode(false)
|
852
|
+
end
|
853
|
+
end
|
854
|
+
end
|
855
|
+
|
856
|
+
@interp.instance_eval{
|
857
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
858
|
+
@encoding ||= TkUtil.untrust([nil])
|
859
|
+
def @encoding.to_s; self.join(nil); end
|
860
|
+
}
|
861
|
+
|
862
|
+
@ip_name = nil
|
863
|
+
|
864
|
+
@callback_status = TkUtil.untrust([])
|
865
|
+
|
866
|
+
@system = Object.new
|
867
|
+
|
868
|
+
@wait_on_mainloop = TkUtil.untrust([true, 0])
|
869
|
+
|
870
|
+
@threadgroup = Thread.current.group
|
871
|
+
|
872
|
+
@safe_base = false
|
873
|
+
|
874
|
+
@safe_level = [$SAFE]
|
875
|
+
|
876
|
+
@cmd_queue = MultiTkIp::Command_Queue.new(@interp)
|
877
|
+
|
878
|
+
@cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
|
879
|
+
|
880
|
+
@threadgroup.add @cmd_receiver
|
881
|
+
@threadgroup.add @receiver_watchdog
|
882
|
+
|
883
|
+
# NOT enclose @threadgroup for @@DEFAULT_MASTER
|
884
|
+
|
885
|
+
@@IP_TABLE[ThreadGroup::Default] = self
|
886
|
+
@@IP_TABLE[@threadgroup] = self
|
887
|
+
|
888
|
+
#################################
|
889
|
+
|
890
|
+
@pseudo_toplevel = [false, nil]
|
891
|
+
|
892
|
+
def self.__pseudo_toplevel
|
893
|
+
Thread.current.group == ThreadGroup::Default &&
|
894
|
+
MultiTkIp.__getip == @@DEFAULT_MASTER &&
|
895
|
+
self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
|
896
|
+
end
|
897
|
+
|
898
|
+
def self.__pseudo_toplevel=(m)
|
899
|
+
unless (Thread.current.group == ThreadGroup::Default &&
|
900
|
+
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
901
|
+
fail SecurityError, "no permission to manipulate"
|
902
|
+
end
|
903
|
+
|
904
|
+
# if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
|
905
|
+
if m.respond_to?(:pseudo_toplevel_evaluable?)
|
906
|
+
@pseudo_toplevel[0] = true
|
907
|
+
@pseudo_toplevel[1] = m
|
908
|
+
else
|
909
|
+
fail ArgumentError, 'fail to set pseudo-toplevel'
|
910
|
+
end
|
911
|
+
self
|
912
|
+
end
|
913
|
+
|
914
|
+
def self.__pseudo_toplevel_evaluable?
|
915
|
+
begin
|
916
|
+
@pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
|
917
|
+
rescue Exception
|
918
|
+
false
|
919
|
+
end
|
920
|
+
end
|
921
|
+
|
922
|
+
def self.__pseudo_toplevel_evaluable=(mode)
|
923
|
+
unless (Thread.current.group == ThreadGroup::Default &&
|
924
|
+
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
925
|
+
fail SecurityError, "no permission to manipulate"
|
926
|
+
end
|
927
|
+
|
928
|
+
@pseudo_toplevel[0] = (mode)? true: false
|
929
|
+
end
|
930
|
+
|
931
|
+
#################################
|
932
|
+
|
933
|
+
@assign_request = Class.new(Exception){
|
934
|
+
def self.new(target, ret)
|
935
|
+
obj = super()
|
936
|
+
obj.target = target
|
937
|
+
obj.ret = ret
|
938
|
+
obj
|
939
|
+
end
|
940
|
+
attr_accessor :target, :ret
|
941
|
+
}
|
942
|
+
|
943
|
+
@assign_thread = Thread.new{
|
944
|
+
loop do
|
945
|
+
begin
|
946
|
+
Thread.stop
|
947
|
+
rescue @assign_request=>req
|
948
|
+
begin
|
949
|
+
req.ret[0] = req.target.instance_eval{
|
950
|
+
@cmd_receiver, @receiver_watchdog =
|
951
|
+
_create_receiver_and_watchdog(@safe_level[0])
|
952
|
+
@threadgroup.add @cmd_receiver
|
953
|
+
@threadgroup.add @receiver_watchdog
|
954
|
+
@threadgroup.enclose
|
955
|
+
true
|
956
|
+
}
|
957
|
+
rescue Exception=>e
|
958
|
+
begin
|
959
|
+
req.ret[0] = e
|
960
|
+
rescue Exception
|
961
|
+
# ignore
|
962
|
+
end
|
963
|
+
end
|
964
|
+
rescue Exception
|
965
|
+
# ignore
|
966
|
+
end
|
967
|
+
end
|
968
|
+
}
|
969
|
+
|
970
|
+
def self.assign_receiver_and_watchdog(target)
|
971
|
+
ret = [nil]
|
972
|
+
@assign_thread.raise(@assign_request.new(target, ret))
|
973
|
+
while ret[0] == nil
|
974
|
+
unless @assign_thread.alive?
|
975
|
+
raise RuntimeError, 'lost the thread to assign a receiver and a watchdog thread'
|
976
|
+
end
|
977
|
+
end
|
978
|
+
if ret[0].kind_of?(Exception)
|
979
|
+
raise ret[0]
|
980
|
+
else
|
981
|
+
ret[0]
|
982
|
+
end
|
983
|
+
end
|
984
|
+
|
985
|
+
#################################
|
986
|
+
|
987
|
+
@init_ip_env_queue = Queue.new
|
988
|
+
Thread.new{
|
989
|
+
current = Thread.current
|
990
|
+
loop {
|
991
|
+
mtx, cond, ret, table, script = @init_ip_env_queue.deq
|
992
|
+
begin
|
993
|
+
ret[0] = table.each{|tg, ip| ip._init_ip_env(script) }
|
994
|
+
rescue Exception => e
|
995
|
+
ret[0] = e
|
996
|
+
ensure
|
997
|
+
mtx.synchronize{ cond.signal }
|
998
|
+
end
|
999
|
+
mtx = cond = ret = table = script = nil # clear variables for GC
|
1000
|
+
}
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
def self.__init_ip_env__(table, script)
|
1004
|
+
ret = []
|
1005
|
+
mtx = (Thread.current[:MultiTk_ip_Mutex] ||= Mutex.new)
|
1006
|
+
cond = (Thread.current[:MultiTk_ip_CondVar] ||= ConditionVariable.new)
|
1007
|
+
mtx.synchronize{
|
1008
|
+
@init_ip_env_queue.enq([mtx, cond, ret, table, script])
|
1009
|
+
cond.wait(mtx)
|
1010
|
+
}
|
1011
|
+
if ret[0].kind_of?(Exception)
|
1012
|
+
raise ret[0]
|
1013
|
+
else
|
1014
|
+
ret[0]
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
#################################
|
1019
|
+
|
1020
|
+
class << self
|
1021
|
+
undef :instance_eval
|
1022
|
+
end
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
@@DEFAULT_MASTER.freeze # defend against modification
|
1026
|
+
|
1027
|
+
######################################
|
1028
|
+
|
1029
|
+
def self.inherited(subclass)
|
1030
|
+
# trust if on ThreadGroup::Default or @@DEFAULT_MASTER's ThreadGroup
|
1031
|
+
if @@IP_TABLE[Thread.current.group] == @@DEFAULT_MASTER
|
1032
|
+
begin
|
1033
|
+
class << subclass
|
1034
|
+
self.methods.each{|m|
|
1035
|
+
name = m.to_s
|
1036
|
+
begin
|
1037
|
+
unless name == '__id__' || name == '__send__' || name == 'freeze'
|
1038
|
+
undef_method(m)
|
1039
|
+
end
|
1040
|
+
rescue Exception
|
1041
|
+
# ignore all exceptions
|
1042
|
+
end
|
1043
|
+
}
|
1044
|
+
end
|
1045
|
+
ensure
|
1046
|
+
subclass.freeze
|
1047
|
+
fail SecurityError,
|
1048
|
+
"cannot create subclass of MultiTkIp on a untrusted ThreadGroup"
|
1049
|
+
end
|
1050
|
+
end
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
######################################
|
1054
|
+
|
1055
|
+
@@SAFE_OPT_LIST = [
|
1056
|
+
'accessPath'.freeze,
|
1057
|
+
'statics'.freeze,
|
1058
|
+
'nested'.freeze,
|
1059
|
+
'deleteHook'.freeze
|
1060
|
+
].freeze
|
1061
|
+
|
1062
|
+
def _parse_slaveopts(keys)
|
1063
|
+
name = nil
|
1064
|
+
safe = false
|
1065
|
+
safe_opts = {}
|
1066
|
+
tk_opts = {}
|
1067
|
+
|
1068
|
+
keys.each{|k,v|
|
1069
|
+
k_str = k.to_s
|
1070
|
+
if k_str == 'name'
|
1071
|
+
name = v
|
1072
|
+
elsif k_str == 'safe'
|
1073
|
+
safe = v
|
1074
|
+
elsif @@SAFE_OPT_LIST.member?(k_str)
|
1075
|
+
safe_opts[k_str] = v
|
1076
|
+
else
|
1077
|
+
tk_opts[k_str] = v
|
1078
|
+
end
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
if keys['without_tk'] || keys[:without_tk]
|
1082
|
+
[name, safe, safe_opts, nil]
|
1083
|
+
else
|
1084
|
+
[name, safe, safe_opts, tk_opts]
|
1085
|
+
end
|
1086
|
+
end
|
1087
|
+
private :_parse_slaveopts
|
1088
|
+
|
1089
|
+
def _create_slave_ip_name
|
1090
|
+
@@SLAVE_IP_ID.mutex.synchronize{
|
1091
|
+
name = @@SLAVE_IP_ID.join('')
|
1092
|
+
@@SLAVE_IP_ID[1].succ!
|
1093
|
+
name.freeze
|
1094
|
+
}
|
1095
|
+
end
|
1096
|
+
private :_create_slave_ip_name
|
1097
|
+
|
1098
|
+
######################################
|
1099
|
+
|
1100
|
+
def __check_safetk_optkeys(optkeys)
|
1101
|
+
# based on 'safetk.tcl'
|
1102
|
+
new_keys = {}
|
1103
|
+
optkeys.each{|k,v| new_keys[k.to_s] = v}
|
1104
|
+
|
1105
|
+
# check 'display'
|
1106
|
+
if !new_keys.key?('display')
|
1107
|
+
begin
|
1108
|
+
#new_keys['display'] = @interp._invoke('winfo screen .')
|
1109
|
+
new_keys['display'] = @interp._invoke('winfo', 'screen', '.')
|
1110
|
+
rescue
|
1111
|
+
if ENV[DISPLAY]
|
1112
|
+
new_keys['display'] = ENV[DISPLAY]
|
1113
|
+
elsif !new_keys.key?('use')
|
1114
|
+
warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'"
|
1115
|
+
new_keys['display'] = ':0.0'
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
# check 'use'
|
1121
|
+
if new_keys.key?('use')
|
1122
|
+
# given 'use'
|
1123
|
+
case new_keys['use']
|
1124
|
+
when TkWindow
|
1125
|
+
new_keys['use'] = TkWinfo.id(new_keys['use'])
|
1126
|
+
#assoc_display = @interp._eval('winfo screen .')
|
1127
|
+
assoc_display = @interp._invoke('winfo', 'screen', '.')
|
1128
|
+
when /^\..*/
|
1129
|
+
new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use'])
|
1130
|
+
assoc_display = @interp._invoke('winfo', 'screen', new_keys['use'])
|
1131
|
+
else
|
1132
|
+
begin
|
1133
|
+
pathname = @interp._invoke('winfo', 'pathname', new_keys['use'])
|
1134
|
+
assoc_display = @interp._invoke('winfo', 'screen', pathname)
|
1135
|
+
rescue
|
1136
|
+
assoc_display = new_keys['display']
|
1137
|
+
end
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
# match display?
|
1141
|
+
if assoc_display != new_keys['display']
|
1142
|
+
if optkeys.key?(:display) || optkeys.key?('display')
|
1143
|
+
fail RuntimeError,
|
1144
|
+
"conflicting 'display'=>#{new_keys['display']} " +
|
1145
|
+
"and display '#{assoc_display}' on 'use'=>#{new_keys['use']}"
|
1146
|
+
else
|
1147
|
+
new_keys['display'] = assoc_display
|
1148
|
+
end
|
1149
|
+
end
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
# return
|
1153
|
+
new_keys
|
1154
|
+
end
|
1155
|
+
private :__check_safetk_optkeys
|
1156
|
+
|
1157
|
+
def __create_safetk_frame(slave_ip, slave_name, app_name, keys)
|
1158
|
+
# display option is used by ::safe::loadTk
|
1159
|
+
loadTk_keys = {}
|
1160
|
+
loadTk_keys['display'] = keys['display']
|
1161
|
+
dup_keys = keys.dup
|
1162
|
+
|
1163
|
+
# keys for toplevel : allow followings
|
1164
|
+
toplevel_keys = {}
|
1165
|
+
['height', 'width', 'background', 'menu'].each{|k|
|
1166
|
+
toplevel_keys[k] = dup_keys.delete(k) if dup_keys.key?(k)
|
1167
|
+
}
|
1168
|
+
toplevel_keys['classname'] = 'SafeTk'
|
1169
|
+
toplevel_keys['screen'] = dup_keys.delete('display')
|
1170
|
+
|
1171
|
+
# other keys used by pack option of container frame
|
1172
|
+
|
1173
|
+
# create toplevel widget
|
1174
|
+
begin
|
1175
|
+
top = TkToplevel.new(toplevel_keys)
|
1176
|
+
rescue NameError => e
|
1177
|
+
fail e unless @interp.safe?
|
1178
|
+
fail SecurityError, "unable create toplevel on the safe interpreter"
|
1179
|
+
end
|
1180
|
+
msg = "Untrusted Ruby/Tk applet (#{slave_name})"
|
1181
|
+
if app_name.kind_of?(String)
|
1182
|
+
top.title "#{app_name} (#{slave_name})"
|
1183
|
+
else
|
1184
|
+
top.title msg
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
# procedure to delete slave interpreter
|
1188
|
+
slave_delete_proc = proc{
|
1189
|
+
unless slave_ip.deleted?
|
1190
|
+
#if slave_ip._invoke('info', 'command', '.') != ""
|
1191
|
+
# slave_ip._invoke('destroy', '.')
|
1192
|
+
#end
|
1193
|
+
#slave_ip.delete
|
1194
|
+
slave_ip._eval_without_enc('exit')
|
1195
|
+
end
|
1196
|
+
begin
|
1197
|
+
top.destroy if top.winfo_exist?
|
1198
|
+
rescue
|
1199
|
+
# ignore
|
1200
|
+
end
|
1201
|
+
}
|
1202
|
+
tag = TkBindTag.new.bind('Destroy', slave_delete_proc)
|
1203
|
+
|
1204
|
+
top.bindtags = top.bindtags.unshift(tag)
|
1205
|
+
|
1206
|
+
# create control frame
|
1207
|
+
TkFrame.new(top, :bg=>'red', :borderwidth=>3, :relief=>'ridge') {|fc|
|
1208
|
+
fc.bindtags = fc.bindtags.unshift(tag)
|
1209
|
+
|
1210
|
+
TkFrame.new(fc, :bd=>0){|f|
|
1211
|
+
TkButton.new(f,
|
1212
|
+
:text=>'Delete', :bd=>1, :padx=>2, :pady=>0,
|
1213
|
+
:highlightthickness=>0, :command=>slave_delete_proc
|
1214
|
+
).pack(:side=>:right, :fill=>:both)
|
1215
|
+
f.pack(:side=>:right, :fill=>:both, :expand=>true)
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
TkLabel.new(fc, :text=>msg, :padx=>2, :pady=>0,
|
1219
|
+
:anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true)
|
1220
|
+
|
1221
|
+
fc.pack(:side=>:bottom, :fill=>:x)
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
# container frame for slave interpreter
|
1225
|
+
dup_keys['fill'] = :both unless dup_keys.key?('fill')
|
1226
|
+
dup_keys['expand'] = true unless dup_keys.key?('expand')
|
1227
|
+
c = TkFrame.new(top, :container=>true).pack(dup_keys)
|
1228
|
+
c.bind('Destroy', proc{top.destroy})
|
1229
|
+
|
1230
|
+
# return keys
|
1231
|
+
loadTk_keys['use'] = TkWinfo.id(c)
|
1232
|
+
[loadTk_keys, top.path]
|
1233
|
+
end
|
1234
|
+
private :__create_safetk_frame
|
1235
|
+
|
1236
|
+
def __create_safe_slave_obj(safe_opts, app_name, tk_opts)
|
1237
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1238
|
+
|
1239
|
+
# safe interpreter
|
1240
|
+
ip_name = _create_slave_ip_name
|
1241
|
+
slave_ip = @interp.create_slave(ip_name, true)
|
1242
|
+
slave_ip.instance_eval{
|
1243
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
1244
|
+
@encoding ||= TkUtil.untrust([nil])
|
1245
|
+
def @encoding.to_s; self.join(nil); end
|
1246
|
+
}
|
1247
|
+
@slave_ip_tbl[ip_name] = slave_ip
|
1248
|
+
def slave_ip.safe_base?
|
1249
|
+
true
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
@interp._eval("::safe::interpInit #{ip_name}")
|
1253
|
+
|
1254
|
+
slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String)
|
1255
|
+
|
1256
|
+
if tk_opts
|
1257
|
+
tk_opts = __check_safetk_optkeys(tk_opts)
|
1258
|
+
if tk_opts.key?('use')
|
1259
|
+
@slave_ip_top[ip_name] = ''
|
1260
|
+
else
|
1261
|
+
tk_opts, top_path = __create_safetk_frame(slave_ip, ip_name, app_name,
|
1262
|
+
tk_opts)
|
1263
|
+
@slave_ip_top[ip_name] = top_path
|
1264
|
+
end
|
1265
|
+
@interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
|
1266
|
+
@interp._invoke('__replace_slave_tk_commands__', ip_name)
|
1267
|
+
else
|
1268
|
+
@slave_ip_top[ip_name] = nil
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
if safe_opts.key?('deleteHook') || safe_opts.key?(:deleteHook)
|
1272
|
+
@interp._eval("::safe::interpConfigure #{ip_name} " +
|
1273
|
+
_keys2opts(safe_opts))
|
1274
|
+
else
|
1275
|
+
@interp._eval("::safe::interpConfigure #{ip_name} " +
|
1276
|
+
_keys2opts(safe_opts) + '-deleteHook {' +
|
1277
|
+
TkComm._get_eval_string(proc{|slave|
|
1278
|
+
self._default_delete_hook(slave)
|
1279
|
+
}) + '}')
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
[slave_ip, ip_name]
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
def __create_trusted_slave_obj(name, keys)
|
1286
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1287
|
+
|
1288
|
+
ip_name = _create_slave_ip_name
|
1289
|
+
slave_ip = @interp.create_slave(ip_name, false)
|
1290
|
+
slave_ip.instance_eval{
|
1291
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
1292
|
+
@encoding ||= TkUtil.untrust([nil])
|
1293
|
+
def @encoding.to_s; self.join(nil); end
|
1294
|
+
}
|
1295
|
+
slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String)
|
1296
|
+
slave_ip._invoke('set', 'argv', _keys2opts(keys))
|
1297
|
+
@interp._invoke('load', '', 'Tk', ip_name)
|
1298
|
+
@interp._invoke('__replace_slave_tk_commands__', ip_name)
|
1299
|
+
@slave_ip_tbl[ip_name] = slave_ip
|
1300
|
+
[slave_ip, ip_name]
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
######################################
|
1304
|
+
|
1305
|
+
def _create_slave_object(keys={})
|
1306
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1307
|
+
|
1308
|
+
ip = MultiTkIp.new_slave(self, keys={})
|
1309
|
+
@slave_ip_tbl[ip.name] = ip
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
######################################
|
1313
|
+
|
1314
|
+
def initialize(master, safeip=true, keys={})
|
1315
|
+
if $SAFE >= 4
|
1316
|
+
fail SecurityError, "cannot create a new interpreter at level #{$SAFE}"
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
if safeip == nil && $SAFE >= 2
|
1320
|
+
fail SecurityError, "cannot create a master-ip at level #{$SAFE}"
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
if master.deleted? && safeip == nil
|
1324
|
+
fail RuntimeError, "cannot create a slave of a deleted interpreter"
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
if !master.deleted? && !master.master? && master.safe?
|
1328
|
+
fail SecurityError, "safe-slave-ip cannot create a new interpreter"
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
if safeip == nil && !master.master?
|
1332
|
+
fail SecurityError, "slave-ip cannot create a master-ip"
|
1333
|
+
end
|
1334
|
+
|
1335
|
+
unless keys.kind_of? Hash
|
1336
|
+
fail ArgumentError, "expecting a Hash object for the 2nd argument"
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
@tk_windows = {}
|
1340
|
+
@tk_table_list = []
|
1341
|
+
@slave_ip_tbl = {}
|
1342
|
+
@slave_ip_top = {}
|
1343
|
+
@cb_error_proc = []
|
1344
|
+
@evloop_thread = []
|
1345
|
+
|
1346
|
+
TkUtil.untrust(@tk_windows) unless @tk_windows.tainted?
|
1347
|
+
TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted?
|
1348
|
+
TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted?
|
1349
|
+
TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted?
|
1350
|
+
TkUtil.untrust(@cb_error_proc) unless @cb_error_proc.tainted?
|
1351
|
+
TkUtil.untrust(@evloop_thread) unless @evloop_thread.tainted?
|
1352
|
+
|
1353
|
+
@callback_status = []
|
1354
|
+
|
1355
|
+
name, safe, safe_opts, tk_opts = _parse_slaveopts(keys)
|
1356
|
+
|
1357
|
+
safe = 4 if safe && !safe.kind_of?(Fixnum)
|
1358
|
+
|
1359
|
+
@safe_base = false
|
1360
|
+
|
1361
|
+
if safeip == nil
|
1362
|
+
# create master-ip
|
1363
|
+
unless WITH_RUBY_VM
|
1364
|
+
@interp = TclTkIp.new(name, _keys2opts(tk_opts))
|
1365
|
+
@interp.instance_eval{
|
1366
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
1367
|
+
@encoding ||= TkUtil.untrust([nil])
|
1368
|
+
def @encoding.to_s; self.join(nil); end
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
else ### Ruby 1.9 !!!!!!!!!!!
|
1372
|
+
=begin
|
1373
|
+
@interp_thread = Thread.new{
|
1374
|
+
Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts))
|
1375
|
+
interp.instance_eval{
|
1376
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
1377
|
+
@encoding ||= TkUtil.untrust([nil])
|
1378
|
+
def @encoding.to_s; self.join(nil); end
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
#sleep
|
1382
|
+
TclTkLib.mainloop(true)
|
1383
|
+
}
|
1384
|
+
until @interp_thread[:interp]
|
1385
|
+
Thread.pass
|
1386
|
+
end
|
1387
|
+
# INTERP_THREAD.run
|
1388
|
+
@interp = @interp_thread[:interp]
|
1389
|
+
=end
|
1390
|
+
@interp_thread = Thread.new{
|
1391
|
+
current = Thread.current
|
1392
|
+
begin
|
1393
|
+
current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts))
|
1394
|
+
rescue e
|
1395
|
+
current[:interp] = e
|
1396
|
+
raise e
|
1397
|
+
end
|
1398
|
+
#sleep
|
1399
|
+
#TclTkLib.mainloop(true)
|
1400
|
+
current[:mutex] = mutex = Mutex.new
|
1401
|
+
current[:root_check] = cond_ver = ConditionVariable.new
|
1402
|
+
|
1403
|
+
status = [nil]
|
1404
|
+
def status.value
|
1405
|
+
self[0]
|
1406
|
+
end
|
1407
|
+
def status.value=(val)
|
1408
|
+
self[0] = val
|
1409
|
+
end
|
1410
|
+
current[:status] = status
|
1411
|
+
|
1412
|
+
begin
|
1413
|
+
begin
|
1414
|
+
current[:status].value = interp.mainloop(true)
|
1415
|
+
rescue SystemExit=>e
|
1416
|
+
current[:status].value = e
|
1417
|
+
rescue Exception=>e
|
1418
|
+
current[:status].value = e
|
1419
|
+
retry if interp.has_mainwindow?
|
1420
|
+
ensure
|
1421
|
+
mutex.synchronize{ cond_var.broadcast }
|
1422
|
+
end
|
1423
|
+
current[:status].value = interp.mainloop(false)
|
1424
|
+
ensure
|
1425
|
+
interp.delete
|
1426
|
+
end
|
1427
|
+
}
|
1428
|
+
until @interp_thread[:interp]
|
1429
|
+
Thread.pass
|
1430
|
+
end
|
1431
|
+
# INTERP_THREAD.run
|
1432
|
+
@interp = @interp_thread[:interp]
|
1433
|
+
|
1434
|
+
@evloop_thread[0] = @interp_thread
|
1435
|
+
|
1436
|
+
def self.mainloop(check_root = true)
|
1437
|
+
begin
|
1438
|
+
TclTkLib.set_eventloop_window_mode(true)
|
1439
|
+
@interp_thread.value
|
1440
|
+
ensure
|
1441
|
+
TclTkLib.set_eventloop_window_mode(false)
|
1442
|
+
end
|
1443
|
+
end
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
@interp.instance_eval{
|
1447
|
+
@force_default_encoding ||= TkUtil.untrust([false])
|
1448
|
+
@encoding ||= TkUtil.untrust([nil])
|
1449
|
+
def @encoding.to_s; self.join(nil); end
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
@ip_name = nil
|
1453
|
+
|
1454
|
+
if safe
|
1455
|
+
safe = $SAFE if safe < $SAFE
|
1456
|
+
@safe_level = [safe]
|
1457
|
+
else
|
1458
|
+
@safe_level = [$SAFE]
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
else
|
1462
|
+
# create slave-ip
|
1463
|
+
if safeip || master.safe?
|
1464
|
+
@safe_base = true
|
1465
|
+
@interp, @ip_name = master.__create_safe_slave_obj(safe_opts,
|
1466
|
+
name, tk_opts)
|
1467
|
+
# @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
|
1468
|
+
@interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
|
1469
|
+
if safe
|
1470
|
+
safe = master.safe_level if safe < master.safe_level
|
1471
|
+
@safe_level = [safe]
|
1472
|
+
else
|
1473
|
+
@safe_level = [4]
|
1474
|
+
end
|
1475
|
+
else
|
1476
|
+
@interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts)
|
1477
|
+
# @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
|
1478
|
+
@interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
|
1479
|
+
if safe
|
1480
|
+
safe = master.safe_level if safe < master.safe_level
|
1481
|
+
@safe_level = [safe]
|
1482
|
+
else
|
1483
|
+
@safe_level = [master.safe_level]
|
1484
|
+
end
|
1485
|
+
end
|
1486
|
+
@set_alias_proc = proc{|name|
|
1487
|
+
master._invoke('interp', 'alias', @ip_name, name, '', name)
|
1488
|
+
}.freeze
|
1489
|
+
end
|
1490
|
+
|
1491
|
+
@system = Object.new
|
1492
|
+
|
1493
|
+
@wait_on_mainloop = TkUtil.untrust([true, 0])
|
1494
|
+
# @wait_on_mainloop = TkUtil.untrust([false, 0])
|
1495
|
+
|
1496
|
+
@threadgroup = ThreadGroup.new
|
1497
|
+
|
1498
|
+
@pseudo_toplevel = [false, nil]
|
1499
|
+
|
1500
|
+
@cmd_queue = MultiTkIp::Command_Queue.new(@interp)
|
1501
|
+
|
1502
|
+
=begin
|
1503
|
+
@cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
|
1504
|
+
|
1505
|
+
@threadgroup.add @cmd_receiver
|
1506
|
+
@threadgroup.add @receiver_watchdog
|
1507
|
+
|
1508
|
+
@threadgroup.enclose
|
1509
|
+
=end
|
1510
|
+
@@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
|
1511
|
+
|
1512
|
+
@@IP_TABLE[@threadgroup] = self
|
1513
|
+
@@TK_TABLE_LIST.size.times{
|
1514
|
+
@tk_table_list << TkUtil.untrust({})
|
1515
|
+
}
|
1516
|
+
_init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
|
1517
|
+
|
1518
|
+
class << self
|
1519
|
+
undef :instance_eval
|
1520
|
+
end
|
1521
|
+
|
1522
|
+
# dummy call for initialization
|
1523
|
+
self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') }
|
1524
|
+
|
1525
|
+
self.freeze # defend against modification
|
1526
|
+
end
|
1527
|
+
|
1528
|
+
######################################
|
1529
|
+
|
1530
|
+
def _default_delete_hook(slave)
|
1531
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1532
|
+
@slave_ip_tbl.delete(slave)
|
1533
|
+
top = @slave_ip_top.delete(slave)
|
1534
|
+
if top.kind_of?(String)
|
1535
|
+
# call default hook of safetk.tcl (ignore exceptions)
|
1536
|
+
if top == ''
|
1537
|
+
begin
|
1538
|
+
@interp._eval("::safe::disallowTk #{slave}")
|
1539
|
+
rescue
|
1540
|
+
warn("Waring: fail to call '::safe::disallowTk'") if $DEBUG
|
1541
|
+
end
|
1542
|
+
else # toplevel path
|
1543
|
+
begin
|
1544
|
+
@interp._eval("::safe::tkDelete {} #{top} #{slave}")
|
1545
|
+
rescue
|
1546
|
+
warn("Waring: fail to call '::safe::tkDelete'") if $DEBUG
|
1547
|
+
begin
|
1548
|
+
@interp._eval("destroy #{top}")
|
1549
|
+
rescue
|
1550
|
+
warn("Waring: fail to destroy toplevel") if $DEBUG
|
1551
|
+
end
|
1552
|
+
end
|
1553
|
+
end
|
1554
|
+
end
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
end
|
1558
|
+
|
1559
|
+
|
1560
|
+
# get target IP
|
1561
|
+
class MultiTkIp
|
1562
|
+
@@CALLBACK_SUBTHREAD = Class.new(Thread){
|
1563
|
+
def self.new(interp, &blk)
|
1564
|
+
super(interp){|ip| Thread.current[:callback_ip] = ip; blk.call}
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
@table = TkUtil.untrust(Hash.new{|h,k| h[k] = TkUtil.untrust([])})
|
1568
|
+
def self.table
|
1569
|
+
@table
|
1570
|
+
end
|
1571
|
+
}
|
1572
|
+
|
1573
|
+
def self._ip_id_
|
1574
|
+
__getip._ip_id_
|
1575
|
+
end
|
1576
|
+
def _ip_id_
|
1577
|
+
# for RemoteTkIp
|
1578
|
+
''
|
1579
|
+
end
|
1580
|
+
|
1581
|
+
def self.__getip
|
1582
|
+
current = Thread.current
|
1583
|
+
if current.kind_of?(@@CALLBACK_SUBTHREAD)
|
1584
|
+
return current[:callback_ip]
|
1585
|
+
end
|
1586
|
+
if TclTkLib.mainloop_thread? != false && current[:callback_ip]
|
1587
|
+
return current[:callback_ip]
|
1588
|
+
end
|
1589
|
+
if current.group == ThreadGroup::Default
|
1590
|
+
@@DEFAULT_MASTER
|
1591
|
+
else
|
1592
|
+
ip = @@IP_TABLE[current.group]
|
1593
|
+
unless ip
|
1594
|
+
fail SecurityError,
|
1595
|
+
"cannot call Tk methods on #{Thread.current.inspect}"
|
1596
|
+
end
|
1597
|
+
ip
|
1598
|
+
end
|
1599
|
+
end
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
|
1603
|
+
# aliases of constructor
|
1604
|
+
class << MultiTkIp
|
1605
|
+
alias __new new
|
1606
|
+
private :__new
|
1607
|
+
|
1608
|
+
def new_master(safe=nil, keys={}, &blk)
|
1609
|
+
if MultiTkIp::WITH_RUBY_VM
|
1610
|
+
#### TODO !!!!!!
|
1611
|
+
fail RuntimeError,
|
1612
|
+
'sorry, still not support multiple master-interpreters on RubyVM'
|
1613
|
+
end
|
1614
|
+
|
1615
|
+
if safe.kind_of?(Hash)
|
1616
|
+
keys = safe
|
1617
|
+
elsif safe.kind_of?(Integer)
|
1618
|
+
raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
|
1619
|
+
if !keys.key?(:safe) && !keys.key?('safe')
|
1620
|
+
keys[:safe] = safe
|
1621
|
+
end
|
1622
|
+
elsif safe == nil
|
1623
|
+
# do nothing
|
1624
|
+
else
|
1625
|
+
raise ArgumentError, "unexpected argument(s)"
|
1626
|
+
end
|
1627
|
+
|
1628
|
+
ip = __new(__getip, nil, keys)
|
1629
|
+
#ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
|
1630
|
+
if block_given?
|
1631
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
|
1632
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)}
|
1633
|
+
ip._proc_on_safelevel(&blk).call(ip.safe_level)
|
1634
|
+
end
|
1635
|
+
ip
|
1636
|
+
end
|
1637
|
+
|
1638
|
+
alias new new_master
|
1639
|
+
|
1640
|
+
def new_slave(safe=nil, keys={}, &blk)
|
1641
|
+
if safe.kind_of?(Hash)
|
1642
|
+
keys = safe
|
1643
|
+
elsif safe.kind_of?(Integer)
|
1644
|
+
raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
|
1645
|
+
if !keys.key?(:safe) && !keys.key?('safe')
|
1646
|
+
keys[:safe] = safe
|
1647
|
+
end
|
1648
|
+
elsif safe == nil
|
1649
|
+
# do nothing
|
1650
|
+
else
|
1651
|
+
raise ArgumentError, "unexpected argument(s)"
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
ip = __new(__getip, false, keys)
|
1655
|
+
# ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
|
1656
|
+
if block_given?
|
1657
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
|
1658
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)}
|
1659
|
+
ip._proc_on_safelevel(&blk).call(ip.safe_level)
|
1660
|
+
end
|
1661
|
+
ip
|
1662
|
+
end
|
1663
|
+
alias new_trusted_slave new_slave
|
1664
|
+
|
1665
|
+
def new_safe_slave(safe=4, keys={}, &blk)
|
1666
|
+
if safe.kind_of?(Hash)
|
1667
|
+
keys = safe
|
1668
|
+
elsif safe.kind_of?(Integer)
|
1669
|
+
raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash)
|
1670
|
+
if !keys.key?(:safe) && !keys.key?('safe')
|
1671
|
+
keys[:safe] = safe
|
1672
|
+
end
|
1673
|
+
else
|
1674
|
+
raise ArgumentError, "unexpected argument(s)"
|
1675
|
+
end
|
1676
|
+
|
1677
|
+
ip = __new(__getip, true, keys)
|
1678
|
+
# ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given?
|
1679
|
+
if block_given?
|
1680
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)}
|
1681
|
+
#Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)}
|
1682
|
+
ip._proc_on_safelevel(&blk).call(ip.safe_level)
|
1683
|
+
end
|
1684
|
+
ip
|
1685
|
+
end
|
1686
|
+
alias new_safeTk new_safe_slave
|
1687
|
+
end
|
1688
|
+
|
1689
|
+
|
1690
|
+
# get info
|
1691
|
+
class MultiTkIp
|
1692
|
+
def inspect
|
1693
|
+
s = self.to_s.chop!
|
1694
|
+
if self.manipulable?
|
1695
|
+
if master?
|
1696
|
+
if @interp.deleted?
|
1697
|
+
s << ':deleted-master'
|
1698
|
+
else
|
1699
|
+
s << ':master'
|
1700
|
+
end
|
1701
|
+
else
|
1702
|
+
if @interp.deleted?
|
1703
|
+
s << ':deleted-slave'
|
1704
|
+
elsif @interp.safe?
|
1705
|
+
s << ':safe-slave'
|
1706
|
+
else
|
1707
|
+
s << ':trusted-slave'
|
1708
|
+
end
|
1709
|
+
end
|
1710
|
+
end
|
1711
|
+
s << '>'
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
def master?
|
1715
|
+
if @ip_name
|
1716
|
+
false
|
1717
|
+
else
|
1718
|
+
true
|
1719
|
+
end
|
1720
|
+
end
|
1721
|
+
def self.master?
|
1722
|
+
__getip.master?
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
def slave?
|
1726
|
+
not master?
|
1727
|
+
end
|
1728
|
+
def self.slave?
|
1729
|
+
not self.master?
|
1730
|
+
end
|
1731
|
+
|
1732
|
+
def alive?
|
1733
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1734
|
+
begin
|
1735
|
+
return false unless @cmd_receiver.alive?
|
1736
|
+
return false if @interp.deleted?
|
1737
|
+
return false if @interp._invoke('interp', 'exists', '') == '0'
|
1738
|
+
rescue Exception
|
1739
|
+
return false
|
1740
|
+
end
|
1741
|
+
true
|
1742
|
+
end
|
1743
|
+
def self.alive?
|
1744
|
+
__getip.alive?
|
1745
|
+
end
|
1746
|
+
|
1747
|
+
def path
|
1748
|
+
@ip_name || ''
|
1749
|
+
end
|
1750
|
+
def self.path
|
1751
|
+
__getip.path
|
1752
|
+
end
|
1753
|
+
def ip_name
|
1754
|
+
@ip_name || ''
|
1755
|
+
end
|
1756
|
+
def self.ip_name
|
1757
|
+
__getip.ip_name
|
1758
|
+
end
|
1759
|
+
def to_eval
|
1760
|
+
@ip_name || ''
|
1761
|
+
end
|
1762
|
+
def self.to_eval
|
1763
|
+
__getip.to_eval
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
def slaves(all = false)
|
1767
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
1768
|
+
@interp._invoke('interp','slaves').split.map!{|name|
|
1769
|
+
if @slave_ip_tbl.key?(name)
|
1770
|
+
@slave_ip_tbl[name]
|
1771
|
+
elsif all
|
1772
|
+
name
|
1773
|
+
else
|
1774
|
+
nil
|
1775
|
+
end
|
1776
|
+
}.compact!
|
1777
|
+
end
|
1778
|
+
def self.slaves(all = false)
|
1779
|
+
__getip.slaves(all)
|
1780
|
+
end
|
1781
|
+
|
1782
|
+
def manipulable?
|
1783
|
+
return true if (Thread.current.group == ThreadGroup::Default)
|
1784
|
+
ip = MultiTkIp.__getip
|
1785
|
+
(ip == self) || ip._is_master_of?(@interp)
|
1786
|
+
end
|
1787
|
+
def self.manipulable?
|
1788
|
+
true
|
1789
|
+
end
|
1790
|
+
|
1791
|
+
def _is_master_of?(tcltkip_obj)
|
1792
|
+
tcltkip_obj.slave_of?(@interp)
|
1793
|
+
end
|
1794
|
+
protected :_is_master_of?
|
1795
|
+
end
|
1796
|
+
|
1797
|
+
|
1798
|
+
# instance methods to treat tables
|
1799
|
+
class MultiTkIp
|
1800
|
+
def _tk_cmd_tbl
|
1801
|
+
tbl = {}
|
1802
|
+
MultiTkIp.tk_cmd_tbl.each{|id, ent| tbl[id] = ent if ent.ip == self }
|
1803
|
+
tbl
|
1804
|
+
end
|
1805
|
+
|
1806
|
+
def _tk_windows
|
1807
|
+
@tk_windows
|
1808
|
+
end
|
1809
|
+
|
1810
|
+
def _tk_table_list
|
1811
|
+
@tk_table_list
|
1812
|
+
end
|
1813
|
+
|
1814
|
+
def _add_new_tables
|
1815
|
+
(@@TK_TABLE_LIST.size - @tk_table_list.size).times{
|
1816
|
+
@tk_table_list << TkUtil.untrust({})
|
1817
|
+
}
|
1818
|
+
end
|
1819
|
+
|
1820
|
+
def _init_ip_env(script)
|
1821
|
+
self.eval_proc{script.call(self)}
|
1822
|
+
end
|
1823
|
+
|
1824
|
+
def _add_tk_procs(name, args, body)
|
1825
|
+
return if slave?
|
1826
|
+
@interp._invoke('proc', name, args, body) if args && body
|
1827
|
+
@interp._invoke('interp', 'slaves').split.each{|slave|
|
1828
|
+
@interp._invoke('interp', 'alias', slave, name, '', name)
|
1829
|
+
}
|
1830
|
+
end
|
1831
|
+
|
1832
|
+
def _remove_tk_procs(*names)
|
1833
|
+
return if slave?
|
1834
|
+
names.each{|name|
|
1835
|
+
name = name.to_s
|
1836
|
+
|
1837
|
+
return if @interp.deleted?
|
1838
|
+
@interp._invoke('rename', name, '')
|
1839
|
+
|
1840
|
+
return if @interp.deleted?
|
1841
|
+
@interp._invoke('interp', 'slaves').split.each{|slave|
|
1842
|
+
return if @interp.deleted?
|
1843
|
+
@interp._invoke('interp', 'alias', slave, name, '') rescue nil
|
1844
|
+
}
|
1845
|
+
}
|
1846
|
+
end
|
1847
|
+
|
1848
|
+
def _init_ip_internal(init_ip_env, add_tk_procs)
|
1849
|
+
#init_ip_env.each{|script| self.eval_proc{script.call(self)}}
|
1850
|
+
init_ip_env.each{|script| self._init_ip_env(script)}
|
1851
|
+
add_tk_procs.each{|name, args, body|
|
1852
|
+
if master?
|
1853
|
+
@interp._invoke('proc', name, args, body) if args && body
|
1854
|
+
else
|
1855
|
+
@set_alias_proc.call(name)
|
1856
|
+
end
|
1857
|
+
}
|
1858
|
+
end
|
1859
|
+
end
|
1860
|
+
|
1861
|
+
|
1862
|
+
# class methods to treat tables
|
1863
|
+
class MultiTkIp
|
1864
|
+
def self.tk_cmd_tbl
|
1865
|
+
@@TK_CMD_TBL
|
1866
|
+
end
|
1867
|
+
def self.tk_windows
|
1868
|
+
__getip._tk_windows
|
1869
|
+
end
|
1870
|
+
def self.tk_object_table(id)
|
1871
|
+
__getip._tk_table_list[id]
|
1872
|
+
end
|
1873
|
+
def self.create_table
|
1874
|
+
if __getip.slave?
|
1875
|
+
begin
|
1876
|
+
raise SecurityError, "slave-IP has no permission creating a new table"
|
1877
|
+
rescue SecurityError => e
|
1878
|
+
#p e.backtrace
|
1879
|
+
# Is called on a Ruby/Tk library?
|
1880
|
+
caller_info = e.backtrace[1]
|
1881
|
+
if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
|
1882
|
+
# Probably, caller is a Ruby/Tk library --> allow creating
|
1883
|
+
else
|
1884
|
+
raise e
|
1885
|
+
end
|
1886
|
+
end
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
id = @@TK_TABLE_LIST.size
|
1890
|
+
obj = Object.new
|
1891
|
+
@@TK_TABLE_LIST << obj
|
1892
|
+
obj.instance_variable_set(:@id, id)
|
1893
|
+
obj.instance_variable_set(:@mutex, Mutex.new)
|
1894
|
+
obj.instance_eval{
|
1895
|
+
def self.mutex
|
1896
|
+
@mutex
|
1897
|
+
end
|
1898
|
+
def self.method_missing(m, *args)
|
1899
|
+
MultiTkIp.tk_object_table(@id).__send__(m, *args)
|
1900
|
+
end
|
1901
|
+
}
|
1902
|
+
obj.freeze
|
1903
|
+
@@IP_TABLE.each{|tg, ip| ip._add_new_tables }
|
1904
|
+
return obj
|
1905
|
+
end
|
1906
|
+
|
1907
|
+
def self.init_ip_env(script = Proc.new)
|
1908
|
+
@@INIT_IP_ENV << script
|
1909
|
+
if __getip.slave?
|
1910
|
+
begin
|
1911
|
+
raise SecurityError, "slave-IP has no permission initializing IP env"
|
1912
|
+
rescue SecurityError => e
|
1913
|
+
#p e.backtrace
|
1914
|
+
# Is called on a Ruby/Tk library?
|
1915
|
+
caller_info = e.backtrace[1]
|
1916
|
+
if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
|
1917
|
+
# Probably, caller is a Ruby/Tk library --> allow creating
|
1918
|
+
else
|
1919
|
+
raise e
|
1920
|
+
end
|
1921
|
+
end
|
1922
|
+
end
|
1923
|
+
|
1924
|
+
# @@IP_TABLE.each{|tg, ip|
|
1925
|
+
# ip._init_ip_env(script)
|
1926
|
+
# }
|
1927
|
+
@@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script)
|
1928
|
+
end
|
1929
|
+
|
1930
|
+
def self.add_tk_procs(name, args=nil, body=nil)
|
1931
|
+
if name.kind_of?(Array) # => an array of [name, args, body]
|
1932
|
+
name.each{|param| self.add_tk_procs(*param)}
|
1933
|
+
else
|
1934
|
+
name = name.to_s
|
1935
|
+
@@ADD_TK_PROCS << [name, args, body]
|
1936
|
+
@@IP_TABLE.each{|tg, ip|
|
1937
|
+
ip._add_tk_procs(name, args, body)
|
1938
|
+
}
|
1939
|
+
end
|
1940
|
+
end
|
1941
|
+
|
1942
|
+
def self.remove_tk_procs(*names)
|
1943
|
+
names.each{|name|
|
1944
|
+
name = name.to_s
|
1945
|
+
@@ADD_TK_PROCS.delete_if{|elem|
|
1946
|
+
elem.kind_of?(Array) && elem[0].to_s == name
|
1947
|
+
}
|
1948
|
+
}
|
1949
|
+
@@IP_TABLE.each{|tg, ip|
|
1950
|
+
ip._remove_tk_procs(*names)
|
1951
|
+
}
|
1952
|
+
end
|
1953
|
+
|
1954
|
+
def self.init_ip_internal
|
1955
|
+
__getip._init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
|
1956
|
+
end
|
1957
|
+
end
|
1958
|
+
|
1959
|
+
# for callback operation
|
1960
|
+
class MultiTkIp
|
1961
|
+
def self.cb_entry_class
|
1962
|
+
@@CB_ENTRY_CLASS
|
1963
|
+
end
|
1964
|
+
def self.get_cb_entry(cmd)
|
1965
|
+
@@CB_ENTRY_CLASS.new(__getip, cmd).freeze
|
1966
|
+
end
|
1967
|
+
|
1968
|
+
=begin
|
1969
|
+
def cb_eval(cmd, *args)
|
1970
|
+
#self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
|
1971
|
+
#ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) }
|
1972
|
+
ret = self.eval_callback(*args){|safe, *params|
|
1973
|
+
$SAFE=safe if $SAFE < safe
|
1974
|
+
TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
1975
|
+
}
|
1976
|
+
if ret.kind_of?(Exception)
|
1977
|
+
raise ret
|
1978
|
+
end
|
1979
|
+
ret
|
1980
|
+
end
|
1981
|
+
=end
|
1982
|
+
def cb_eval(cmd, *args)
|
1983
|
+
self.eval_callback(*args,
|
1984
|
+
&_proc_on_safelevel{|*params|
|
1985
|
+
TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
1986
|
+
})
|
1987
|
+
end
|
1988
|
+
=begin
|
1989
|
+
def cb_eval(cmd, *args)
|
1990
|
+
self.eval_callback(*args){|safe, *params|
|
1991
|
+
$SAFE=safe if $SAFE < safe
|
1992
|
+
# TkUtil.eval_cmd(cmd, *params)
|
1993
|
+
TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
1994
|
+
}
|
1995
|
+
end
|
1996
|
+
=end
|
1997
|
+
=begin
|
1998
|
+
def cb_eval(cmd, *args)
|
1999
|
+
@callback_status[0] ||= TkVariable.new
|
2000
|
+
@callback_status[1] ||= TkVariable.new
|
2001
|
+
st, val = @callback_status
|
2002
|
+
th = Thread.new{
|
2003
|
+
self.eval_callback(*args){|safe, *params|
|
2004
|
+
#p [status, val, safe, *params]
|
2005
|
+
$SAFE=safe if $SAFE < safe
|
2006
|
+
begin
|
2007
|
+
TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params))
|
2008
|
+
rescue TkCallbackContinue
|
2009
|
+
st.value = 4
|
2010
|
+
rescue TkCallbackBreak
|
2011
|
+
st.value = 3
|
2012
|
+
rescue TkCallbackReturn
|
2013
|
+
st.value = 2
|
2014
|
+
rescue Exception => e
|
2015
|
+
val.value = e.message
|
2016
|
+
st.value = 1
|
2017
|
+
else
|
2018
|
+
st.value = 0
|
2019
|
+
end
|
2020
|
+
}
|
2021
|
+
}
|
2022
|
+
begin
|
2023
|
+
st.wait
|
2024
|
+
status = st.numeric
|
2025
|
+
retval = val.value
|
2026
|
+
rescue => e
|
2027
|
+
fail e
|
2028
|
+
end
|
2029
|
+
|
2030
|
+
if status == 1
|
2031
|
+
fail RuntimeError, retval
|
2032
|
+
elsif status == 2
|
2033
|
+
fail TkCallbackReturn, "Tk callback returns 'return' status"
|
2034
|
+
elsif status == 3
|
2035
|
+
fail TkCallbackBreak, "Tk callback returns 'break' status"
|
2036
|
+
elsif status == 4
|
2037
|
+
fail TkCallbackContinue, "Tk callback returns 'continue' status"
|
2038
|
+
else
|
2039
|
+
''
|
2040
|
+
end
|
2041
|
+
end
|
2042
|
+
=end
|
2043
|
+
|
2044
|
+
end
|
2045
|
+
|
2046
|
+
# pseudo-toplevel operation support
|
2047
|
+
class MultiTkIp
|
2048
|
+
# instance method
|
2049
|
+
def __pseudo_toplevel
|
2050
|
+
ip = MultiTkIp.__getip
|
2051
|
+
(ip == @@DEFAULT_MASTER || ip == self) &&
|
2052
|
+
self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
|
2053
|
+
end
|
2054
|
+
|
2055
|
+
def __pseudo_toplevel=(m)
|
2056
|
+
unless (Thread.current.group == ThreadGroup::Default &&
|
2057
|
+
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
2058
|
+
fail SecurityError, "no permission to manipulate"
|
2059
|
+
end
|
2060
|
+
|
2061
|
+
# if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
|
2062
|
+
if m.respond_to?(:pseudo_toplevel_evaluable?)
|
2063
|
+
@pseudo_toplevel[0] = true
|
2064
|
+
@pseudo_toplevel[1] = m
|
2065
|
+
else
|
2066
|
+
fail ArgumentError, 'fail to set pseudo-toplevel'
|
2067
|
+
end
|
2068
|
+
self
|
2069
|
+
end
|
2070
|
+
|
2071
|
+
def __pseudo_toplevel_evaluable?
|
2072
|
+
begin
|
2073
|
+
@pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
|
2074
|
+
rescue Exception
|
2075
|
+
false
|
2076
|
+
end
|
2077
|
+
end
|
2078
|
+
|
2079
|
+
def __pseudo_toplevel_evaluable=(mode)
|
2080
|
+
unless (Thread.current.group == ThreadGroup::Default &&
|
2081
|
+
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
2082
|
+
fail SecurityError, "no permission to manipulate"
|
2083
|
+
end
|
2084
|
+
|
2085
|
+
@pseudo_toplevel[0] = (mode)? true: false
|
2086
|
+
end
|
2087
|
+
end
|
2088
|
+
|
2089
|
+
# evaluate a procedure on the proper interpreter
|
2090
|
+
class MultiTkIp
|
2091
|
+
# instance & class method
|
2092
|
+
def _proc_on_safelevel(cmd=nil, &blk) # require a block for eval
|
2093
|
+
if cmd
|
2094
|
+
if cmd.kind_of?(Method)
|
2095
|
+
_proc_on_safelevel{|*args| cmd.call(*args)}
|
2096
|
+
else
|
2097
|
+
_proc_on_safelevel(&cmd)
|
2098
|
+
end
|
2099
|
+
else
|
2100
|
+
#Proc.new{|safe, *args| $SAFE=safe if $SAFE < safe; yield(*args)}
|
2101
|
+
Proc.new{|safe, *args|
|
2102
|
+
# avoid security error on Exception objects
|
2103
|
+
untrust_proc = proc{|err|
|
2104
|
+
begin
|
2105
|
+
err.untrust if err.respond_to?(:untrust)
|
2106
|
+
rescue SecurityError
|
2107
|
+
end
|
2108
|
+
err
|
2109
|
+
}
|
2110
|
+
$SAFE=safe if $SAFE < safe;
|
2111
|
+
begin
|
2112
|
+
yield(*args)
|
2113
|
+
rescue Exception => e
|
2114
|
+
fail untrust_proc.call(e)
|
2115
|
+
end
|
2116
|
+
}
|
2117
|
+
end
|
2118
|
+
end
|
2119
|
+
def MultiTkIp._proc_on_safelevel(cmd=nil, &blk)
|
2120
|
+
MultiTkIp.__getip._proc_on_safelevel(cmd, &blk)
|
2121
|
+
end
|
2122
|
+
|
2123
|
+
def _proc_on_current_safelevel(cmd=nil, &blk) # require a block for eval
|
2124
|
+
safe = $SAFE
|
2125
|
+
cmd = _proc_on_safelevel(cmd, &blk)
|
2126
|
+
Proc.new{|*args| cmd.call(safe, *args)}
|
2127
|
+
end
|
2128
|
+
def MultiTkIp._proc_on_current_safelevel(cmd=nil, &blk)
|
2129
|
+
MultiTkIp.__getip._proc_on_current_safelevel(cmd, &blk)
|
2130
|
+
end
|
2131
|
+
|
2132
|
+
######################################
|
2133
|
+
# instance method
|
2134
|
+
def eval_proc_core(req_val, cmd, *args)
|
2135
|
+
# check
|
2136
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2137
|
+
unless cmd.kind_of?(Proc) || cmd.kind_of?(Method)
|
2138
|
+
raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument"
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
# on IP thread
|
2142
|
+
if @cmd_receiver == Thread.current ||
|
2143
|
+
(!req_val && TclTkLib.mainloop_thread? != false) # callback
|
2144
|
+
begin
|
2145
|
+
ret = cmd.call(safe_level, *args)
|
2146
|
+
rescue SystemExit => e
|
2147
|
+
# exit IP
|
2148
|
+
warn("Warning: "+ e.inspect + " on " + self.inspect) if $DEBUG
|
2149
|
+
begin
|
2150
|
+
self._eval_without_enc('exit')
|
2151
|
+
rescue Exception => e
|
2152
|
+
end
|
2153
|
+
self.delete
|
2154
|
+
ret = nil
|
2155
|
+
rescue Exception => e
|
2156
|
+
if $DEBUG
|
2157
|
+
warn("Warning: " + e.class.inspect +
|
2158
|
+
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
2159
|
+
" on " + self.inspect)
|
2160
|
+
end
|
2161
|
+
=begin
|
2162
|
+
begin
|
2163
|
+
bt = _toUTF8(e.backtrace.join("\n"))
|
2164
|
+
bt.instance_variable_set(:@encoding, 'utf-8')
|
2165
|
+
rescue Exception
|
2166
|
+
bt = e.backtrace.join("\n")
|
2167
|
+
end
|
2168
|
+
begin
|
2169
|
+
@interp._set_global_var('errorInfo', bt)
|
2170
|
+
rescue Exception
|
2171
|
+
end
|
2172
|
+
=end
|
2173
|
+
ret = e
|
2174
|
+
end
|
2175
|
+
return ret
|
2176
|
+
end
|
2177
|
+
|
2178
|
+
# send cmd to the proc-queue
|
2179
|
+
unless req_val
|
2180
|
+
begin
|
2181
|
+
@cmd_queue.enq([nil, cmd, *args])
|
2182
|
+
rescue Exception => e
|
2183
|
+
# ignore
|
2184
|
+
if $DEBUG
|
2185
|
+
warn("Warning: " + e.class.inspect +
|
2186
|
+
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
2187
|
+
" on " + self.inspect)
|
2188
|
+
end
|
2189
|
+
return e
|
2190
|
+
end
|
2191
|
+
return nil
|
2192
|
+
end
|
2193
|
+
|
2194
|
+
# send and get return value by exception
|
2195
|
+
begin
|
2196
|
+
@cmd_queue.enq([Thread.current, cmd, *args])
|
2197
|
+
Thread.stop
|
2198
|
+
rescue MultiTkIp_OK => ret
|
2199
|
+
# return value
|
2200
|
+
return ret.value
|
2201
|
+
rescue SystemExit => e
|
2202
|
+
# exit IP
|
2203
|
+
warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG
|
2204
|
+
begin
|
2205
|
+
self._eval_without_enc('exit')
|
2206
|
+
rescue Exception
|
2207
|
+
end
|
2208
|
+
if !self.deleted? && !safe? && allow_ruby_exit?
|
2209
|
+
self.delete
|
2210
|
+
fail e
|
2211
|
+
else
|
2212
|
+
self.delete
|
2213
|
+
end
|
2214
|
+
rescue Exception => e
|
2215
|
+
if $DEBUG
|
2216
|
+
warn("Warning: " + e.class.inspect +
|
2217
|
+
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
2218
|
+
" on " + self.inspect)
|
2219
|
+
end
|
2220
|
+
return e
|
2221
|
+
end
|
2222
|
+
return nil
|
2223
|
+
end
|
2224
|
+
private :eval_proc_core
|
2225
|
+
|
2226
|
+
if false && WITH_RUBY_VM ### Ruby 1.9
|
2227
|
+
# Not stable, so disable this feature
|
2228
|
+
def eval_callback(*args)
|
2229
|
+
if block_given?
|
2230
|
+
cmd = Proc.new
|
2231
|
+
else
|
2232
|
+
cmd = args.shift
|
2233
|
+
end
|
2234
|
+
begin
|
2235
|
+
if @@CALLBACK_SUBTHREAD.table[self].index(Thread.current)
|
2236
|
+
last_th = nil
|
2237
|
+
else
|
2238
|
+
last_th = @@CALLBACK_SUBTHREAD.table[self][-1]
|
2239
|
+
end
|
2240
|
+
@@CALLBACK_SUBTHREAD.new(self){
|
2241
|
+
@@CALLBACK_SUBTHREAD.table[self] << Thread.current
|
2242
|
+
begin
|
2243
|
+
last_th.join if last_th
|
2244
|
+
eval_proc_core(false, cmd, *args)
|
2245
|
+
rescue Exception=>e
|
2246
|
+
e
|
2247
|
+
ensure
|
2248
|
+
@@CALLBACK_SUBTHREAD.table[self].delete(Thread.current)
|
2249
|
+
end
|
2250
|
+
}
|
2251
|
+
end
|
2252
|
+
end
|
2253
|
+
else ### Ruby 1.8
|
2254
|
+
def eval_callback(*args)
|
2255
|
+
if block_given?
|
2256
|
+
cmd = Proc.new
|
2257
|
+
else
|
2258
|
+
cmd = args.shift
|
2259
|
+
end
|
2260
|
+
begin
|
2261
|
+
eval_proc_core(false, cmd, *args)
|
2262
|
+
rescue Exception=>e
|
2263
|
+
e
|
2264
|
+
ensure
|
2265
|
+
end
|
2266
|
+
end
|
2267
|
+
end
|
2268
|
+
|
2269
|
+
def eval_proc(*args, &blk)
|
2270
|
+
if block_given?
|
2271
|
+
cmd = _proc_on_safelevel(&blk)
|
2272
|
+
else
|
2273
|
+
unless (cmd = args.shift)
|
2274
|
+
fail ArgumentError, "A Proc or Method object is expected for 1st argument"
|
2275
|
+
end
|
2276
|
+
cmd = _proc_on_safelevel(&cmd)
|
2277
|
+
end
|
2278
|
+
if TclTkLib.mainloop_thread? == true
|
2279
|
+
# call from eventloop
|
2280
|
+
current = Thread.current
|
2281
|
+
backup_ip = current[:callback_ip]
|
2282
|
+
current[:callback_ip] = self
|
2283
|
+
begin
|
2284
|
+
eval_proc_core(false, cmd, *args)
|
2285
|
+
ensure
|
2286
|
+
current[:callback_ip] = backup_ip
|
2287
|
+
end
|
2288
|
+
else
|
2289
|
+
eval_proc_core(true,
|
2290
|
+
proc{|safe, *params|
|
2291
|
+
Thread.new{cmd.call(safe, *params)}.value
|
2292
|
+
},
|
2293
|
+
*args)
|
2294
|
+
end
|
2295
|
+
end
|
2296
|
+
=begin
|
2297
|
+
def eval_proc(*args)
|
2298
|
+
# The scope of the eval-block of 'eval_proc' method is different from
|
2299
|
+
# the external. If you want to pass local values to the eval-block,
|
2300
|
+
# use arguments of eval_proc method. They are passed to block-arguments.
|
2301
|
+
if block_given?
|
2302
|
+
cmd = Proc.new
|
2303
|
+
else
|
2304
|
+
unless (cmd = args.shift)
|
2305
|
+
fail ArgumentError, "A Proc or Method object is expected for 1st argument"
|
2306
|
+
end
|
2307
|
+
end
|
2308
|
+
if TclTkLib.mainloop_thread? == true
|
2309
|
+
# call from eventloop
|
2310
|
+
current = Thread.current
|
2311
|
+
backup_ip = current[:callback_ip]
|
2312
|
+
current[:callback_ip] = self
|
2313
|
+
begin
|
2314
|
+
eval_proc_core(false,
|
2315
|
+
proc{|safe, *params|
|
2316
|
+
$SAFE=safe if $SAFE < safe
|
2317
|
+
cmd.call(*params)
|
2318
|
+
}, *args)
|
2319
|
+
ensure
|
2320
|
+
current[:callback_ip] = backup_ip
|
2321
|
+
end
|
2322
|
+
else
|
2323
|
+
eval_proc_core(true,
|
2324
|
+
proc{|safe, *params|
|
2325
|
+
$SAFE=safe if $SAFE < safe
|
2326
|
+
Thread.new(*params, &cmd).value
|
2327
|
+
},
|
2328
|
+
*args)
|
2329
|
+
end
|
2330
|
+
end
|
2331
|
+
=end
|
2332
|
+
alias call eval_proc
|
2333
|
+
|
2334
|
+
def bg_eval_proc(*args)
|
2335
|
+
if block_given?
|
2336
|
+
cmd = Proc.new
|
2337
|
+
else
|
2338
|
+
unless (cmd = args.shift)
|
2339
|
+
fail ArgumentError, "A Proc or Method object is expected for 1st argument"
|
2340
|
+
end
|
2341
|
+
end
|
2342
|
+
Thread.new{
|
2343
|
+
eval_proc(cmd, *args)
|
2344
|
+
=begin
|
2345
|
+
eval_proc_core(false,
|
2346
|
+
proc{|safe, *params|
|
2347
|
+
$SAFE=safe if $SAFE < safe
|
2348
|
+
Thread.new(*params, &cmd).value
|
2349
|
+
},
|
2350
|
+
safe_level, *args)
|
2351
|
+
=end
|
2352
|
+
}
|
2353
|
+
end
|
2354
|
+
alias background_eval_proc bg_eval_proc
|
2355
|
+
alias thread_eval_proc bg_eval_proc
|
2356
|
+
alias bg_call bg_eval_proc
|
2357
|
+
alias background_call bg_eval_proc
|
2358
|
+
|
2359
|
+
def eval_string(cmd, *eval_args)
|
2360
|
+
# cmd string ==> proc
|
2361
|
+
unless cmd.kind_of?(String)
|
2362
|
+
raise RuntimeError, "A String object is expected for the 'cmd' argument"
|
2363
|
+
end
|
2364
|
+
|
2365
|
+
eval_proc_core(true,
|
2366
|
+
proc{|safe|
|
2367
|
+
Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
|
2368
|
+
*eval_args)
|
2369
|
+
})
|
2370
|
+
end
|
2371
|
+
alias eval_str eval_string
|
2372
|
+
|
2373
|
+
def bg_eval_string(cmd, *eval_args)
|
2374
|
+
# cmd string ==> proc
|
2375
|
+
unless cmd.kind_of?(String)
|
2376
|
+
raise RuntimeError, "A String object is expected for the 'cmd' argument"
|
2377
|
+
end
|
2378
|
+
Thread.new{
|
2379
|
+
eval_proc_core(true,
|
2380
|
+
proc{|safe|
|
2381
|
+
Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd,
|
2382
|
+
*eval_args)
|
2383
|
+
})
|
2384
|
+
}
|
2385
|
+
end
|
2386
|
+
alias background_eval_string bg_eval_string
|
2387
|
+
alias bg_eval_str bg_eval_string
|
2388
|
+
alias background_eval_str bg_eval_string
|
2389
|
+
|
2390
|
+
def eval(*args, &blk)
|
2391
|
+
if block_given?
|
2392
|
+
eval_proc(*args, &blk)
|
2393
|
+
elsif args[0]
|
2394
|
+
if args[0].respond_to?(:call)
|
2395
|
+
eval_proc(*args)
|
2396
|
+
else
|
2397
|
+
eval_string(*args)
|
2398
|
+
end
|
2399
|
+
else
|
2400
|
+
fail ArgumentError, "no argument to eval"
|
2401
|
+
end
|
2402
|
+
end
|
2403
|
+
|
2404
|
+
def bg_eval(*args, &blk)
|
2405
|
+
if block_given?
|
2406
|
+
bg_eval_proc(*args, &blk)
|
2407
|
+
elsif args[0]
|
2408
|
+
if args[0].respond_to?(:call)
|
2409
|
+
bg_eval_proc(*args)
|
2410
|
+
else
|
2411
|
+
bg_eval_string(*args)
|
2412
|
+
end
|
2413
|
+
else
|
2414
|
+
fail ArgumentError, "no argument to eval"
|
2415
|
+
end
|
2416
|
+
end
|
2417
|
+
alias background_eval bg_eval
|
2418
|
+
end
|
2419
|
+
|
2420
|
+
class << MultiTkIp
|
2421
|
+
# class method
|
2422
|
+
def eval_proc(*args, &blk)
|
2423
|
+
# class ==> interp object
|
2424
|
+
__getip.eval_proc(*args, &blk)
|
2425
|
+
end
|
2426
|
+
alias call eval_proc
|
2427
|
+
|
2428
|
+
def bg_eval_proc(*args, &blk)
|
2429
|
+
# class ==> interp object
|
2430
|
+
__getip.bg_eval_proc(*args, &blk)
|
2431
|
+
end
|
2432
|
+
alias background_eval_proc bg_eval_proc
|
2433
|
+
alias thread_eval_proc bg_eval_proc
|
2434
|
+
alias bg_call bg_eval_proc
|
2435
|
+
alias background_call bg_eval_proc
|
2436
|
+
|
2437
|
+
def eval_string(cmd, *eval_args)
|
2438
|
+
# class ==> interp object
|
2439
|
+
__getip.eval_string(cmd, *eval_args)
|
2440
|
+
end
|
2441
|
+
alias eval_str eval_string
|
2442
|
+
|
2443
|
+
def bg_eval_string(cmd, *eval_args)
|
2444
|
+
# class ==> interp object
|
2445
|
+
__getip.bg_eval_string(cmd, *eval_args)
|
2446
|
+
end
|
2447
|
+
alias background_eval_string bg_eval_string
|
2448
|
+
alias bg_eval_str bg_eval_string
|
2449
|
+
alias background_eval_str bg_eval_string
|
2450
|
+
|
2451
|
+
def eval(*args, &blk)
|
2452
|
+
# class ==> interp object
|
2453
|
+
__getip.eval(*args, &blk)
|
2454
|
+
end
|
2455
|
+
def bg_eval(*args, &blk)
|
2456
|
+
# class ==> interp object
|
2457
|
+
__getip.bg_eval(*args, &blk)
|
2458
|
+
end
|
2459
|
+
alias background_eval bg_eval
|
2460
|
+
end
|
2461
|
+
|
2462
|
+
|
2463
|
+
# event loop
|
2464
|
+
# all master/slave IPs are controled by only one event-loop
|
2465
|
+
class MultiTkIp
|
2466
|
+
def self.default_master?
|
2467
|
+
__getip == @@DEFAULT_MASTER
|
2468
|
+
end
|
2469
|
+
end
|
2470
|
+
class << MultiTkIp
|
2471
|
+
def mainloop(check_root = true)
|
2472
|
+
__getip.mainloop(check_root)
|
2473
|
+
end
|
2474
|
+
def mainloop_watchdog(check_root = true)
|
2475
|
+
__getip.mainloop_watchdog(check_root)
|
2476
|
+
end
|
2477
|
+
def do_one_event(flag = TclTkLib::EventFlag::ALL)
|
2478
|
+
__getip.do_one_event(flag)
|
2479
|
+
end
|
2480
|
+
def mainloop_abort_on_exception
|
2481
|
+
# __getip.mainloop_abort_on_exception
|
2482
|
+
TclTkLib.mainloop_abort_on_exception
|
2483
|
+
end
|
2484
|
+
def mainloop_abort_on_exception=(mode)
|
2485
|
+
# __getip.mainloop_abort_on_exception=(mode)
|
2486
|
+
TclTkLib.mainloop_abort_on_exception=(mode)
|
2487
|
+
end
|
2488
|
+
def set_eventloop_tick(tick)
|
2489
|
+
__getip.set_eventloop_tick(tick)
|
2490
|
+
end
|
2491
|
+
def get_eventloop_tick
|
2492
|
+
__getip.get_eventloop_tick
|
2493
|
+
end
|
2494
|
+
def set_no_event_wait(tick)
|
2495
|
+
__getip.set_no_event_wait(tick)
|
2496
|
+
end
|
2497
|
+
def get_no_event_wait
|
2498
|
+
__getip.get_no_event_wait
|
2499
|
+
end
|
2500
|
+
def set_eventloop_weight(loop_max, no_event_tick)
|
2501
|
+
__getip.set_eventloop_weight(loop_max, no_event_tick)
|
2502
|
+
end
|
2503
|
+
def get_eventloop_weight
|
2504
|
+
__getip.get_eventloop_weight
|
2505
|
+
end
|
2506
|
+
end
|
2507
|
+
|
2508
|
+
# class methods to delegate to TclTkIp
|
2509
|
+
class << MultiTkIp
|
2510
|
+
def method_missing(id, *args)
|
2511
|
+
__getip.__send__(id, *args)
|
2512
|
+
end
|
2513
|
+
|
2514
|
+
def make_safe
|
2515
|
+
__getip.make_safe
|
2516
|
+
end
|
2517
|
+
|
2518
|
+
def safe?
|
2519
|
+
__getip.safe?
|
2520
|
+
end
|
2521
|
+
|
2522
|
+
def safe_base?
|
2523
|
+
begin
|
2524
|
+
__getip.safe_base?
|
2525
|
+
rescue
|
2526
|
+
false
|
2527
|
+
end
|
2528
|
+
end
|
2529
|
+
|
2530
|
+
def allow_ruby_exit?
|
2531
|
+
__getip.allow_ruby_exit?
|
2532
|
+
end
|
2533
|
+
|
2534
|
+
def allow_ruby_exit= (mode)
|
2535
|
+
__getip.allow_ruby_exit = mode
|
2536
|
+
end
|
2537
|
+
|
2538
|
+
def delete
|
2539
|
+
__getip.delete
|
2540
|
+
end
|
2541
|
+
|
2542
|
+
def deleted?
|
2543
|
+
__getip.deleted?
|
2544
|
+
end
|
2545
|
+
|
2546
|
+
def has_mainwindow?
|
2547
|
+
__getip.has_mainwindow?
|
2548
|
+
end
|
2549
|
+
|
2550
|
+
def invalid_namespace?
|
2551
|
+
__getip.invalid_namespace?
|
2552
|
+
end
|
2553
|
+
|
2554
|
+
def abort(msg = nil)
|
2555
|
+
__getip.abort(msg)
|
2556
|
+
end
|
2557
|
+
|
2558
|
+
def exit(st = true)
|
2559
|
+
__getip.exit(st)
|
2560
|
+
end
|
2561
|
+
|
2562
|
+
def exit!(st = false)
|
2563
|
+
__getip.exit!(st)
|
2564
|
+
end
|
2565
|
+
|
2566
|
+
def restart(app_name = nil, keys = {})
|
2567
|
+
init_ip_internal
|
2568
|
+
|
2569
|
+
__getip._invoke('set', 'argv0', app_name) if app_name
|
2570
|
+
if keys.kind_of?(Hash)
|
2571
|
+
__getip._invoke('set', 'argv', _keys2opts(keys))
|
2572
|
+
end
|
2573
|
+
|
2574
|
+
__getip.restart
|
2575
|
+
end
|
2576
|
+
|
2577
|
+
def _eval(str)
|
2578
|
+
__getip._eval(str)
|
2579
|
+
end
|
2580
|
+
|
2581
|
+
def _invoke(*args)
|
2582
|
+
__getip._invoke(*args)
|
2583
|
+
end
|
2584
|
+
|
2585
|
+
def _eval_without_enc(str)
|
2586
|
+
__getip._eval_without_enc(str)
|
2587
|
+
end
|
2588
|
+
|
2589
|
+
def _invoke_without_enc(*args)
|
2590
|
+
__getip._invoke_without_enc(*args)
|
2591
|
+
end
|
2592
|
+
|
2593
|
+
def _eval_with_enc(str)
|
2594
|
+
__getip._eval_with_enc(str)
|
2595
|
+
end
|
2596
|
+
|
2597
|
+
def _invoke_with_enc(*args)
|
2598
|
+
__getip._invoke_with_enc(*args)
|
2599
|
+
end
|
2600
|
+
|
2601
|
+
def _toUTF8(str, encoding=nil)
|
2602
|
+
__getip._toUTF8(str, encoding)
|
2603
|
+
end
|
2604
|
+
|
2605
|
+
def _fromUTF8(str, encoding=nil)
|
2606
|
+
__getip._fromUTF8(str, encoding)
|
2607
|
+
end
|
2608
|
+
|
2609
|
+
def _thread_vwait(var)
|
2610
|
+
__getip._thread_vwait(var)
|
2611
|
+
end
|
2612
|
+
|
2613
|
+
def _thread_tkwait(mode, target)
|
2614
|
+
__getip._thread_tkwait(mode, target)
|
2615
|
+
end
|
2616
|
+
|
2617
|
+
def _return_value
|
2618
|
+
__getip._return_value
|
2619
|
+
end
|
2620
|
+
|
2621
|
+
def _get_variable(var, flag)
|
2622
|
+
__getip._get_variable(var, flag)
|
2623
|
+
end
|
2624
|
+
def _get_variable2(var, idx, flag)
|
2625
|
+
__getip._get_variable2(var, idx, flag)
|
2626
|
+
end
|
2627
|
+
def _set_variable(var, value, flag)
|
2628
|
+
__getip._set_variable(var, value, flag)
|
2629
|
+
end
|
2630
|
+
def _set_variable2(var, idx, value, flag)
|
2631
|
+
__getip._set_variable2(var, idx, value, flag)
|
2632
|
+
end
|
2633
|
+
def _unset_variable(var, flag)
|
2634
|
+
__getip._unset_variable(var, flag)
|
2635
|
+
end
|
2636
|
+
def _unset_variable2(var, idx, flag)
|
2637
|
+
__getip._unset_variable2(var, idx, flag)
|
2638
|
+
end
|
2639
|
+
|
2640
|
+
def _get_global_var(var)
|
2641
|
+
__getip._get_global_var(var)
|
2642
|
+
end
|
2643
|
+
def _get_global_var2(var, idx)
|
2644
|
+
__getip._get_global_var2(var, idx)
|
2645
|
+
end
|
2646
|
+
def _set_global_var(var, value)
|
2647
|
+
__getip._set_global_var(var, value)
|
2648
|
+
end
|
2649
|
+
def _set_global_var2(var, idx, value)
|
2650
|
+
__getip._set_global_var2(var, idx, value)
|
2651
|
+
end
|
2652
|
+
def _unset_global_var(var)
|
2653
|
+
__getip._unset_global_var(var)
|
2654
|
+
end
|
2655
|
+
def _unset_global_var2(var, idx)
|
2656
|
+
__getip._unset_global_var2(var, idx)
|
2657
|
+
end
|
2658
|
+
|
2659
|
+
def _make_menu_embeddable(menu_path)
|
2660
|
+
__getip._make_menu_embeddable(menu_path)
|
2661
|
+
end
|
2662
|
+
|
2663
|
+
def _split_tklist(str)
|
2664
|
+
__getip._split_tklist(str)
|
2665
|
+
end
|
2666
|
+
def _merge_tklist(*args)
|
2667
|
+
__getip._merge_tklist(*args)
|
2668
|
+
end
|
2669
|
+
def _conv_listelement(arg)
|
2670
|
+
__getip._conv_listelement(arg)
|
2671
|
+
end
|
2672
|
+
|
2673
|
+
def _create_console
|
2674
|
+
__getip._create_console
|
2675
|
+
end
|
2676
|
+
end
|
2677
|
+
|
2678
|
+
|
2679
|
+
# wrap methods on TclTkLib : not permit calling TclTkLib module methods
|
2680
|
+
class << TclTkLib
|
2681
|
+
def mainloop(check_root = true)
|
2682
|
+
MultiTkIp.mainloop(check_root)
|
2683
|
+
end
|
2684
|
+
def mainloop_watchdog(check_root = true)
|
2685
|
+
MultiTkIp.mainloop_watchdog(check_root)
|
2686
|
+
end
|
2687
|
+
def do_one_event(flag = TclTkLib::EventFlag::ALL)
|
2688
|
+
MultiTkIp.do_one_event(flag)
|
2689
|
+
end
|
2690
|
+
#def mainloop_abort_on_exception
|
2691
|
+
# MultiTkIp.mainloop_abort_on_exception
|
2692
|
+
#end
|
2693
|
+
#def mainloop_abort_on_exception=(mode)
|
2694
|
+
# MultiTkIp.mainloop_abort_on_exception=(mode)
|
2695
|
+
#end
|
2696
|
+
def set_eventloop_tick(tick)
|
2697
|
+
MultiTkIp.set_eventloop_tick(tick)
|
2698
|
+
end
|
2699
|
+
def get_eventloop_tick
|
2700
|
+
MultiTkIp.get_eventloop_tick
|
2701
|
+
end
|
2702
|
+
def set_no_event_wait(tick)
|
2703
|
+
MultiTkIp.set_no_event_wait(tick)
|
2704
|
+
end
|
2705
|
+
def get_no_event_wait
|
2706
|
+
MultiTkIp.get_no_event_wait
|
2707
|
+
end
|
2708
|
+
def set_eventloop_weight(loop_max, no_event_tick)
|
2709
|
+
MultiTkIp.set_eventloop_weight(loop_max, no_event_tick)
|
2710
|
+
end
|
2711
|
+
def get_eventloop_weight
|
2712
|
+
MultiTkIp.get_eventloop_weight
|
2713
|
+
end
|
2714
|
+
def restart(*args)
|
2715
|
+
MultiTkIp.restart(*args)
|
2716
|
+
end
|
2717
|
+
|
2718
|
+
def _merge_tklist(*args)
|
2719
|
+
MultiTkIp._merge_tklist(*args)
|
2720
|
+
end
|
2721
|
+
def _conv_listelement(arg)
|
2722
|
+
MultiTkIp._conv_listelement(arg)
|
2723
|
+
end
|
2724
|
+
end
|
2725
|
+
|
2726
|
+
|
2727
|
+
# depend on TclTkIp
|
2728
|
+
class MultiTkIp
|
2729
|
+
# def mainloop(check_root = true, restart_on_dead = true)
|
2730
|
+
def mainloop(check_root = true, restart_on_dead = false)
|
2731
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2732
|
+
|
2733
|
+
if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
|
2734
|
+
return @interp_thread.value if @interp_thread
|
2735
|
+
end
|
2736
|
+
|
2737
|
+
#return self if self.slave?
|
2738
|
+
#return self if self != @@DEFAULT_MASTER
|
2739
|
+
if self != @@DEFAULT_MASTER
|
2740
|
+
if @wait_on_mainloop[0]
|
2741
|
+
begin
|
2742
|
+
@wait_on_mainloop[1] += 1
|
2743
|
+
if $SAFE >= 4
|
2744
|
+
_receiver_mainloop(check_root).join
|
2745
|
+
else
|
2746
|
+
@cmd_queue.enq([@system, 'call_mainloop',
|
2747
|
+
Thread.current, check_root])
|
2748
|
+
Thread.stop
|
2749
|
+
end
|
2750
|
+
rescue MultiTkIp_OK => ret
|
2751
|
+
# return value
|
2752
|
+
if ret.value.kind_of?(Thread)
|
2753
|
+
return ret.value.value
|
2754
|
+
else
|
2755
|
+
return ret.value
|
2756
|
+
end
|
2757
|
+
rescue SystemExit => e
|
2758
|
+
# exit IP
|
2759
|
+
warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG
|
2760
|
+
begin
|
2761
|
+
self._eval_without_enc('exit')
|
2762
|
+
rescue Exception
|
2763
|
+
end
|
2764
|
+
self.delete
|
2765
|
+
rescue StandardError => e
|
2766
|
+
if $DEBUG
|
2767
|
+
warn("Warning: " + e.class.inspect +
|
2768
|
+
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
2769
|
+
" on " + self.inspect)
|
2770
|
+
end
|
2771
|
+
return e
|
2772
|
+
rescue Exception => e
|
2773
|
+
return e
|
2774
|
+
ensure
|
2775
|
+
@wait_on_mainloop[1] -= 1
|
2776
|
+
end
|
2777
|
+
end
|
2778
|
+
return
|
2779
|
+
end
|
2780
|
+
|
2781
|
+
unless restart_on_dead
|
2782
|
+
@wait_on_mainloop[1] += 1
|
2783
|
+
=begin
|
2784
|
+
begin
|
2785
|
+
@interp.mainloop(check_root)
|
2786
|
+
rescue StandardError => e
|
2787
|
+
if $DEBUG
|
2788
|
+
warn("Warning: " + e.class.inspect +
|
2789
|
+
((e.message.length > 0)? ' "' + e.message + '"': '') +
|
2790
|
+
" on " + self.inspect)
|
2791
|
+
end
|
2792
|
+
end
|
2793
|
+
=end
|
2794
|
+
begin
|
2795
|
+
@interp.mainloop(check_root)
|
2796
|
+
ensure
|
2797
|
+
@wait_on_mainloop[1] -= 1
|
2798
|
+
end
|
2799
|
+
else
|
2800
|
+
loop do
|
2801
|
+
break unless self.alive?
|
2802
|
+
if check_root
|
2803
|
+
begin
|
2804
|
+
break if TclTkLib.num_of_mainwindows == 0
|
2805
|
+
rescue StandardError
|
2806
|
+
break
|
2807
|
+
end
|
2808
|
+
end
|
2809
|
+
break if @interp.deleted?
|
2810
|
+
begin
|
2811
|
+
@wait_on_mainloop[1] += 1
|
2812
|
+
@interp.mainloop(check_root)
|
2813
|
+
rescue StandardError => e
|
2814
|
+
if TclTkLib.mainloop_abort_on_exception != nil
|
2815
|
+
#STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
|
2816
|
+
# " exception (ignore) : ", $!.message, "\n");
|
2817
|
+
if $DEBUG
|
2818
|
+
warn("Warning: Tk mainloop receives " << e.class.inspect <<
|
2819
|
+
" exception (ignore) : " << e.message);
|
2820
|
+
end
|
2821
|
+
end
|
2822
|
+
#raise e
|
2823
|
+
rescue Exception => e
|
2824
|
+
=begin
|
2825
|
+
if TclTkLib.mainloop_abort_on_exception != nil
|
2826
|
+
#STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
|
2827
|
+
# " exception (ignore) : ", $!.message, "\n");
|
2828
|
+
if $DEBUG
|
2829
|
+
warn("Warning: Tk mainloop receives " << e.class.inspect <<
|
2830
|
+
" exception (ignore) : " << e.message);
|
2831
|
+
end
|
2832
|
+
end
|
2833
|
+
=end
|
2834
|
+
raise e
|
2835
|
+
ensure
|
2836
|
+
@wait_on_mainloop[1] -= 1
|
2837
|
+
Thread.pass # avoid eventloop conflict
|
2838
|
+
end
|
2839
|
+
end
|
2840
|
+
end
|
2841
|
+
self
|
2842
|
+
end
|
2843
|
+
|
2844
|
+
def make_safe
|
2845
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2846
|
+
@interp.make_safe
|
2847
|
+
end
|
2848
|
+
|
2849
|
+
def safe?
|
2850
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2851
|
+
@interp.safe?
|
2852
|
+
end
|
2853
|
+
|
2854
|
+
def safe_base?
|
2855
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2856
|
+
@safe_base
|
2857
|
+
end
|
2858
|
+
|
2859
|
+
def allow_ruby_exit?
|
2860
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2861
|
+
@interp.allow_ruby_exit?
|
2862
|
+
end
|
2863
|
+
|
2864
|
+
def allow_ruby_exit= (mode)
|
2865
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2866
|
+
@interp.allow_ruby_exit = mode
|
2867
|
+
end
|
2868
|
+
|
2869
|
+
def delete
|
2870
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2871
|
+
@slave_ip_tbl.each{|name, subip|
|
2872
|
+
_destroy_slaves_of_slaveIP(subip)
|
2873
|
+
=begin
|
2874
|
+
begin
|
2875
|
+
subip._invoke('destroy', '.') unless subip.deleted?
|
2876
|
+
rescue Exception
|
2877
|
+
end
|
2878
|
+
=end
|
2879
|
+
begin
|
2880
|
+
# subip._eval_without_enc("foreach i [after info] {after cancel $i}")
|
2881
|
+
unless subip.deleted?
|
2882
|
+
after_ids = subip._eval_without_enc("after info")
|
2883
|
+
subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
2884
|
+
end
|
2885
|
+
rescue Exception
|
2886
|
+
end
|
2887
|
+
|
2888
|
+
# safe_base?
|
2889
|
+
if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0'
|
2890
|
+
begin
|
2891
|
+
@interp._eval_without_enc("::safe::interpDelete #{name}")
|
2892
|
+
rescue Exception
|
2893
|
+
else
|
2894
|
+
next if subip.deleted?
|
2895
|
+
end
|
2896
|
+
end
|
2897
|
+
if subip.respond_to?(:safe_base?) && subip.safe_base? &&
|
2898
|
+
!subip.deleted?
|
2899
|
+
# do 'exit' to call the delete_hook procedure
|
2900
|
+
begin
|
2901
|
+
subip._eval_without_enc('exit')
|
2902
|
+
rescue Exception
|
2903
|
+
end
|
2904
|
+
else
|
2905
|
+
begin
|
2906
|
+
subip.delete unless subip.deleted?
|
2907
|
+
rescue Exception
|
2908
|
+
end
|
2909
|
+
end
|
2910
|
+
}
|
2911
|
+
|
2912
|
+
begin
|
2913
|
+
# @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
|
2914
|
+
after_ids = @interp._eval_without_enc("after info")
|
2915
|
+
@interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}")
|
2916
|
+
rescue Exception
|
2917
|
+
end
|
2918
|
+
|
2919
|
+
begin
|
2920
|
+
@interp._invoke('destroy', '.') unless @interp.deleted?
|
2921
|
+
rescue Exception
|
2922
|
+
end
|
2923
|
+
|
2924
|
+
if @safe_base && !@interp.deleted?
|
2925
|
+
# do 'exit' to call the delete_hook procedure
|
2926
|
+
@interp._eval_without_enc('exit')
|
2927
|
+
end
|
2928
|
+
@interp.delete
|
2929
|
+
self
|
2930
|
+
end
|
2931
|
+
|
2932
|
+
def deleted?
|
2933
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2934
|
+
@interp.deleted?
|
2935
|
+
end
|
2936
|
+
|
2937
|
+
def has_mainwindow?
|
2938
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2939
|
+
@interp.has_mainwindow?
|
2940
|
+
end
|
2941
|
+
|
2942
|
+
def invalid_namespace?
|
2943
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2944
|
+
@interp.invalid_namespace?
|
2945
|
+
end
|
2946
|
+
|
2947
|
+
def abort(msg = nil)
|
2948
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2949
|
+
if master? && !safe? && allow_ruby_exit?
|
2950
|
+
if msg
|
2951
|
+
Kernel.abort(msg)
|
2952
|
+
else
|
2953
|
+
Kernel.abort
|
2954
|
+
end
|
2955
|
+
else
|
2956
|
+
# ignore msg
|
2957
|
+
delete
|
2958
|
+
1
|
2959
|
+
end
|
2960
|
+
end
|
2961
|
+
|
2962
|
+
def exit(st = true)
|
2963
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2964
|
+
if master? && !safe? && allow_ruby_exit?
|
2965
|
+
Kernel.exit(st)
|
2966
|
+
else
|
2967
|
+
delete
|
2968
|
+
st
|
2969
|
+
end
|
2970
|
+
end
|
2971
|
+
|
2972
|
+
def exit!(st = false)
|
2973
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2974
|
+
if master? && !safe? && allow_ruby_exit?
|
2975
|
+
Kernel.exit!(st)
|
2976
|
+
else
|
2977
|
+
delete
|
2978
|
+
st
|
2979
|
+
end
|
2980
|
+
end
|
2981
|
+
|
2982
|
+
def restart(app_name = nil, keys = {})
|
2983
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2984
|
+
|
2985
|
+
_init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
|
2986
|
+
|
2987
|
+
@interp._invoke('set', 'argv0', app_name) if app_name
|
2988
|
+
if keys.kind_of?(Hash)
|
2989
|
+
@interp._invoke('set', 'argv', _keys2opts(keys))
|
2990
|
+
end
|
2991
|
+
|
2992
|
+
@interp.restart
|
2993
|
+
end
|
2994
|
+
|
2995
|
+
def __eval(str)
|
2996
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
2997
|
+
@interp.__eval(str)
|
2998
|
+
end
|
2999
|
+
|
3000
|
+
def __invoke(*args)
|
3001
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3002
|
+
@interp.__invoke(*args)
|
3003
|
+
end
|
3004
|
+
|
3005
|
+
def _eval(str)
|
3006
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3007
|
+
@interp._eval(str)
|
3008
|
+
end
|
3009
|
+
|
3010
|
+
def _invoke(*args)
|
3011
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3012
|
+
@interp._invoke(*args)
|
3013
|
+
end
|
3014
|
+
|
3015
|
+
def _eval_without_enc(str)
|
3016
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3017
|
+
@interp._eval_without_enc(str)
|
3018
|
+
end
|
3019
|
+
|
3020
|
+
def _invoke_without_enc(*args)
|
3021
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3022
|
+
@interp._invoke_without_enc(*args)
|
3023
|
+
end
|
3024
|
+
|
3025
|
+
def _eval_with_enc(str)
|
3026
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3027
|
+
@interp._eval_with_enc(str)
|
3028
|
+
end
|
3029
|
+
|
3030
|
+
def _invoke_with_enc(*args)
|
3031
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3032
|
+
@interp._invoke_with_enc(*args)
|
3033
|
+
end
|
3034
|
+
|
3035
|
+
def _toUTF8(str, encoding=nil)
|
3036
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3037
|
+
@interp._toUTF8(str, encoding)
|
3038
|
+
end
|
3039
|
+
|
3040
|
+
def _fromUTF8(str, encoding=nil)
|
3041
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3042
|
+
@interp._fromUTF8(str, encoding)
|
3043
|
+
end
|
3044
|
+
|
3045
|
+
def _thread_vwait(var)
|
3046
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3047
|
+
@interp._thread_vwait(var)
|
3048
|
+
end
|
3049
|
+
|
3050
|
+
def _thread_tkwait(mode, target)
|
3051
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3052
|
+
@interp._thread_tkwait(mode, target)
|
3053
|
+
end
|
3054
|
+
|
3055
|
+
def _return_value
|
3056
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3057
|
+
@interp._return_value
|
3058
|
+
end
|
3059
|
+
|
3060
|
+
def _get_variable(var, flag)
|
3061
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3062
|
+
@interp._get_variable(var, flag)
|
3063
|
+
end
|
3064
|
+
def _get_variable2(var, idx, flag)
|
3065
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3066
|
+
@interp._get_variable2(var, idx, flag)
|
3067
|
+
end
|
3068
|
+
def _set_variable(var, value, flag)
|
3069
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3070
|
+
@interp._set_variable(var, value, flag)
|
3071
|
+
end
|
3072
|
+
def _set_variable2(var, idx, value, flag)
|
3073
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3074
|
+
@interp._set_variable2(var, idx, value, flag)
|
3075
|
+
end
|
3076
|
+
def _unset_variable(var, flag)
|
3077
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3078
|
+
@interp._unset_variable(var, flag)
|
3079
|
+
end
|
3080
|
+
def _unset_variable2(var, idx, flag)
|
3081
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3082
|
+
@interp._unset_variable2(var, idx, flag)
|
3083
|
+
end
|
3084
|
+
|
3085
|
+
def _get_global_var(var)
|
3086
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3087
|
+
@interp._get_global_var(var)
|
3088
|
+
end
|
3089
|
+
def _get_global_var2(var, idx)
|
3090
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3091
|
+
@interp._get_global_var2(var, idx)
|
3092
|
+
end
|
3093
|
+
def _set_global_var(var, value)
|
3094
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3095
|
+
@interp._set_global_var(var, value)
|
3096
|
+
end
|
3097
|
+
def _set_global_var2(var, idx, value)
|
3098
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3099
|
+
@interp._set_global_var2(var, idx, value)
|
3100
|
+
end
|
3101
|
+
def _unset_global_var(var)
|
3102
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3103
|
+
@interp._unset_global_var(var)
|
3104
|
+
end
|
3105
|
+
def _unset_global_var2(var, idx)
|
3106
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3107
|
+
@interp._unset_global_var2(var, idx)
|
3108
|
+
end
|
3109
|
+
|
3110
|
+
def _make_menu_embeddable(menu_path)
|
3111
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3112
|
+
@interp._make_menu_embeddable(menu_path)
|
3113
|
+
end
|
3114
|
+
|
3115
|
+
def _split_tklist(str)
|
3116
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3117
|
+
@interp._split_tklist(str)
|
3118
|
+
end
|
3119
|
+
def _merge_tklist(*args)
|
3120
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3121
|
+
@interp._merge_tklist(*args)
|
3122
|
+
end
|
3123
|
+
def _conv_listelement(arg)
|
3124
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3125
|
+
@interp._conv_listelement(arg)
|
3126
|
+
end
|
3127
|
+
end
|
3128
|
+
|
3129
|
+
|
3130
|
+
# interp command support
|
3131
|
+
class MultiTkIp
|
3132
|
+
def _lst2ary(str)
|
3133
|
+
return [] if str == ""
|
3134
|
+
idx = str.index('{')
|
3135
|
+
while idx and idx > 0 and str[idx-1] == ?\\
|
3136
|
+
idx = str.index('{', idx+1)
|
3137
|
+
end
|
3138
|
+
return str.split unless idx
|
3139
|
+
|
3140
|
+
list = str[0,idx].split
|
3141
|
+
str = str[idx+1..-1]
|
3142
|
+
i = -1
|
3143
|
+
brace = 1
|
3144
|
+
str.each_byte {|c|
|
3145
|
+
c = c.chr
|
3146
|
+
i += 1
|
3147
|
+
brace += 1 if c == '{'
|
3148
|
+
brace -= 1 if c == '}'
|
3149
|
+
break if brace == 0
|
3150
|
+
}
|
3151
|
+
if i == 0
|
3152
|
+
list.push ''
|
3153
|
+
elsif str[0, i] == ' '
|
3154
|
+
list.push ' '
|
3155
|
+
else
|
3156
|
+
list.push str[0..i-1]
|
3157
|
+
end
|
3158
|
+
#list += _lst2ary(str[i+1..-1])
|
3159
|
+
list.concat(_lst2ary(str[i+1..-1]))
|
3160
|
+
list
|
3161
|
+
end
|
3162
|
+
private :_lst2ary
|
3163
|
+
|
3164
|
+
def _slavearg(slave)
|
3165
|
+
if slave.kind_of?(MultiTkIp)
|
3166
|
+
slave.path
|
3167
|
+
elsif slave.kind_of?(String)
|
3168
|
+
slave
|
3169
|
+
else
|
3170
|
+
slave.to_s
|
3171
|
+
end
|
3172
|
+
end
|
3173
|
+
private :_slavearg
|
3174
|
+
|
3175
|
+
def alias_info(slave, cmd_name)
|
3176
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3177
|
+
_lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name))
|
3178
|
+
end
|
3179
|
+
def self.alias_info(slave, cmd_name)
|
3180
|
+
__getip.alias_info(slave, cmd_name)
|
3181
|
+
end
|
3182
|
+
|
3183
|
+
def alias_delete(slave, cmd_name)
|
3184
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3185
|
+
@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '')
|
3186
|
+
self
|
3187
|
+
end
|
3188
|
+
def self.alias_delete(slave, cmd_name)
|
3189
|
+
__getip.alias_delete(slave, cmd_name)
|
3190
|
+
self
|
3191
|
+
end
|
3192
|
+
|
3193
|
+
def def_alias(slave, new_cmd, org_cmd, *args)
|
3194
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3195
|
+
ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd,
|
3196
|
+
'', org_cmd, *args)
|
3197
|
+
(ret == new_cmd)? self: nil
|
3198
|
+
end
|
3199
|
+
def self.def_alias(slave, new_cmd, org_cmd, *args)
|
3200
|
+
ret = __getip.def_alias(slave, new_cmd, org_cmd, *args)
|
3201
|
+
(ret == new_cmd)? self: nil
|
3202
|
+
end
|
3203
|
+
|
3204
|
+
def aliases(slave = '')
|
3205
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3206
|
+
_lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave)))
|
3207
|
+
end
|
3208
|
+
def self.aliases(slave = '')
|
3209
|
+
__getip.aliases(slave)
|
3210
|
+
end
|
3211
|
+
|
3212
|
+
def delete_slaves(*args)
|
3213
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3214
|
+
slaves = args.collect{|s| _slavearg(s)}
|
3215
|
+
@interp._invoke('interp', 'delete', *slaves) if slaves.size > 0
|
3216
|
+
self
|
3217
|
+
end
|
3218
|
+
def self.delete_slaves(*args)
|
3219
|
+
__getip.delete_slaves(*args)
|
3220
|
+
self
|
3221
|
+
end
|
3222
|
+
|
3223
|
+
def exist?(slave = '')
|
3224
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3225
|
+
ret = @interp._invoke('interp', 'exists', _slavearg(slave))
|
3226
|
+
(ret == '1')? true: false
|
3227
|
+
end
|
3228
|
+
def self.exist?(slave = '')
|
3229
|
+
__getip.exist?(slave)
|
3230
|
+
end
|
3231
|
+
|
3232
|
+
def delete_cmd(slave, cmd)
|
3233
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3234
|
+
slave_invoke = @interp._invoke('list', 'rename', cmd, '')
|
3235
|
+
@interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke)
|
3236
|
+
self
|
3237
|
+
end
|
3238
|
+
def self.delete_cmd(slave, cmd)
|
3239
|
+
__getip.delete_cmd(slave, cmd)
|
3240
|
+
self
|
3241
|
+
end
|
3242
|
+
|
3243
|
+
def expose_cmd(slave, cmd, aliasname = nil)
|
3244
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3245
|
+
if aliasname
|
3246
|
+
@interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname)
|
3247
|
+
else
|
3248
|
+
@interp._invoke('interp', 'expose', _slavearg(slave), cmd)
|
3249
|
+
end
|
3250
|
+
self
|
3251
|
+
end
|
3252
|
+
def self.expose_cmd(slave, cmd, aliasname = nil)
|
3253
|
+
__getip.expose_cmd(slave, cmd, aliasname)
|
3254
|
+
self
|
3255
|
+
end
|
3256
|
+
|
3257
|
+
def hide_cmd(slave, cmd, aliasname = nil)
|
3258
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3259
|
+
if aliasname
|
3260
|
+
@interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname)
|
3261
|
+
else
|
3262
|
+
@interp._invoke('interp', 'hide', _slavearg(slave), cmd)
|
3263
|
+
end
|
3264
|
+
self
|
3265
|
+
end
|
3266
|
+
def self.hide_cmd(slave, cmd, aliasname = nil)
|
3267
|
+
__getip.hide_cmd(slave, cmd, aliasname)
|
3268
|
+
self
|
3269
|
+
end
|
3270
|
+
|
3271
|
+
def hidden_cmds(slave = '')
|
3272
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3273
|
+
_lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave)))
|
3274
|
+
end
|
3275
|
+
def self.hidden_cmds(slave = '')
|
3276
|
+
__getip.hidden_cmds(slave)
|
3277
|
+
end
|
3278
|
+
|
3279
|
+
def invoke_hidden(slave, cmd, *args)
|
3280
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3281
|
+
if args[-1].kind_of?(Hash)
|
3282
|
+
keys = _symbolkey2str(args.pop)
|
3283
|
+
else
|
3284
|
+
keys = []
|
3285
|
+
end
|
3286
|
+
keys << _slavearg(slave)
|
3287
|
+
if Tk::TCL_MAJOR_VERSION > 8 ||
|
3288
|
+
(Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
|
3289
|
+
keys << '--'
|
3290
|
+
end
|
3291
|
+
keys << cmd
|
3292
|
+
keys.concat(args)
|
3293
|
+
@interp._invoke('interp', 'invokehidden', *keys)
|
3294
|
+
end
|
3295
|
+
def self.invoke_hidden(slave, cmd, *args)
|
3296
|
+
__getip.invoke_hidden(slave, cmd, *args)
|
3297
|
+
end
|
3298
|
+
|
3299
|
+
def invoke_hidden_on_global(slave, cmd, *args)
|
3300
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3301
|
+
if args[-1].kind_of?(Hash)
|
3302
|
+
keys = _symbolkey2str(args.pop)
|
3303
|
+
else
|
3304
|
+
keys = []
|
3305
|
+
end
|
3306
|
+
keys << _slavearg(slave)
|
3307
|
+
keys << '-global'
|
3308
|
+
if Tk::TCL_MAJOR_VERSION > 8 ||
|
3309
|
+
(Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
|
3310
|
+
keys << '--'
|
3311
|
+
end
|
3312
|
+
keys << cmd
|
3313
|
+
keys.concat(args)
|
3314
|
+
@interp._invoke('interp', 'invokehidden', *keys)
|
3315
|
+
end
|
3316
|
+
def self.invoke_hidden_on_global(slave, cmd, *args)
|
3317
|
+
__getip.invoke_hidden_on_global(slave, cmd, *args)
|
3318
|
+
end
|
3319
|
+
|
3320
|
+
def invoke_hidden_on_namespace(slave, ns, cmd, *args)
|
3321
|
+
# for Tcl8.5 or later
|
3322
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3323
|
+
if args[-1].kind_of?(Hash)
|
3324
|
+
keys = _symbolkey2str(args.pop)
|
3325
|
+
else
|
3326
|
+
keys = []
|
3327
|
+
end
|
3328
|
+
keys << _slavearg(slave)
|
3329
|
+
keys << '-namespace' << TkComm._get_eval_string(ns)
|
3330
|
+
keys << '--' << cmd
|
3331
|
+
keys.concat(args)
|
3332
|
+
@interp._invoke('interp', 'invokehidden', *keys)
|
3333
|
+
end
|
3334
|
+
def self.invoke_hidden_on_namespace(slave, ns, cmd, *args)
|
3335
|
+
__getip.invoke_hidden_on_namespace(slave, ns, cmd, *args)
|
3336
|
+
end
|
3337
|
+
|
3338
|
+
def mark_trusted(slave = '')
|
3339
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3340
|
+
@interp._invoke('interp', 'marktrusted', _slavearg(slave))
|
3341
|
+
self
|
3342
|
+
end
|
3343
|
+
def self.mark_trusted(slave = '')
|
3344
|
+
__getip.mark_trusted(slave)
|
3345
|
+
self
|
3346
|
+
end
|
3347
|
+
|
3348
|
+
def set_bgerror_handler(cmd = Proc.new, slave = nil, &b)
|
3349
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3350
|
+
|
3351
|
+
unless TkComm._callback_entry?(cmd)
|
3352
|
+
if !slave && b
|
3353
|
+
slave = cmd
|
3354
|
+
cmd = Proc.new(&b)
|
3355
|
+
end
|
3356
|
+
end
|
3357
|
+
slave = '' unless slave
|
3358
|
+
|
3359
|
+
@interp._invoke('interp', 'bgerror', _slavearg(slave), cmd)
|
3360
|
+
end
|
3361
|
+
def self.bgerror(cmd = Proc.new, slave = nil, &b)
|
3362
|
+
__getip.bgerror(cmd, slave, &b)
|
3363
|
+
end
|
3364
|
+
|
3365
|
+
def get_bgerror_handler(slave = '')
|
3366
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3367
|
+
procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave)))
|
3368
|
+
end
|
3369
|
+
def self.bgerror(slave = '')
|
3370
|
+
__getip.bgerror(slave)
|
3371
|
+
end
|
3372
|
+
|
3373
|
+
def set_limit(limit_type, slave = '', opts = {})
|
3374
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3375
|
+
@interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts)
|
3376
|
+
end
|
3377
|
+
def self.set_limit(limit_type, slave = '', opts = {})
|
3378
|
+
__getip.set_limit(limit_type, slave, opts)
|
3379
|
+
end
|
3380
|
+
|
3381
|
+
def get_limit(limit_type, slave = '', slot = nil)
|
3382
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3383
|
+
|
3384
|
+
if slot
|
3385
|
+
num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave),
|
3386
|
+
limit_type, slot))
|
3387
|
+
else
|
3388
|
+
l = @interp._split_tklist(@interp._invoke_without_enc('interp', 'limit',
|
3389
|
+
_slavearg(slave),
|
3390
|
+
limit_type))
|
3391
|
+
l.map!{|s| _fromUTF8(s)}
|
3392
|
+
r = {}
|
3393
|
+
until l.empty?
|
3394
|
+
key = l.shift[1..-1]
|
3395
|
+
val = l.shift
|
3396
|
+
val = num_or_str(val) if val
|
3397
|
+
r[key] = val
|
3398
|
+
end
|
3399
|
+
r
|
3400
|
+
end
|
3401
|
+
end
|
3402
|
+
def self.get_limit(limit_type, slave = '', slot = nil)
|
3403
|
+
__getip.get_limit(limit_type, slave, slot)
|
3404
|
+
end
|
3405
|
+
|
3406
|
+
def recursion_limit(slave = '', limit = None)
|
3407
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3408
|
+
number(@interp._invoke('interp', 'recursionlimit',
|
3409
|
+
_slavearg(slave), limit))
|
3410
|
+
end
|
3411
|
+
def self.recursion_limit(slave = '', limit = None)
|
3412
|
+
__getip.recursion_limit(slave)
|
3413
|
+
end
|
3414
|
+
|
3415
|
+
def alias_target(aliascmd, slave = '')
|
3416
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3417
|
+
@interp._invoke('interp', 'target', _slavearg(slave), aliascmd)
|
3418
|
+
end
|
3419
|
+
def self.alias_target(aliascmd, slave = '')
|
3420
|
+
__getip.alias_target(aliascmd, slave)
|
3421
|
+
end
|
3422
|
+
|
3423
|
+
def share_stdin(dist, src = '')
|
3424
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3425
|
+
@interp._invoke('interp', 'share', src, 'stdin', dist)
|
3426
|
+
self
|
3427
|
+
end
|
3428
|
+
def self.share_stdin(dist, src = '')
|
3429
|
+
__getip.share_stdin(dist, src)
|
3430
|
+
self
|
3431
|
+
end
|
3432
|
+
|
3433
|
+
def share_stdout(dist, src = '')
|
3434
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3435
|
+
@interp._invoke('interp', 'share', src, 'stdout', dist)
|
3436
|
+
self
|
3437
|
+
end
|
3438
|
+
def self.share_stdout(dist, src = '')
|
3439
|
+
__getip.share_stdout(dist, src)
|
3440
|
+
self
|
3441
|
+
end
|
3442
|
+
|
3443
|
+
def share_stderr(dist, src = '')
|
3444
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3445
|
+
@interp._invoke('interp', 'share', src, 'stderr', dist)
|
3446
|
+
self
|
3447
|
+
end
|
3448
|
+
def self.share_stderr(dist, src = '')
|
3449
|
+
__getip.share_stderr(dist, src)
|
3450
|
+
self
|
3451
|
+
end
|
3452
|
+
|
3453
|
+
def transfer_stdin(dist, src = '')
|
3454
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3455
|
+
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
|
3456
|
+
self
|
3457
|
+
end
|
3458
|
+
def self.transfer_stdin(dist, src = '')
|
3459
|
+
__getip.transfer_stdin(dist, src)
|
3460
|
+
self
|
3461
|
+
end
|
3462
|
+
|
3463
|
+
def transfer_stdout(dist, src = '')
|
3464
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3465
|
+
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
|
3466
|
+
self
|
3467
|
+
end
|
3468
|
+
def self.transfer_stdout(dist, src = '')
|
3469
|
+
__getip.transfer_stdout(dist, src)
|
3470
|
+
self
|
3471
|
+
end
|
3472
|
+
|
3473
|
+
def transfer_stderr(dist, src = '')
|
3474
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3475
|
+
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
|
3476
|
+
self
|
3477
|
+
end
|
3478
|
+
def self.transfer_stderr(dist, src = '')
|
3479
|
+
__getip.transfer_stderr(dist, src)
|
3480
|
+
self
|
3481
|
+
end
|
3482
|
+
|
3483
|
+
def share_stdio(dist, src = '')
|
3484
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3485
|
+
@interp._invoke('interp', 'share', src, 'stdin', dist)
|
3486
|
+
@interp._invoke('interp', 'share', src, 'stdout', dist)
|
3487
|
+
@interp._invoke('interp', 'share', src, 'stderr', dist)
|
3488
|
+
self
|
3489
|
+
end
|
3490
|
+
def self.share_stdio(dist, src = '')
|
3491
|
+
__getip.share_stdio(dist, src)
|
3492
|
+
self
|
3493
|
+
end
|
3494
|
+
|
3495
|
+
def transfer_stdio(dist, src = '')
|
3496
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3497
|
+
@interp._invoke('interp', 'transfer', src, 'stdin', dist)
|
3498
|
+
@interp._invoke('interp', 'transfer', src, 'stdout', dist)
|
3499
|
+
@interp._invoke('interp', 'transfer', src, 'stderr', dist)
|
3500
|
+
self
|
3501
|
+
end
|
3502
|
+
def self.transfer_stdio(dist, src = '')
|
3503
|
+
__getip.transfer_stdio(dist, src)
|
3504
|
+
self
|
3505
|
+
end
|
3506
|
+
end
|
3507
|
+
|
3508
|
+
|
3509
|
+
# Safe Base :: manipulating safe interpreter
|
3510
|
+
class MultiTkIp
|
3511
|
+
def safeip_configure(slot, value=None)
|
3512
|
+
# use for '-noStatics' option ==> {statics=>false}
|
3513
|
+
# for '-nestedLoadOk' option ==> {nested=>true}
|
3514
|
+
if slot.kind_of?(Hash)
|
3515
|
+
ip = MultiTkIp.__getip
|
3516
|
+
ip._eval('::safe::interpConfigure ' + @ip_name + ' ' + _keys2opts(slot))
|
3517
|
+
else
|
3518
|
+
ip._eval('::safe::interpConfigure ' + @ip_name + ' ' +
|
3519
|
+
"-#{slot} #{_get_eval_string(value)}")
|
3520
|
+
end
|
3521
|
+
self
|
3522
|
+
end
|
3523
|
+
|
3524
|
+
def safeip_configinfo(slot = nil)
|
3525
|
+
ip = MultiTkIp.__getip
|
3526
|
+
ret = {}
|
3527
|
+
if slot
|
3528
|
+
conf = _lst2ary(ip._eval("::safe::interpConfigure " +
|
3529
|
+
@ip_name + " -#{slot}"))
|
3530
|
+
if conf[0] == '-deleteHook'
|
3531
|
+
=begin
|
3532
|
+
if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/
|
3533
|
+
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
|
3534
|
+
=end
|
3535
|
+
if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
|
3536
|
+
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
|
3537
|
+
else
|
3538
|
+
ret[conf[0][1..-1]] = conf[1]
|
3539
|
+
end
|
3540
|
+
else
|
3541
|
+
ret[conf[0][1..-1]] = conf[1]
|
3542
|
+
end
|
3543
|
+
else
|
3544
|
+
Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
|
3545
|
+
@ip_name))].each{|k, v|
|
3546
|
+
if k == '-deleteHook'
|
3547
|
+
=begin
|
3548
|
+
if v =~ /^rb_out\S* (c(_\d+_)?\d+)/
|
3549
|
+
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
|
3550
|
+
=end
|
3551
|
+
if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
|
3552
|
+
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4]
|
3553
|
+
else
|
3554
|
+
ret[k[1..-1]] = v
|
3555
|
+
end
|
3556
|
+
else
|
3557
|
+
ret[k[1..-1]] = v
|
3558
|
+
end
|
3559
|
+
}
|
3560
|
+
end
|
3561
|
+
ret
|
3562
|
+
end
|
3563
|
+
|
3564
|
+
def safeip_delete
|
3565
|
+
ip = MultiTkIp.__getip
|
3566
|
+
ip._eval("::safe::interpDelete " + @ip_name)
|
3567
|
+
end
|
3568
|
+
|
3569
|
+
def safeip_add_to_access_path(dir)
|
3570
|
+
ip = MultiTkIp.__getip
|
3571
|
+
ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}")
|
3572
|
+
end
|
3573
|
+
|
3574
|
+
def safeip_find_in_access_path(dir)
|
3575
|
+
ip = MultiTkIp.__getip
|
3576
|
+
ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}")
|
3577
|
+
end
|
3578
|
+
|
3579
|
+
def safeip_set_log_cmd(cmd = Proc.new)
|
3580
|
+
ip = MultiTkIp.__getip
|
3581
|
+
ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}")
|
3582
|
+
end
|
3583
|
+
end
|
3584
|
+
|
3585
|
+
|
3586
|
+
# encoding convert
|
3587
|
+
class << MultiTkIp
|
3588
|
+
def encoding_table
|
3589
|
+
__getip.encoding_table
|
3590
|
+
end
|
3591
|
+
|
3592
|
+
def force_default_encoding=(mode)
|
3593
|
+
__getip.force_default_encoding=(mode)
|
3594
|
+
end
|
3595
|
+
|
3596
|
+
def force_default_encoding?
|
3597
|
+
__getip.force_default_encoding?
|
3598
|
+
end
|
3599
|
+
|
3600
|
+
def default_encoding=(enc)
|
3601
|
+
__getip.default_encoding=(enc)
|
3602
|
+
end
|
3603
|
+
|
3604
|
+
def encoding=(enc)
|
3605
|
+
__getip.encoding=(enc)
|
3606
|
+
end
|
3607
|
+
|
3608
|
+
def encoding_name
|
3609
|
+
__getip.encoding_name
|
3610
|
+
end
|
3611
|
+
|
3612
|
+
def encoding_obj
|
3613
|
+
__getip.encoding_obj
|
3614
|
+
end
|
3615
|
+
alias encoding encoding_name
|
3616
|
+
alias default_encoding encoding_name
|
3617
|
+
|
3618
|
+
def encoding_convertfrom(str, enc=None)
|
3619
|
+
__getip.encoding_convertfrom(str, enc)
|
3620
|
+
end
|
3621
|
+
alias encoding_convert_from encoding_convertfrom
|
3622
|
+
|
3623
|
+
def encoding_convertto(str, enc=None)
|
3624
|
+
__getip.encoding_convertto(str, enc)
|
3625
|
+
end
|
3626
|
+
alias encoding_convert_to encoding_convertto
|
3627
|
+
end
|
3628
|
+
class MultiTkIp
|
3629
|
+
def encoding_table
|
3630
|
+
@interp.encoding_table
|
3631
|
+
end
|
3632
|
+
|
3633
|
+
def force_default_encoding=(mode)
|
3634
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3635
|
+
@interp.force_default_encoding = mode
|
3636
|
+
end
|
3637
|
+
def force_default_encoding?
|
3638
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3639
|
+
@interp.force_default_encoding?
|
3640
|
+
end
|
3641
|
+
|
3642
|
+
def default_encoding=(enc)
|
3643
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3644
|
+
@interp.default_encoding = enc
|
3645
|
+
end
|
3646
|
+
|
3647
|
+
def encoding=(enc)
|
3648
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3649
|
+
@interp.encoding = enc
|
3650
|
+
end
|
3651
|
+
def encoding_name
|
3652
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3653
|
+
@interp.encoding_name
|
3654
|
+
end
|
3655
|
+
def encoding_obj
|
3656
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3657
|
+
@interp.encoding_obj
|
3658
|
+
end
|
3659
|
+
alias encoding encoding_name
|
3660
|
+
alias default_encoding encoding_name
|
3661
|
+
|
3662
|
+
def encoding_convertfrom(str, enc=None)
|
3663
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3664
|
+
@interp.encoding_convertfrom(str, enc)
|
3665
|
+
end
|
3666
|
+
alias encoding_convert_from encoding_convertfrom
|
3667
|
+
|
3668
|
+
def encoding_convertto(str, enc=None)
|
3669
|
+
raise SecurityError, "no permission to manipulate" unless self.manipulable?
|
3670
|
+
@interp.encoding_convertto(str, enc)
|
3671
|
+
end
|
3672
|
+
alias encoding_convert_to encoding_convertto
|
3673
|
+
end
|
3674
|
+
|
3675
|
+
|
3676
|
+
# remove methods for security
|
3677
|
+
=begin
|
3678
|
+
class MultiTkIp
|
3679
|
+
INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread')
|
3680
|
+
INTERP_MUTEX = INTERP_THREAD[:mutex]
|
3681
|
+
INTERP_ROOT_CHECK = INTERP_THREAD[:root_check]
|
3682
|
+
|
3683
|
+
# undef_method :instance_eval
|
3684
|
+
undef_method :instance_variable_get
|
3685
|
+
undef_method :instance_variable_set
|
3686
|
+
end
|
3687
|
+
|
3688
|
+
module TkCore
|
3689
|
+
if MultiTkIp::WITH_RUBY_VM &&
|
3690
|
+
! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
|
3691
|
+
INTERP_THREAD = MultiTkIp::INTERP_THREAD
|
3692
|
+
INTERP_MUTEX = MultiTkIp::INTERP_MUTEX
|
3693
|
+
INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK
|
3694
|
+
end
|
3695
|
+
end
|
3696
|
+
class MultiTkIp
|
3697
|
+
remove_const(:INTERP_THREAD)
|
3698
|
+
remove_const(:INTERP_MUTEX)
|
3699
|
+
remove_const(:INTERP_ROOT_CHECK)
|
3700
|
+
end
|
3701
|
+
=end
|
3702
|
+
if MultiTkIp::WITH_RUBY_VM &&
|
3703
|
+
! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
|
3704
|
+
class MultiTkIp
|
3705
|
+
INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread')
|
3706
|
+
INTERP_THREAD_STATUS = INTERP_THREAD[:status]
|
3707
|
+
INTERP_MUTEX = INTERP_THREAD[:mutex]
|
3708
|
+
INTERP_ROOT_CHECK = INTERP_THREAD[:root_check]
|
3709
|
+
end
|
3710
|
+
module TkCore
|
3711
|
+
INTERP_THREAD = MultiTkIp::INTERP_THREAD
|
3712
|
+
INTERP_THREAD_STATUS = MultiTkIp::INTERP_THREAD_STATUS
|
3713
|
+
INTERP_MUTEX = MultiTkIp::INTERP_MUTEX
|
3714
|
+
INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK
|
3715
|
+
end
|
3716
|
+
class MultiTkIp
|
3717
|
+
remove_const(:INTERP_THREAD)
|
3718
|
+
remove_const(:INTERP_THREAD_STATUS)
|
3719
|
+
remove_const(:INTERP_MUTEX)
|
3720
|
+
remove_const(:INTERP_ROOT_CHECK)
|
3721
|
+
end
|
3722
|
+
end
|
3723
|
+
|
3724
|
+
class MultiTkIp
|
3725
|
+
# undef_method :instance_eval
|
3726
|
+
undef_method :instance_variable_get
|
3727
|
+
undef_method :instance_variable_set
|
3728
|
+
end
|
3729
|
+
# end of MultiTkIp definition
|
3730
|
+
|
3731
|
+
# defend against modification
|
3732
|
+
#MultiTkIp.freeze
|
3733
|
+
#TclTkLib.freeze
|
3734
|
+
|
3735
|
+
########################################
|
3736
|
+
# start Tk which depends on MultiTkIp
|
3737
|
+
module TkCore
|
3738
|
+
INTERP = MultiTkIp
|
3739
|
+
end
|
3740
|
+
require 'tk'
|