OSDN Git Service

change prefix to '/data/ruby'
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / lib / remote-tk.rb
1 #
2 #               remote-tk.rb - supports to control remote Tk interpreters
3 #                       by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
4
5 if defined? MultiTkIp
6   fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'"
7 end
8
9 class MultiTkIp; end
10 class RemoteTkIp < MultiTkIp; end
11
12 class MultiTkIp
13   @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
14   @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
15   def self._IP_TABLE; @@IP_TABLE; end
16   def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end
17
18   @flag = true
19   def self._DEFAULT_MASTER
20     # work only once
21     if @flag
22       @flag = nil
23       @@DEFAULT_MASTER
24     else
25       nil
26     end
27   end
28 end
29 class RemoteTkIp
30   @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE)
31   @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST)
32 end
33 class << MultiTkIp
34   undef _IP_TABLE
35   undef _TK_TABLE_LIST
36 end
37
38 require 'multi-tk'
39
40 class RemoteTkIp
41   if defined?(@@DEFAULT_MASTER)
42     MultiTkIp._DEFAULT_MASTER
43   else
44     @@DEFAULT_MASTER = MultiTkIp._DEFAULT_MASTER
45   end
46 end
47
48
49 ###############################
50
51 class << RemoteTkIp
52   undef new_master, new_slave, new_safe_slave
53   undef new_trusted_slave, new_safeTk
54
55   def new(*args, &b)
56     ip = __new(*args)
57     ip.eval_proc(&b) if b
58     ip
59   end
60 end
61
62 class RemoteTkIp
63   def initialize(remote_ip, displayof=nil, timeout=5)
64     if $SAFE >= 4
65       fail SecurityError, "cannot access another interpreter at level #{$SAFE}"
66     end
67
68     @interp = MultiTkIp.__getip
69     if @interp.safe?
70       fail SecurityError, "safe-IP cannot create RemoteTkIp"
71     end
72
73
74     @interp.allow_ruby_exit = false
75     @appname = @interp._invoke('tk', 'appname')
76     @remote = remote_ip.to_s.dup.freeze
77     if displayof.kind_of?(TkWindow)
78       @displayof = displayof.path.dup.freeze
79     else
80       @displayof = nil
81     end
82     if self.deleted?
83       fail RuntimeError, "no Tk application named \"#{@remote}\""
84     end
85
86     @tk_windows = {}
87     @tk_table_list = []
88     @slave_ip_tbl = {}
89     @slave_ip_top = {}
90
91     @force_default_encoding ||= [false].taint
92     @encoding ||= [nil].taint
93     def @encoding.to_s; self.join(nil); end
94
95     @tk_windows.taint unless @tk_windows.tainted?
96     @tk_table_list.taint unless @tk_table_list.tainted?
97     @slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
98     @slave_ip_top.taint unless @slave_ip_top.tainted?
99
100     @system = Object.new
101
102     @threadgroup  = ThreadGroup.new
103
104     @safe_level = [$SAFE]
105
106     @wait_on_mainloop = [true, 0]
107
108     @cmd_queue = Queue.new
109
110 =begin
111     @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
112
113     @threadgroup.add @cmd_receiver
114     @threadgroup.add @receiver_watchdog
115
116     @threadgroup.enclose
117 =end
118     @@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
119
120     @@IP_TABLE[@threadgroup] = self
121     @@TK_TABLE_LIST.size.times{ 
122       (tbl = {}).tainted? || tbl.taint
123       @tk_table_list << tbl
124     }
125
126     @ret_val = TkVariable.new
127     if timeout > 0 && ! _available_check(timeout)
128       fail RuntimeError, "cannot create connection"
129     end
130     @ip_id = _create_connection
131
132     class << self
133       undef :instance_eval
134     end
135
136     self.freeze  # defend against modification
137   end
138
139   def manipulable?
140     return true if (Thread.current.group == ThreadGroup::Default)
141     MultiTkIp.__getip == @interp && ! @interp.safe?
142   end
143   def self.manipulable?
144     true
145   end
146
147   def _is_master_of?(tcltkip_obj)
148     tcltkip_obj == @interp
149   end
150   protected :_is_master_of?
151
152   def _ip_id_
153     @ip_id
154   end
155
156   def _available_check(timeout = 5)
157     raise SecurityError, "no permission to manipulate" unless self.manipulable?
158
159     return nil if timeout < 1
160     @ret_val.value = ''
161     @interp._invoke('send', '-async', @remote, 
162                     'send', '-async', Tk.appname, 
163                     "set #{@ret_val.id} ready")
164     Tk.update
165     if @ret_val != 'ready'
166       (1..(timeout*5)).each{
167         sleep 0.2 
168         Tk.update
169         break if @ret_val == 'ready'
170       }
171     end
172     @ret_val.value == 'ready'
173   end
174   private :_available_check
175
176   def _create_connection
177     raise SecurityError, "no permission to manipulate" unless self.manipulable?
178
179     ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_'
180       if {[catch {set _rubytk_control_ip_id_} ret] != 0} {
181         set _rubytk_control_ip_id_ 0
182       } else {
183         set _rubytk_control_ip_id_ [expr $ret + 1]
184       }
185       return $_rubytk_control_ip_id_
186     EOS
187
188     @interp._invoke('send', @remote, <<-EOS)
189       proc rb_out#{ip_id} args {
190         send #{@appname} rb_out \$args
191       }
192     EOS
193
194     ip_id
195   end
196   private :_create_connection
197
198   def _appsend(enc_mode, async, *cmds)
199     raise SecurityError, "no permission to manipulate" unless self.manipulable?
200
201     p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG
202     if $SAFE >= 4
203       fail SecurityError, "cannot send commands at level 4"
204     elsif $SAFE >= 1 && cmds.find{|obj| obj.tainted?}
205       fail SecurityError, "cannot send tainted commands at level #{$SAFE}"
206     end
207
208     cmds = @interp._merge_tklist(*TkUtil::_conv_args([], enc_mode, *cmds))
209     if @displayof
210       if async
211         @interp.__invoke('send', '-async', '-displayof', @displayof, 
212                          '--', @remote, *cmds)
213       else
214         @interp.__invoke('send', '-displayof', @displayof, 
215                          '--', @remote, *cmds)
216       end
217     else
218       if async
219         @interp.__invoke('send', '-async', '--', @remote, *cmds)
220       else
221         @interp.__invoke('send', '--', @remote, *cmds)
222       end
223     end
224   end
225   private :_appsend
226
227   def ready?(timeout=5)
228     if timeout < 0
229       fail ArgumentError, "timeout must be positive number"
230     end
231     _available_check(timeout)
232   end
233
234   def is_rubytk?
235     return false if _appsend(false, false, 'info', 'command', 'ruby') == ""
236     [ _appsend(false, false, 'ruby', 'RUBY_VERSION'), 
237       _appsend(false, false, 'set', 'tk_patchLevel') ]
238   end
239
240   def appsend(async, *args)
241     raise SecurityError, "no permission to manipulate" unless self.manipulable?
242
243     if async != true && async != false && async != nil
244       args.unshift(async)
245       async = false
246     end
247     if @displayof
248       Tk.appsend_displayof(@remote, @displayof, async, *args)
249     else
250       Tk.appsend(@remote, async, *args)
251     end
252   end
253
254   def rb_appsend(async, *args)
255     raise SecurityError, "no permission to manipulate" unless self.manipulable?
256
257     if async != true && async != false && async != nil
258       args.unshift(async)
259       async = false
260     end
261     if @displayof
262       Tk.rb_appsend_displayof(@remote, @displayof, async, *args)
263     else
264       Tk.rb_appsend(@remote, async, *args)
265     end
266   end
267
268   def create_slave(name, safe=false)
269     if safe
270       safe_opt = ''
271     else
272       safe_opt = '-safe'
273     end
274     _appsend(false, false, "interp create #{safe_opt} -- #{name}")
275   end
276
277   def make_safe
278     fail RuntimeError, 'cannot change safe mode of the remote interpreter'
279   end
280
281   def safe?
282     _appsend(false, false, 'interp issafe')
283   end
284
285   def safe_base?
286     false
287   end
288
289   def allow_ruby_exit?
290     false
291   end
292
293   def allow_ruby_exit= (mode)
294     fail RuntimeError, 'cannot change mode of the remote interpreter'
295   end
296
297   def delete
298     _appsend(false, true, 'exit')
299   end
300
301   def deleted?
302     raise SecurityError, "no permission to manipulate" unless self.manipulable?
303
304     if @displayof
305       lst = @interp._invoke_without_enc('winfo', 'interps', 
306                                         '-displayof', @displayof)
307     else
308       lst = @interp._invoke_without_enc('winfo', 'interps')
309     end
310     # unless @interp._split_tklist(lst).index(@remote)
311     unless @interp._split_tklist(lst).index(_toUTF8(@remote))
312       true
313     else
314       false
315     end
316   end
317
318   def has_mainwindow?
319     raise SecurityError, "no permission to manipulate" unless self.manipulable?
320
321     begin
322       inf = @interp._invoke_without_enc('info', 'command', '.')
323     rescue Exception
324       return nil
325     end
326     if !inf.kind_of?(String) || inf != '.'
327       false
328     else
329       true
330     end
331   end
332
333   def invalid_namespace?
334     false
335   end
336
337   def restart
338     fail RuntimeError, 'cannot restart the remote interpreter'
339   end
340
341   def __eval(str)
342     _appsend(false, false, str)
343   end
344   def _eval(str)
345     _appsend(nil, false, str)
346   end
347   def _eval_without_enc(str)
348     _appsend(false, false, str)
349   end
350   def _eval_with_enc(str)
351     _appsend(true, false, str)
352   end
353
354   def _invoke(*args)
355     _appsend(nil, false, *args)
356   end
357
358   def __invoke(*args)
359     _appsend(false, false, *args)
360   end
361   def _invoke(*args)
362     _appsend(nil, false, *args)
363   end
364   def _invoke_without_enc(*args)
365     _appsend(false, false, *args)
366   end
367   def _invoke_with_enc(*args)
368     _appsend(true, false, *args)
369   end
370
371   def _toUTF8(str, encoding=nil)
372     raise SecurityError, "no permission to manipulate" unless self.manipulable?
373     @interp._toUTF8(str, encoding)
374   end
375
376   def _fromUTF8(str, encoding=nil)
377     raise SecurityError, "no permission to manipulate" unless self.manipulable?
378     @interp._fromUTF8(str, encoding)
379   end
380
381   def _thread_vwait(var_name)
382     _appsend(false, 'thread_vwait', varname)
383   end
384
385   def _thread_tkwait(mode, target)
386     _appsend(false, 'thread_tkwait', mode, target)
387   end
388
389   def _return_value
390     raise SecurityError, "no permission to manipulate" unless self.manipulable?
391     @interp._return_value
392   end
393
394   def _get_variable(var_name, flag)
395     # ignore flag
396     _appsend(false, 'set', TkComm::_get_eval_string(var_name))
397   end
398   def _get_variable2(var_name, index_name, flag)
399     # ignore flag
400     _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
401   end
402
403   def _set_variable(var_name, value, flag)
404     # ignore flag
405     _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
406   end
407   def _set_variable2(var_name, index_name, value, flag)
408     # ignore flag
409     _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
410   end
411
412   def _unset_variable(var_name, flag)
413     # ignore flag
414     _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
415   end
416   def _unset_variable2(var_name, index_name, flag)
417     # ignore flag
418     _appsend(false, 'unset', "#{var_name}(#{index_name})")
419   end
420
421   def _get_global_var(var_name)
422     _appsend(false, 'set', TkComm::_get_eval_string(var_name))
423   end
424   def _get_global_var2(var_name, index_name)
425     _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})")
426   end
427
428   def _set_global_var(var_name, value)
429     _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value))
430   end
431   def _set_global_var2(var_name, index_name, value)
432     _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value))
433   end
434
435   def _unset_global_var(var_name)
436     _appsend(false, 'unset', TkComm::_get_eval_string(var_name))
437   end
438   def _unset_global_var2(var_name, index_name)
439     _appsend(false, 'unset', "#{var_name}(#{index_name})")
440   end
441
442   def _split_tklist(str)
443     raise SecurityError, "no permission to manipulate" unless self.manipulable?
444     @interp._split_tklist(str)
445   end
446
447   def _merge_tklist(*args)
448     raise SecurityError, "no permission to manipulate" unless self.manipulable?
449     @interp._merge_tklist(*args)
450   end
451
452   def _conv_listelement(str)
453     raise SecurityError, "no permission to manipulate" unless self.manipulable?
454     @interp._conv_listelement(str)
455   end
456
457   def _create_console
458     fail RuntimeError, 'not support "_create_console" on the remote interpreter'
459   end
460
461   def mainloop
462     fail RuntimeError, 'not support "mainloop" on the remote interpreter'
463   end
464   def mainloop_watchdog
465     fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
466   end
467   def do_one_evant(flag = nil)
468     fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
469   end
470   def mainloop_abort_on_exception
471     fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
472   end
473   def mainloop_abort_on_exception=(mode)
474     fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
475   end
476   def set_eventloop_tick(*args)
477     fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
478   end
479   def get_eventloop_tick
480     fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
481   end
482   def set_no_event_wait(*args)
483     fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
484   end
485   def get_no_event_wait
486     fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
487   end
488   def set_eventloop_weight(*args)
489     fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
490   end
491   def get_eventloop_weight
492     fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
493   end
494 end
495
496 class << RemoteTkIp
497   def mainloop(*args)
498     fail RuntimeError, 'not support "mainloop" on the remote interpreter'
499   end
500   def mainloop_watchdog(*args)
501     fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
502   end
503   def do_one_evant(flag = nil)
504     fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
505   end
506   def mainloop_abort_on_exception
507     fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
508   end
509   def mainloop_abort_on_exception=(mode)
510     fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
511   end
512   def set_eventloop_tick(*args)
513     fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
514   end
515   def get_eventloop_tick
516     fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
517   end
518   def set_no_event_wait(*args)
519     fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
520   end
521   def get_no_event_wait
522     fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
523   end
524   def set_eventloop_weight(*args)
525     fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
526   end
527   def get_eventloop_weight
528     fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
529   end
530 end