tk_as_gem 0.0.0

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