From ffcedd79505ea2e99f859c7cea2fb2221c948d4c Mon Sep 17 00:00:00 2001 From: nagai Date: Thu, 1 Jul 2004 09:38:48 +0000 Subject: [PATCH] * ext/tk/lib/tcltklib : bug fix * ext/tk/lib/tk : bug fix and add Tcl/Tk extension support libraries git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6559 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 + ext/tcltklib/MANIFEST | 1 + ext/tcltklib/README.ActiveTcl | 42 + ext/tcltklib/extconf.rb | 10 +- ext/tcltklib/tcltklib.c | 12 + ext/tk/ChangeLog.tkextlib | 3 + ext/tk/MANIFEST | 170 +- ext/tk/README.1st | 2 + ext/tk/lib/README | 11 + ext/tk/lib/tk.rb | 1478 +++++++-- ext/tk/lib/tk/autoload.rb | 7 + ext/tk/lib/tk/canvas.rb | 56 +- ext/tk/lib/tk/canvastag.rb | 8 + ext/tk/lib/tk/event.rb | 35 +- ext/tk/lib/tk/font.rb | 176 +- ext/tk/lib/tk/itemconfig.rb | 781 +++++ ext/tk/lib/tk/itemfont.rb | 366 ++- ext/tk/lib/tk/listbox.rb | 26 +- ext/tk/lib/tk/menu.rb | 42 +- ext/tk/lib/tk/optionobj.rb | 212 ++ ext/tk/lib/tk/package.rb | 88 +- ext/tk/lib/tk/scrollable.rb | 21 + ext/tk/lib/tk/scrollbar.rb | 7 + ext/tk/lib/tk/scrollbox.rb | 5 + ext/tk/lib/tk/text.rb | 82 +- ext/tk/lib/tk/textmark.rb | 8 + ext/tk/lib/tk/texttag.rb | 13 + ext/tk/lib/tk/validation.rb | 171 +- ext/tk/lib/tk/variable.rb | 96 +- ext/tk/lib/tkextlib/ICONS.rb | 16 + ext/tk/lib/tkextlib/ICONS/icons.rb | 84 + ext/tk/lib/tkextlib/ICONS/setup.rb | 8 + ext/tk/lib/tkextlib/SUPPORT_STATUS | 161 + ext/tk/lib/tkextlib/pkg_checker.rb | 129 + ext/tk/lib/tkextlib/setup.rb | 8 + ext/tk/lib/tkextlib/tcllib.rb | 57 + ext/tk/lib/tkextlib/tcllib/README | 135 + ext/tk/lib/tkextlib/tcllib/autoscroll.rb | 100 + ext/tk/lib/tkextlib/tcllib/ctext.rb | 141 + ext/tk/lib/tkextlib/tcllib/cursor.rb | 41 + ext/tk/lib/tkextlib/tcllib/datefield.rb | 50 + ext/tk/lib/tkextlib/tcllib/ip_entry.rb | 53 + ext/tk/lib/tkextlib/tcllib/plotchart.rb | 666 ++++ ext/tk/lib/tkextlib/tcllib/setup.rb | 8 + ext/tk/lib/tkextlib/tcllib/style.rb | 30 + ext/tk/lib/tkextlib/tcllib/tkpiechart.rb | 284 ++ ext/tk/lib/tkextlib/tile.rb | 73 + ext/tk/lib/tkextlib/tile/setup.rb | 8 + ext/tk/lib/tkextlib/tile/style.rb | 67 + ext/tk/lib/tkextlib/tile/tbutton.rb | 28 + ext/tk/lib/tkextlib/tile/tcheckbutton.rb | 33 + ext/tk/lib/tkextlib/tile/tlabel.rb | 28 + ext/tk/lib/tkextlib/tile/tmenubutton.rb | 28 + ext/tk/lib/tkextlib/tile/tnotebook.rb | 90 + ext/tk/lib/tkextlib/tile/tradiobutton.rb | 33 + ext/tk/lib/tkextlib/tkDND.rb | 25 + ext/tk/lib/tkextlib/tkDND/setup.rb | 8 + ext/tk/lib/tkextlib/tkDND/shape.rb | 96 + ext/tk/lib/tkextlib/tkDND/tkdnd.rb | 108 + ext/tk/lib/tkextlib/tkHTML.rb | 16 + ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb | 427 +++ ext/tk/lib/tkextlib/tkHTML/setup.rb | 8 + ext/tk/lib/tkextlib/tkimg.rb | 23 + ext/tk/lib/tkextlib/tkimg/README | 26 + ext/tk/lib/tkextlib/tkimg/bmp.rb | 14 + ext/tk/lib/tkextlib/tkimg/gif.rb | 14 + ext/tk/lib/tkextlib/tkimg/ico.rb | 14 + ext/tk/lib/tkextlib/tkimg/jpeg.rb | 14 + ext/tk/lib/tkextlib/tkimg/pcx.rb | 14 + ext/tk/lib/tkextlib/tkimg/pixmap.rb | 21 + ext/tk/lib/tkextlib/tkimg/png.rb | 14 + ext/tk/lib/tkextlib/tkimg/ppm.rb | 14 + ext/tk/lib/tkextlib/tkimg/ps.rb | 14 + ext/tk/lib/tkextlib/tkimg/setup.rb | 8 + ext/tk/lib/tkextlib/tkimg/sgi.rb | 14 + ext/tk/lib/tkextlib/tkimg/sun.rb | 14 + ext/tk/lib/tkextlib/tkimg/tga.rb | 14 + ext/tk/lib/tkextlib/tkimg/tiff.rb | 14 + ext/tk/lib/tkextlib/tkimg/window.rb | 14 + ext/tk/lib/tkextlib/tkimg/xbm.rb | 14 + ext/tk/lib/tkextlib/tkimg/xpm.rb | 14 + ext/tk/lib/tkextlib/tktrans.rb | 17 + ext/tk/lib/tkextlib/tktrans/setup.rb | 8 + ext/tk/lib/tkextlib/tktrans/tktrans.rb | 53 + ext/tk/lib/tkextlib/treectrl.rb | 16 + ext/tk/lib/tkextlib/treectrl/setup.rb | 8 + ext/tk/lib/tkextlib/treectrl/tktreectrl.rb | 887 ++++++ ext/tk/lib/tkextlib/vu.rb | 40 + ext/tk/lib/tkextlib/vu/bargraph.rb | 50 + ext/tk/lib/tkextlib/vu/charts.rb | 47 + ext/tk/lib/tkextlib/vu/dial.rb | 102 + ext/tk/lib/tkextlib/vu/pie.rb | 229 ++ ext/tk/lib/tkextlib/vu/setup.rb | 8 + ext/tk/lib/tkextlib/vu/spinbox.rb | 17 + ext/tk/sample/demos-en/paned2.rb | 2 +- ext/tk/sample/demos-jp/entry3.rb | 2 +- ext/tk/sample/demos-jp/menu8x.rb | 3 +- ext/tk/sample/demos-jp/paned2.rb | 2 +- ext/tk/sample/optobj_sample.rb | 67 + ext/tk/sample/tkcombobox.rb | 7 + ext/tk/sample/tkextlib/tcllib/datefield.rb | 29 + ext/tk/sample/tkextlib/tcllib/plotdemos1.rb | 158 + ext/tk/sample/tkextlib/tcllib/plotdemos2.rb | 71 + ext/tk/sample/tkextlib/tcllib/plotdemos3.rb | 83 + ext/tk/sample/tkextlib/tcllib/xyplot.rb | 17 + ext/tk/sample/tkextlib/tkHTML/README | 12 + ext/tk/sample/tkextlib/tkHTML/hv.rb | 306 ++ ext/tk/sample/tkextlib/tkHTML/page1/image1 | Bin 0 -> 8995 bytes ext/tk/sample/tkextlib/tkHTML/page1/image10 | Bin 0 -> 3095 bytes ext/tk/sample/tkextlib/tkHTML/page1/image11 | Bin 0 -> 1425 bytes ext/tk/sample/tkextlib/tkHTML/page1/image12 | Bin 0 -> 2468 bytes ext/tk/sample/tkextlib/tkHTML/page1/image13 | Bin 0 -> 4073 bytes ext/tk/sample/tkextlib/tkHTML/page1/image14 | Bin 0 -> 53 bytes ext/tk/sample/tkextlib/tkHTML/page1/image2 | Bin 0 -> 42 bytes ext/tk/sample/tkextlib/tkHTML/page1/image3 | Bin 0 -> 3473 bytes ext/tk/sample/tkextlib/tkHTML/page1/image4 | Bin 0 -> 1988 bytes ext/tk/sample/tkextlib/tkHTML/page1/image5 | Bin 0 -> 973 bytes ext/tk/sample/tkextlib/tkHTML/page1/image6 | Bin 0 -> 2184 bytes ext/tk/sample/tkextlib/tkHTML/page1/image7 | Bin 0 -> 2022 bytes ext/tk/sample/tkextlib/tkHTML/page1/image8 | Bin 0 -> 1186 bytes ext/tk/sample/tkextlib/tkHTML/page1/image9 | Bin 0 -> 139 bytes .../sample/tkextlib/tkHTML/page1/index.html | 115 + ext/tk/sample/tkextlib/tkHTML/page2/image1 | Bin 0 -> 1966 bytes ext/tk/sample/tkextlib/tkHTML/page2/image10 | Bin 0 -> 255 bytes ext/tk/sample/tkextlib/tkHTML/page2/image11 | Bin 0 -> 590 bytes ext/tk/sample/tkextlib/tkHTML/page2/image12 | Bin 0 -> 254 bytes ext/tk/sample/tkextlib/tkHTML/page2/image13 | Bin 0 -> 493 bytes ext/tk/sample/tkextlib/tkHTML/page2/image14 | Bin 0 -> 195 bytes ext/tk/sample/tkextlib/tkHTML/page2/image15 | Bin 0 -> 68 bytes ext/tk/sample/tkextlib/tkHTML/page2/image16 | Bin 0 -> 157 bytes ext/tk/sample/tkextlib/tkHTML/page2/image17 | Bin 0 -> 81 bytes ext/tk/sample/tkextlib/tkHTML/page2/image18 | Bin 0 -> 545 bytes ext/tk/sample/tkextlib/tkHTML/page2/image19 | Bin 0 -> 53 bytes ext/tk/sample/tkextlib/tkHTML/page2/image2 | Bin 0 -> 49 bytes ext/tk/sample/tkextlib/tkHTML/page2/image20 | Bin 0 -> 533 bytes ext/tk/sample/tkextlib/tkHTML/page2/image21 | Bin 0 -> 564 bytes ext/tk/sample/tkextlib/tkHTML/page2/image22 | Bin 0 -> 81 bytes ext/tk/sample/tkextlib/tkHTML/page2/image23 | Bin 0 -> 539 bytes ext/tk/sample/tkextlib/tkHTML/page2/image24 | Bin 0 -> 151 bytes ext/tk/sample/tkextlib/tkHTML/page2/image25 | Bin 0 -> 453 bytes ext/tk/sample/tkextlib/tkHTML/page2/image26 | Bin 0 -> 520 bytes ext/tk/sample/tkextlib/tkHTML/page2/image27 | Bin 0 -> 565 bytes ext/tk/sample/tkextlib/tkHTML/page2/image28 | Bin 0 -> 416 bytes ext/tk/sample/tkextlib/tkHTML/page2/image29 | Bin 0 -> 121 bytes ext/tk/sample/tkextlib/tkHTML/page2/image3 | Bin 0 -> 10835 bytes ext/tk/sample/tkextlib/tkHTML/page2/image30 | Bin 0 -> 663 bytes ext/tk/sample/tkextlib/tkHTML/page2/image31 | Bin 0 -> 78 bytes ext/tk/sample/tkextlib/tkHTML/page2/image32 | Bin 0 -> 556 bytes ext/tk/sample/tkextlib/tkHTML/page2/image33 | Bin 0 -> 598 bytes ext/tk/sample/tkextlib/tkHTML/page2/image34 | Bin 0 -> 496 bytes ext/tk/sample/tkextlib/tkHTML/page2/image35 | Bin 0 -> 724 bytes ext/tk/sample/tkextlib/tkHTML/page2/image36 | Bin 0 -> 404 bytes ext/tk/sample/tkextlib/tkHTML/page2/image37 | Bin 0 -> 124 bytes ext/tk/sample/tkextlib/tkHTML/page2/image38 | Bin 0 -> 8330 bytes ext/tk/sample/tkextlib/tkHTML/page2/image39 | Bin 0 -> 369 bytes ext/tk/sample/tkextlib/tkHTML/page2/image4 | Bin 0 -> 268 bytes ext/tk/sample/tkextlib/tkHTML/page2/image5 | Bin 0 -> 492 bytes ext/tk/sample/tkextlib/tkHTML/page2/image6 | Bin 0 -> 246 bytes ext/tk/sample/tkextlib/tkHTML/page2/image7 | Bin 0 -> 551 bytes ext/tk/sample/tkextlib/tkHTML/page2/image8 | Bin 0 -> 497 bytes ext/tk/sample/tkextlib/tkHTML/page2/image9 | Bin 0 -> 492 bytes .../sample/tkextlib/tkHTML/page2/index.html | 433 +++ ext/tk/sample/tkextlib/tkHTML/page3/image1 | Bin 0 -> 113 bytes ext/tk/sample/tkextlib/tkHTML/page3/image10 | Bin 0 -> 5088 bytes ext/tk/sample/tkextlib/tkHTML/page3/image11 | Bin 0 -> 4485 bytes ext/tk/sample/tkextlib/tkHTML/page3/image12 | Bin 0 -> 3579 bytes ext/tk/sample/tkextlib/tkHTML/page3/image13 | Bin 0 -> 5119 bytes ext/tk/sample/tkextlib/tkHTML/page3/image14 | Bin 0 -> 3603 bytes ext/tk/sample/tkextlib/tkHTML/page3/image2 | Bin 0 -> 74 bytes ext/tk/sample/tkextlib/tkHTML/page3/image3 | Bin 0 -> 681 bytes ext/tk/sample/tkextlib/tkHTML/page3/image4 | Bin 0 -> 3056 bytes ext/tk/sample/tkextlib/tkHTML/page3/image5 | Bin 0 -> 2297 bytes ext/tk/sample/tkextlib/tkHTML/page3/image6 | Bin 0 -> 79 bytes ext/tk/sample/tkextlib/tkHTML/page3/image7 | Bin 0 -> 1613 bytes ext/tk/sample/tkextlib/tkHTML/page3/image8 | Bin 0 -> 864 bytes ext/tk/sample/tkextlib/tkHTML/page3/image9 | Bin 0 -> 2379 bytes .../sample/tkextlib/tkHTML/page3/index.html | 2787 +++++++++++++++++ ext/tk/sample/tkextlib/tkHTML/page4/image1 | Bin 0 -> 42 bytes ext/tk/sample/tkextlib/tkHTML/page4/image2 | Bin 0 -> 14343 bytes ext/tk/sample/tkextlib/tkHTML/page4/image3 | Bin 0 -> 17750 bytes ext/tk/sample/tkextlib/tkHTML/page4/image4 | Bin 0 -> 61 bytes ext/tk/sample/tkextlib/tkHTML/page4/image5 | Bin 0 -> 201 bytes ext/tk/sample/tkextlib/tkHTML/page4/image6 | Bin 0 -> 214 bytes ext/tk/sample/tkextlib/tkHTML/page4/image7 | Bin 0 -> 149 bytes ext/tk/sample/tkextlib/tkHTML/page4/image8 | Bin 0 -> 203 bytes ext/tk/sample/tkextlib/tkHTML/page4/image9 | Bin 0 -> 1504 bytes .../sample/tkextlib/tkHTML/page4/index.html | 768 +++++ ext/tk/sample/tkextlib/tkHTML/ss.rb | 404 +++ ext/tk/sample/tkextlib/vu/README.txt | 50 + ext/tk/sample/tkextlib/vu/canvItems.rb | 90 + ext/tk/sample/tkextlib/vu/canvSticker.rb | 82 + ext/tk/sample/tkextlib/vu/canvSticker2.rb | 99 + ext/tk/sample/tkextlib/vu/dial.rb | 113 + ext/tk/sample/tkextlib/vu/m128_000.xbm | 174 + ext/tk/sample/tkextlib/vu/oscilloscope.rb | 68 + ext/tk/sample/tkextlib/vu/pie.rb | 56 + ext/tk/sample/tkextlib/vu/vu.rb | 67 + ext/tk/sample/tkmultilistbox.rb | 4 +- ext/tk/tkutil.c | 77 +- 199 files changed, 14221 insertions(+), 677 deletions(-) create mode 100644 ext/tcltklib/README.ActiveTcl create mode 100644 ext/tk/ChangeLog.tkextlib create mode 100644 ext/tk/lib/tk/itemconfig.rb create mode 100644 ext/tk/lib/tk/optionobj.rb create mode 100644 ext/tk/lib/tkextlib/ICONS.rb create mode 100644 ext/tk/lib/tkextlib/ICONS/icons.rb create mode 100644 ext/tk/lib/tkextlib/ICONS/setup.rb create mode 100644 ext/tk/lib/tkextlib/SUPPORT_STATUS create mode 100755 ext/tk/lib/tkextlib/pkg_checker.rb create mode 100644 ext/tk/lib/tkextlib/setup.rb create mode 100644 ext/tk/lib/tkextlib/tcllib.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/README create mode 100644 ext/tk/lib/tkextlib/tcllib/autoscroll.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/ctext.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/cursor.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/datefield.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/ip_entry.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/plotchart.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/setup.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/style.rb create mode 100644 ext/tk/lib/tkextlib/tcllib/tkpiechart.rb create mode 100644 ext/tk/lib/tkextlib/tile.rb create mode 100644 ext/tk/lib/tkextlib/tile/setup.rb create mode 100644 ext/tk/lib/tkextlib/tile/style.rb create mode 100644 ext/tk/lib/tkextlib/tile/tbutton.rb create mode 100644 ext/tk/lib/tkextlib/tile/tcheckbutton.rb create mode 100644 ext/tk/lib/tkextlib/tile/tlabel.rb create mode 100644 ext/tk/lib/tkextlib/tile/tmenubutton.rb create mode 100644 ext/tk/lib/tkextlib/tile/tnotebook.rb create mode 100644 ext/tk/lib/tkextlib/tile/tradiobutton.rb create mode 100644 ext/tk/lib/tkextlib/tkDND.rb create mode 100644 ext/tk/lib/tkextlib/tkDND/setup.rb create mode 100644 ext/tk/lib/tkextlib/tkDND/shape.rb create mode 100644 ext/tk/lib/tkextlib/tkDND/tkdnd.rb create mode 100644 ext/tk/lib/tkextlib/tkHTML.rb create mode 100644 ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb create mode 100644 ext/tk/lib/tkextlib/tkHTML/setup.rb create mode 100644 ext/tk/lib/tkextlib/tkimg.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/README create mode 100644 ext/tk/lib/tkextlib/tkimg/bmp.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/gif.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/ico.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/jpeg.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/pcx.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/pixmap.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/png.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/ppm.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/ps.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/setup.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/sgi.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/sun.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/tga.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/tiff.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/window.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/xbm.rb create mode 100644 ext/tk/lib/tkextlib/tkimg/xpm.rb create mode 100644 ext/tk/lib/tkextlib/tktrans.rb create mode 100644 ext/tk/lib/tkextlib/tktrans/setup.rb create mode 100644 ext/tk/lib/tkextlib/tktrans/tktrans.rb create mode 100644 ext/tk/lib/tkextlib/treectrl.rb create mode 100644 ext/tk/lib/tkextlib/treectrl/setup.rb create mode 100644 ext/tk/lib/tkextlib/treectrl/tktreectrl.rb create mode 100644 ext/tk/lib/tkextlib/vu.rb create mode 100644 ext/tk/lib/tkextlib/vu/bargraph.rb create mode 100644 ext/tk/lib/tkextlib/vu/charts.rb create mode 100644 ext/tk/lib/tkextlib/vu/dial.rb create mode 100644 ext/tk/lib/tkextlib/vu/pie.rb create mode 100644 ext/tk/lib/tkextlib/vu/setup.rb create mode 100644 ext/tk/lib/tkextlib/vu/spinbox.rb create mode 100644 ext/tk/sample/optobj_sample.rb create mode 100644 ext/tk/sample/tkextlib/tcllib/datefield.rb create mode 100644 ext/tk/sample/tkextlib/tcllib/plotdemos1.rb create mode 100644 ext/tk/sample/tkextlib/tcllib/plotdemos2.rb create mode 100644 ext/tk/sample/tkextlib/tcllib/plotdemos3.rb create mode 100644 ext/tk/sample/tkextlib/tcllib/xyplot.rb create mode 100644 ext/tk/sample/tkextlib/tkHTML/README create mode 100644 ext/tk/sample/tkextlib/tkHTML/hv.rb create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image1 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image10 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image11 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image12 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image13 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image14 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image2 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image3 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image4 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image5 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image6 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image7 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image8 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/image9 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page1/index.html create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image1 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image10 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image11 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image12 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image13 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image14 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image15 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image16 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image17 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image18 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image19 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image2 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image20 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image21 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image22 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image23 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image24 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image25 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image26 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image27 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image28 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image29 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image3 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image30 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image31 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image32 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image33 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image34 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image35 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image36 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image37 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image38 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image39 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image4 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image5 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image6 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image7 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image8 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/image9 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page2/index.html create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image1 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image10 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image11 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image12 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image13 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image14 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image2 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image3 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image4 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image5 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image6 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image7 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image8 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/image9 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page3/index.html create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image1 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image2 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image3 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image4 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image5 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image6 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image7 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image8 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/image9 create mode 100644 ext/tk/sample/tkextlib/tkHTML/page4/index.html create mode 100644 ext/tk/sample/tkextlib/tkHTML/ss.rb create mode 100644 ext/tk/sample/tkextlib/vu/README.txt create mode 100644 ext/tk/sample/tkextlib/vu/canvItems.rb create mode 100644 ext/tk/sample/tkextlib/vu/canvSticker.rb create mode 100644 ext/tk/sample/tkextlib/vu/canvSticker2.rb create mode 100644 ext/tk/sample/tkextlib/vu/dial.rb create mode 100644 ext/tk/sample/tkextlib/vu/m128_000.xbm create mode 100644 ext/tk/sample/tkextlib/vu/oscilloscope.rb create mode 100644 ext/tk/sample/tkextlib/vu/pie.rb create mode 100644 ext/tk/sample/tkextlib/vu/vu.rb diff --git a/ChangeLog b/ChangeLog index ca58fa91ba..8ab4c6424c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Jul 1 18:36:08 2004 Hidetoshi NAGAI + + * ext/tk/lib/tcltklib : bug fix + + * ext/tk/lib/tk : bug fix and add Tcl/Tk extension support libraries + Thu Jul 1 18:31:31 2004 Nobuyoshi Nakada * lib/pstore.rb (PStore#transaction): get rid of opening in write mode diff --git a/ext/tcltklib/MANIFEST b/ext/tcltklib/MANIFEST index e408dc3ee8..92a6ed642b 100644 --- a/ext/tcltklib/MANIFEST +++ b/ext/tcltklib/MANIFEST @@ -1,5 +1,6 @@ MANIFEST README.1st +README.ActiveTcl README.euc MANUAL.euc MANUAL.eng diff --git a/ext/tcltklib/README.ActiveTcl b/ext/tcltklib/README.ActiveTcl new file mode 100644 index 0000000000..c9cc691973 --- /dev/null +++ b/ext/tcltklib/README.ActiveTcl @@ -0,0 +1,42 @@ +ActiveTcl is ActiveState's quality-assured distribution of Tcl. + +# see +# + +If you want to use ActiveTcl binary package as the Tcl/Tk libraries, +please use the following configure options. + + --with-tcl-dir= + --with-tk-dir= + +And use the followings if you need. + + --with-tcllib= + --with-tklib= + --enable-tcltk-stubs + +For example, when you install ActiveTcl-8.4.x to '/usr/local/ActiveTcl', + + configure --with-tcl-dir=/usr/local/ActiveTcl/ \ + --with-tk-dir=/usr/local/ActiveTcl/ \ + --with-tcllib=tcl8.4 \ + --with-tklib=tk8.4 \ + --enable-tcltk-stubs + +It depends on your environment that you have to add the directory of +ActiveTcl's dynamic link libraries to your library path when execute +Ruby/Tk. + +# For example, on Linux, one of the ways is to use LD_LIBRARY_PATH +# environment variable. +# +# [bash]$ LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH \ +# ruby your-Ruby/Tk-script +# +# [bash]$ LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH irb + +Then, you'll be able to use Tcl/Tk extension libraries included in the +ActiveTcl package (e.g. call TkPackage.require('BWidget'), and then, +use functions/widgets of BWidget extention). + + Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb index 83b4a2ac31..ac48812d7a 100644 --- a/ext/tcltklib/extconf.rb +++ b/ext/tcltklib/extconf.rb @@ -5,6 +5,12 @@ require 'mkmf' is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM) is_macosx = (/darwin/ =~ RUBY_PLATFORM) +mac_need_framework = + is_macosx && + enable_config("mac-tcltk-framework", false) && + FileTest.directory?("/Library/Frameworks/Tcl.framework/") && + FileTest.directory?("/Library/Frameworks/Tk.framework/") + unless is_win32 have_library("nsl", "t_open") have_library("socket", "socket") @@ -210,7 +216,7 @@ EOF end end -if is_macosx || +if mac_need_framework || (have_header("tcl.h") && have_header("tk.h") && (is_win32 || find_library("X11", "XOpenDisplay", "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) && @@ -219,7 +225,7 @@ if is_macosx || $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM - if is_macosx + if mac_need_framework $CPPFLAGS += ' -I/Library/Frameworks/Tcl.framework/headers -I/Library/Frameworks/Tk.framework/Headers' $LDFLAGS += ' -framework Tk -framework Tcl' end diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index cb3826ba9f..c68fe661e9 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -1201,12 +1201,15 @@ ip_ruby_eval(clientData, interp, argc, argv) rb_thread_critical = thr_crit_bup; if (eclass == eTkCallbackReturn) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (eclass == eTkCallbackBreak) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (eclass == eTkCallbackContinue) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else if (eclass == rb_eSystemExit) { @@ -1239,12 +1242,15 @@ ip_ruby_eval(clientData, interp, argc, argv) } if (SYM2ID(reason) == ID_return) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (SYM2ID(reason) == ID_break) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (SYM2ID(reason) == ID_next) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else { @@ -1572,12 +1578,15 @@ ip_ruby_cmd(clientData, interp, argc, argv) rb_thread_critical = thr_crit_bup; if (eclass == eTkCallbackReturn) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (eclass == eTkCallbackBreak) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (eclass == eTkCallbackContinue) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else if (eclass == rb_eSystemExit) { @@ -1609,12 +1618,15 @@ ip_ruby_cmd(clientData, interp, argc, argv) } if (SYM2ID(reason) == ID_return) { + ip_set_exc_message(interp, res); return TCL_RETURN; } else if (SYM2ID(reason) == ID_break) { + ip_set_exc_message(interp, res); return TCL_BREAK; } else if (SYM2ID(reason) == ID_next) { + ip_set_exc_message(interp, res); return TCL_CONTINUE; } else { diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib new file mode 100644 index 0000000000..48e6228e27 --- /dev/null +++ b/ext/tk/ChangeLog.tkextlib @@ -0,0 +1,3 @@ +2004-07-01 Hidetoshi NAGAI + + * 1st release of tkextlib ( to support Tcl/Tk extensions ) diff --git a/ext/tk/MANIFEST b/ext/tk/MANIFEST index c2ac51eddc..fbba82daef 100644 --- a/ext/tk/MANIFEST +++ b/ext/tk/MANIFEST @@ -1,6 +1,7 @@ MANIFEST README.1st README.fork +ChangeLog.tkextlib extconf.rb depend tkutil.c @@ -44,6 +45,7 @@ lib/tk/font.rb lib/tk/frame.rb lib/tk/grid.rb lib/tk/image.rb +lib/tk/itemconfig.rb lib/tk/itemfont.rb lib/tk/kinput.rb lib/tk/label.rb @@ -58,6 +60,7 @@ lib/tk/mngfocus.rb lib/tk/msgcat.rb lib/tk/namespace.rb lib/tk/optiondb.rb +lib/tk/optionobj.rb lib/tk/pack.rb lib/tk/package.rb lib/tk/palette.rb @@ -87,6 +90,71 @@ lib/tk/winfo.rb lib/tk/winpkg.rb lib/tk/wm.rb lib/tk/xim.rb +lib/tkextlib/SUPPORT_STATUS +lib/tkextlib/pkg_checker.rb +lib/tkextlib/setup.rb +lib/tkextlib/ICONS.rb +lib/tkextlib/ICONS/icons.rb +lib/tkextlib/ICONS/setup.rb +lib/tkextlib/tcllib.rb +lib/tkextlib/tcllib/README +lib/tkextlib/tcllib/autoscroll.rb +lib/tkextlib/tcllib/ctext.rb +lib/tkextlib/tcllib/cursor.rb +lib/tkextlib/tcllib/datefield.rb +lib/tkextlib/tcllib/ip_entry.rb +lib/tkextlib/tcllib/plotchart.rb +lib/tkextlib/tcllib/setup.rb +lib/tkextlib/tcllib/style.rb +lib/tkextlib/tcllib/tkpiechart.rb +lib/tkextlib/tile.rb +lib/tkextlib/tile/setup.rb +lib/tkextlib/tile/style.rb +lib/tkextlib/tile/tbutton.rb +lib/tkextlib/tile/tcheckbutton.rb +lib/tkextlib/tile/tlabel.rb +lib/tkextlib/tile/tmenubutton.rb +lib/tkextlib/tile/tnotebook.rb +lib/tkextlib/tile/tradiobutton.rb +lib/tkextlib/tkDND.rb +lib/tkextlib/tkDND/setup.rb +lib/tkextlib/tkDND/shape.rb +lib/tkextlib/tkDND/tkdnd.rb +lib/tkextlib/tkHTML.rb +lib/tkextlib/tkHTML/htmlwidget.rb +lib/tkextlib/tkHTML/setup.rb +lib/tkextlib/tkimg.rb +lib/tkextlib/tkimg/README +lib/tkextlib/tkimg/bmp.rb +lib/tkextlib/tkimg/gif.rb +lib/tkextlib/tkimg/ico.rb +lib/tkextlib/tkimg/jpeg.rb +lib/tkextlib/tkimg/pcx.rb +lib/tkextlib/tkimg/pixmap.rb +lib/tkextlib/tkimg/png.rb +lib/tkextlib/tkimg/ppm.rb +lib/tkextlib/tkimg/ps.rb +lib/tkextlib/tkimg/setup.rb +lib/tkextlib/tkimg/sgi.rb +lib/tkextlib/tkimg/sun.rb +lib/tkextlib/tkimg/tga.rb +lib/tkextlib/tkimg/tiff.rb +lib/tkextlib/tkimg/window.rb +lib/tkextlib/tkimg/xbm.rb +lib/tkextlib/tkimg/xpm.rb +lib/tkextlib/tktrans.rb +lib/tkextlib/tktrans/setup.rb +lib/tkextlib/tktrans/tktrans.rb +lib/tkextlib/treectrl.rb +lib/tkextlib/treectrl/setup.rb +lib/tkextlib/treectrl/tktreectrl.rb +lib/tkextlib/vu.rb +lib/tkextlib/vu/bargraph.rb +lib/tkextlib/vu/charts.rb +lib/tkextlib/vu/dial.rb +lib/tkextlib/vu/pie.rb +lib/tkextlib/vu/setup.rb +lib/tkextlib/vu/spinbox.rb sample/binding_sample.rb sample/bindtag_sample.rb sample/binstr_usage.rb @@ -95,12 +163,13 @@ sample/encstr_usage.rb sample/iso2022-kr.txt sample/menubar1.rb sample/menubar2.rb +sample/optobj_sample.rb sample/propagate.rb +sample/remote-ip_sample.rb +sample/remote-ip_sample2.rb sample/resource.en sample/resource.ja sample/safe-tk.rb -sample/remote-ip_sample.rb -sample/remote-ip_sample2.rb sample/tkalignbox.rb sample/tkballoonhelp.rb sample/tkbiff.rb @@ -313,3 +382,100 @@ sample/msgs_tk/ja.msg sample/msgs_tk/nl.msg sample/msgs_tk/pl.msg sample/msgs_tk/ru.msg +sample/tkextlib/tcllib/datefield.rb +sample/tkextlib/tcllib/plotdemos1.rb +sample/tkextlib/tcllib/plotdemos2.rb +sample/tkextlib/tcllib/plotdemos3.rb +sample/tkextlib/tcllib/xyplot.rb +sample/tkextlib/tkHTML/README +sample/tkextlib/tkHTML/hv.rb +sample/tkextlib/tkHTML/ss.rb +sample/tkextlib/tkHTML/page1/image1 +sample/tkextlib/tkHTML/page1/image10 +sample/tkextlib/tkHTML/page1/image11 +sample/tkextlib/tkHTML/page1/image12 +sample/tkextlib/tkHTML/page1/image13 +sample/tkextlib/tkHTML/page1/image14 +sample/tkextlib/tkHTML/page1/image2 +sample/tkextlib/tkHTML/page1/image3 +sample/tkextlib/tkHTML/page1/image4 +sample/tkextlib/tkHTML/page1/image5 +sample/tkextlib/tkHTML/page1/image6 +sample/tkextlib/tkHTML/page1/image7 +sample/tkextlib/tkHTML/page1/image8 +sample/tkextlib/tkHTML/page1/image9 +sample/tkextlib/tkHTML/page1/index.html +sample/tkextlib/tkHTML/page2/image1 +sample/tkextlib/tkHTML/page2/image10 +sample/tkextlib/tkHTML/page2/image11 +sample/tkextlib/tkHTML/page2/image12 +sample/tkextlib/tkHTML/page2/image13 +sample/tkextlib/tkHTML/page2/image14 +sample/tkextlib/tkHTML/page2/image15 +sample/tkextlib/tkHTML/page2/image16 +sample/tkextlib/tkHTML/page2/image17 +sample/tkextlib/tkHTML/page2/image18 +sample/tkextlib/tkHTML/page2/image19 +sample/tkextlib/tkHTML/page2/image2 +sample/tkextlib/tkHTML/page2/image20 +sample/tkextlib/tkHTML/page2/image21 +sample/tkextlib/tkHTML/page2/image22 +sample/tkextlib/tkHTML/page2/image23 +sample/tkextlib/tkHTML/page2/image24 +sample/tkextlib/tkHTML/page2/image25 +sample/tkextlib/tkHTML/page2/image26 +sample/tkextlib/tkHTML/page2/image27 +sample/tkextlib/tkHTML/page2/image28 +sample/tkextlib/tkHTML/page2/image29 +sample/tkextlib/tkHTML/page2/image3 +sample/tkextlib/tkHTML/page2/image30 +sample/tkextlib/tkHTML/page2/image31 +sample/tkextlib/tkHTML/page2/image32 +sample/tkextlib/tkHTML/page2/image33 +sample/tkextlib/tkHTML/page2/image34 +sample/tkextlib/tkHTML/page2/image35 +sample/tkextlib/tkHTML/page2/image36 +sample/tkextlib/tkHTML/page2/image37 +sample/tkextlib/tkHTML/page2/image38 +sample/tkextlib/tkHTML/page2/image39 +sample/tkextlib/tkHTML/page2/image4 +sample/tkextlib/tkHTML/page2/image5 +sample/tkextlib/tkHTML/page2/image6 +sample/tkextlib/tkHTML/page2/image7 +sample/tkextlib/tkHTML/page2/image8 +sample/tkextlib/tkHTML/page2/image9 +sample/tkextlib/tkHTML/page2/index.html +sample/tkextlib/tkHTML/page3/image1 +sample/tkextlib/tkHTML/page3/image10 +sample/tkextlib/tkHTML/page3/image11 +sample/tkextlib/tkHTML/page3/image12 +sample/tkextlib/tkHTML/page3/image13 +sample/tkextlib/tkHTML/page3/image14 +sample/tkextlib/tkHTML/page3/image2 +sample/tkextlib/tkHTML/page3/image3 +sample/tkextlib/tkHTML/page3/image4 +sample/tkextlib/tkHTML/page3/image5 +sample/tkextlib/tkHTML/page3/image6 +sample/tkextlib/tkHTML/page3/image7 +sample/tkextlib/tkHTML/page3/image8 +sample/tkextlib/tkHTML/page3/image9 +sample/tkextlib/tkHTML/page3/index.html +sample/tkextlib/tkHTML/page4/image1 +sample/tkextlib/tkHTML/page4/image2 +sample/tkextlib/tkHTML/page4/image3 +sample/tkextlib/tkHTML/page4/image4 +sample/tkextlib/tkHTML/page4/image5 +sample/tkextlib/tkHTML/page4/image6 +sample/tkextlib/tkHTML/page4/image7 +sample/tkextlib/tkHTML/page4/image8 +sample/tkextlib/tkHTML/page4/image9 +sample/tkextlib/tkHTML/page4/index.html +sample/tkextlib/vu/README.txt +sample/tkextlib/vu/canvItems.rb +sample/tkextlib/vu/canvSticker.rb +sample/tkextlib/vu/canvSticker2.rb +sample/tkextlib/vu/dial.rb +sample/tkextlib/vu/m128_000.xbm +sample/tkextlib/vu/oscilloscope.rb +sample/tkextlib/vu/pie.rb +sample/tkextlib/vu/vu.rb diff --git a/ext/tk/README.1st b/ext/tk/README.1st index ff92fdd8a3..038528e553 100644 --- a/ext/tk/README.1st +++ b/ext/tk/README.1st @@ -1,6 +1,7 @@ If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so which is working collectry. If you fail to call 'require "tcltklib"', you may not have tcltklib.so. +( see also README files of tcltklib ) Even if there is a tcltklib.so on your Ruby library directry, it will not work without Tcl/Tk libraries (e.g. libtcl8.4.so) on your environment. You must also check that your Tcl/Tk is @@ -12,6 +13,7 @@ installed properly. Ruby/Tk (tk.rb など) を使いたい場合には,tcltklib.so が正しく 動いていなければなりません.もし require "tcltklib" に失敗する ようなら,tcltklib.so が存在していないのかもしれません. +( tcltklib の README ファイルも見てください ) たとえ Ruby のライブラリディレクトリに tcltklib.so が存在して いたとしても,実行環境に Tcl/Tk ライブラリ (libtcl8.4.so など) がなければ機能しません.Tcl/Tk が正しくインストールされているか diff --git a/ext/tk/lib/README b/ext/tk/lib/README index c003adb2c8..5918fe4bf0 100644 --- a/ext/tk/lib/README +++ b/ext/tk/lib/README @@ -1,6 +1,17 @@ README this file multi-tk.rb multiple Tk interpreter (included safe-Tk) support +remotei-tk.rb control remote Tk interpreter on the other process support tk.rb Tk interface + +tk/ library files construct Ruby/Tk + +tkextlib/ non-standard Tcl/Tk extension support libraries + +********************************************************************* +*** The followings exists for backward compatibility only. +*** The only thing which they work is that requires current +*** library files ( tk/*.rb ). +********************************************************************* tkafter.rb handles Tcl after tkbgerror.rb Tk error module tkcanvas.rb Tk canvas interface diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 8462c3064c..9cf2ac3e07 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -103,6 +103,8 @@ module TkComm gen_class_name = 'TkWidget_' + tk_class classname_def = "WidgetClassName = '#{tk_class}'.freeze" end + +=begin unless Object.const_defined? gen_class_name Object.class_eval "class #{gen_class_name}<#{ruby_class_name} #{classname_def} @@ -110,6 +112,21 @@ module TkComm end Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', 'without_creating'=>true)" +=end + base = Object + gen_class_name.split('::').each{|klass| + next if klass == '' + if base.const_defined?(klass) + base = base.class_eval klass + else + base = base.class_eval "class #{klass}<#{ruby_class_name} + #{classname_def} + end + #{klass}" + end + } + base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', + 'without_creating'=>true)" end private :_genobj_for_tkwidget module_function :_genobj_for_tkwidget @@ -790,8 +807,8 @@ module TkComm } end end - private :install_bind, :tk_event_sequence, - :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo + private :tk_event_sequence + private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo def bind(tagOrClass, context, cmd=Proc.new, args=nil) _bind(["bind", tagOrClass], context, cmd, args) @@ -1403,9 +1420,17 @@ module Tk TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze + major, minor = TCL_VERSION.split('.') + TCL_MAJOR_VERSION = major.to_i + TCL_MINOR_VERSION = minor.to_i + TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze + major, minor = TK_VERSION.split('.') + TK_MAJOR_VERSION = major.to_i + TK_MINOR_VERSION = minor.to_i + JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands", "kanji") != "").freeze @@ -1888,156 +1913,6 @@ else end -module TkTreatFont - def font_configinfo(name = nil) - ret = TkFont.used_on(self.path) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(self.path, self.path, 'configure') - end -=end - ret = TkFont.init_widget_font(self.path, self.path, 'configure') - end - ret - end - alias fontobj font_configinfo - - def font_configure(slot) - slot = _symbolkey2str(slot) - - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(self.path, self.path,'configure',slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - else - slot['font'] = fnt - tk_call(self.path, 'configure', *hash_kv(slot)) - end - end - return self - end - end - - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') - - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(self.path, self.path, - 'configure', slot) - end - - latinfont_configure(lfnt) if lfnt - kanjifont_configure(kfnt) if kfnt - - tk_call(self.path, 'configure', *hash_kv(slot)) if slot != {} - self - end - - def latinfont_configure(ltn, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object - else - tk_call(self.path, 'configure', '-font', ltn) - return self - end - - if fobj.kind_of?(TkFont) - if ltn.kind_of? TkFont - conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.latin_configure(conf.update(keys)) - else - fobj.latin_configure(conf) - end - else - fobj.latin_replace(ltn) - end - end - - return fobj.call_font_configure(self.path, self.path, 'configure', {}) - end - alias asciifont_configure latinfont_configure - - def kanjifont_configure(knj, keys=nil) - if (fobj = TkFont.used_on(self.path)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object - else - tk_call(self.path, 'configure', '-font', knj) - return self - end - - if fobj.kind_of?(TkFont) - if knj.kind_of? TkFont - conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.kanji_configure(conf.update(keys)) - else - fobj.kanji_configure(conf) - end - else - fobj.kanji_replace(knj) - end - end - - return fobj.call_font_configure(self.path, self.path, 'configure', {}) - end - - def font_copy(window, tag=nil) - if tag - fnt = window.tagfontobj(tag).dup - else - fnt = window.fontobj.dup - end - fnt.call_font_configure(self.path, self.path, 'configure', {}) - self - end - - def latinfont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.latin_replace(window.tagfontobj(tag).latin_font_id) - else - fontobj.latin_replace(window.fontobj.latin_font_id) - end - self - end - alias asciifont_copy latinfont_copy - - def kanjifont_copy(window, tag=nil) - fontobj.dup.call_font_configure(self.path, self.path, 'configure', {}) - if tag - fontobj.kanji_replace(window.tagfontobj(tag).kanji_font_id) - else - fontobj.kanji_replace(window.fontobj.kanji_font_id) - end - self - end -end - - module TkBindCore def bind(context, cmd=Proc.new, args=nil) Tk.bind(self, context, cmd, args) @@ -2057,9 +1932,1057 @@ module TkBindCore end +module TkTreatFont + def __font_optkeys + ['font'] + end + private :__font_optkeys + + def __pathname + self.path + end + private :__pathname + + ################################ + + def font_configinfo(key = nil) + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + else + fonts = {} + optkeys.each{|key| + key = key.to_s + pathname = [win, tag, key].join(';') + fonts[key] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *__config_cmd) + } + fonts + end + end + alias fontobj font_configinfo + + def font_configure(slot) + pathname = __pathname + + slot = _symbolkey2str(slot) + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey + + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) + + fnt.call_font_configure([pathname, optkey], *(__config_cmd << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__config_cmd << {})) + next + else + tk_call(*(__config_cmd << "-#{optkey}" << fnt)) + end + end + next + end + end + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__config_cmd << {})) + elsif lfnt + latinfont_configure([lfnt, optkey]) + elsif kfnt + kanjifont_configure([kfnt, optkey]) + end + } + + # configure other (without font) options + tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {} + self + end + + def latinfont_configure(ltn, keys=nil) + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] + else + key = nil + end + + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__config_cmd << "-#{optkey}" << ltn)) + next + end + + if fobj.kind_of?(TkFont) + if ltn.kind_of?(TkFont) + conf = {} + ltn.latin_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.latin_configure(conf.update(keys)) + else + fobj.latin_configure(conf) + end + else + fobj.latin_replace(ltn) + end + end + + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self + end + alias asciifont_configure latinfont_configure + + def kanjifont_configure(knj, keys=nil) + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] + else + key = nil + end + + optkeys = __font_optkeys + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __pathname.split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object + else + tk_call(*(__config_cmd << "-#{optkey}" << knj)) + next + end + + if fobj.kind_of?(TkFont) + if knj.kind_of?(TkFont) + conf = {} + knj.kanji_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.kanji_configure(conf.update(keys)) + else + fobj.kanji_configure(conf) + end + else + fobj.kanji_replace(knj) + end + end + + fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) + } + self + end + + def font_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end + else + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup + end + end + + if targetkey + fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {})) + else + fnt.call_font_configure(__pathname, *(__config_cmd << {})) + end + self + end + + def latinfont_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) + else + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.latin_replace(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end + else + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end + end + self + end + alias asciifont_copy latinfont_copy + + def kanjifont_copy(window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], + *(__config_cmd << {})) + else + fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end + end + self + end +end + + +module TkConfigMethod + include TkUtil + include TkTreatFont + + def __cget_cmd + [self.path, 'cget'] + end + private :__cget_cmd + + def __config_cmd + [self.path, 'configure'] + end + private :__config_cmd + + def __configinfo_struct + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + private :__configinfo_struct + + def __numval_optkeys + [] + end + private :__numval_optkeys + + def __numstrval_optkeys + [] + end + private :__numstrval_optkeys + + def __boolval_optkeys + [] + end + private :__boolval_optkeys + + def __strval_optkeys + ['text', 'label', 'show', 'data', 'file'] + end + private :__strval_optkeys + + def __listval_optkeys + [] + end + private :__listval_optkeys + + def __numlistval_optkeys + [] + end + private :__numlistval_optkeys + + def __methodcall_optkeys # { key=>method, ... } + {} + end + private :__methodcall_optkeys + + def __keyonly_optkeys # { def_key=>undef_key or nil, ... } + {} + end + private :__keyonly_optkeys + + def __conv_keyonly_opts(keys) + return keys unless keys.kind_of?(Hash) + keyonly = __keyonly_optkeys + keys2 = {} + keys.each{|k, v| + optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} + if optkey + defkey, undefkey = optkey + if v + keys2[defkey.to_s] = None + elsif undefkey + keys2[undefkey.to_s] = None + else + # remove key + end + else + keys2[k.to_s] = v + end + } + keys2 + end + + def config_hash_kv(keys, enc_mode = nil, conf = nil) + hash_kv(__conv_keyonly_opts(keys), enc_mode, conf) + end + + ################################ + + def cget(slot) + slot = slot.to_s + + if ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + return self.__send__(method) + end + + case slot + when /^(#{__numval_optkeys.join('|')})$/ + begin + number(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__boolval_optkeys.join('|')})$/ + begin + bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + rescue + nil + end + + when /^(#{__listval_optkeys.join('|')})$/ + simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) + if conf =~ /^[0-9+-]/ + list(conf) + else + conf + end + + when /^(#{__strval_optkeys.join('|')})$/ + _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) + + when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/ + fontcode = $1 + fontkey = $2 + fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true) + unless fnt.kind_of?(TkFont) + fnt = fontobj(fontkey) + end + if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + # obsolete; just for compatibility + fnt.kanji_font + else + fnt + end + + else + tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true) + end + end + + def configure(slot, value=None) + if slot.kind_of? Hash + slot = _symbolkey2str(slot) + + __methodcall_optkeys.each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, value) if value + } + + __keyonly_optkeys.each{|defkey, undefkey| + conf = slot.find{|kk, vv| kk == defkey.to_s} + if conf + k, v = conf + if v + slot[k] = None + else + slot[undefkey.to_s] = None if undefkey + slot.delete(k) + end + end + } + + if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/}) + font_configure(slot) + elsif slot.size > 0 + tk_call(*(__config_cmd.concat(hash_kv(slot)))) + end + + else + slot = slot.to_s + if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} ) + defkey, undefkey = conf + if value + tk_call(*(__config_cmd << "-#{defkey}")) + elsif undefkey + tk_call(*(__config_cmd << "-#{undefkey}")) + end + elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) + self.__send__(method, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + if value == None + fontobj($2) + else + font_configure({slot=>value}) + end + else + tk_call(*(__config_cmd << "-#{slot}" << value)) + end + end + self + end + + def configure_cmd(slot, value) + configure(slot, install_cmd(value)) + end + + def configinfo(slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + conf + else + if slot + slot = slot.to_s + case slot + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return [slot, '', '', '', self.__send__(method)] + + when /^(#{__numval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]]) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__strval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + else + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + end + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + + conf + + else + ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + else + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) + else + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) + end + end + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) + else + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) + end + end + end + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 \ + && conf[__configinfo_struct[:alias]][0] == ?- ) + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + + conf + } + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf && fontconf.size > 2 + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret.push(fontconf) + end + } + + __methodcall_optkeys.each{|optkey, method| + ret << [optkey.to_s, '', '', '', self.__send__(method)] + } + + ret + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{fontkey}")))) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + conf[__configinfo_struct[:current_value]] = fontobj(fontkey) + { conf.shift => conf } + elsif ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + else + if slot + slot = slot.to_s + case slot + when /^(#{__methodcall_optkeys.keys.join('|')})$/ + method = _symbolkey2str(__methodcall_optkeys)[slot] + return {slot => ['', '', '', self.__send__(method)]} + + when /^(#{__numval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__strval_optkeys.join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__config_cmd << "-#{slot}")))) + else + conf = tk_split_list(_fromUTF8(tk_send_without_enc(*(__config_cmd << "-#{slot}")))) + end + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + + else + ret = {} + tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__config_cmd))).each{|conflist| + conf = tk_split_simplelist(conflist) + conf[__configinfo_struct[:key]] = + conf[__configinfo_struct[:key]][1..-1] + + case conf[__configinfo_struct[:key]] + when /^(#{__strval_optkeys.join('|')})$/ + # do nothing + + when /^(#{__numval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + number(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + number(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__numstrval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + num_or_str(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + num_or_str(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__boolval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + begin + conf[__configinfo_struct[:default_value]] = + bool(conf[__configinfo_struct[:default_value]]) + rescue + conf[__configinfo_struct[:default_value]] = nil + end + end + if ( conf[__configinfo_struct[:current_value]] ) + begin + conf[__configinfo_struct[:current_value]] = + bool(conf[__configinfo_struct[:current_value]]) + rescue + conf[__configinfo_struct[:current_value]] = nil + end + end + + when /^(#{__listval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + conf[__configinfo_struct[:default_value]] = + simplelist(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] ) + conf[__configinfo_struct[:current_value]] = + simplelist(conf[__configinfo_struct[:current_value]]) + end + + when /^(#{__numlistval_optkeys.join('|')})$/ + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] \ + && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:default_value]] = + list(conf[__configinfo_struct[:default_value]]) + end + if ( conf[__configinfo_struct[:current_value]] \ + && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) + conf[__configinfo_struct[:current_value]] = + list(conf[__configinfo_struct[:current_value]]) + end + + else + if ( __configinfo_struct[:default_value] \ + && conf[__configinfo_struct[:default_value]] ) + if conf[__configinfo_struct[:default_value]].index('{') + conf[__configinfo_struct[:default_value]] = + tk_split_list(conf[__configinfo_struct[:default_value]]) + else + conf[__configinfo_struct[:default_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) + end + end + if conf[__configinfo_struct[:current_value]] + if conf[__configinfo_struct[:current_value]].index('{') + conf[__configinfo_struct[:current_value]] = + tk_split_list(conf[__configinfo_struct[:current_value]]) + else + conf[__configinfo_struct[:current_value]] = + tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) + end + end + end + + if ( __configinfo_struct[:alias] \ + && conf.size == __configinfo_struct[:alias] + 1 ) + if conf[__configinfo_struct[:alias]][0] == ?- + conf[__configinfo_struct[:alias]] = + conf[__configinfo_struct[:alias]][1..-1] + end + ret[conf[0]] = conf[1] + else + ret[conf.shift] = conf + end + } + + __font_optkeys.each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) + ret[optkey] = fontconf + end + } + + __methodcall_optkeys.each{|optkey, method| + ret[optkey.to_s] = ['', '', '', self.__send__(method)] + } + + ret + end + end + end + end + + def current_configinfo(slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = configinfo(slot) + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__configinfo_struct[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" + else + ret = {} + configinfo().each{|conf| + if ( ! __configinfo_struct[:alias] \ + || conf.size > __configinfo_struct[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + configinfo(slot).each{|key, conf| + ret[key] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +end + class TkObject definition is moved to TkUtil module @@ -2117,194 +3040,6 @@ class TkObject 0 - tk_call(path, 'configure', *hash_kv(slot)) - end - - else - if (slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont || - slot == 'latinfont' || slot == :latinfont || - slot == 'asciifont' || slot == :asciifont ) - if value == None - fontobj - else - font_configure({slot=>value}) - end - else - tk_call(path, 'configure', "-#{slot}", value) - end - end - self - end - - def configure_cmd(slot, value) - configure(slot, install_cmd(value)) - end - - def configinfo(slot = nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - conf[0] = conf[0][1..-1] - conf[4] = fontobj(conf[4]) - conf - else - if slot - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - end - conf[0] = conf[0][1..-1] - conf - else - ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure'))).collect{|conflist| - conf = tk_split_simplelist(conflist) - conf[0] = conf[0][1..-1] - case conf[0] - when 'text', 'label', 'show', 'data', 'file' - else - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) - else - conf[3] = tk_tcl2ruby(conf[3]) - end - end - if conf[4] - if conf[4].index('{') - conf[4] = tk_split_list(conf[4]) - else - conf[4] = tk_tcl2ruby(conf[4]) - end - end - end - conf[1] = conf[1][1..-1] if conf.size == 2 # alias info - conf - } - fontconf = ret.assoc('font') - if fontconf - ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} - fontconf[4] = fontobj(fontconf[4]) - ret.push(fontconf) - else - ret - end - end - end - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if slot == 'font' || slot == :font || - slot == 'kanjifont' || slot == :kanjifont - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - key = conf.shift[1..-1] - conf[3] = fontobj(conf[3]) - { key => conf } - else - if slot - case slot.to_s - when 'text', 'label', 'show', 'data', 'file' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('configure', "-#{slot}"))) - end - key = conf.shift[1..-1] - { key => conf } - else - ret = {} - tk_split_simplelist(_fromUTF8(tk_send_without_enc('configure'))).each{|conflist| - conf = tk_split_simplelist(conflist) - key = conf.shift[1..-1] - case key - when 'text', 'label', 'show', 'data', 'file' - else - if conf[2] - if conf[2].index('{') - conf[2] = tk_split_list(conf[2]) - else - conf[2] = tk_tcl2ruby(conf[2]) - end - end - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) - else - conf[3] = tk_tcl2ruby(conf[3]) - end - end - end - if conf.size == 1 - ret[key] = conf[0][1..-1] # alias info - else - ret[key] = conf - end - } - fontconf = ret['font'] - if fontconf - ret.delete('font') - ret.delete('kanjifont') - fontconf[3] = fontobj(fontconf[3]) - ret['font'] = fontconf - end - ret - end - end - end - end - - def current_configinfo(slot = nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot - conf = configinfo(slot) - {conf[0] => conf[4]} - else - ret = {} - configinfo().each{|conf| - ret[conf[0]] = conf[4] if conf.size > 2 - } - ret - end - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - ret = {} - configinfo(slot).each{|key, conf| - ret[key] = conf[-1] if conf.kind_of?(Array) - } - ret - end - end - def event_generate(context, keys=nil) if keys #tk_call('event', 'generate', path, @@ -2337,7 +3072,12 @@ class TkWindow If TkCommandNames[0] is a string (not a null string), + ## assume the string is a Tcl/Tk's create command of the widget class. WidgetClassName = ''.freeze + # WidgetClassNames[WidgetClassName] = self + ## ==> If self is a widget class, entry to the WidgetClassNames table. def self.to_eval self::WidgetClassName end @@ -2375,22 +3115,56 @@ class TkWindow 0) + rescue + fail RuntimeError, "class #{self.class} may be an abstract class" + end + + if keys and keys != None + tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) + else + tk_call_without_enc(cmd, @path) + end end private :create_self @@ -2912,3 +3686,11 @@ module Tk autoload :LIBRARY_PATH, 'tk/variable' autoload :TCL_PRECISION, 'tk/variable' end + + +# call setup script for Tk extension libraries (base configuration) +begin + require 'tkextlib/setup.rb' +rescue LoadError + # ignore +end diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb index 0a8251af8b..e3c29e96ea 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -63,6 +63,8 @@ autoload :TkImage, 'tk/image' autoload :TkBitmapImage, 'tk/image' autoload :TkPhotoImage, 'tk/image' +autoload :TkItemConfigMethod, 'tk/itemconfig' + autoload :TkTreatItemFont, 'tk/itemfont' autoload :TkKinput, 'tk/kinput' @@ -150,6 +152,7 @@ autoload :TkToplevel, 'tk/toplevel' autoload :TkTextWin, 'tk/txtwin_abst' autoload :TkValidation, 'tk/validation' + autoload :TkVariable, 'tk/variable' autoload :TkVarAccess, 'tk/variable' @@ -167,9 +170,13 @@ autoload :TkXIM, 'tk/xim' # sub-module of Tk module Tk autoload :Clock, 'tk/clock' + autoload :OptionObj, 'tk/optionobj' autoload :Scrollable, 'tk/scrollable' autoload :Wm, 'tk/wm' + autoload :ValidateConfigure, 'tk/validation' + autoload :ItemValidateConfigure, 'tk/validation' + autoload :EncodedString, 'tk/encodedstr' def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb index b311db6e20..17a05c0ce1 100644 --- a/ext/tk/lib/tk/canvas.rb +++ b/ext/tk/lib/tk/canvas.rb @@ -7,16 +7,16 @@ # require 'tk' require 'tk/canvastag' -require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' -module TkTreatCItemFont - include TkTreatItemFont +module TkCanvasItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_methodcall_optkeys(id) + {'coords'=>'coords'} end + private :__item_methodcall_optkeys def __item_pathname(tagOrId) if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag) @@ -25,12 +25,11 @@ module TkTreatCItemFont self.path + ';' + tagOrId.to_s end end - - private :__conf_cmd, :__item_pathname + private :__item_pathname end class TkCanvas, , ] - key_tbl = [ + KEY_TBL = [ [ ?#, ?n, :serial ], [ ?a, ?s, :above ], [ ?b, ?n, :num ], @@ -76,7 +86,7 @@ module TkEvent ] # [ , ] - proc_tbl = [ + PROC_TBL = [ [ ?n, TkComm.method(:num_or_str) ], [ ?s, TkComm.method(:string) ], [ ?b, TkComm.method(:bool) ], @@ -106,13 +116,13 @@ module TkEvent # ( which are Tcl strings ) to ruby objects based on the key string # that is generated by _get_subst_key() or _get_all_subst_keys(). # - _setup_subst_table(key_tbl, proc_tbl); + _setup_subst_table(KEY_TBL, PROC_TBL); end - def install_bind(cmd, *args) + def install_bind_for_event_class(klass, cmd, *args) if args.compact.size > 0 args = args.join(' ') - keys = Event._get_subst_key(args) + keys = klass._get_subst_key(args) if cmd.kind_of?(String) id = cmd @@ -120,12 +130,12 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, *Event.scan_args(keys, arg)) + TkUtil.eval_cmd(cmd, *klass.scan_args(keys, arg)) }) end id + ' ' + args else - keys, args = Event._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd @@ -133,10 +143,17 @@ module TkEvent id = install_cmd(cmd) else id = install_cmd(proc{|*arg| - TkUtil.eval_cmd(cmd, Event.new(*Event.scan_args(keys, arg))) + TkUtil.eval_cmd(cmd, klass.new(*klass.scan_args(keys, arg))) }) end id + ' ' + args end end + + def install_bind(cmd, *args) + install_bind_for_event_class(Event, cmd, *args) + end +end + +################################################ end diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb index 9b38531f59..b4c5c79213 100644 --- a/ext/tk/lib/tk/font.rb +++ b/ext/tk/lib/tk/font.rb @@ -73,25 +73,18 @@ class TkFont when 'unix' ltn = {'family'=>'Helvetica'.freeze, 'size'=>-12, 'weight'=>'bold'.freeze} - #knj = 'k14' - #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' - knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' when 'windows' ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} - knj = 'mincho' when 'macintosh' ltn = 'system' - knj = 'mincho' else # unknown ltn = 'Helvetica' - knj = 'mincho' end rescue ltn = 'Helvetica' - knj = 'mincho' end - knj = ltn + knj = ltn.dup end DEFAULT_LATIN_FONT_NAME = ltn.freeze @@ -202,54 +195,74 @@ class TkFont end end - def TkFont.init_widget_font(path, *args) + def TkFont.init_widget_font(pathname, *args) + win, tag, key = pathname.split(';') + key = 'font' unless key + path = [win, tag, key].join(';') + case (Tk::TK_VERSION) when /^4\.*/ - conf = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop[0..5]=='-font ' || prop[0..10]=='-kanjifont '}. + regexp = /^-(|kanji)#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} - if font_inf = conf.assoc('-font') - ltn = font_inf[4] - ltn = nil if ltn == [] - else - #ltn = nil - raise RuntimeError, "unknown option '-font'" + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" end - if font_inf = conf.assoc('-kanjifont') - knj = font_inf[4] - knj = nil if knj == [] - else - knj = nil - end - TkFont.new(ltn, knj).call_font_configure(path, *(args + [{}])) + + args << {} + + ltn_key = "-#{key}" + knj_key = "-kanji#{key}" + + ltn_info = conf_list.find{|conf| conf[0] == ltn_key} + ltn = ltn_info[-1] + ltn = nil if ltn == [] || ltn == "" + + knj_info = conf_list.find{|conf| conf[0] == knj_key} + knj = knj_info[-1] + knj = nil if knj == [] || knj == "" + + TkFont.new(ltn, knj).call_font_configure([path, key], *args) when /^8\.*/ - font_prop = tk_split_simplelist(tk_call(*args)).find{|prop| - prop[0..5] == '-font ' - } - unless font_prop - raise RuntimeError, "unknown option '-font'" + regexp = /^-#{key} / + + conf_list = tk_split_simplelist(tk_call(*args)). + find_all{|prop| prop =~ regexp}. + collect{|prop| tk_split_simplelist(prop)} + + if conf_list.size == 0 + raise RuntimeError, "the widget may not support 'font' option" end - fnt = tk_split_simplelist(font_prop)[4] - if fnt == "" - TkFont.new(nil, nil).call_font_configure(path, *(args + [{}])) + + args << {} + + optkey = "-#{key}" + + info = conf_list.find{|conf| conf[0] == optkey} + fnt = info[-1] + fnt = nil if fnt == [] || fnt == "" + + unless fnt + TkFont.new(nil, nil).call_font_configure([path, key], *args) else begin compound = tk_split_simplelist( - Hash[*tk_split_simplelist(tk_call('font', 'configure', - fnt))].collect{|key,value| - [key[1..-1], value] - }.assoc('compound')[1]) + Hash[*tk_split_simplelist(tk_call('font', 'configure', + fnt))].collect{|key,value| + [key[1..-1], value] + }.assoc('compound')[1]) rescue compound = [] end if compound == [] - #TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \ - #.call_font_configure(path, *(args + [{}])) - TkFont.new(fnt).call_font_configure(path, *(args + [{}])) + TkFont.new(fnt).call_font_configure([path, key], *args) else - TkFont.new(compound[0], compound[1]) \ - .call_font_configure(path, *(args + [{}])) + TkFont.new(compound[0], + compound[1]).call_font_configure([path, key], *args) end end end @@ -854,15 +867,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'font' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'font'=>@latinfont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-font', @latinfont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-font', @latinfont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-font', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -888,15 +902,16 @@ class TkFont if self == fobj begin if w.include?(';') - win, tag = w.split(';') + win, tag, optkey = w.split(';') + optkey = 'kanjifont' unless optkey winobj = tk_tcl2ruby(win) # winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) if winobj.kind_of? TkText - tk_call(win, 'tag', 'configure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkCanvas - tk_call(win, 'itemconfigure', tag, '-kanjifont', @kanjifont) + tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) elsif winobj.kind_of? TkMenu - tk_call(win, 'entryconfigure', tag, '-kanjifont', @latinfont) + tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) else raise RuntimeError, "unknown widget type" end @@ -1128,36 +1143,77 @@ class TkFont end def call_font_configure(path, *args) - keys = args.pop.update(@fontslot) + if path.kind_of?(Array) + # [path, optkey] + win, tag = path[0].split(';') + optkey = path[1].to_s + else + win, tag, optkey = path.split(';') + end + + fontslot = _symbolkey2str(@fontslot) + if optkey && optkey != "" + ltn = fontslot.delete('font') + knj = fontslot.delete('kanjifont') + fontslot[optkey] = ltn if ltn + fontslot["kanji#{optkey}"] = knj if knj + end + + keys = _symbolkey2str(args.pop).update(fontslot) args.concat(hash_kv(keys)) tk_call(*args) - Tk_FontUseTBL[path] = self + Tk_FontUseTBL[[win, tag, optkey].join(';')] = self self end def used ret = [] Tk_FontUseTBL.each{|key,value| + next unless self == value if key.include?(';') - win, tag = key.split(';') + win, tag, optkey = key.split(';') winobj = tk_tcl2ruby(win) if winobj.kind_of? TkText - ret.push([winobj, winobj.tagid2obj(tag)]) + if optkey + ret.push([winobj, winobj.tagid2obj(tag), optkey]) + else + ret.push([winobj, winobj.tagid2obj(tag)]) + end elsif winobj.kind_of? TkCanvas if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag - ret.push([winobj, tagobj]) - elsif (tagobj = TkcItem.id2obj(tag)).kind_of? TkcItem - ret.push([winobj, tagobj]) + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end + elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem + if optkey + ret.push([winobj, tagobj, optkey]) + else + ret.push([winobj, tagobj]) + end + else + if optkey + ret.push([winobj, tag, optkey]) + else + ret.push([winobj, tag]) + end + end + elsif winobj.kind_of? TkMenu + if optkey + ret.push([winobj, tag, optkey]) else ret.push([winobj, tag]) end - elsif winobj.kind_of? TkMenu - ret.push([winobj, tag]) else - ret.push([win, tag]) + if optkey + ret.push([win, tag, optkey]) + else + ret.push([win, tag]) + end end else - ret.push(tk_tcl2ruby(key)) if value == self + ret.push(tk_tcl2ruby(key)) end } ret diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb new file mode 100644 index 0000000000..b1cc776748 --- /dev/null +++ b/ext/tk/lib/tk/itemconfig.rb @@ -0,0 +1,781 @@ +# +# tk/itemconfig.rb : control item/tag configuration of widget +# +require 'tk' +require 'tkutil' +require 'tk/itemfont.rb' + +module TkItemConfigOptkeys + def __item_numval_optkeys(id) + [] + end + private :__item_numval_optkeys + + def __item_numstrval_optkeys(id) + [] + end + private :__item_numstrval_optkeys + + def __item_boolval_optkeys(id) + [] + end + private :__item_boolval_optkeys + + def __item_strval_optkeys(id) + # maybe need to override + ['text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile'] + end + private :__item_strval_optkeys + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys + + def __item_numlistval_optkeys(id) + # maybe need to override + ['dash', 'activedash', 'disableddash'] + end + private :__item_numlistval_optkeys + + def __item_methodcall_optkeys(id) # { key=>method, ... } + # maybe need to override + # {'coords'=>'coords'} + {} + end + private :__item_methodcall_optkeys + + ################################################ + + def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... } + # maybe need to override + {} + end + private :__item_keyonly_optkeys + + + def __conv_item_keyonly_opts(id, keys) + return keys unless keys.kind_of?(Hash) + keyonly = __item_keyonly_optkeys(id) + keys2 = {} + keys.each{|k, v| + optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} + if optkey + defkey, undefkey = optkey + if v + keys2[defkey.to_s] = None + else + keys2[undefkey.to_s] = None + end + else + keys2[k.to_s] = v + end + } + keys2 + end + + def itemconfig_hash_kv(id, keys, enc_mode = nil, conf = nil) + hash_kv(__conv_item_keyonly_opts(id, keys), enc_mode, conf) + end +end + +module TkItemConfigMethod + include TkUtil + include TkTreatItemFont + include TkItemConfigOptkeys + + def __item_cget_cmd(id) + # maybe need to override + [self.path, 'itemcget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + # maybe need to override + [self.path, 'itemconfigure', id] + end + private :__item_config_cmd + + def __item_configinfo_struct(id) + # maybe need to override + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + private :__item_configinfo_struct + + ################################################ + + def itemcget(tagOrId, option) + option = option.to_s + + if ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[option] ) + return self.__send__(method, tagOrId) + end + + case option + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + number(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + rescue + nil + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + num_or_str(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + begin + bool(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + rescue + nil + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + simplelist(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")) + if conf =~ /^[0-9]/ + list(conf) + else + conf + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + _fromUTF8(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))) + + when /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/ + fontcode = $1 + fontkey = $2 + fnt = tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{fontkey}")), true) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tagid(tagOrId), fontkey) + end + if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ + # obsolete; just for compatibility + fnt.kanji_font + else + fnt + end + else + tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true) + end + end + + def itemconfigure(tagOrId, slot, value=None) + if slot.kind_of? Hash + slot = _symbolkey2str(slot) + + __item_methodcall_optkeys(tagid(tagOrId)).each{|key, method| + value = slot.delete(key.to_s) + self.__send__(method, tagOrId, value) if value + } + + __item_keyonly_optkeys(tagid(tagOrId)).each{|defkey, undefkey| + conf = slot.find{|kk, vv| kk == defkey.to_s} + if conf + k, v = conf + if v + slot[k] = None + else + slot[undefkey.to_s] = None if undefkey + slot.delete(k) + end + end + } + + if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/}) + tagfont_configure(tagid(tagOrId), slot) + elsif slot.size > 0 + tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) + end + + else + slot = slot.to_s + if ( conf = __item_keyonly_optkeys(tagid(tagOrId)).find{|k, v| k.to_s == slot } ) + defkey, undefkey = conf + if value + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{defkey}")) + elsif undefkey + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{undefkey}")) + end + elsif ( method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] ) + self.__send__(method, tagOrId, value) + elsif (slot =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + if value == None + tagfontobj(tagid(tagOrId), $2) + else + tagfont_configure(tagid(tagOrId), {slot=>value}) + end + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}" << value)) + end + end + self + end + + def itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey) + elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + conf + else + if slot + slot = slot.to_s + case slot + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return [slot, '', '', '', self.__send__(method, tagOrId)] + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + else + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + + conf + + else + ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)))))).collect{|conflist| + conf = tk_split_simplelist(conflist) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + case conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + else + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + end + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + end + end + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- ) + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + + conf + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret.assoc(optkey) + if fontconf && fontconf.size > 2 + ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} + fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) + ret.push(fontconf) + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret << [optkey.to_s, '', '', '', self.__send__(method, tagOrId)] + } + + ret + end + end + + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + if (slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/) + fontkey = $2 + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{fontkey}")))) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey) + { conf.shift => conf } + elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + else + if slot + slot = slot.to_s + case slot + when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/ + method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot] + return {slot => ['', '', '', self.__send__(method, tagOrId)]} + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_stre(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + + else + conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)) << "-#{slot}")))) + end + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + { conf[0] => conf[1] } + else + { conf.shift => conf } + end + + else + ret = {} + tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__item_config_cmd(tagid(tagOrId)))))).each{|conflist| + conf = tk_split_simplelist(conflist) + conf[__item_configinfo_struct(tagid(tagOrId))[:key]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1] + + case conf[__item_configinfo_struct(tagid(tagOrId))[:key]] + when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/ + # do nothing + + when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + number(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + num_or_str(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = nil + end + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + begin + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + bool(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + rescue + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil + end + end + + when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + simplelist(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/ + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + if ( conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] =~ /^[0-9]/ ) + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + + else + if ( __item_configinfo_struct(tagid(tagOrId))[:default_value] \ + && conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]) + end + end + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] + if conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]].index('{') + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_split_list(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + else + conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = + tk_tcl2ruby(conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]]) + end + end + end + + if ( __item_configinfo_struct(tagid(tagOrId))[:alias] \ + && conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + if conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][0] == ?- + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] = + conf[__item_configinfo_struct(tagid(tagOrId))[:alias]][1..-1] + end + ret[conf[0]] = conf[1] + else + ret[conf.shift] = conf + end + } + + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + fontconf = ret[optkey] + if fontconf.kind_of?(Array) + ret.delete(optkey) + ret.delete('latin' << optkey) + ret.delete('ascii' << optkey) + ret.delete('kanji' << optkey) + fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey) + ret[optkey] = fontconf + end + } + + __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method| + ret[optkey.to_s] = ['', '', '', self.__send__(method, tagOrId)] + } + + ret + end + end + end + end + + def current_itemconfiginfo(tagOrId, slot = nil) + if TkComm::GET_CONFIGINFO_AS_ARRAY + if slot + org_slot = slot + begin + conf = itemconfiginfo(tagOrId, slot) + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + return {conf[0] => conf[-1]} + end + slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]] + end while(org_slot != slot) + fail RuntimeError, + "there is a configure alias loop about '#{org_slot}'" + else + ret = {} + itemconfiginfo(tagOrId).each{|conf| + if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \ + || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 ) + ret[conf[0]] = conf[-1] + end + } + ret + end + else # ! TkComm::GET_CONFIGINFO_AS_ARRAY + ret = {} + itemconfiginfo(slot).each{|key, conf| + ret[key] = conf[-1] if conf.kind_of?(Array) + } + ret + end + end +end diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb index 6e92fc001c..f653755b06 100644 --- a/ext/tk/lib/tk/itemfont.rb +++ b/ext/tk/lib/tk/itemfont.rb @@ -3,182 +3,294 @@ # require 'tk' -module TkTreatItemFont - def __conf_cmd(idx) - raise NotImplementedError, "need to define `__conf_cmd'" +module TkItemFontOptkeys + def __item_font_optkeys(id) + # maybe need to override + ['font'] end - def __item_pathname(tagOrId) - raise NotImplementedError, "need to define `__item_pathname'" - end - private :__conf_cmd, :__item_pathname + private :__item_font_optkeys +end - def tagfont_configinfo(tagOrId, name = nil) - pathname = __item_pathname(tagOrId) - ret = TkFont.used_on(pathname) - if ret == nil -=begin - if name - ret = name - else - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) - end -=end - ret = TkFont.init_widget_font(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId) +module TkTreatItemFont + include TkItemFontOptkeys + + def __item_pathname(id) + # maybe need to override + [self.path, id].join(';') + end + private :__item_pathname + + ################################################ + + def tagfont_configinfo(tagOrId, key = nil) + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + if key + pathname = [win, tag, key].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + elsif optkeys.size == 1 + pathname = [win, tag, optkeys[0]].join(';') + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + else + fonts = {} + optkeys.each{|key| + key = key.to_s + pathname = [win, tag, key].join(';') + fonts[key] = + TkFont.used_on(pathname) || + TkFont.init_widget_font(pathname, *(__item_config_cmd(tagid(tagOrId)))) + } + fonts end - ret end alias tagfontobj tagfont_configinfo def tagfont_configure(tagOrId, slot) - pathname = __item_pathname(tagOrId) + pathname = __item_pathname(tagid(tagOrId)) + slot = _symbolkey2str(slot) - if slot.key?('font') - fnt = slot.delete('font') - if fnt.kind_of? TkFont - return fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, slot) - else - if fnt - if (slot.key?('kanjifont') || - slot.key?('latinfont') || - slot.key?('asciifont')) - fnt = TkFont.new(fnt) + __item_font_optkeys(tagid(tagOrId)).each{|optkey| + optkey = optkey.to_s + l_optkey = 'latin' << optkey + a_optkey = 'ascii' << optkey + k_optkey = 'kanji' << optkey - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') + if slot.key?(optkey) + fnt = slot.delete(optkey) + if fnt.kind_of?(TkFont) + slot.delete(l_optkey) + slot.delete(a_optkey) + slot.delete(k_optkey) - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + if fnt + if (slot.key?(l_optkey) || + slot.key?(a_optkey) || + slot.key?(k_optkey)) + fnt = TkFont.new(fnt) + + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) + + fnt.latin_replace(lfnt) if lfnt + fnt.kanji_replace(kfnt) if kfnt + + fnt.call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + next + else + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt)) + end end - - slot['font'] = fnt - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) + next end - return self end - end - lfnt = slot.delete('latinfont') - lfnt = slot.delete('asciifont') if slot.key?('asciifont') - kfnt = slot.delete('kanjifont') + lfnt = slot.delete(l_optkey) + lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) + kfnt = slot.delete(k_optkey) - if lfnt && kfnt - return TkFont.new(lfnt, kfnt).call_font_configure(pathname, self.path, - __conf_cmd(0), - __conf_cmd(1), - tagOrId, slot) - end + if lfnt && kfnt + TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) + elsif lfnt + latintagfont_configure([lfnt, optkey]) + elsif kfnt + kanjitagfont_configure([kfnt, optkey]) + end + } - latintagfont_configure(tagOrId, lfnt) if lfnt - kanjitagfont_configure(tagOrId, kfnt) if kfnt - - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), - tagOrId, *hash_kv(slot)) if slot != {} + # configure other (without font) options + tk_call(*(__item_config_cmd(tagid(tagOrId)).concat(hash_kv(slot)))) if slot != {} self end def latintagfont_configure(tagOrId, ltn, keys=nil) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if ltn.kind_of?(Array) + key = ltn[1] + ltn = ltn[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', ltn) - return self + key = nil end - if fobj.kind_of?(TkFont) - if ltn.kind_of? TkFont - conf = {} - ltn.latin_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.latin_configure(conf.update(keys)) - else - fobj.latin_configure(conf) - end + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object else - fobj.latin_replace(ltn) + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn)) + next end - end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) + if fobj.kind_of?(TkFont) + if ltn.kind_of?(TkFont) + conf = {} + ltn.latin_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.latin_configure(conf.update(keys)) + else + fobj.latin_configure(conf) + end + else + fobj.latin_replace(ltn) + end + end + + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self end alias asciitagfont_configure latintagfont_configure def kanjitagfont_configure(tagOrId, knj, keys=nil) - pathname = __item_pathname(tagOrId) - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = tagfontobj(tagOrId) # create a new TkFont object + if knj.kind_of?(Array) + key = knj[1] + knj = knj[0] else - tk_call(self.path, __conf_cmd(0), __conf_cmd(1), tagOrId, '-font', knj) - return self + key = nil end - if fobj.kind_of?(TkFont) - if knj.kind_of? TkFont - conf = {} - knj.kanji_configinfo.each{|key,val| conf[key] = val} - if keys - fobj.kanji_configure(conf.update(keys)) - else - fobj.kanji_configure(conf) - end + optkeys = __item_font_optkeys(tagid(tagOrId)) + if key && !optkeys.find{|opt| opt.to_s == key.to_s} + fail ArgumentError, "unknown font option name `#{key}'" + end + + win, tag = __item_pathname(tagid(tagOrId)).split(':') + + optkeys = [key] if key + + optkeys.each{|optkey| + optkey = optkey.to_s + + pathname = [win, tag, optkey].join(';') + + if (fobj = TkFont.used_on(pathname)) + fobj = TkFont.new(fobj) # create a new TkFont object + elsif Tk::JAPANIZED_TK + fobj = fontobj # create a new TkFont object else - fobj.kanji_replace(knj) + tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj)) + next + end + + if fobj.kind_of?(TkFont) + if knj.kind_of?(TkFont) + conf = {} + knj.kanji_configinfo.each{|key,val| conf[key] = val} + if keys + fobj.kanji_configure(conf.update(keys)) + else + fobj.kanji_configure(conf) + end + else + fobj.kanji_replace(knj) + end + end + + fobj.call_font_configure([pathname, optkey], *(__item_config_cmd(tagid(tagOrId)) << {})) + } + self + end + + def tagfont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) + if wintag + if winkey + fnt = window.tagfontobj(wintag, winkey).dup + else + fnt = window.tagfontobj(wintag).dup + end + else + if winkey + fnt = window.fontobj(winkey).dup + else + fnt = window.fontobj.dup end end - return fobj.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) - end - - def tagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - if wintag - fnt = window.tagfontobj(wintag).dup + if targetkey + fnt.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) else - fnt = window.fontobj.dup + fnt.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) end - fnt.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), tagOrId, {}) - return self + self end - def latintagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) - if wintag - tagfontobj(tagOrId). - latin_replace(window.tagfontobj(wintag).latin_font_id) + + def latintagfont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) else - tagfontobj(tagOrId).latin_replace(window.fontobj.latin_font_id) + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + + if wintag + if winkey + fontobj.latin_replace(window.tagfontobj(wintag, winkey).latin_font_id) + else + fontobj.latin_replace(window.tagfontobj(wintag).latin_font_id) + end + else + if winkey + fontobj.latin_replace(window.fontobj(winkey).latin_font_id) + else + fontobj.latin_replace(window.fontobj.latin_font_id) + end end self end alias asciitagfont_copy latintagfont_copy - def kanjitagfont_copy(tagOrId, window, wintag=nil) - pathname = __item_pathname(tagOrId) - tagfontobj(tagOrId).dup.call_font_configure(pathname, self.path, - __conf_cmd(0), __conf_cmd(1), - tagOrId, {}) - if wintag - tagfontobj(tagOrId). - kanji_replace(window.tagfontobj(wintag).kanji_font_id) + def kanjifont_copy(tagOrId, window, wintag=nil, winkey=nil, targetkey=nil) + if targetkey + fontobj(targetkey).dup.call_font_configure([__item_pathname(tagid(tagOrId)), targetkey], + *(__item_config_cmd(tagid(tagOrId)) << {})) else - tagfontobj(tagOrId).kanji_replace(window.fontobj.kanji_font_id) + fontobj.dup.call_font_configure(__item_pathname(tagid(tagOrId)), + *(__item_config_cmd(tagid(tagOrId)) << {})) + end + + if wintag + if winkey + fontobj.kanji_replace(window.tagfontobj(wintag, winkey).kanji_font_id) + else + fontobj.kanji_replace(window.tagfontobj(wintag).kanji_font_id) + end + else + if winkey + fontobj.kanji_replace(window.fontobj(winkey).kanji_font_id) + else + fontobj.kanji_replace(window.fontobj.kanji_font_id) + end end self end diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb index 611226682a..799d573b1d 100644 --- a/ext/tk/lib/tk/listbox.rb +++ b/ext/tk/lib/tk/listbox.rb @@ -2,27 +2,21 @@ # tk/listbox.rb : treat listbox widget # require 'tk' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatListItemFont - include TkTreatItemFont +module TkListItemConfig + include TkItemConfigMethod - ItemCMD = ['itemconfigure'.freeze, TkComm::None].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_listval_optkeys(id) + [] end - - def __item_pathname(tagOrId) - self.path + ';' + tagOrId.to_s - end - - private :__conf_cmd, :__item_pathname + private :__item_listval_optkeys end - class TkListbox1, 'bbb'=>Tk::None, 'ccc'=>3}) +# => ["-aaa", 1, "-bbb", "-ccc", 3] +# +require 'tk' + +module Tk + class OptionObj < Hash + include TkUtil + + def initialize(hash = nil) + super() + @observ = [] + update_without_notify(_symbolkey2str(hash)) if hash + end + + def observ_info + @observ.dup + end + + def observs + @observ.collect{|win| + if win.kind_of?(Array) + win[0] + else + win + end + } + end + + def _remove_win(win) + if win.kind_of?(Array) + widget, method = win + @observ.delete_if{|x| + if x.kind_of?(Array) + x[0] == widget + else + x == widget + end + } + else + @observ.delete_if{|x| + if x.kind_of?(Array) + x[0] == win + else + x == win + end + } + end + end + private :_remove_win + + def assign(*wins) + # win := + # widget #==> call widget.configure(hash) + # [widget] #==> call widget.configure(hash) + # [widget, nil, {src=>target, ... }] + # #==> call widget.configure(hash) + # with converting hash-key + # [widget, method] #==> call widget.method(hash) + # [widget, method, {src=>target, ... }] + # #==> call widget.method(hash) + # with converting hash-key + # [widget [receiver, method, arg, ... ]] + # #==> call receiver.method(arg, ... , hash) + # [widget [receiver, method, arg, ... ], {src=>target, ... }] + # #==> call receiver.method(arg, ... , hash) + # with onverting hash-key + # + # src := option_name_on_optobj + # + # target := + # nil #==> not use the src + # option_name_on_target_widget + # [ option_name_on_target_widget, ... ] + # #==> set all of them + # + wins.each{|win| + _remove_win(win) + @observ << win + notify(win) + } + self + end + + def unassign(*wins) + wins.each{|win| + _remove_win(win) + } + self + end + + def notify(target = nil) + if target + targets = [target] + elsif @observ.empty? + return self + else + targets = @observ.dup + end + + return self if empty? + + org_hash = _symbolkey2str(self) + + targets.each{|win| + widget = receiver = win + hash = org_hash + begin + if win.kind_of?(Array) + widget, method, conv_tbl = win + receiver = widget + + if conv_tbl + hash = {} + org_hash.each{|key, val| + key = conv_tbl[key] if conv_tbl.key?(key) + next unless key + if key.kind_of?(Array) + key.each{|k| hash[k] = val} + else + hash[key] = val + end + } + end + + if method.kind_of?(Array) + receiver, method, *args = method + receiver.__send__(method, *(args << hash)) + elsif method + widget.__send__(method, hash) + else + widget.configure(hash) + end + + else + widget.configure(self) + end + rescue => e + if ( ( widget.kind_of?(TkObject) \ + && widget.respond_to?('exist?') \ + && ! receiver.exist? ) \ + || ( receiver.kind_of?(TkObject) \ + && receiver.respond_to?('exist?') \ + && ! receiver.exist? ) ) + @observ.delete(win) + else + fail e + end + end + } + + self + end + alias apply notify + + def +(hash) + unless hash.kind_of?(Hash) + fail ArgumentError, "expect a Hash" + end + new_obj = self.dup + new_obj.update_without_notify(_symbolkey2str(hash)) + new_obj + end + + alias update_without_notify update + + def update(hash) + update_without_notify(_symbolkey2str(hash)) + notify + end + + def configure(key, value=nil) + if key.kind_of?(Hash) + update(key) + else + store(key,value) + end + end + + def [](key) + super(key.to_s) + end + alias cget [] + + def store(key, val) + key = key.to_s + super(key, val) + notify + end + def []=(key, val) + store(key,val) + end + + def replace(hash) + super(_symbolkey2str(hash)) + notify + end + + def default(opt) + fail RuntimeError, "unknown option `#{opt}'" + end + private :default + + undef :default= + end +end diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb index 8768bf1c79..dbb0ca33e8 100644 --- a/ext/tk/lib/tk/package.rb +++ b/ext/tk/lib/tk/package.rb @@ -18,6 +18,36 @@ module TkPackage nil end + def if_needed(pkg, ver, *arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'ifneeded', pkg, ver)) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'ifneeded', pkg, ver, cmd) + cmd + else + # remove proc + tk_call('package', 'ifneeded', pkg, ver, '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end + end + def names tk_split_simplelist(tk_call('package', 'names')) end @@ -25,26 +55,74 @@ module TkPackage def provide(package, version=nil) if version tk_call('package', 'provide', package, version) + end + if (ret = tk_call('package', 'provide', package)) == '' nil else - tk_call('package', 'provide', package) + ret end end def present(package, version=None) - tk_call('package', 'present', package, version) + begin + tk_call('package', 'present', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def present_exact(package, version) - tk_call('package', 'present', '-exact', package, version) + begin + tk_call('package', 'present', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def require(package, version=None) - tk_call('package', 'require', package, version) + begin + tk_call('package', 'require', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end end def require_exact(package, version) - tk_call('package', 'require', '-exact', package, version) + begin + tk_call('package', 'require', '-exact', package, version) + rescue => e + fail e.class, 'TkPackage ' << e.message + end + end + + def unknown_proc(*arg, &b) + size = arg.size + + if size==0 && !b + # proc info + procedure(tk_call('package', 'unknown')) + + elsif size==0 && b + # set proc + cmd = proc(&b) + tk_call('package', 'unknown', cmd) + cmd + + elsif size==1 && !b + # set proc + cmd = arg[0] + if cmd + tk_call('package', 'unknown', cmd) + cmd + else + # remove proc + tk_call('package', 'unknown', '') + nil + end + + else + fail ArgumentError, 'too many arguments' + end end def versions(package) diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb index e591a299ab..c5f4fdb70c 100644 --- a/ext/tk/lib/tk/scrollable.rb +++ b/ext/tk/lib/tk/scrollable.rb @@ -7,10 +7,15 @@ module Tk module Scrollable def xscrollcommand(cmd=Proc.new) configure_cmd 'xscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd + # Tk.update # avoid scrollbar trouble + self end + def xview(*index) if index.size == 0 list(tk_send_without_enc('xview')) @@ -19,6 +24,13 @@ module Tk self end end + def xview_moveto(*index) + xview('moveto', *index) + end + def xview_scroll(*index) + xview('scroll', *index) + end + def yview(*index) if index.size == 0 list(tk_send_without_enc('yview')) @@ -27,6 +39,13 @@ module Tk self end end + def yview_moveto(*index) + yview('moveto', *index) + end + def yview_scroll(*index) + yview('scroll', *index) + end + def xscrollbar(bar=nil) if bar @xscrollbar = bar @@ -34,6 +53,7 @@ module Tk self.xscrollcommand {|*arg| @xscrollbar.set(*arg)} @xscrollbar.command {|*arg| self.xview(*arg)} end + Tk.update # avoid scrollbar trouble @xscrollbar end def yscrollbar(bar=nil) @@ -43,6 +63,7 @@ module Tk self.yscrollcommand {|*arg| @yscrollbar.set(*arg)} @yscrollbar.command {|*arg| self.yview(*arg)} end + Tk.update # avoid scrollbar trouble @yscrollbar end end diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb index 0ee4423c9a..8d4d40322d 100644 --- a/ext/tk/lib/tk/scrollbar.rb +++ b/ext/tk/lib/tk/scrollbar.rb @@ -41,6 +41,7 @@ class TkScrollbar'left','fill'=>'both','expand'=>'yes' scroll.configure 'command', list.path+" yview" scroll.pack 'side'=>'right','fill'=>'y' +=end + list.yscrollbar(scroll) + list.pack('side'=>'left','fill'=>'both','expand'=>'yes') + scroll.pack('side'=>'right','fill'=>'y') delegate('DEFAULT', list) delegate('foreground', list) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index be3f814505..7593b59368 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -4,32 +4,66 @@ # by Yukihiro Matsumoto require 'tk' require 'tk/itemfont' +require 'tk/itemconfig' require 'tk/scrollable' require 'tk/txtwin_abst' -module TkTreatTextTagFont +module TkTextTagConfig include TkTreatItemFont + include TkItemConfigMethod - ItemCMD = ['tag'.freeze, 'configure'.freeze].freeze - def __conf_cmd(idx) - ItemCMD[idx] + def __item_cget_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'cget', id[1]] end + private :__item_cget_cmd - def __item_pathname(tagOrId) - if tagOrId.kind_of?(TkTextTag) - self.path + ';' + tagOrId.id - else - self.path + ';' + tagOrId + def __item_config_cmd(id) # id := [ type, tagOrId ] + [self.path, id[0], 'configure', id[1]] + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + id = tagid(id[1]) end + [self.path, id].join(';') + end + private :__item_pathname + + def tag_cget(tagOrId, option) + itemcget(['tag', tagOrId], option) + end + def tag_configure(tagOrId, slot, value=None) + itemconfigure(['tag', tagOrId], slot, value) + end + def tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) + end + def current_tag_configinfo(tagOrId, slot=nil) + itemconfigure(['tag', tagOrId], slot) end - private :__conf_cmd, :__item_pathname -end + def window_cget(tagOrId, option) + itemcget(['window', tagOrId], option) + end + def window_configure(tagOrId, slot, value=None) + itemconfigure(['window', tagOrId], slot, value) + end + def window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + def current_window_configinfo(tagOrId, slot=nil) + itemconfigure(['window', tagOrId], slot) + end + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo +end class TkText 0 args = args.join(' ') - keys = ValidateArgs._get_subst_key(args) + keys = klass._get_subst_key(args) if cmd.kind_of?(String) id = cmd elsif cmd.kind_of?(TkCallbackEntry) @id = install_cmd(cmd) else @id = install_cmd(proc{|*arg| - (cmd.call(*ValidateArgs.scan_args(keys, arg)))? '1':'0' + (cmd.call(*klass.scan_args(keys, arg)))? '1':'0' }) + ' ' + args end else - keys, args = ValidateArgs._get_all_subst_keys + keys, args = klass._get_all_subst_keys if cmd.kind_of?(String) id = cmd elsif cmd.kind_of?(TkCallbackEntry) @@ -83,13 +189,17 @@ module TkValidation else @id = install_cmd(proc{|*arg| (cmd.call( - ValidateArgs.new(*ValidateArgs.scan_args(keys,arg))) + klass.new(*klass.scan_args(keys,arg))) )? '1': '0' }) + ' ' + args end end end + def initialize(cmd = Proc.new, *args) + _initialize_for_cb_class(ValidateArgs, cmd, *args) + end + def to_eval @id end @@ -97,49 +207,8 @@ module TkValidation ##################################### - def configure(slot, value=TkComm::None) - if slot.kind_of? Hash - slot = _symbolkey2str(slot) - if slot['vcmd'].kind_of? Array - cmd, *args = slot['vcmd'] - slot['vcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['vcmd'].kind_of? Proc - slot['vcmd'] = ValidateCmd.new(slot['vcmd']) - end - if slot['validatecommand'].kind_of? Array - cmd, *args = slot['validatecommand'] - slot['validatecommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['validatecommand'].kind_of? Proc - slot['validatecommand'] = ValidateCmd.new(slot['validatecommand']) - end - if slot['invcmd'].kind_of? Array - cmd, *args = slot['invcmd'] - slot['invcmd'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invcmd'].kind_of? Proc - slot['invcmd'] = ValidateCmd.new(slot['invcmd']) - end - if slot['invalidcommand'].kind_of? Array - cmd, *args = slot['invalidcommand'] - slot['invalidcommand'] = ValidateCmd.new(cmd, args.join(' ')) - elsif slot['invalidcommand'].kind_of? Proc - slot['invalidcommand'] = ValidateCmd.new(slot['invalidcommand']) - end - super(slot) - else - if (slot == 'vcmd' || slot == :vcmd || - slot == 'validatecommand' || slot == :validatecommand || - slot == 'invcmd' || slot == :invcmd || - slot == 'invalidcommand' || slot == :invalidcommand) - if value.kind_of? Array - cmd, *args = value - value = ValidateCmd.new(cmd, args.join(' ')) - elsif value.kind_of? Proc - value = ValidateCmd.new(value) - end - end - super(slot, value) - end - self + def __validation_class_list + super << ValidateCmd end def validatecommand(cmd = Proc.new, args = nil) diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index 43baac458d..61d6e8a410 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -84,6 +84,14 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') end end + def self.new_hash(val = {}) + if val.kind_of?(Hash) + self.new(val) + else + fail ArgumentError, 'Hash is expected' + end + end + def initialize(val="") # @id = Tk_VARIABLE_ID.join('') @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_) @@ -103,6 +111,12 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') INTERP._invoke_without_enc('global', @id) #INTERP._invoke('global', @id) + # create and init + if val.kind_of?(Hash) + # assoc-array variable + self[''] = 0 + self.clear + end self.value = val =begin @@ -185,7 +199,7 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') def is_hash? #ITNERP._eval("global #{@id}; array exist #{@id}") == '1' - ITNERP._invoke_without_enc('array', 'exist', @id) == '1' + INTERP._invoke_without_enc('array', 'exist', @id) == '1' end def is_scalar? @@ -197,7 +211,23 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL') fail RuntimeError, 'cannot get keys from a scalar variable' end #tk_split_simplelist(INTERP._eval("global #{@id}; array get #{@id}")) - tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'get', @id))) + tk_split_simplelist(INTERP._fromUTF8(INTERP._invoke_without_enc('array', 'names', @id))) + end + + def clear + if (is_scalar?) + fail RuntimeError, 'cannot clear a scalar variable' + end + keys.each{|k| unset(k)} + self + end + + def update(hash) + if (is_scalar?) + fail RuntimeError, 'cannot update a scalar variable' + end + hash.each{|k,v| self[k] = v} + self end @@ -222,10 +252,11 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def value=(val) if val.kind_of?(Hash) + self.clear val.each{|k, v| #INTERP._set_global_var2(@id, _toUTF8(_get_eval_string(k)), # _toUTF8(_get_eval_string(v))) - INTERP._set_global_var2(@id, __get_eval_string(k, true), + INTERP._set_global_var2(@id, _get_eval_string(k, true), _get_eval_string(v, true)) } self.value @@ -260,7 +291,7 @@ if USE_TCLs_SET_VARIABLE_FUNCTIONS def unset(elem=nil) if elem - INTERP._unset_global_var2(@id, tk_tcl2ruby(elem)) + INTERP._unset_global_var2(@id, _get_eval_string(elem, true)) else INTERP._unset_global_var(@id) end @@ -359,7 +390,7 @@ else def unset(elem=nil) if elem INTERP._eval(Kernel.format('global %s; unset %s(%s)', - @id, @id, tk_tcl2ruby(elem))) + @id, @id, _get_eval_string(elem))) #INTERP._eval(Kernel.format('unset %s(%s)', @id, tk_tcl2ruby(elem))) #INTERP._eval('unset ' + @id + '(' + _get_eval_string(elem) + ')') else @@ -387,6 +418,29 @@ end val end + def bool + # see Tcl_GetBoolean man-page + case value.downcase + when '0', 'false', 'no', 'off' + false + else + true + end + end + + def bool=(val) + if ! val + self.value = '0' + else + case val.to_s.downcase + when 'false', '0', 'no', 'off' + self.value = '0' + else + self.value = '1' + end + end + end + def to_i number(value).to_i end @@ -570,7 +624,8 @@ end def trace(opts, cmd = Proc.new) @trace_var = [] if @trace_var == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_var.unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -619,7 +674,8 @@ end def trace_element(elem, opts, cmd = Proc.new) @trace_elem = {} if @trace_elem == nil @trace_elem[elem] = [] if @trace_elem[elem] == nil - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') @trace_elem[elem].unshift([opts,cmd]) if @trace_opts == nil TkVar_CB_TBL[@id] = self @@ -678,7 +734,8 @@ end def trace_vdelete(opts,cmd) return self unless @trace_var.kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 newopts = '' @trace_var.each_with_index{|e,i| @@ -702,7 +759,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -739,7 +797,8 @@ end def trace_vdelete_for_element(elem,opts,cmd) return self unless @trace_elem.kind_of? Hash return self unless @trace_elem[elem].kind_of? Array - opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + # opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('') + opts = ['r','w','u'].find_all{|c| opts.to_s.index(c)}.join('') idx = -1 @trace_elem[elem].each_with_index{|e,i| if idx < 0 && e[0] == opts && e[1] == cmd @@ -765,7 +824,8 @@ end } } - newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + #newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('') + newopts = ['r','w','u'].find_all{|c| newopts.to_s.index(c)}.join('') if newopts != @trace_opts Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts, 'rb_var') =begin @@ -807,6 +867,15 @@ class TkVarAccesstrue)} + end + + def self.delete(*icons) + return if icons.empty? + tk_call('::icons::icons', 'delete', icons) + end + + def self.query(*args) + if args[-1].kind_of?(Hash) + keys = args.pop + list(tk_call('::icons::icons', 'query', + *(hash_kv(keys).concat(args.flatten)))) + else + list(tk_call('::icons::icons', 'query', *(args.flatten))) + end + end + + ########################################## + + def self.new(name, keys=nil) + Tk_IMGTBL["::icon::#{name}"] || super + end + + def initialize(name, keys=nil) + if name.kind_of?(String) && name =~ /^::icon::(.+)$/ + @name = $1 + @path = name + else + @name = name.to_s + @path = "::icon::#{@name}" + end + keys = _symbolkey2str(keys) + unless keys.delete('without_creating') + tk_call('::icons::icons', 'create', *(hash_kv(keys) << @name)) + end + Tk_IMGTBL[@path] = self + end + + def name + @name + end + + def delete + Tk_IMGTBL.delete(@path) + tk_call('::icons::icons', 'delete', @name) + self + end + + def query(keys) + list(simplelist(tk_call('::icons::icons', 'query', + *(hash_kv(keys) << @name)) + )[0]) + end + end +end diff --git a/ext/tk/lib/tkextlib/ICONS/setup.rb b/ext/tk/lib/tkextlib/ICONS/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/ICONS/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS new file mode 100644 index 0000000000..6cc5e15617 --- /dev/null +++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS @@ -0,0 +1,161 @@ + + [ current support status of Tcl/Tk extensions ] + +The following list shows *CURRENT* status when this file was modifyed +at last. If you want to add other Tcl/Tk extensions to the planed list +(or change its status position), please request them at the ruby-talk, +ruby-list, or ruby-dev ML. Although we cannot promise to support your +requests, we'll try to do. + +If you want to check that wrapper libraries are ready to use on your +environment, please execute 'pkg_checker.rb' with no arguments. The +script may give you some hints about that. + + + ***** IMPORTANT NOTE ********************************************** + + 'support' means that Ruby/Tk's wrapper libraries are released. + 'not support' does *NOT* mean that the extension doesn't work + on Ruby/Tk. + + Even if the status of the extension is 'not support', you can + control the functions/widgets of the extension without wrapper + libraries by Tk.tk_call(), Tk.ip_eval(), and so on. + + If you cannot use installed Tcl/Tk extension, please check the + followings. + + (1) On your Tcl/Tk, does the extention work? + + (2) Do DLL libraries of the extension exist on DLL load-path? + (See also "/ext/tcltklib/README.ActiveTcl") + + (3) Is the Tcl library directory of the extension included in + library search-path of the Tcl interpreter linked Ruby/Tk? + + The check results may request you to do some setup operations + before using the extension. If so, then please write the step + of setup oprations into the "setup.rb" file in the directory + of the wrapper libraries for the extention (It is the wrapper + libraries have the standard structure of the libraries in this + directory). The "setup" file is required before requiring the + Tcl library package (TkPackage.require()). + + ******************************************************************* + + +===< support with some examples (may be beta quality) >======================= + +Tcllib http://sf.net/projects/tcllib + ==> tcllib (partial support; Tklib part only) + +vu http://tktable.sourceforge.net ==> vu + +TkHTML http://www.hwaci.com/sw/tkhtml/index.html ==> tkHTML + + + +===< support (may be alpha or beta quality) >================================= + +TkImg http://sf.net/projects/tkimg ==> tkimg + +TkTreeCtrl http://tktreectrl.sourceforge.net/ ==> treectrl + +Tile http://tktable.sourceforge.net/tile/ ==> tile + + + +===< possibly support (not tested; alpha quality) >=========================== + +TkTrans http://www2.cmp.uea.ac.uk/~fuzz/tktrans/default.html + ==> tktrans (win32 only) + +TkDND http://sourceforge.net/projects/tkdnd ==> tkDND + +ICONS http://www.satisoft.com/tcltk/icons/ ==> ICONS + + + +===< plan to support (alpha quality libraries may be included) >============== + +TclX http://sf.net/projects/tclx * may support Tk part only + +IncrTcl http://sf.net/projects/incrTcl * may support Tk part only + +IWidgets http://sf.net/projects/incrTcl + +TkTable http://sf.net/projects/tktable + * see http://www.korus.hu/~fery/ruby/tktable.rb + +BWidgets http://sf.net/projects/tcllib + +winico http://tktable.sourceforge.net + + + +===< not determined to supprt or not >======================================== + +GraphViz http://www.graphviz.org/ + +BLT http://sourceforge.net/projects/blt + +Tix http://tixlibrary.sourceforge.net/ + +Tkgeomap http://tkgeomap.sourceforge.net/index.html + +XBit http://www.geocities.com/~chengye/ + +TkZinc http://www.tkzinc.org/ + +Wbc http://home.t-online.de/home/csaba.nemethi/ + +Mentry http://home.t-online.de/home/csaba.nemethi/ + +Tablelist http://home.t-online.de/home/csaba.nemethi/ + +vfwtcl http://sourceforge.net/projects/avicaptcl + +QuickTimeTcl http://hem.fyristorg.com/matben/qt/ + +ANIGIF http://cardtable.sourceforge.net/tcltk/ + +IMG_ROTATE http://cardtable.sourceforge.net/tcltk/ + +TclVfs http://sourceforge.net/projects/tclvfs/ + + + +===< may not support (already exist, out of Ruby/Tk scope, and so on) >======= + +TkCon http://sf.net/projects/tkcon + +Expect http://sf.net/projects/expect + +TclXML http://sf.net/projects/tclxml + +TclXSLT http://sf.net/projects/tclxml + +TclDOM http://sf.net/projects/tclxml + +TclSOAP http://sf.net/projects/tclsoap + +Snack http://www.speech.kth.se/~kare/snack2.2.tar.gz + * use Snack for Ruby (see http://rbsnack.sourceforge.net/) + +Tcom http://www.vex.net/~cthuang/tcom/ + +tDOM http://www.tdom.org + +Mk4tcl http://www.equi4.com/metakit/tcl.html + +Memchan http://memchan.sourceforge.net/ + + + +===< tool (may not supprt) >================================================== + +tbcload/tclcompiler http://www.tcl.tk/software/tclpro/ + + + +(End of List) \ No newline at end of file diff --git a/ext/tk/lib/tkextlib/pkg_checker.rb b/ext/tk/lib/tkextlib/pkg_checker.rb new file mode 100755 index 0000000000..813273e65b --- /dev/null +++ b/ext/tk/lib/tkextlib/pkg_checker.rb @@ -0,0 +1,129 @@ +#!/usr/bin/env ruby +# +# Ruby/Tk extension library checker +# +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +TkRoot.new.withdraw # hide root window + +name = File.basename(__FILE__) + +if ARGV[0] + dir = File.expand_path(ARGV[0]) +else + dir = File.dirname(File.expand_path(__FILE__)) +end + +print "\nRuby/Tk extension library checker\n" +print "( Note:: This check is very simple one. Shown status may be wrong. )\n" +print "\n check directory :: #{dir}\n" + +def get_pkg_list(file) + pkg_list = [] + + File.foreach(file){|l| + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)TkPackage\s*\.\s*require\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :package] + pkg_list << pkg unless pkg_list.member?(pkg) + end + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)Tk\s*\.\s*load_tcllibrary\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :library] + pkg_list << pkg unless pkg_list.member?(pkg) + end + if l =~ /^(?:[^#]+\s|\s*)(?:|;\s*)Tk\s*\.\s*load_tclscript\s*\(?\s*(["'])((\w|:)+)\1/ + pkg = [$2, :script] + pkg_list << pkg unless pkg_list.member?(pkg) + end + } + + pkg_list +end + +def check_pkg(file) + pkg_list = get_pkg_list(file) + + error_list = [] + success_list = {} + + pkg_list.each{|name, type| + next if success_list[name] + + begin + case type + when :package + ver = TkPackage.require(name) + success_list[name] = ver + error_list.delete_if{|n, t| n == name} + + when :library + Tk.load_tcllibrary(name) + success_list[name] = :library + error_list.delete_if{|n, t| n == name} + + when :script + Tk.load_tclscript(name) + success_list[name] = :script + error_list.delete_if{|n, t| n == name} + + end + rescue + error_list << [name, type] + end + } + + success_list.dup.each{|name, ver| + unless ver.kind_of?(String) + begin + ver = TkPackage.require(name) + sccess_list[name] = ver + rescue + end + end + } + + [success_list, error_list] +end + +def subdir_check(dir) + Dir.foreach(dir){|f| + next if f == '.' || f == '..' + if File.directory?(f) + subdir_check(File.join(dir, f)) + elsif File.extname(f) == '.rb' + path = File.join(dir, f) + suc, err = check_pkg(path) + if err.empty? + print 'Ready : ', path, ' : require->', suc.inspect, "\n" + else + print '*LACK : ', path, ' : require->', suc.inspect, + ' FAIL->', err.inspect, "\n" + end + end + } +end + +Dir.chdir(dir) + +(Dir['*.rb'] - ['setup.rb', name]).each{|f| + subdir = File.basename(f, '.*') + begin + # read 'setup.rb' as if the library has standard structure + require File.join(subdir, 'setup.rb') + rescue LoadError + # ignore error + end + + print "\n" + + suc, err = check_pkg(f) + if err.empty? + print 'Ready : ', f, ' : require->', suc.inspect, "\n" + else + print '*LACK : ', f, ' : require->', suc.inspect, + ' FAIL->', err.inspect, "\n" + end + + subdir_check(subdir) if File.directory?(subdir) +} diff --git a/ext/tk/lib/tkextlib/setup.rb b/ext/tk/lib/tkextlib/setup.rb new file mode 100644 index 0000000000..12867e8f9c --- /dev/null +++ b/ext/tk/lib/tkextlib/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before using Tk extension libraries +# +# If you need some setup operations for Tk extensions (for example, +# modify the dynamic library path) required, please write the setup +# operations in this file. This file is required at the last of +# "require 'tk'". +# diff --git a/ext/tk/lib/tkextlib/tcllib.rb b/ext/tk/lib/tkextlib/tcllib.rb new file mode 100644 index 0000000000..56f21556ae --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib.rb @@ -0,0 +1,57 @@ +# +# tcllib extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# package:: autoscroll +#require 'tkextlib/tcllib/autoscroll' +require File.join(dir, 'autoscroll') + +# package:: cursor +#require 'tkextlib/tcllib/cursor' +require File.join(dir, 'cursor') + +# package:: style +#require 'tkextlib/tcllib/style' +require File.join(dir, 'style') + + +# autoload +module Tk + module Tcllib + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + # package:: ctext + #autoload :CText, 'tkextlib/tcllib/ctext' + autoload :CText, File.join(dir, 'ctext') + + # package:: datefield + #autoload :Datefield, 'tkextlib/tcllib/datefield' + #autoload :DateField, 'tkextlib/tcllib/datefield' + autoload :Datefield, File.join(dir, 'datefield') + autoload :DateField, File.join(dir, 'datefield') + + # package:: ipentry + #autoload :IP_Entry, 'tkextlib/tcllib/ip_entry' + autoload :IP_Entry, File.join(dir, 'ip_entry') + + # package:: Plotchart + #autoload :Plotchart, 'tkextlib/tcllib/plotchart' + autoload :Plotchart, File.join(dir, 'plotchart') + + # package:: tkpiechart + #autoload :Tkpiechart, 'tkextlib/tcllib/tkpiechart' + autoload :Tkpiechart, File.join(dir, 'tkpiechart') + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/README b/ext/tk/lib/tkextlib/tcllib/README new file mode 100644 index 0000000000..953239befa --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/README @@ -0,0 +1,135 @@ + + [ tcllib extension support files ] + +Tcllib includes many utilities. But currently, supports TKLib part +only (see the following 'tcllib contents'). + +If you request to support others, please send your message to one of +ruby-talk/ruby-list/ruby-dev/ruby-ext mailing lists. + +--------------------------------- +Tcllib is a collection of utility modules for Tcl. These modules provide +a wide variety of functionality, from implementations of standard data +structures to implementations of common networking protocols. The intent +is to collect commonly used function into a single library, which users +can rely on to be available and stable. +--------------------------------------------------------- + +-----< tcllib contents (based on tcllib-1.6.1) >--------- +Programming tools + * cmdline - Procedures to process command lines and options. + * comm - A remote communications facility for Tcl (7.6, 8.0, and later) + * control - Procedures for control flow structures. + * fileutil - Procedures implementing some file utilities + * log - Procedures to log messages of libraries and applications. + * logger - System to control logging of events. + * multiplexer - One-to-many communication with sockets. + * snit - Snit's Not Incr Tcl + * snitfaq - Snit Frequently Asked Questions + * stooop - Object oriented extension. + * stoop - Simple Tcl Only Object Oriented Programming + * switched - stooop switched class + * profiler - Tcl source code profiler + +Mathematics + * math::statistics - Basic statistical functions and procedures + * math::calculus - Integration and ordinary differential equations + * math::optimize - Optimisation routines + * math::fuzzy - Fuzzy comparison of floating-point numbers + * counter - Procedures for counters and histograms + * combinatorics - Combinatorial functions in the Tcl Math Library + +Data structures + * struct::list - Procedures for manipulating lists + * struct::set - Procedures for manipulating sets + * struct::stack - Create and manipulate stack objects + * struct::queue - Create and manipulate queue objects + * struct::prioqueue - Create and manipulate prioqueue objects + * struct::skiplist - Create and manipulate skiplists + * struct::tree - Create and manipulate tree objects + * struct::graph - Create and manipulate directed graph objects + * struct::record - Define and create records (similar to 'C' structures) + * struct::matrix - Create and manipulate matrix objects + * struct::pool - Create and manipulate pool objects (of discrete items) + * report - Create and manipulate report objects + +Text processing + * expander - Procedures to process templates and expand text. + * base64 - Procedures to encode and decode base64 + * yencode - encode/decoding a binary file + * uuencode - encode/decoding a binary file + * csv - Procedures to handle CSV data. + * inifile - Parsing of Windows INI files + * htmlparse - Procedures to parse HTML strings + * mime - Manipulation of MIME body parts + * Tcl MIME - generates and parses MIME body parts + * textutil - Procedures to manipulate texts and strings. + * exif - Tcl EXIF extracts and parses EXIF fields from digital images + * EXIF - extract and parse EXIF fields from digital images + +Hashes, checksums, and encryption + * cksum - calculate a cksum(1) compatible checksum + * crc16 - Perform a 16bit Cyclic Redundancy Check + * crc32 - Perform a 32bit Cyclic Redundancy Check + * des - Perform DES encryption of Tcl data + * md4 - MD4 Message-Digest Algorithm + * md5 - MD5 Message-Digest Algorithm + * ripemd160 - RIPEMD-160 Message-Digest Algorithm + * ripemd128 - RIPEMD-128 Message-Digest Algorithm + * md5crypt - MD5-based password encryption + * sha1 - Perform sha1 hashing + * sum - calculate a sum(1) compatible checksum + * soundex - Soundex + +Documentation tools + * mpexpand - Markup processor + * doctools - Create and manipulate doctools converter object + * doctoc_fmt - Specification of simple tcl markup for table of contents + * doctools_api - Interface specification for formatter code + * doctools_fmt - Specification of simple tcl markup for manpages + * docidx - Create and manipulate docidx converter objects + * docidx_api - Interface specification for index formatting code + * docidx_fmt - Specification of simple tcl markup for an index + * doctoc - Create and manipulate doctoc converter objects + * doctoc_api - Interface specification for toc formatting code + * doctools::changelog - Handle text in Emacs ChangeLog format + * doctools::cvs - Handle text in 'cvs log' format + +Networking + * uri - URI utilities + * dns - Tcl Domain Name Service Client + * ntp_time - Tcl Time Service Client + * nntp - Tcl client for the NNTP protocol + * pop3 - Tcl client for POP3 email protocol + * pop3d - Tcl POP3 server implementation + * pop3d::udb - Simple user database for pop3d + * pop3d::dbox - Simple mailbox database for pop3d + * ftp - Client-side tcl implementation of the ftp protocol + * ftp - Client-side tcl implementation of the ftp protocol + * ftpd - Tcl FTP server implementation + * smtp - Client-side tcl implementation of the smtp protocol + * smtpd - Tcl SMTP server implementation + * irc - Create IRC connection and interface. + +CGI programming + * ncgi - Procedures to manipulate CGI values. + * html - Procedures to generate HTML structures + * javascript - Procedures to generate HTML and Java Script structures. + +Grammars and finite automata + * grammar::fa - Create and manipulate finite automatons + * grammar::fa::op - Operations on finite automatons + * grammar::dacceptor - Create and use deterministic acceptors + * grammar::dexec - Execute deterministic finite automatons + +TKLib + * Plotchart - Simple plotting and charting package + * autoscroll - Provides for a scrollbar to automatically mapped and + unmapped as needed + * ctext - An extended text widget with customizable Syntax highlighting + * cursor - Procedures to handle CURSOR data + * datefield - Tk datefield widget + * style - Changes default Tk look&feel + * ipentry - An IP address entry widget + * tkpiechart - Creates and dynamically updates 2D or 3D pie charts +--------------------------------------------------------- diff --git a/ext/tk/lib/tkextlib/tcllib/autoscroll.rb b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb new file mode 100644 index 0000000000..9c161d7ec9 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb @@ -0,0 +1,100 @@ +# +# tkextlib/tcllib/autoscroll.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Provides for a scrollbar to automatically mapped and unmapped as needed +# +# (The following is the original description of the library.) +# +# This package allows scrollbars to be mapped and unmapped as needed +# depending on the size and content of the scrollbars scrolled widget. +# The scrollbar must be managed by either pack or grid, other geometry +# managers are not supported. +# +# When managed by pack, any geometry changes made in the scrollbars parent +# between the time a scrollbar is unmapped, and when it is mapped will be +# lost. It is an error to destroy any of the scrollbars siblings while the +# scrollbar is unmapped. When managed by grid, if anything becomes gridded +# in the same row and column the scrollbar occupied it will be replaced by +# the scrollbar when remapped. +# +# This package may be used on any scrollbar-like widget as long as it +# supports the set subcommand in the same style as scrollbar. If the set +# subcommand is not used then this package will have no effect. +# + +require 'tk' +require 'tk/scrollbar' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('autoscroll', '1.0') +TkPackage.require('autoscroll') + +module Tk + module Scrollable + def autoscroll(mode = nil) + case mode + when :x, 'x' + if @xscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @xscrollbar) + end + when :y, 'y' + if @yscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @xscrollbar) + end + if @yscrollbar + tk_send_without_enc('::autoscroll::autoscroll', @yscrollbar) + end + else + fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected" + end + self + end + def unautoscroll(mode = nil) + case mode + when :x, 'x' + if @xscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @xscrollbar) + end + when :y, 'y' + if @yscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @yscrollbar) + end + when nil, :both, 'both' + if @xscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @xscrollbar) + end + if @yscrollbar + tk_send_without_enc('::autoscroll::unautoscroll', @yscrollbar) + end + else + fail ArgumentError, "'x', 'y' or 'both' (String or Symbol) is expected" + end + self + end + end +end + +class TkScrollbar + def autoscroll + # Arranges for the already existing scrollbar to be mapped + # and unmapped as needed. + tk_send_without_enc('::autoscroll::autoscroll', @path) + self + end + def unautoscroll + # Returns the scrollbar to its original static state. + tk_send_without_enc('::autoscroll::unautoscroll', @path) + self + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/ctext.rb b/ext/tk/lib/tkextlib/tcllib/ctext.rb new file mode 100644 index 0000000000..6fa3e2edda --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb @@ -0,0 +1,141 @@ +# +# tkextlib/tcllib/ctext.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Overloads the text widget and provides new commands +# + +require 'tk' +require 'tk/text' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('ctext', '3.1') +TkPackage.require('ctext') + +module Tk + module Tcllib + class CText < TkText + end + end +end + +class Tk::Tcllib::CText + TkCommandNames = ['ctext'.freeze].freeze + WidgetClassName = 'Ctext'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('ctext', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('ctext', @path) + end + end + private :create_self + + def append(*args) + tk_send('append', *args) + end + + def copy + tk_send('copy') + end + + def cut + tk_send('cut') + end + + def fast_delete(*args) + tk_send('fastdelete', *args) + end + + def fast_insert(*args) + tk_send('fastinsert', *args) + end + + def highlight(*args) + tk_send('highlight', *args) + end + + def paste + tk_send('paste') + end + + def edit(*args) + tk_send('edit', *args) + end + + def add_highlight_class(klass, col, *keywords) + tk_call('ctext::addHighlightClass', @path, klass, col, keywords.flatten) + self + end + + def add_highlight_class_for_special_chars(klass, col, *chrs) + tk_call('ctext::addHighlightClassForSpecialChars', + @path, klass, col, chrs.join('')) + self + end + + def add_highlight_class_for_regexp(klass, col, tcl_regexp) + tk_call('ctext::addHighlightClassForRegexp', + @path, klass, col, tcl_regexp) + self + end + + def add_highlight_class_with_only_char_start(klass, col, chr) + tk_call('ctext::addHighlightClassWithOnlyCharStart', + @path, klass, col, chr) + self + end + + def clear_highlight_classes + tk_call('ctext::clearHighlightClasses', @path) + self + end + + def get_highlight_classes + tk_split_simplelist(tk_call('ctext::getHighlightClasses', @path)) + end + + def delete_highlight_class(klass) + tk_call('ctext::deleteHighlightClass', @path, klass) + self + end + + def enable_C_comments + tk_call('ctext::enableComments', @path) + self + end + + def disable_C_comments + tk_call('ctext::disableComments', @path) + self + end + + def find_next_char(idx, chr) + tk_call('ctext::findNextChar', @path, idx, chr) + end + + def find_next_space(idx) + tk_call('ctext::findNextSpace', @path, idx) + end + + def find_previous_space(idx) + tk_call('ctext::findPreviousSpace', @path, idx) + end + + def set_update_proc(cmd=Proc.new) + tk_call('proc', 'ctext::update', '', cmd) + self + end + + def modified(mode) + bool(tk_call('ctext::modified', @path, mode)) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/cursor.rb b/ext/tk/lib/tkextlib/tcllib/cursor.rb new file mode 100644 index 0000000000..cf4f247209 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/cursor.rb @@ -0,0 +1,41 @@ +# +# tkextlib/tcllib/cursor.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Procedures to handle CURSOR data +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('cursor', '0.1') +TkPackage.require('cursor') + +module Tk + def self.cursor_display(parent=None) + # Pops up a dialog with a listbox containing all the cursor names. + # Selecting a cursor name will display it in that dialog. + # This is simply for viewing any available cursors on the platform . + tk_call_without_enc('::cursor::display', parent) + end +end + +class TkWindow + def cursor_propagate(cursor) + # Sets the cursor for self and all its descendants to cursor. + tk_send_without_enc('::cursor::propagate', @path, cursor) + end + def cursor_restore(cursor = None) + # Restore the original or previously set cursor for self and all its + # descendants. If cursor is specified, that will be used if on any + # widget that did not have a preset cursor (set by a previous call + # to TkWindow#cursor_propagate). + tk_send_without_enc('::cursor::restore', @path, cursor) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/datefield.rb b/ext/tk/lib/tkextlib/tcllib/datefield.rb new file mode 100644 index 0000000000..6d3ba4693f --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/datefield.rb @@ -0,0 +1,50 @@ +# +# tkextlib/tcllib/datefield.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Tk datefield widget +# +# (The following is the original description of the library.) +# +# The datefield package provides the datefield widget which is an enhanced +# text entry widget for the purpose of date entry. Only valid dates of the +# form MM/DD/YYYY can be entered. +# +# The datefield widget is, in fact, just an entry widget with specialized +# bindings. This means all the command and options for an entry widget apply +# equally here. + +require 'tk' +require 'tk/entry' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('datefield', '0.1') +TkPackage.require('datefield') + +module Tk + module Tcllib + class Datefield < TkEntry + end + DateField = Datefield + end +end + +class Tk::Tcllib::Datefield + TkCommandNames = ['::datefield::datefield'.freeze].freeze + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('::datefield::datefield', @path, + *hash_kv(keys, true)) + else + tk_call_without_enc('::datefield::datefield', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb new file mode 100644 index 0000000000..aed47da63a --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb @@ -0,0 +1,53 @@ +# +# tkextlib/tcllib/ip_entry.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * An IP address entry widget +# +# (The following is the original description of the library.) +# +# This package provides a widget for the entering of a IP address. +# It guarantees a valid address at all times. + +require 'tk' +require 'tk/entry' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('ipentry', '0.1') +TkPackage.require('ipentry') + +module Tk + module Tcllib + class IP_Entry < TkEntry + end + end +end + +class Tk::Tcllib::IP_Entry + TkCommandNames = ['::ipentry::ipentry'.freeze].freeze + WidgetClassName = 'IPEntry'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('::ipentry::ipentry', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('::ipentry::ipentry', @path) + end + end + private :create_self + + def complete? + bool(tk_send_without_enc('complete')) + end + + def insert(*ip) + tk_send_without_enc('insert', array2tk_list(ip.flatten)) + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb new file mode 100644 index 0000000000..108507b05b --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb @@ -0,0 +1,666 @@ +# +# tkextlib/tcllib/plotchart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Simple plotting and charting package +# +# (The following is the original description of the library.) +# +# Plotchart is a Tcl-only package that focuses on the easy creation of +# xy-plots, barcharts and other common types of graphical presentations. +# The emphasis is on ease of use, rather than flexibility. The procedures +# that create a plot use the entire canvas window, making the layout of the +# plot completely automatic. +# +# This results in the creation of an xy-plot in, say, ten lines of code: +# -------------------------------------------------------------------- +# package require Plotchart +# +# canvas .c -background white -width 400 -height 200 +# pack .c -fill both +# +# # +# # Create the plot with its x- and y-axes +# # +# set s [::Plotchart::createXYPlot .c {0.0 100.0 10.0} {0.0 100.0 20.0}] +# +# foreach {x y} {0.0 32.0 10.0 50.0 25.0 60.0 78.0 11.0 } { +# $s plot series1 $x $y +# } +# +# $s title "Data series" +# -------------------------------------------------------------------- +# +# A drawback of the package might be that it does not do any data management. +# So if the canvas that holds the plot is to be resized, the whole plot must +# be redrawn. The advantage, though, is that it offers a number of plot and +# chart types: +# +# * XY-plots like the one shown above with any number of data series. +# * Stripcharts, a kind of XY-plots where the horizontal axis is adjusted +# automatically. The result is a kind of sliding window on the data +# series. +# * Polar plots, where the coordinates are polar instead of cartesian. +# * Isometric plots, where the scale of the coordinates in the two +# directions is always the same, i.e. a circle in world coordinates +# appears as a circle on the screen. +# You can zoom in and out, as well as pan with these plots (Note: this +# works best if no axes are drawn, the zooming and panning routines do +# not distinguish the axes), using the mouse buttons with the control +# key and the arrow keys with the control key. +# * Piecharts, with automatic scaling to indicate the proportions. +# * Barcharts, with either vertical or horizontal bars, stacked bars or +# bars side by side. +# * Timecharts, where bars indicate a time period and milestones or other +# important moments in time are represented by triangles. +# * 3D plots (both for displaying surfaces and 3D bars) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('Plotchart', '0.9') +TkPackage.require('Plotchart') + +module Tk + module Tcllib + module Plotchart + end + end +end + +module Tk::Tcllib::Plotchart + ############################ + def self.view_port(w, *args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', w.path, *(args.flatten)) + end + + def self.world_coordinates(w, *args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + w.path, *(args.flatten)) + end + + def self.world_3D_coordinates(w, *args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + w.path, *(args.flatten)) + end + + def self.coords_to_pixel(w, x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', w.path, x, y)) + end + + def self.coords_3D_to_pixel(w, x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', w.path, x, y, z)) + end + + def self.polar_coordinates(w, radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', w.path, radmax) + end + + def self.polar_to_pixel(w, rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', w.path, rad, phi)) + end + + def self.pixel_to_coords(w, x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', w.path, x, y)) + end + + def self.determine_scale(w, xmax, ymax) + tk_call_without_enc('::Plotchart::determineScale', w.path, xmax, ymax) + end + + def self.set_zoom_pan(w) + tk_call_without_enc('::Plotchart::setZoomPan', w.path) + end + + ############################ + module ChartMethod + include TkUtil + + def title(str) + tk_call_without_enc(@chart, 'title', _get_eval_enc_str(str)) + self + end + + def save_plot(filename) + tk_call_without_enc(@chart, 'saveplot', filename) + self + end + + def xtext(str) + tk_call_without_enc(@chart, 'xtext', _get_eval_enc_str(str)) + self + end + + def ytext(str) + tk_call_without_enc(@chart, 'ytext', _get_eval_enc_str(str)) + self + end + + def xconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'xconfig', *hash_kv(key, true)) + else + tk_call_without_enc(@chart, 'xconfig', + "-#{key}", _get_eval_enc_str(value)) + end + self + end + + def yconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'yconfig', *hash_kv(key, true)) + else + tk_call_without_enc(@chart, 'yconfig', + "-#{key}", _get_eval_enc_str(value)) + end + self + end + + ############################ + def view_port(*args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', @path, *(args.flatten)) + self + end + + def world_coordinates(*args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + @path, *(args.flatten)) + self + end + + def world_3D_coordinates(*args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + @path, *(args.flatten)) + self + end + + def coords_to_pixel(x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', @path, x, y)) + end + + def coords_3D_to_pixel(x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', @path, x, y, z)) + end + + def polar_coordinates(radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', @path, radmax) + self + end + + def polar_to_pixel(rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', @path, rad, phi)) + end + + def pixel_to_coords(x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', @path, x, y)) + end + + def determine_scale(xmax, ymax) + tk_call_without_enc('::Plotchart::determineScale', @path, xmax, ymax) + self + end + + def set_zoom_pan() + tk_call_without_enc('::Plotchart::setZoomPan', @path) + self + end + end + + ############################ + class XYPlot < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createXYPlot'.freeze].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis)) + end + private :_create_chart + + def plot(series, x, y) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), x, y) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) + else + tk_call_without_enc(@chart, 'dataconfig', series, + "-#{key}", _get_eval_enc_str(value)) + end + end + end + + ############################ + class Stripchart < XYPlot + TkCommandNames = ['::Plotchart::createStripchart'.freeze].freeze + end + + ############################ + class PolarPlot < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createPolarplot'.freeze].freeze + + def initialize(*args) # args := ([parent,] radius_data [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @radius_data = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @radius_data = args.shift + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@radius_data)) + end + private :_create_chart + + def plot(series, radius, angle) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), + radius, angle) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) + else + tk_call_without_enc(@chart, 'dataconfig', series, + "-#{key}", _get_eval_enc_str(value)) + end + end + end + Polarplot = PolarPlot + + ############################ + class IsometricPlot < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createIsometricPlot'.freeze].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, [, step] [, keys]) + # xaxis := Array of [minimum, maximum] + # yaxis := Array of [minimum, maximum] + # step := Float of stepsize | "noaxes" | :noaxes + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis), + @stepsize) + end + private :_create_chart + + def plot(type, *args) + self.__send__("plot_#{type.to_s.tr('-', '_')}", *args) + end + + def plot_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'rectangle', *(args.flatten)) + self + end + + def plot_filled_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'filled-rectangle', *(args.flatten)) + self + end + + def plot_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'circle', *(args.flatten)) + self + end + + def plot_filled_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'filled-circle', *(args.flatten)) + self + end + end + Isometricplot = IsometricPlot + + ############################ + class Plot3D < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::create3DPlot'.freeze].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, zaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xaxis), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def plot_function(cmd=Proc.new) + Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}") + tk_call_without_enc(@chart, 'plotfunc', "#{@path}_#{@chart}") + self + end + + def grid_size(nxcells, nycells) + tk_call_without_enc(@chart, 'gridsize', nxcells, nycells) + self + end + + def plot_data(dat) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotdata', dat) + self + end + + def colour(fill, border) + # configure the colours to use for polygon borders and inner area + tk_call_without_enc(@chart, 'colour', fill, border) + self + end + alias colours colour + alias colors colour + alias color colour + end + + ############################ + class Piechart < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createPiechart'.freeze].freeze + + def initialize(*args) # args := ([parent] [, keys]) + if args[0].kind_of?(TkCanvas) + parent = args.shift + @path = parent.path + else + super(*args) # create canvas widget + end + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path) + end + private :_create_chart + + def plot(*dat) # argument is a list of [label, value] + tk_call_without_enc(@chart, 'plot', dat.flatten) + self + end + end + + ############################ + class Barchart < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createBarchart'.freeze].freeze + + def initialize(*args) + # args := ([parent,] xlabels, ylabels [, series] [, keys]) + # xlabels, ylabels := labels | axis ( depend on normal or horizontal ) + # labels := Array of [label, label, ...] + # (It determines the number of bars that will be plotted per series.) + # axis := Array of [minimum, maximum, stepsize] + # series := Integer number of data series | 'stacked' | :stacked + if args[0].kind_of?(Array) + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + array2tk_list(@xlabels), array2tk_list(@ylabels), + @series_size) + end + private :_create_chart + + def plot(series, dat, col=None) + tk_call_without_enc(@chart, 'plot', series, dat, col) + self + end + + def colours(*cols) + # set the colours to be used + tk_call_without_enc(@chart, 'colours', *cols) + self + end + alias colour colours + alias colors colours + alias color colours + end + + ############################ + class HorizontalBarchart < Barchart + TkCommandNames = ['::Plotchart::createHorizontalBarchart'.freeze].freeze + end + + ############################ + class Timechart < TkCanvas + include ChartMethod + + TkCommandNames = ['::Plotchart::createTimechart'.freeze].freeze + + def initialize(*args) + # args := ([parent,] time_begin, time_end, items [, keys]) + # time_begin := String of time format (e.g. "1 january 2004") + # time_end := String of time format (e.g. "1 january 2004") + # items := Expected/maximum number of items + # ( This determines the vertical spacing. ) + if args[0].kind_of?(Array) + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + if parent.kind_of?(TkCanvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[0] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[0], @path, + @time_begin, @time_end, @items) + end + private :_create_chart + + def period(txt, time_begin, time_end, col=None) + tk_call_without_enc(@chart, 'period', txt, time_begin, time_end, col) + self + end + + def milestone(txt, time, col=None) + tk_call_without_enc(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call_without_enc(@chart, 'vertline', txt, time) + self + end + end + + ############################ + class PlotSeries < TkObject + SeriesID_TBL = TkCore::INTERP.create_table + Series_ID = ['series'.freeze, '00000'.taint].freeze + TkCore::INTERP.init_ip_env{ SeriesID_TBL.clear } + + def self.id2obj(chart, id) + path = chart.path + return id unless SeriesID_TBL[path] + SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id + end + + def initialize(chart, keys=nil) + @parent = @chart_obj = chart + @ppath = @chart_obj.path + @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_) + SeriesID_TBL[@id] = self + SeriesID_TBL[@ppath] = {} unless SeriesID_TBL[@ppath] + SeriesID_TBL[@ppath][@id] = self + Series_ID[1].succ! + dataconfig(keys) if keys.kind_of?(Hash) + end + + def plot(*args) + @chart_obj.plot(@series, *args) + end + + def dataconfig(key, value=None) + @chart_obj.dataconfig(@series, key, value) + end + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/setup.rb b/ext/tk/lib/tkextlib/tcllib/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/tcllib/style.rb b/ext/tk/lib/tkextlib/tcllib/style.rb new file mode 100644 index 0000000000..e441cd83b0 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/style.rb @@ -0,0 +1,30 @@ +# +# tkextlib/tcllib/style.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * select and use some 'style' of option (resource) DB +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('style', '0.1') +TkPackage.require('style') + +module Tk + module Style + def self.names + tk_split_simplelist(tk_call('style::names')) + end + + def self.use(style) + tk_call('style::use', style) + end + end +end diff --git a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb new file mode 100644 index 0000000000..1ef49ef4f4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb @@ -0,0 +1,284 @@ +# +# tkextlib/tcllib/tkpiechart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Create 2D or 3D pies with labels in Tcl canvases +# + +require 'tk' +require 'tk/canvas' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('tkpiechart', '6.6') +TkPackage.require('tkpiechart') + +module Tk + module Tcllib + module Tkpiechart + end + end +end + +module Tk::Tcllib::Tkpiechart + module ConfigMethod + include TkConfigMethod + + def __pathname + self.path + ';' + self.tag + end + private :__pathname + + def __cget_cmd + ['::switched::cget', self.tag] + end + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + def __configinfo_struct + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>1, :current_value=>2} + end + private :__configinfo_struct + end + + #################################### + class PieChartObj < TkcItem + include ConfigMethod + + def __font_optkeys + ['titlefont'] + end + private :__font_optkeys + end + + #################################### + class Pie < TkcItem + include ConfigMethod + + def create_self(x, y, width, height, keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'pie', + @c, x, y, *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'pie', @c, x, y) + end + + @slice_tbl = {} + + id = "pie(#{@tag_key})" + + @tag = @tag_pie = TkcNamedTag(@c, id) + @tag_slices = TkcNamedTag(@c, "pieSlices(#{@tag_key})") + + id + end + private :create_self + + def tag_key + @tag_key + end + def tag + @tag + end + def canvas + @c + end + def _entry_slice(slice) + @slice_tbl[slice.to_eval] = slice + end + def _delete_slice(slice) + @slice_tbl.delete(slice.to_eval) + end + + def delete + tk_call_without_enc('::stooop::delete', @tag_key) + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + self + end + + def new_slice(text=None) + Slice.new(self, text) + end + + def delete_slice(slice) + unless slice.kind_of?(Slice) + unless (slice = @slice_tbl[slice]) + return tk_call_without_enc('pie::deleteSlice', @tag_key, slice) + end + end + unless slice.kind_of?(Slice) && slice.pie == self + fail ArgumentError, "argument is not a slice of self" + end + slice.delete + end + + def selected_slices + tk_split_simplelist(tk_call_without_enc('pie::selectedSlices', + @tag_key)).collect{|slice| + @slice_tbl[slice] || Slice.new(:no_create, self, slice) + } + end + end + + #################################### + class Slice < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def initialize(pie, *args) + unless pie.kind_of?(Pie) && pie != :no_create + fail ArgumentError, "expects TkPiechart::Pie for 1st argument" + end + + if pie == :no_create + @pie, @tag_key = args + else + text = args[0] || None + @pie = pie + @tag_key = tk_call_without_enc('pie::newSlice', @pie.tag_key, text) + end + @parent = @c = @pie.canvas + @path = @parent.path + + @pie._entry_slice(self) + + @id = "slices(#{@tag_key})" + @tag = TkcNamedTag.new(@pie.canvas, @id) + + CItemID_TBL[@path] = {} unless CItemID_TBL[@path] + CItemID_TBL[@path][@id] = self + end + + def tag_key + @tag_key + end + def tag + @tag + end + def pie + @pie + end + + def delete + tk_call_without_enc('pie::deleteSlice', @pie.tag_key, @tag_key) + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] + @pie._delete_slice(self) + self + end + + def size(share, disp=None) + tk_call_without_enc('pie::sizeSlice', + @pie.tag_key, @tag_key, share, disp) + self + end + + def label(text) + tk_call_without_enc('pie::labelSlice', @pie.tag_key, @tag_key, text) + self + end + end + + #################################### + class BoxLabeler < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'pieBoxLabeler', + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'pieBoxLabeler') + end + + id = "pieBoxLabeler(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end + + #################################### + class PeripheralLabeler < TkcItem + include ConfigMethod + + def __font_optkeys + ['font', 'smallfont'] + end + private :__font_optkeys + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', + 'piePeripheralLabeler', + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'piePeripheralLabeler') + end + + id = "piePeripheralLabeler(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end + + #################################### + class Label < TkcItem + include ConfigMethod + + def __config_cmd + ['::switched::configure', self.tag] + end + private :__config_cmd + + #------------------------ + + def create_self(x, y, keys=None) + if keys and keys != None + @tag_key = tk_call_without_enc('::stooop::new', 'canvasLabel', + @c, x, y, width, height, + *hash_kv(keys, true)) + else + @tag_key = tk_call_without_enc('::stooop::new', 'canvasLabel', + @c, x, y, width, height) + end + + id = "canvasLabel(#{@tag_key})" + @tag = TkcNamedTag(@c, id) + + id + end + private :create_self + end +end diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb new file mode 100644 index 0000000000..866cdf0644 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile.rb @@ -0,0 +1,73 @@ +# +# Tile theme engin (tile widget set) support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load package +# TkPackage.require('tile', '0.4') +TkPackage.require('tile') + +# autoload +module Tk + module Tile + module TileWidget + def instate(state, script=nil, &b) + if script + tk_send('instate', state, script) + elsif b + tk_send('instate', state, Proc.new(&b)) + else + bool(tk_send('instate', state)) + end + end + + def state(state=nil) + if state + tk_send('state', state) + else + list(tk_send('state')) + end + end + end + + + # library directory + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + #autoload :TButton, 'tkextlib/tile/tbutton' + autoload :TButton, File.join(dir, 'tbutton') + + #autoload :TCheckButton, 'tkextlib/tile/tcheckbutton' + #autoload :TCheckbutton, 'tkextlib/tile/tcheckbutton' + autoload :TCheckButton, File.join(dir, 'tcheckbutton') + autoload :TCheckbutton, File.join(dir, 'tcheckbutton') + + #autoload :TLabel, 'tkextlib/tile/tlabel' + autoload :TLabel, File.join(dir, 'tlabel') + + #autoload :TMenubutton, 'tkextlib/tile/tmenubutton' + autoload :TMenubutton, File.join(dir, 'tmenubutton') + + #autoload :TNotebook, 'tkextlib/tile/tnotebook' + autoload :TNotebook, File.join(dir, 'tnotebook') + + #autoload :TRadioButton, 'tkextlib/tile/tradiobutton' + #autoload :TRadiobutton, 'tkextlib/tile/tradiobutton' + autoload :TRadioButton, File.join(dir, 'tradiobutton') + autoload :TRadiobutton, File.join(dir, 'tradiobutton') + + #autoload :Style, 'tkextlib/tile/style' + autoload :Style, File.join(dir, 'style') + end +end diff --git a/ext/tk/lib/tkextlib/tile/setup.rb b/ext/tk/lib/tkextlib/tile/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb new file mode 100644 index 0000000000..be4b45ab73 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/style.rb @@ -0,0 +1,67 @@ +# +# style commands +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +module Tk::Tile::Style +end + +class << Tk::Tile::Style + def default(style, keys=nil) + if keys && keys != None + tk_call('style', 'default', style, *hash_kv(keys)) + else + tk_call('style', 'default', style) + end + end + + def map(style, keys=nil) + if keys && keys != None + tk_call('style', 'map', style, *hash_kv(keys)) + else + tk_call('style', 'map', style) + end + end + + def layout(style, spec=nil) + if spec + tk_call('style', 'layout', style, spec) + else + tk_call('style', 'layout', style) + end + end + + def element_create(name, type, *args) + tk_call('style', 'element', 'create', name, type, *args) + end + + def element_names() + list(tk_call('style', 'element', 'names')) + end + + def theme_create(name, keys=nil) + if keys && keys != None + tk_call('style', 'theme', 'create', name, type, *hash_kv(keys)) + else + tk_call('style', 'theme', 'create', name, type) + end + end + + def theme_settings(name, cmd=nil, &b) + end + + def theme_names() + list(tk_call('style', 'theme', 'names')) + end + + def theme_use(name) + tk_call('style', 'use', name) + end +end diff --git a/ext/tk/lib/tkextlib/tile/tbutton.rb b/ext/tk/lib/tkextlib/tile/tbutton.rb new file mode 100644 index 0000000000..c73b7904ed --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tbutton.rb @@ -0,0 +1,28 @@ +# +# tbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TButton < TkButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tbutton'.freeze].freeze + WidgetClassName = 'TButton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tbutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tbutton', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb new file mode 100644 index 0000000000..f5ab008820 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb @@ -0,0 +1,33 @@ +# +# tcheckbutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TCheckButton < TkCheckButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tcheckbutton'.freeze].freeze + WidgetClassName = 'TCheckbutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tcheckbutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tcheckbutton', @path) + end + end + private :create_self +end +module Tk + module Tile + TCheckbutton = TCheckButton + end +end diff --git a/ext/tk/lib/tkextlib/tile/tlabel.rb b/ext/tk/lib/tkextlib/tile/tlabel.rb new file mode 100644 index 0000000000..1b7302cab1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tlabel.rb @@ -0,0 +1,28 @@ +# +# tlabel widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TLabel < TkLabel + include Tk::Tile::TileWidget + + TkCommandNames = ['tlabel'.freeze].freeze + WidgetClassName = 'TLabel'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tlabel', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tlabel', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/ext/tk/lib/tkextlib/tile/tmenubutton.rb new file mode 100644 index 0000000000..c827629c7d --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb @@ -0,0 +1,28 @@ +# +# tmenubutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TMenubutton < TkMenubutton + include Tk::Tile::TileWidget + + TkCommandNames = ['tmenubutton'.freeze].freeze + WidgetClassName = 'TMenubutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tmenubutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tmenubutton', @path) + end + end + private :create_self +end diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb new file mode 100644 index 0000000000..40242b5235 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb @@ -0,0 +1,90 @@ +# +# tnotebook widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TNotebook < TkWindow + ################################ + include TkItemConfigMethod + + def __item_cget_cmd(id) + [self.path, 'tabcget', id] + end + private :__item_cget_cmd + + def __item_config_cmd(id) + [self.path, 'tabconfigure', id] + end + private :__item_config_cmd + + + def __item_listval_optkeys + [] + end + private :__item_listval_optkeys + + def __item_methodcall_optkeys # { key=>method, ... } + {} + end + private :__item_listval_optkeys + + alias tabcget itemcget + alias tabconfigure itemconfigure + alias tabconfiginfo itemconfiginfo + alias current_tabconfiginfo current_itemconfiginfo + ################################ + + include Tk::Tile::TileWidget + + TkCommandNames = ['tnotebook'.freeze].freeze + WidgetClassName = 'TNotebook'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tnotebook', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tnotebook', @path) + end + end + private :create_self + + def enable_traversal() + tk_call_without_end('tile::enableNotebookTraversal', @path) + self + end + + def add(child, keys=nil) + if keys && keys != None + tk_send_without_enc('add', _epath(child), *hash_kv(keys)) + else + tk_send_without_enc('add', _epath(child)) + end + self + end + + def forget(idx) + tk_send('forget', idx) + self + end + + def index(idx) + number(tk_send('index', idx)) + end + + def select(idx) + tk_send('select', idx) + self + end + + def tabs + list(tk_send('tabs')) + end +end diff --git a/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/ext/tk/lib/tkextlib/tile/tradiobutton.rb new file mode 100644 index 0000000000..2587a74cf3 --- /dev/null +++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb @@ -0,0 +1,33 @@ +# +# tradiobutton widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script -- /tkextlib/tile.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Tile::TRadioButton < TkRadioButton + include Tk::Tile::TileWidget + + TkCommandNames = ['tradiobutton'.freeze].freeze + WidgetClassName = 'TRadiobutton'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('tradiobutton', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('tradiobutton', @path) + end + end + private :create_self +end +module Tk + module Tile + TRadiobutton = TRadioButton + end +end diff --git a/ext/tk/lib/tkextlib/tkDND.rb b/ext/tk/lib/tkextlib/tkDND.rb new file mode 100644 index 0000000000..ba5b23b538 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND.rb @@ -0,0 +1,25 @@ +# +# TkDND (Tk Drag & Drop Extension) support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +module Tk + module TkDND + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + #autoload :DND 'tkextlib/tkDND/tkdnd' + #autoload :Shape 'tkextlib/tkDND/shape' + autoload :DND File.join(dir, 'tkdnd') + autoload :Shape File.join(dir, 'shape') + end +end diff --git a/ext/tk/lib/tkextlib/tkDND/setup.rb b/ext/tk/lib/tkextlib/tkDND/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/tkDND/shape.rb b/ext/tk/lib/tkextlib/tkDND/shape.rb new file mode 100644 index 0000000000..3e4a94f526 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND/shape.rb @@ -0,0 +1,96 @@ +# +# tkextlib/tkDND/shape.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('shape', '0.3') +TkPackage.require('shape') + +module Tk + module TkDND + module Shape + def self.version + tk_call('shape', 'version') + end + + ############################ + + def shape_bounds(kind=nil) + if kind + ret = tk_call('shape', 'bounds', @path, "-#{kind}") + else + ret = tk_call('shape', 'bounds', @path) + end + if ret == "" + nil + else + list(ret) + end + end + + def shape_get(kind=nil) + if kind + list(tk_call('shape', 'get', @path, "-#{kind}")) + else + list(tk_call('shape', 'get', @path)) + end + end + + def shape_offset(x, y, kind=nil) + if kind + tk_call('shape', 'get', @path, "-#{kind}", x, y) + else + tk_call('shape', 'get', @path, x, y) + end + self + end + + def _parse_shapespec_param(args) + cmd = [] + + kind_keys = ['bounding', 'clip', 'both'] + offset_keys = ['offset'] + srckind_keys = ['bitmap', 'rectangles', 'reset', 'test', 'window'] + + cmd << "-#{args.shift}" if kind_keys.member?(args[0].to_s) + + if offset_keys.member?(args[0].to_s) + cmd << "-#{args.shift}" + cmd << args.shift # xOffset + cmd << args.shift # yOffset + end + + if srckind_keys.member?(args[0].to_s) + cmd << "-#{args.shift}" + end + + cmd.concat(args) + + cmd + end + private :_parse_shapespec_param + + def shape_set(*args) # ?kind? ?offset ? srckind ?arg ...? + tk_call('shape', 'set', @path, *(_parse_shapespec_param(args))) + self + end + + def shape_update(op, *args) # ?kind? ?offset ? srckind ?arg ...? + tk_call('shape', 'update', @path, op, *(_parse_shapespec_param(args))) + self + end + end + end +end + +class TkWindow + include Tk::TkDND::Shape +end diff --git a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb new file mode 100644 index 0000000000..036d1998bd --- /dev/null +++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb @@ -0,0 +1,108 @@ +# +# tkextlib/tkDND/tkdnd.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +TkPackage.require('tkdnd') + +module Tk + module TkDND + class DND_Subst < TkUtil::CallbackSubst + KEY_TBL = [ + [ ?a, ?l, :actions ], + [ ?A, ?s, :action ], + [ ?b, ?L, :codes ], + [ ?c, ?s, :code ], + [ ?d, ?l, :descriptions ], + [ ?D, ?l, :data ], + [ ?L, ?l, :source_types ], + [ ?m, ?l, :modifiers ], + [ ?t, ?l, :types ], + [ ?T, ?s, :type ], + [ ?W, ?w, :widget ], + [ ?x, ?n, :x ], + [ ?X, ?n, :x_root ], + [ ?y, ?n, :y ], + [ ?Y, ?n, :y_root ], + nil + ] + + PROC_TBL = [ + [ ?n, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?l, TkComm.method(:list) ], + [ ?L, TkComm.method(:simplelist) ], + [ ?w, TkComm.method(:window) ], + nil + ] + + # setup tables + _setup_subst_table(KEY_TBL, PROC_TBL); + end + + module DND + def dnd_bindtarget_info(type=nil, event=nil) + if event + procedure(tk_call('dnd', 'bindtarget', @path, type, event)) + elsif type + procedure(tk_call('dnd', 'bindtarget', @path, type)) + else + simplelist(tk_call('dnd', 'bindtarget', @path)) + end + end + + def dnd_bindtarget(type, event, cmd=Proc.new, prior=50, *args) + event = tk_event_sequence(event) + if prior.kind_of?(Numeric) + tk_call('dnd', 'bindtarget', @path, type, event, + install_bind_for_event_class(DND_Subst, cmd, *args), + prior) + else + tk_call('dnd', 'bindtarget', @path, type, event, + install_bind_for_event_class(DND_Subst, cmd, prior, *args)) + end + self + end + + def dnd_cleartarget + tk_call('dnd', 'cleartarget', @path) + self + end + + def dnd_bindsource_info(type=nil) + if type + procedure(tk_call('dnd', 'bindsource', @path, type)) + else + simplelist(tk_call('dnd', 'bindsource', @path)) + end + end + + def dnd_bindsource(type, cmd=Proc.new, prior=None) + tk_call('dnd', 'bindsource', @path, type, cmd, prior) + self + end + + def dnd_clearsource() + tk_call('dnd', 'clearsource', @path) + self + end + + def dnd_drag(keys=nil) + tk_call('dnd', 'drag', @path, *hash_kv(keys)) + self + end + end + end +end + +class TkWindow + include Tk::TkDND::DND +end diff --git a/ext/tk/lib/tkextlib/tkHTML.rb b/ext/tk/lib/tkextlib/tkHTML.rb new file mode 100644 index 0000000000..f32aed99f1 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkHTML.rb @@ -0,0 +1,16 @@ +# +# TkHtml support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load library +require File.join(dir, 'htmlwidget') diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb new file mode 100644 index 0000000000..5c0657025a --- /dev/null +++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb @@ -0,0 +1,427 @@ +# +# tkextlib/tkHTML/htmlwidget.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('Tkhtml', '2.0') +TkPackage.require('Tkhtml') + +module Tk + class HTML_Widget < TkWindow + class ClippingWindow < TkWindow + end + end +end + +class Tk::HTML_Widget::ClippingWindow + extend TkUtil + + WidgetClassName = 'HtmlClip'.freeze + WidgetClassNames[WidgetClassName] = self + + HtmlClip_TBL = TkCore::INTERP.create_table + TkCore::INTERP.init_ip_env{ HtmlClip_TBL.clear } + + def self.new(parent, keys={}) + if parent.kind_of?(Hash) + keys = _symbolkey2str(parent) + parent = keys.delete('parent') + end + + if parent.kind_of?(String) + ppath = parent.path + elsif parent + ppath = parent + else + ppath = '' + end + return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath] + + widgetname = keys.delete('widgetname') + if widgetname =~ /^(.*)\.[^.]+$/ + ppath2 = $1 + if ppath2[0] != ?. + ppath2 = ppath + '.' + ppath2 + end + return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2] + + ppath = ppath2 + end + + parent = TkComm._genobj_for_tkwidget(ppath) + unless parent.kind_of?(Tk::HTML_Widget) + fail ArgumentError, "parent must be a Tk::HTML_Widget instance" + end + + super(parent) + end + + def initialize(parent) + @parent = parent + @ppath = parent.path + @path = @id = @ppath + '.x' + HtmlClip_TBL[@ppath] = self + end + + def method_missing(m, *args, &b) + @parent.__send__(m, *args, &b) + end +end + +class Tk::HTML_Widget + include Scrollable + + TkCommandNames = ['html'.freeze].freeze + WidgetClassName = 'Html'.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('html', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('html', @path) + end + end + private :create_self + + ################################### + # class methods + ################################### + def self.reformat(src, dst, txt) + tk_call('html', 'reformat', src, dst, txt) + end + + def self.url_join(*args) # args := sheme authority path query fragment + tk_call('html', 'urljoin', *args) + end + + def self.url_split(uri) + tk_call('html', 'urlsplit', uri) + end + + def self.lockcopy(src, dst) + tk_call('html', 'lockcopy', src, dst) + end + + def self.gzip_file(file, dat) + tk_call('html', 'gzip', 'file', file, dat) + end + + def self.gunzip_file(file, dat) + tk_call('html', 'gunzip', 'file', filet) + end + + def self.gzip_data(dat) + tk_call('html', 'gzip', 'data', file, dat) + end + + def self.gunzip_data(dat) + tk_call('html', 'gunzip', 'data', filet) + end + + def self.base64_encode(dat) + tk_call('html', 'base64', 'encode', dat) + end + + def self.base64_decode(dat) + tk_call('html', 'base64', 'encode', dat) + end + + def self.text_format(dat, len) + tk_call('html', 'text', 'format', dat, len) + end + + def self.xor(cmd, *args) + tk_call('html', 'xor', cmd, *args) + end + + def self.stdchan(cmd, channel) + tk_call('html', 'stdchan', cmd, channel) + end + + def self.crc32(data) + tk_call('html', 'crc32', data) + end + + ################################### + # instance methods + ################################### + def clipping_window + ClippingWindow.new(self) + end + alias clipwin clipping_window + alias htmlclip clipping_window + + def bgimage(image, tid=None) + tk_send('bgimage', image, tid) + self + end + + def clear() + tk_send('clear') + self + end + + def coords(index=None, percent=None) + tk_send('coords', index, percent) + end + + def forminfo(*args) + tk_send('forminfo', *args) + end + alias form_info forminfo + + def href(x, y) + simplelist(tk_send('href', x, y)) + end + + def image_add(id, img) + tk_send('imageadd', id, img) + self + end + + def image_at(x, y) + tk_send('imageat', x, y) + end + + def images() + list(tk_send('images')) + end + + def image_set(id, num) + tk_send('imageset', id, num) + self + end + + def image_update(id, imgs) + tk_send('imageupdate', id, imgs) + self + end + + def index(idx, count=None, unit=None) + tk_send('index', idx, count, unit) + end + + def insert_cursor(idx) + tk_send('insert', idx) + end + + def names() + simple_list(tk_send('names')) + end + + def on_screen(id, x, y) + bool(tk_send('onscreen', id, x, y)) + end + + def over(x, y) + list(tk_send('over', x, y)) + end + + def over_markup(x, y) + list(tk_send('over', x, y, '-muponly')) + end + + def over_attr(x, y, attrs) + list(tk_send('overattr', x, y, attrs)) + end + + def parse(txt) + tk_send('parse', txt) + self + end + + def resolver(*uri_args) + tk_send('resolver', *uri_args) + end + + def selection_clear() + tk_send('selection', 'clear') + self + end + + def selection_set(first, last) + tk_send('selection', 'set', first, last) + self + end + + def refresh(*opts) + tk_send('refresh', *opts) + end + + def layout() + tk_send('layout') + end + + def sizewindow(*args) + tk_send('sizewindow', *args) + end + + def postscript(*args) + tk_send('postscript', *args) + end + + def source() + tk_send('source') + end + + def plain_text(first, last) + tk_send('text', 'ascii', first, last) + end + alias ascii_text plain_text + alias text_ascii plain_text + + def text_delete(first, last) + tk_send('text', 'delete', first, last) + self + end + + def html_text(first, last) + tk_send('text', 'html', first, last) + end + alias text_html html_text + + def text_insert(idx, txt) + tk_send('text', 'insert', idx, txt) + self + end + + def break_text(idx) + tk_send('text', 'break', idx) + end + alias text_break break_text + + def text_find(txt, *args) + tk_send('text', 'find', txt, *args) + end + + def text_table(idx, imgs=None, attrs=None) + tk_send('text', 'table', idx, imgs, attrs) + end + + def token_append(tag, *args) + tk_send('token', 'append', tag, *args) + self + end + + def token_delete(first, last=None) + tk_send('token', 'delete', first, last) + self + end + + def token_define(*args) + tk_send('token', 'defile', *args) + self + end + + def token_find(tag, *args) + list(tk_send('token', 'find', tag, *args)) + end + + def token_get(first, last=None) + list(tk_send('token', 'get', first, last)) + end + + def token_list(first, last=None) + list(tk_send('token', 'list', first, last)) + end + + def token_markup(first, last=None) + list(tk_send('token', 'markup', first, last)) + end + + def token_DOM(first, last=None) + list(tk_send('token', 'domtokens', first, last)) + end + alias token_dom token_DOM + alias token_domtokens token_DOM + alias token_dom_tokens token_DOM + + def token_get_end(idx) + tk_send('token', 'getend', idx) + end + alias token_getend token_get_end + + def token_offset(start, num1, num2) + list(tk_send('token', 'offset', start, num1, num2)) + end + + def token_get_attr(idx, name=None) + list(tk_send('token', 'attr', idx, name)) + end + + def token_set_attr(idx, name=None, val=None) + tk_send('token', 'attr', idx, name, val) + self + end + + def token_handler(tag, cmd=nil, &b) + cmd = Proc.new(&b) if !cmd && b + if cmd + tk_send('token', 'handler', tag, cmd) + return self + else + return tk_send('token', 'handler', tag) + end + end + + def token_insert(idx, tag, *args) + tk_send('token', 'insert', idx, tag, *args) + self + end + + def token_attrs(*args) + list(tk_send('token', 'attrs', *args)) + end + + def token_unique(*args) + list(tk_send('token', 'unique', *args)) + end + + def token_on_events(*args) + list(tk_send('token', 'onEvents', *args)) + end + + def dom_nameidx(tag, name) + number(tk_send('dom', 'nameidx', tag, name)) + end + alias dom_name_index dom_nameidx + + def dom_radioidx(tag, name) + number(tk_send('dom', 'radioidx', tag, name)) + end + alias dom_radio_index dom_radioidx + + def dom_id(*spec) + tk_send('dom', 'id', *spec) + end + + def dom_ids(*spec) + list(tk_send('dom', 'ids', *spec)) + end + + def dom_value(*spec) + list(tk_send('dom', 'value', *spec)) + end + + def dom_attr(idx) + tk_send('dom', 'attr', idx) + end + + def dom_formel(name) + tk_send('dom', 'formel', name) + end + alias dom_form_element dom_formel + + def dom_tree(idx, val) + list(tk_send('dom', 'tree', idx, val)) + end +end diff --git a/ext/tk/lib/tkextlib/tkHTML/setup.rb b/ext/tk/lib/tkextlib/tkHTML/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkHTML/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/tkimg.rb b/ext/tk/lib/tkextlib/tkimg.rb new file mode 100644 index 0000000000..06184589b4 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg.rb @@ -0,0 +1,23 @@ +# +# TkImg extension support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load all image format handlers +#TkPackage.require('Img', '1.3') +TkPackage.require('Img') + +# autoload +#autoload :TkPixmapImage, 'tkextlib/tkimg/pixmap' +autoload :TkPixmapImage, File.join(dir, 'pixmap') diff --git a/ext/tk/lib/tkextlib/tkimg/README b/ext/tk/lib/tkextlib/tkimg/README new file mode 100644 index 0000000000..65d36365d0 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/README @@ -0,0 +1,26 @@ + + [ Tcl/Tk Image formats (TkImg) support ] + +TkImg contains a collection of format handlers for the Tk photo +image type, and a new image type, pixmaps. + +Supported formats of TkImg version 1.3 are +------------------------------------------------------- + bmp : Windows Bitmap Format + gif : Graphics Interchange Format + ico : Windows Icon Format + jpeg : Joint Picture Expert Group format + pcx : Paintbrush Format + pixmap : Pixmap Image type + png : Portable Network Graphics format + ppm : Portable Pixmap format + ps : Adobe PostScript Format + sgi : SGI Native Format + sun : Sun Raster Format + tga : Truevision Targa Format + tiff : Tagged Image File Format + window : Tk Windows + xbm : X Window Bitmap Format + xpm : X Window Pixmap Format +------------------------------------------------------- + diff --git a/ext/tk/lib/tkextlib/tkimg/bmp.rb b/ext/tk/lib/tkextlib/tkimg/bmp.rb new file mode 100644 index 0000000000..5bef0c7168 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/bmp.rb @@ -0,0 +1,14 @@ +# +# TkImg - format 'bmp' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +#TkPackage.require('img::bmp', '1.3') +TkPackage.require('img::bmp') diff --git a/ext/tk/lib/tkextlib/tkimg/gif.rb b/ext/tk/lib/tkextlib/tkimg/gif.rb new file mode 100644 index 0000000000..65c3b88a50 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/gif.rb @@ -0,0 +1,14 @@ +# +# TkImg - format 'gif' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::gif', '1.3') +TkPackage.require('img::gif') diff --git a/ext/tk/lib/tkextlib/tkimg/ico.rb b/ext/tk/lib/tkextlib/tkimg/ico.rb new file mode 100644 index 0000000000..43646ec8da --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/ico.rb @@ -0,0 +1,14 @@ +# +# TkImg - format 'ico' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::ico', '1.3') +TkPackage.require('img::ico') diff --git a/ext/tk/lib/tkextlib/tkimg/jpeg.rb b/ext/tk/lib/tkextlib/tkimg/jpeg.rb new file mode 100644 index 0000000000..7b4df8c050 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/jpeg.rb @@ -0,0 +1,14 @@ +# +# TkImg - format 'jpeg' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::jpeg', '1.3') +TkPackage.require('img::jpeg') diff --git a/ext/tk/lib/tkextlib/tkimg/pcx.rb b/ext/tk/lib/tkextlib/tkimg/pcx.rb new file mode 100644 index 0000000000..4486ba2449 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/pcx.rb @@ -0,0 +1,14 @@ +# +# TkImg - format 'pcx' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::pcx', '1.3') +TkPackage.require('img::pcx') diff --git a/ext/tk/lib/tkextlib/tkimg/pixmap.rb b/ext/tk/lib/tkextlib/tkimg/pixmap.rb new file mode 100644 index 0000000000..0c18c71408 --- /dev/null +++ b/ext/tk/lib/tkextlib/tkimg/pixmap.rb @@ -0,0 +1,21 @@ +# +# TkImg - format 'pixmap' +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# call setup script +require File.join(File.dirname(File.expand_path(__FILE__)), 'setup.rb') + +# TkPackage.require('img::pixmap', '1.3') +TkPackage.require('img::pixmap') + +class TkPixmapImage, , ] + KEY_TBL = [ + [ ?c, ?n, :item_num ], + [ ?d, ?s, :detail ], + [ ?D, ?l, :items ], + [ ?e, ?e, :event ], + [ ?I, ?n, :id ], + [ ?l, ?b, :lower_bound ], + [ ?p, ?n, :active_id ], + [ ?S, ?l, :sel_items ], + [ ?T, ?w, :widget ], + [ ?U, ?b, :upper_bound ], + [ ?W, ?o, :object ], + nil + ] + + # [ , ] + PROC_TBL = [ + [ ?n, TkComm.method(:num_or_str) ], + [ ?s, TkComm.method(:string) ], + [ ?l, TkComm.method(:list) ], + [ ?w, TkComm.method(:window) ], + + [ ?b, proc{|val| list(val)} ], + + [ ?e, proc{|val| + case val + when /^<<[^<>]+>>$/ + TkVirtualEvent.getobj(val[1..-2]) + when /^<[^<>]+>$/ + val[1..-2] + else + val + end + } + ], + + [ ?o, proc{|val| tk_tcl2ruby(val)} ], + + nil + ] + + # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys + # + # _get_subst_key() and _get_all_subst_keys() generates key-string + # which describe how to convert callback arguments to ruby objects. + # When binding parameters are given, use _get_subst_key(). + # But when no parameters are given, use _get_all_subst_keys() to + # create a Event class object as a callback parameter. + # + # scan_args() is used when doing callback. It convert arguments + # ( which are Tcl strings ) to ruby objects based on the key string + # that is generated by _get_subst_key() or _get_all_subst_keys(). + # + _setup_subst_table(KEY_TBL, PROC_TBL); +end + +############################################## + +module Tk::TreeCtrl_Widget::ConfigMethod + include TkItemConfigMethod + + def treectrl_tagid(key, obj) + if key.kind_of?(Array) + key = key.join(' ') + else + key = key.to_s + end + + case key + when 'column' + obj + + when 'dragimage' + obj + + when 'element' + obj + + when 'item element' + obj + + when 'marquee' + obj + + when 'notify' + obj + + when 'style' + obj + + else + obj + end + end + + def tagid(mixed_id) + if mixed_id.kind_of?(Array) + [mixed_id[0], treectrl_tagid(*mixed_id)] + else + tagid(mixed_id.split(':')) + end + fail ArgumentError, "unknown id format" + end + + def __item_cget_cmd(mixed_id) + if mixed_id[1].kind_of?(Array) + id = mixed_id[1] + else + id = [mixed_id[1]] + end + + if mixed_id[0].kind_of?(Array) + ([self.path].concat(mixed_id[0]) << 'cget').concat(id) + else + [self.path, mixed_id[0], 'cget'].concat(id) + end + end + private :__item_cget_cmd + + def __item_config_cmd(mixed_id) + if mixed_id[1].kind_of?(Array) + id = mixed_id[1] + else + id = [mixed_id[1]] + end + + if mixed_id[0].kind_of?(Array) + ([self.path].concat(mixed_id[0]) << 'configure').concat(id) + else + [self.path, mixed_id[0], 'configure'].concat(id) + end + end + private :__item_config_cmd + + def __item_pathname(id) + if id.kind_of?(Array) + key = id[0] + if key.kind_of?(Array) + key = key.join(' ') + end + + tag = id[1] + if tag.kind_of?(Array) + tag = tag.join(' ') + end + + id = [key, tag].join(':') + end + [self.path, id].join(';') + end + private :__item_pathname + + def __item_configinfo_struct(id) + if id.kind_of?(Array) && id[0].to_s == 'notify' + {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, + :default_value=>nil, :current_value=>1} + else + {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, + :default_value=>3, :current_value=>4} + end + end + private :__item_configinfo_struct + + def __item_listval_optkeys(id) + [] + end + private :__item_listval_optkeys + + def __item_keyonly_optkeys(id) # { def_key=>(undef_key|nil), ... } + { + 'notreally'=>nil, + 'increasing'=>'decreasing', + 'decreasing'=>'increasing', + 'ascii'=>nil, + 'dictionary'=>nil, + 'integer'=>nil, + 'real'=>nil + } + end + private :__item_keyonly_optkeys + + def column_cget(tagOrId, option) + itemcget(['column', tagOrId], option) + end + def column_configure(tagOrId, slot, value=None) + itemconfigure(['column', tagOrId], slot, value) + end + def column_configinfo(tagOrId, slot=nil) + itemconfigure(['column', tagOrId], slot) + end + def current_column_configinfo(tagOrId, slot=nil) + itemconfigure(['column', tagOrId], slot) + end + + def dragimage_cget(tagOrId, option) + itemcget(['dragimage', tagOrId], option) + end + def dragimage_configure(tagOrId, slot, value=None) + itemconfigure(['dragimage', tagOrId], slot, value) + end + def dragimage_configinfo(tagOrId, slot=nil) + itemconfigure(['dragimage', tagOrId], slot) + end + def current_dragimage_configinfo(tagOrId, slot=nil) + itemconfigure(['dragimage', tagOrId], slot) + end + + def element_cget(tagOrId, option) + itemcget(['element', tagOrId], option) + end + def element_configure(tagOrId, slot, value=None) + itemconfigure(['element', tagOrId], slot, value) + end + def element_configinfo(tagOrId, slot=nil) + itemconfigure(['element', tagOrId], slot) + end + def current_element_configinfo(tagOrId, slot=nil) + itemconfigure(['element', tagOrId], slot) + end + + def item_element_cget(tagOrId, option) + itemcget([['item', 'element'], tagOrId], option) + end + def item_element_configure(tagOrId, slot, value=None) + itemconfigure([['item', 'element'], tagOrId], slot, value) + end + def item_element_configinfo(tagOrId, slot=nil) + itemconfigure([['item', 'element'], tagOrId], slot) + end + def current_item_element_configinfo(tagOrId, slot=nil) + itemconfigure([['item', 'element'], tagOrId], slot) + end + + def marquee_cget(tagOrId, option) + itemcget(['marquee', tagOrId], option) + end + def marquee_configure(tagOrId, slot, value=None) + itemconfigure(['marquee', tagOrId], slot, value) + end + def marquee_configinfo(tagOrId, slot=nil) + itemconfigure(['marquee', tagOrId], slot) + end + def current_marquee_configinfo(tagOrId, slot=nil) + itemconfigure(['marquee', tagOrId], slot) + end + + def notify_cget(win, pattern, option) + itemconfigure(['notify', [win, pattern]], option) + end + def notify_configure(win, pattern, slot, value=None) + itemconfigure(['notify', [win, pattern]], slot, value) + end + def notify_configinfo(win, pattern, slot=nil) + itemconfigure(['notify', [win, pattern]], slot) + end + alias current_notify_configinfo notify_configinfo + + def style_cget(tagOrId, option) + itemcget(['style', tagOrId], option) + end + def style_configure(tagOrId, slot, value=None) + itemconfigure(['style', tagOrId], slot, value) + end + def style_configinfo(tagOrId, slot=nil) + itemconfigure(['style', tagOrId], slot) + end + def current_style_configinfo(tagOrId, slot=nil) + itemconfigure(['style', tagOrId], slot) + end + + private :itemcget, :itemconfigure + private :itemconfiginfo, :current_itemconfiginfo +end + +############################################## + +class Tk::TreeCtrl_Widget + include Tk::TreeCtrl_Widget::ConfigMethod + include Scrollable + + TkCommandNames = ['treectrl'.freeze].freeze + WidgetClassName = ''.freeze + WidgetClassNames[WidgetClassName] = self + + def create_self(keys) + if keys and keys != None + tk_call_without_enc('treectrl', @path, *hash_kv(keys, true)) + else + tk_call_without_enc('treectrl', @path) + end + end + private :create_self + + ######################### + + def activate(desc) + tk_send('activate', desc) + self + end + + def canvasx(x) + number(tk_send('canvasx', x)) + end + + def canvasy(y) + number(tk_send('canvasy', y)) + end + + def collapse(*dsc) + tk_send('collapse', *dsc) + self + end + + def collapse_recurse(*dsc) + tk_send('collapse', '-recurse', *dsc) + self + end + + def column_bbox(idx) + list(tk_send('column', 'bbox', idx)) + end + + def column_delete(idx) + tk_send('column', 'delete', idx) + self + end + + def column_index(idx) + num_or_str(tk_send('column', 'index', idx)) + end + + def column_move(idx, to) + tk_send('column', 'move', idx, to) + self + end + + def column_needed_width(idx) + num_or_str(tk_send('column', 'neededwidth', idx)) + end + alias column_neededwidth column_needed_width + + def column_width(idx) + num_or_str(tk_send('column', 'width', idx)) + end + + def compare(item1, op, item2) + number(tk_send('compare', item1, op, item2)) + end + + def contentbox() + list(tk_send('contentbox')) + end + + def depth(item=None) + num_or_str(tk_send('depth', item)) + end + + def dragimage_add(item, *args) + tk_send('dragimage', 'add', item, *args) + self + end + + def dragimage_clear() + tk_send('dragimage', 'clear') + self + end + + def dragimage_offset(*args) # x, y + if args.empty? + list(tk_send('dragimage', 'offset')) + else + tk_send('dragimage', 'offset', *args) + self + end + end + + def dragimage_visible(*args) # mode + if args..empty? + bool(tk_send('dragimage', 'visible')) + else + tk_send('dragimage', 'visible', *args) + self + end + end + def dragimage_visible? + dragimage_visible() + end + + def element_create(elem, type, keys=nil) + if keys && keys.kind_of?(Hash) + tk_send('element', 'create', elem, type, *hash_kv(keys)) + else + tk_send('element', 'create', elem, type) + end + end + + def element_delete(*elems) + tk_send('element', 'delete', *elems) + self + end + + def element_names() + list(tk_send('element', 'names')) + end + + def element_type(elem) + tk_send('element', 'type', elem) + end + + def expand(*dsc) + tk_send('expand', *dsc) + self + end + + def expand_recurse(*dsc) + tk_send('expand', '-recurse', *dsc) + self + end + + def identify(x, y) + list(tk_send('identify', x, y)) + end + + def index(idx) + num_or_str(tk_send('index', idx)) + end + + def item_ancestors(item) + list(tk_send('item', 'ancestors', item)) + end + + def item_bbox(item, *args) + list(tk_send('item', 'bbox', item, *args)) + end + + def item_children(item) + list(tk_send('item', 'children', item)) + end + + def item_complex(item, *args) + tk_send('item', 'complex', item, *args) + self + end + + def item_create() + num_or_str(tk_send('item', 'create')) + end + + def item_delete(first, last=None) + tk_send('item', 'delete', first, last) + self + end + + def item_dump(item) + list(tk_send('item', 'dump', item)) + end + + def item_element_actual(item, column, elem, key) + tk_send('item', 'element', 'actual', item, column, elem, "-#{key}") + end + + def item_firstchild(parent, child=nil) + if child + tk_send('item', 'firstchild', parent, child) + self + else + num_or_str(tk_send('item', 'firstchild', parent)) + end + end + alias item_first_child item_firstchild + + def item_hashbutton(item, st=None) + if st == None + bool(tk_send('item', 'hashbutton')) + else + tk_send('item', 'hashbutton', st) + self + end + end + def item_hashbutton?(item) + item_hashbutton(item) + end + + def item_index(item) + list(tk_send('item', 'index', item)) + end + + def item_isancestor(item, des) + bool(tk_send('item', 'isancestor', item, des)) + end + alias item_is_ancestor item_isancestor + alias item_isancestor? item_isancestor + alias item_is_ancestor? item_isancestor + + def item_isopen(item) + bool(tk_send('item', 'isopen', item)) + end + alias item_is_open item_isopen + alias item_isopen? item_isopen + alias item_is_open? item_isopen + + def item_lastchild(parent, child=nil) + if child + tk_send('item', 'lastchild', parent, child) + self + else + num_or_str(tk_send('item', 'lastchild', parent)) + end + end + alias item_last_child item_lastchild + + def item_nextsibling(sibling, nxt=nil) + if nxt + tk_send('item', 'nextsibling', sibling, nxt) + self + else + num_or_str(tk_send('item', 'nextsibling', sibling)) + end + end + alias item_next_sibling item_nextsibling + + def item_numchildren() + number(tk_send('item', 'numchildren')) + end + alias item_num_children item_numchildren + alias item_children_size item_numchildren + + def item_parent(item) + num_or_str(tk_send('item', 'parent', item)) + end + + def item_prevsibling(sibling, prev=nil) + if prev + tk_send('item', 'prevsibling', sibling, prev) + self + else + num_or_str(tk_send('item', 'prevsibling', sibling)) + end + end + alias item_prev_sibling item_prevsibling + + def item_remove(item) + list(tk_send('item', 'remove', item)) + end + + def item_rnc(item) + list(tk_send('item', 'rnc', item)) + end + + def item_sort(item, *opts) + flag = false + if opts[-1].kind_of?(Hash) + opts[-1,1] = __conv_item_keyonly_opts(item, opts[-1]).to_a + end + + opts = opts.collect{|opt| + if opt.kind_of?(Array) + key = "-#{opt[0]}" + flag = true if key == '-notreally' + ["-#{opt[0]}", opt[1]] + else + key = "-#{opt}" + flag = true if key == '-notreally' + key + end + }.flatten + + ret = tk_send('item', 'sort', item, *opts) + if flag + list(ret) + else + ret + end + end + + def item_state_get(item, *args) + if args.empty? + list(tk_send('item', 'state', 'get', item *args)) + else + bool(tk_send('item', 'state', 'get', item)) + end + end + + def item_state_set(item, *args) + tk_send('item', 'state', 'set', *args) + self + end + + def item_style_elements(item, colun) + list(tk_send('item', 'style', 'elements', item, column)) + end + + def item_style_map(item, column, style, map) + tk_send('item', 'style', 'map', item, column, style, map) + self + end + + def item_style_set(item, column=nil, *args) + if args.empty? + if column + tk_send('item', 'style', 'set', item, column) + else + list(tk_send('item', 'style', 'set', item)) + end + else + tk_send('item', 'style', 'set', item, *(args.flatten)) + self + end + end + + def item_text(item, column, txt=nil, *args) + if args.empty? + if txt + tk_send('item', 'text', item, column, txt) + self + else + tk_send('item', 'text', item, column) + end + else + tk_send('item', 'text', item, txt, *args) + self + end + end + + def item_visible(item, st=None) + if st == None + bool(tk_send('item', 'visible', item)) + else + tk_send('item', 'visible', item, st) + self + end + end + def item_visible?(item) + item_visible(item) + end + + def marquee_anchor(*args) + if args.empty? + list(tk_send('marquee', 'anchor')) + else + tk_send('marquee', 'anchor', *args) + self + end + end + + def marquee_coords(*args) + if args.empty? + list(tk_send('marquee', 'coords')) + else + tk_send('marquee', 'coords', *args) + self + end + end + + def marquee_corner(*args) + if args.empty? + tk_send('marquee', 'corner') + else + tk_send('marquee', 'corner', *args) + self + end + end + + def marquee_identify() + list(tk_send('marquee', 'identify')) + end + + def marquee_visible(st=None) + if st == None + bool(tk_send('marquee', 'visible')) + else + tk_send('marquee', 'visible', st) + self + end + end + def marquee_visible?() + marquee_visible() + end + + def notify_bind(obj, event, cmd=Proc.new, args=nil) + _bind([@path, 'notify', 'bind', obj], event, cmd, args) + self + end + + def notify_bind_append(obj, event, cmd=Proc.new, args=nil) + _bind([@path, 'notify', 'bind', obj], event, cmd, args) + self + end + + def notify_bindinfo(obj, event=nil) + _bindinfo([@path, 'notify', 'bind', obj], event) + end + + def notify_detailnames(event) + list(tk_send('notify', 'detailnames', event)) + end + + def notify_eventnames() + list(tk_send('notify', 'eventnames')) + end + + def notify_generate(pattern, char_map=None) + tk_send('notify', 'generate', pattern, char_map) + self + end + + def notify_install_detail(event, detail, percents_cmd=nil, &b) + percents_cmd = Proc.new(&b) if !percents_cmd && b + if percents_cmd + tk_send('notify', 'install', 'detail', event, detail, percents_cmd) + else + tk_send('notify', 'install', 'detail', event, detail) + end + end + + def notify_install_event(event, percents_cmd=nil, &b) + percents_cmd = Proc.new(&b) if !percents_cmd && b + if percents_cmd + tk_send('notify', 'install', 'event', event, percents_cmd) + else + tk_send('notify', 'install', 'event', event) + end + end + + def notify_linkage(event, detail=None) + tk_send('notify', 'linkage', event, detail) + end + + def notify_uninstall_detail(event, detail) + tk_send('notify', 'uninstall', 'detail', event, detail) + self + end + + def notify_uninstall_event(event) + tk_send('notify', 'uninstall', 'event', event) + self + end + + def numcolumns() + num_or_str(tk_send('numcolumns')) + end + + def numitems() + num_or_str(tk_send('numitems')) + end + + def orphans() + list(tk_send('orphans')) + end + + def range(first, last) + list(tk_send('range', first, last)) + end + + def state_define(name) + tk_send('state', 'define', name) + self + end + + def state_linkage(name) + tk_send('state', 'linkage', name) + end + + def state_names() + list(tk_send('state', 'names')) + end + + def state_undefine(*names) + tk_send('state', 'undefine', *names) + self + end + + def see(item) + tk_send('see', item) + self + end + + def selection_add(first, last=None) + tk_send('selection', 'add', first, last) + self + end + + def selection_anchor(item=None) + num_or_str(tk_send('selection', 'anchor', item)) + end + + def selection_clear(*args) # first, last + tk_send('selection', 'clear' *args) + self + end + + def selection_count() + number(tk_send('selection', 'count')) + end + + def selection_get() + list(tk_send('selection', 'get')) + end + + def selection_includes(item) + bool(tk_send('selection', 'includes', item)) + end + + def selection_modify(sel, desel) + tk_send('selection', 'modify', sel, desel) + self + end + + def style_create(style, keys=None) + if keys && keys != None + tk_send('style', 'create', style, *hash_kv(keys)) + else + tk_send('style', 'create', style) + end + end + + def style_delete(*args) + tk_send('style', 'delete', *args) + self + end + + def style_elements(style, *elems) + if elems.empty? + list(tk_send('style', 'elements', style)) + else + tk_send('style', 'elements', style, elems.flatten) + self + end + end + + def style_layout(style, elem, keys=None) + if keys && keys != None + if keys.kind_of?(Hash) + tk_send('style', 'layout', style, elem, *hash_kv(keys)) + self + else + tk_send('style', 'layout', style, elem, "-#{keys}") + end + else + list(tk_send('style', 'layout', style, elem)) + end + end + + def style_names() + list(tk_send('style', 'names')) + end + + def toggle(*items) + tk_send('toggle', *items) + self + end + + def toggle_recurse() + tk_send('toggle', '-recurse', *items) + self + end +end diff --git a/ext/tk/lib/tkextlib/vu.rb b/ext/tk/lib/tkextlib/vu.rb new file mode 100644 index 0000000000..923b67ce4e --- /dev/null +++ b/ext/tk/lib/tkextlib/vu.rb @@ -0,0 +1,40 @@ +# +# The vu widget set support +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +require 'tk' + +# call setup script for general 'tkextlib' libraries +require 'tkextlib/setup.rb' + +# library directory +dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + +# call setup script +require File.join(dir, 'setup.rb') + +# load package +# TkPackage.require('vu', '2.1') +#TkPackage.require('vu') + +# autoload +module Tk + module Vu + # load package + # VERSION = TkPackage.require('vu', '2.1') + VERSION = TkPackage.require('vu') + + dir = File.expand_path(__FILE__).sub(/#{File.extname(__FILE__)}$/, '') + + autoload :Dial, File.join(dir, 'dial') + + autoload :Pie, File.join(dir, 'pie') + autoload :PieSlice, File.join(dir, 'pie') + autoload :NamedPieSlice, File.join(dir, 'pie') + + autoload :Spinbox, File.join(dir, 'spinbox') + + autoload :Bargraph, File.join(dir, 'bargraph') + end +end diff --git a/ext/tk/lib/tkextlib/vu/bargraph.rb b/ext/tk/lib/tkextlib/vu/bargraph.rb new file mode 100644 index 0000000000..1dbd49db28 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/bargraph.rb @@ -0,0 +1,50 @@ +# +# ::vu::bargraph widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# create module/class +module Tk + module Vu + class Bargraph < TkWindow + end + end +end + +# call setup script -- /tkextlib/vu.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +class Tk::Vu::Bargraph < TkWindow + TkCommandNames = ['::vu::bargraph'.freeze].freeze + WidgetClassName = 'Bargraph'.freeze + WidgetClassNames[WidgetClassName] = self + + ############################### + + def __boolval_optkeys + ['showminmax', 'showvalue'] + end + private :__boolval_optkeys + + def __listval_optkeys + ['alabels', 'blabels'] + end + private :__listval_optkeys + + def __font_optkeys + ['alabfont', 'blabfont'] + end + private :__font_optkeys + + ############################### + + def set(val = None) + tk_call_without_enc(@path, 'set', val) + self + end + + def get() + num_or_str(tk_call_without_enc(@path, 'get')) + end +end diff --git a/ext/tk/lib/tkextlib/vu/charts.rb b/ext/tk/lib/tkextlib/vu/charts.rb new file mode 100644 index 0000000000..bf2a3075bd --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/charts.rb @@ -0,0 +1,47 @@ +# +# charts -- Create and manipulate canvas Add-On Items +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' +require 'tk/canvas' + +# call setup script -- /tkextlib/vu.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +module Tk + module Vu + module ChartsConfig + include TkItemConfigOptkeys + def __item_boolval_optkeys(id) + super(id) << 'lefttrunc' << 'autocolor' + end + private :__item_boolval_optkeys + + def __item_listval_optkeys(id) + super(id) << 'values' << 'tags' + end + private :__item_listval_optkeys + end + + class TkcSticker < TkcItem + include ChartsConfig + + CItemTypeName = 'sticker'.freeze + CItemTypeToClass[CItemTypeName] = self + end + + class TkcStripchart < TkcItem + include ChartsConfig + + CItemTypeName = 'stripchart'.freeze + CItemTypeToClass[CItemTypeName] = self + end + + class TkcBarchart < TkcItem + include ChartsConfig + + CItemTypeName = 'barchart'.freeze + CItemTypeToClass[CItemTypeName] = self + end + end +end diff --git a/ext/tk/lib/tkextlib/vu/dial.rb b/ext/tk/lib/tkextlib/vu/dial.rb new file mode 100644 index 0000000000..4d5770a320 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/dial.rb @@ -0,0 +1,102 @@ +# +# ::vu::dial widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +require 'tk' + +# create module/class +module Tk + module Vu + class Dial < TkWindow + end + end +end + +# call setup script -- /tkextlib/vu.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +# define module/class +class Tk::Vu::Dial < TkWindow + TkCommandNames = ['::vu::dial'.freeze].freeze + WidgetClassName = 'Dial'.freeze + WidgetClassNames[WidgetClassName] = self + + ############################### + + def __methodcall_optkeys # { key=>method, ... } + {'coords'=>'coords'} + end + private :__methodcall_optkeys + + ############################### + + def coords(val = nil) + if val + tk_split_list(tk_send_without_enc('coords')) + else + tk_send_without_enc('coords', val) + self + end + end + + def constrain(val = None) + num_or_str(tk_call(@path, 'constrain', val)) + end + + def get(*args) + num_or_str(tk_call(@path, 'get', *args)) + end + + def identify(x, y) + tk_call(@path, 'identify', x, y) + end + + def get_label(val=nil) + if val + tk_call(@path, 'label', val) + else + ret = [] + lst = simplelist(tk_call(@path, 'label')) + while lst.size > 0 + ret << ([num_or_str(lst.shift)] << lst.shift) + end + end + end + + def set_label(val, str, *args) + tk_call(@path, 'label', val, str, *args) + self + end + + def set_label_constrain(val, str, *args) + tk_call(@path, 'label', '-constrain', val, str, *args) + self + end + + def get_tag(val=nil) + if val + tk_call(@path, 'tag', val) + else + ret = [] + lst = simplelist(tk_call(@path, 'tag')) + while lst.size > 0 + ret << ([num_or_str(lst.shift)] << lst.shift) + end + end + end + + def set_tag(val, str, *args) + tk_call(@path, 'tag', val, str, *args) + self + end + + def set_tag_constrain(val, str, *args) + tk_call(@path, 'tag', '-constrain', val, str, *args) + self + end + + def set(val = None) + tk_call_without_enc(@path, 'set', val) + self + end +end diff --git a/ext/tk/lib/tkextlib/vu/pie.rb b/ext/tk/lib/tkextlib/vu/pie.rb new file mode 100644 index 0000000000..833039c9f2 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/pie.rb @@ -0,0 +1,229 @@ +# +# ::vu::pie widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# + +# create module/class +module Tk + module Vu + module PieSliceConfigMethod + end + class Pie < TkWindow + end + class PieSlice < TkObject + end + class NamedPieSlice < PieSlice + end + end +end + +# call setup script -- /tkextlib/vu.rb +require(File.dirname(File.expand_path(__FILE__)) + '.rb') + +module Tk::Vu::PieSliceConfigMethod + include TkItemConfigMethod + + def __item_pathname(tagOrId) + if tagOrId.kind_of?(Tk::Vu::PieSlice) + self.path + ';' + tagOrId.id.to_s + else + self.path + ';' + tagOrId.to_s + end + end + private :__item_pathname +end + +class Tk::Vu::Pie < TkWindow + TkCommandNames = ['::vu::pie'.freeze].freeze + WidgetClassName = 'Pie'.freeze + WidgetClassNames[WidgetClassName] = self + + ############################### + + include Tk::Vu::PieSliceConfigMethod + + def tagid(tag) + if tag.kind_of?(Tk::Vu::PieSlice) + tag.id + else + tag + end + end + + ############################### + + def delete(*glob_pats) + tk_call(@path, 'delete', *glob_pats) + self + end + + def explode(slice, *args) + tk_call(@path, 'explode', slice, *args) + self + end + + def explode_value(slice) + num_or_str(tk_call(@path, 'explode', slice)) + end + + def lower(slice, below=None) + tk_call(@path, 'lower', slice, below) + self + end + + def names(*glob_pats) + simplelist(tk_call(@path, 'names', *glob_pats)) + end + alias slices names + + def order(*args) + tk_call(@path, 'order', *args) + self + end + + def raise(slice, above=None) + tk_call(@path, 'raise', slice, above) + self + end + + def swap(slice1, slice2) + tk_call(@path, 'swap', slice1, slice2) + self + end + + def set(slice, *args) + num_or_str(tk_call(@path, 'set', slice, *args)) + end + alias set_value set + alias set_values set + alias create set + + def slice_value(slice) + num_or_str(tk_call(@path, 'set', slice)) + end + + def value(val = None) + num_or_str(tk_call_without_enc(@path, 'value')) + end + alias sum_value value +end + +class Tk::Vu::PieSlice + SliceID_TBL = TkCore::INTERP.create_table + Pie_Slice_ID = ['vu_pie'.freeze, '00000'.taint].freeze + TkCore::INTERP.init_ip_env{ SliceID_TBL.clear } + + def self.id2obj(pie, id) + pie_path = pie.path + return id unless SliceID_TBL[pie_path] + SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id + end + + def initialize(parent, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArguemntError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_) + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + Pie_Slice_ID[1].succ! + + if args[-1].kind_of?(Hash) + keys = args.unshift + end + @pie.set(@id, *args) + configure(keys) + end + + def id + @id + end + + def [](key) + cget key + end + + def []=(key,val) + configure key, val + val + end + + def cget(slot) + @pie.itemcget(@id, slot) + end + + def configure(*args) + @pie.itemconfigure(@id, *args) + self + end + + def configinfo(*args) + @pie.itemconfiginfo(@id, *args) + end + + def current_configinfo(*args) + @pie.current_itemconfiginfo(@id, *args) + end + + def delete + @pie.delete(@id) + end + + def explode(value) + @pie.explode(@id, value) + self + end + + def explode_value + @pie.explode_value(@id) + end + + def lower(other=None) + @pie.lower(@id, other) + self + end + + def raise(other=None) + @pie.raise(@id, other) + self + end + + def set(value) + @pie.set(@id, value) + self + end + alias set_value set + + def value + @pie.set(@id) + end +end + +class Tk::Vu::NamedPieSlice + def self.new(parent, name, *args) + if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name] + return SliceID_TBL[parent.path][name] + else + super(parent, name, *args) + end + end + + def initialize(parent, name, *args) + unless parent.kind_of?(Tk::Vu::Pie) + fail ArguemntError, "expect a Tk::Vu::Pie instance for 1st argument" + end + @parent = @pie = parent + @ppath = parent.path + @path = @id = name.to_s + SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath] + SliceID_TBL[@ppath][@id] = self + + if args[-1].kind_of?(Hash) + keys = args.unshift + end + @pie.set(@id, *args) + configure(keys) + end +end diff --git a/ext/tk/lib/tkextlib/vu/setup.rb b/ext/tk/lib/tkextlib/vu/setup.rb new file mode 100644 index 0000000000..ce0f0bd4d4 --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/setup.rb @@ -0,0 +1,8 @@ +# +# setup.rb -- setup script before calling TkPackage.require() +# +# If you need some setup operations (for example, add a library path +# to the library search path) before using Tcl/Tk library packages +# wrapped by Ruby scripts in this directory, please write the setup +# operations in this file. +# diff --git a/ext/tk/lib/tkextlib/vu/spinbox.rb b/ext/tk/lib/tkextlib/vu/spinbox.rb new file mode 100644 index 0000000000..db2743613c --- /dev/null +++ b/ext/tk/lib/tkextlib/vu/spinbox.rb @@ -0,0 +1,17 @@ +# +# ::vu::spinbox widget +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# a standard spinbox (<= 8.3) +# This is the same as the 8.4 core spinbox widget. +# + +if (Tk::TK_MAJOR_VERSION < 8 || + (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION < 4)) + # call setup script -- /tkextlib/vu.rb + require(File.dirname(File.expand_path(__FILE__)) + '.rb') + + Tk.tk_call('namespace', 'import', '::vu::spinbox') +end + +Tk::Vu::Spinbox = TkSpinbox diff --git a/ext/tk/sample/demos-en/paned2.rb b/ext/tk/sample/demos-en/paned2.rb index c8c5abb470..53c19c0ffa 100644 --- a/ext/tk/sample/demos-en/paned2.rb +++ b/ext/tk/sample/demos-en/paned2.rb @@ -75,7 +75,7 @@ TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f| } }, - TkFrame.new(f) {|paned2_bottom| + TkFrame.new(f, :height=>120) {|paned2_bottom| # The bottom window is a text widget with scrollbar paned2_xscr = TkScrollbar.new(paned2_bottom) paned2_yscr = TkScrollbar.new(paned2_bottom) diff --git a/ext/tk/sample/demos-jp/entry3.rb b/ext/tk/sample/demos-jp/entry3.rb index f0e9bc868b..4dff97a93a 100644 --- a/ext/tk/sample/demos-jp/entry3.rb +++ b/ext/tk/sample/demos-jp/entry3.rb @@ -64,7 +64,7 @@ TkFrame.new($entry3_demo){|f| # count - Counter to control the number of times flashed def focusAndFlash(widget, fg, bg, count=5) return if count <= 0 - TkTimer.new(200, count, + TkTimer.new(100, count, proc{widget.configure(:foreground=>bg, :background=>fg)}, proc{widget.configure(:foreground=>fg, :background=>bg)} ).start diff --git a/ext/tk/sample/demos-jp/menu8x.rb b/ext/tk/sample/demos-jp/menu8x.rb index 08598f88f8..e2f477da8b 100644 --- a/ext/tk/sample/demos-jp/menu8x.rb +++ b/ext/tk/sample/demos-jp/menu8x.rb @@ -173,7 +173,8 @@ TkMenu.new($menu8x_demo, 'tearoff'=>false) {|m| TkMenu.new(m, 'tearoff'=>false) {|icon_menu| m.add('cascade', 'label'=>'Icons', 'menu'=>icon_menu, 'underline'=>0) add('command', - 'bitmap'=>'@'+[$demo_dir,'images','pattern.bmp'].join(File::Separator), + 'bitmap'=>'@'+[$demo_dir,'..', + 'images','pattern.xbm'].join(File::Separator), 'hidemargin'=>1, 'command'=>proc{TkDialog.new('title'=>'Bitmap Menu Entry', 'text'=>'今あなたが選択したメニューの項目はテキストではなくビットマップを表示していました。それ以外の点では他のメニュー項目と変わりません。', diff --git a/ext/tk/sample/demos-jp/paned2.rb b/ext/tk/sample/demos-jp/paned2.rb index b0261d50f0..c6b0f06914 100644 --- a/ext/tk/sample/demos-jp/paned2.rb +++ b/ext/tk/sample/demos-jp/paned2.rb @@ -78,7 +78,7 @@ TkPanedwindow.new($paned2_demo, :orient=>:vertical){|f| } }, - TkFrame.new(f) {|paned2_bottom| + TkFrame.new(f, :height=>120) {|paned2_bottom| # The bottom window is a text widget with scrollbar paned2_xscr = TkScrollbar.new(paned2_bottom) paned2_yscr = TkScrollbar.new(paned2_bottom) diff --git a/ext/tk/sample/optobj_sample.rb b/ext/tk/sample/optobj_sample.rb new file mode 100644 index 0000000000..b7bab06324 --- /dev/null +++ b/ext/tk/sample/optobj_sample.rb @@ -0,0 +1,67 @@ +#!/usr/bin/env ruby +# +# sample script of Tk::OptionObj +# +require "tk" + +optobj = Tk::OptionObj.new('foreground'=>'red', 'background'=>'black') + +f = TkFrame.new.pack(:side=>:left, :anchor=>:n, :padx=>5, :pady=>30) + +b1 = TkButton.new(f, :text=>'AAA').pack(:fill=>:x) +b2 = TkButton.new(f, :text=>'BBB').pack(:fill=>:x) +b3 = TkButton.new(f, :text=>'CCC').pack(:fill=>:x) + +optobj.assign( b1, + [ b2, 'configure', + { 'foreground'=>'background', + 'background'=>'foreground' } ], + [ b3, nil, + { 'foreground'=>'background', + 'activeforeground'=>nil, + 'background'=>['foreground', 'activeforeground'] } ] ) + +optobj.update('activeforeground'=>'yellow') + +TkButton.new(f){ + configure( optobj.assign(self) + {:text=>'DDD'} ) + pack(:fill=>:x) +} + +TkButton.new(f){ + configure( optobj.assign([self, nil, + {'foreground'=>'activeforeground', + 'background'=>'foreground', + 'activeforeground'=>'background'}]) \ + + {:text=>'EEE', :relief=>:groove, :borderwidth=>5} ) + pack(:fill=>:x) +} + +optobj.notify # To apply the convert_key ( 3rd element of widget info + # (that is, {'foreground'=>'activeforeground', ,,, } ) + # of the 'EEE' button + +TkButton.new(f, :text=>'toggle', + :command=>proc{ + fg = optobj['foreground'] + bg = optobj['background'] + optobj.configure('foreground'=>bg, 'background'=>fg) + }).pack(:fill=>:x, :pady=>10) + +TkButton.new(f, :text=>'exit', + :command=>proc{exit}).pack(:fill=>:x, :pady=>10) + +TkFrame.new{|f| + pack(:side=>:right, :expand=>true, :fill=>:both) + TkLabel.new(f, :text=>'source::').pack(:anchor=>:w) + TkFrame.new(f){|ff| + TkText.new(ff){ + yscrollbar(TkScrollbar.new(ff){pack(:fill=>:y, :side=>:right)}) + insert('end', File.read(__FILE__)) + pack(:side=>:left, :expand=>true, :fill=>:both) + } + pack(:expand=>true, :fill=>:both) + } +} + +Tk.mainloop diff --git a/ext/tk/sample/tkcombobox.rb b/ext/tk/sample/tkcombobox.rb index f0cbdac3ba..61ab254691 100644 --- a/ext/tk/sample/tkcombobox.rb +++ b/ext/tk/sample/tkcombobox.rb @@ -62,6 +62,9 @@ EOD delegate('relief', @frame) delegate('borderwidth', @frame) + delegate_alias('arrowrelief', 'relief', @up_arrow, @down_arrow) + delegate_alias('arrowborderwidth', 'borderwidth', @up_arrow, @down_arrow) + scrollbar(keys.delete('scrollbar')){false} configure keys unless keys.empty? @@ -324,6 +327,9 @@ EOD delegate('relief', @frame) delegate('borderwidth', @frame) + delegate('arrowrelief', @lst) + delegate('arrowborderwidth', @lst) + if mode = keys.delete('scrollbar') scrollbar(mode) end @@ -391,6 +397,7 @@ end if __FILE__ == $0 v = TkVariable.new e = TkCombobox.new(:height=>7, :scrollbar=>true, :textvariable=>v, + :arrowrelief=>:flat, :arrowborderwidth=>0, :startwait=>400, :interval=>200).pack e.values(%w(aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu)) #e.see(e.list_index('end') - 2) diff --git a/ext/tk/sample/tkextlib/tcllib/datefield.rb b/ext/tk/sample/tkextlib/tcllib/datefield.rb new file mode 100644 index 0000000000..1b0a29c0b9 --- /dev/null +++ b/ext/tk/sample/tkextlib/tcllib/datefield.rb @@ -0,0 +1,29 @@ +#!/usr/bin/ruby + +require 'tk' +require 'tkextlib/tcllib/datefield' +require 'parsedate' + +Tk.root.title('Datefield example') + + +my_date1 = TkVariable.new +my_date2 = TkVariable.new +my_date1.trace('w'){ + begin + t = Time.local(*(ParseDate.parsedate(my_date1.value))) + my_date2.value = t.strftime('%A') + rescue + # ignore error + end +} + +df = Tk::Tcllib::Datefield.new(:textvariable=>my_date1) +Tk.grid(TkLabel.new(:text=>'Enter a date:', :anchor=>:e), df, :sticky=>:ew) +Tk.grid(TkLabel.new(:text=>'That date ia a:', :anchor=>:e), + TkLabel.new(:textvariable=>my_date2, :relief=>:sunken, :width=>12), + :sticky=>:ew) + +df.set_focus + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tcllib/plotdemos1.rb b/ext/tk/sample/tkextlib/tcllib/plotdemos1.rb new file mode 100644 index 0000000000..6077d8ab2c --- /dev/null +++ b/ext/tk/sample/tkextlib/tcllib/plotdemos1.rb @@ -0,0 +1,158 @@ +#!/usr/bin/ruby + +require 'tk' +require 'tkextlib/tcllib/plotchart' + +############################### + +c1 = TkCanvas.new(:background=>'white', :width=>400, :height=>200) +c2 = TkCanvas.new(:background=>'white', :width=>400, :height=>200) +c3 = TkCanvas.new(:background=>'white', :width=>400, :height=>200) +Tk.pack(c1,c2,c3, :fill=>:both, :side=>:top) + +h = TkToplevel.new(:title=>'h') +hc1 = TkCanvas.new(h, :background=>'white', :width=>400, :height=>200) +hc2 = TkCanvas.new(h, :background=>'white', :width=>400, :height=>200) +Tk.pack(hc1,hc2, :fill=>:both, :side=>:top) + +v = TkToplevel.new(:title=>'v') +vc1 = TkCanvas.new(v, :background=>'white', :width=>400, :height=>200) +vc2 = TkCanvas.new(v, :background=>'white', :width=>400, :height=>200) +vc3 = TkCanvas.new(v, :background=>'white', :width=>400, :height=>200) +Tk.pack(vc1,vc2,vc3, :fill=>:both, :side=>:top) + +############################### + +s = Tk::Tcllib::Plotchart::XYPlot.new(c1, [0.0, 100.0, 10.0], + [0.0, 100.0, 20.0]) + + +xd = 5.0 +yd = 20.0 +xold = 0.0 +yold = 50.0 + +s.dataconfig('series1', :color=>'red') + +(0..19).each{|i| + xnew = xold + xd + ynew = yold + (rand() - 0.5) * yd + ynew2 = yold + (rand() - 0.5) * 2.0 * yd + s.plot('series1', xnew, ynew) + s.plot('series2', xnew, ynew2) + xold = xnew + yold = ynew +} + +s.xtext "X-coordinate" +s.ytext "Y-data" +s.title "Aha!" + +c1.wait_visibility + +s.save_plot "aha.ps" + +############################### + +s = Tk::Tcllib::Plotchart::Piechart.new(c2) + +s.plot([ ["Long names", 10], ["Short names", 30], + ["Average", 40], ["Ultra-short names", 5] ]) + +# +# Note: title should be shifted up +# - distinguish a separate title area +# +s.title "Okay - this works" + +############################### + +s = Tk::Tcllib::Plotchart::PolarPlot.new(c3, [3.0, 1.0]) + +0.step(359, 10){|angle| + rad = 1.0+Math.cos(angle*Math::PI/180.0) + s.plot('cardioid', rad, angle) +} + +s.title "Cardioid" + +############################### + +s = Tk::Tcllib::Plotchart::Barchart.new(hc1, %w(A B C D E), + [0.0, 10.0, 2.0], 2) + +s.plot('series1', [1.0, 4.0, 6.0, 1.0, 7.0], 'red') +s.plot('series2', [0.0, 3.0, 7.0, 9.3, 2.0], 'green') +s.title "Arbitrary data" + +############################### + +s = Tk::Tcllib::Plotchart::Barchart.new(hc2, %w(A B C D E), + [0.0, 20.0, 5.0], :stacked) + +s.plot('series1', [1.0, 4.0, 6.0, 1.0, 7.0], 'red') +s.plot('series2', [0.0, 3.0, 7.0, 9.3, 2.0], 'green') +s.title "Stacked diagram" + +############################### + +s = Tk::Tcllib::Plotchart::HorizontalBarchart.new(vc1, [0.0, 10.0, 2.0], + %w(A B C D E), 2) + +s.plot('series1', [1.0, 4.0, 6.0, 1.0, 7.0], 'red') +s.plot('series2', [0.0, 3.0, 7.0, 9.3, 2.0], 'green') +s.title "Arbitrary data" + +############################### + +s = Tk::Tcllib::Plotchart::HorizontalBarchart.new(vc2, [0.0, 20.0, 5.0], + %w(A B C D E), :stacked) + +s.plot('series1', [1.0, 4.0, 6.0, 1.0, 7.0], 'red') +s.plot('series2', [0.0, 3.0, 7.0, 9.3, 2.0], 'green') +s.title "Stacked diagram" + +############################### + +s = Tk::Tcllib::Plotchart::Timechart.new(vc3, "1 january 2004", + "31 december 2004", 4) + +s.period("Spring", "1 march 2004", "1 june 2004", 'green') +s.period("Summer", "1 june 2004", "1 september 2004", 'yellow') +s.vertline("1 jan", "1 january 2004") +s.vertline("1 apr", "1 april 2004") +s.vertline("1 jul", "1 july 2004") +s.vertline("1 oct", "1 october 2004") +s.milestone("Longest day", "21 july 2004") +s.title "Seasons (northern hemisphere)" + +############################### + +z = TkToplevel.new(:title=>'3D') + +zc1 = TkCanvas.new(z, :background=>'white', :width=>400, :height=>300) +zc2 = TkCanvas.new(z, :background=>'white', :width=>400, :height=>250) +Tk.pack(zc1,zc2) + +s = Tk::Tcllib::Plotchart::Plot3D.new(zc1, + [0, 10, 3], [-10, 10, 10], [0, 10, 2.5]) + +s.title "3D Plot" +s.plot_function{|x, y| + # cowboyhat + x1 = x.to_f/9.0 + y1 = y.to_f/9.0 + 3.0 * (1.0-(x1*x1+y1*y1))*(1.0-(x1*x1+y1*y1)) +} + +s = Tk::Tcllib::Plotchart::Plot3D.new(zc2, + [0, 10, 3], [-10, 10, 10], [0, 10, 2.5]) +s.title "3D Plot - data " +s.colour("green", "black") +s.plot_data([ [1.0, 2.0, 1.0, 0.0], + [1.1, 3.0, 1.1, -0.5], + [3.0, 1.0, 4.0, 5.0] ]) + +############################### + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tcllib/plotdemos2.rb b/ext/tk/sample/tkextlib/tcllib/plotdemos2.rb new file mode 100644 index 0000000000..3fd57f3804 --- /dev/null +++ b/ext/tk/sample/tkextlib/tcllib/plotdemos2.rb @@ -0,0 +1,71 @@ +#!/usr/bin/ruby + +require 'tk' +require 'tkextlib/tcllib/plotchart' + +############################### + +c1 = TkCanvas.new(:background=>'white', :width=>400, :height=>200) +c2 = TkCanvas.new(:background=>'white', :width=>400, :height=>200) +Tk.pack(c1,c2, :fill=>:both, :side=>:top) + +############################### +# Set up a strip chart +############################### +slipchart = Tk::Tcllib::Plotchart::Stripchart.new(c1, [0.0, 100.0, 10.0], + [0.0, 100.0, 20.0]) + +TkTimer.new(500, -1, proc{|obj| # obj --> TkTimer object + slipchart, xold, xd, yold, yd = obj.return_value + xnew = xold + xd + ynew = yold + (rand() - 0.5) * yd + ynew2 = yold + (rand() - 0.5) * 2.0 * yd + slipchart.plot('series1', xnew, ynew) + slipchart.plot('series2', xnew, ynew2) + obj.stop if xnew >= 200 + [slipchart, xnew, xd, ynew, yd] # return_value + }).start(100, proc{ + # init return_value + [slipchart, 0.0, 15.0, 50.0, 30.0] + }) + +slipchart.title "Aha!" + +############################### +# Set up an isometric plot +############################### +s = Tk::Tcllib::Plotchart::IsometricPlot.new(c2, [0.0, 100.0], [0.0, 200.0], + :noaxes) + +s.set_zoom_pan + +s.plot('rectangle', [10.0, 10.0, 50.0, 50.0], 'green') +s.plot('filled-rectangle', [20.0, 20.0, 40.0, 40.0], 'red') +s.plot('filled-circle', [70.0, 70.0, 40.0], 'yellow') +s.plot('circle', [70.0, 70.0, 42.0]) + +############################### +# Check the symbols +############################### +h = TkToplevel.new(:title=>'h') +c = TkCanvas.new(h, :bg=>'white', :width=>400, :height=>200).pack(:fill=>:both) + +s = Tk::Tcllib::Plotchart::XYPlot.new(c, [0.0, 100.0, 10.0], + [0.0, 100.0, 20.0]) +s.dataconfig('series1', :colour=>'red', :type=>:symbol) +s.dataconfig('series2', :colour=>'green', :type=>:both) + +s.yconfig(:format=>"%12.2e") + +x = 5.0 +%w(plus cross circle up down dot upfilled downfilled).each{|sym| + s.dataconfig('series1', :symbol=>sym) + s.dataconfig('series2', :symbol=>sym) + s.plot('series1', x, 50.0) + s.plot('series2', x, 20) + x += 10 +} + +############################## + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tcllib/plotdemos3.rb b/ext/tk/sample/tkextlib/tcllib/plotdemos3.rb new file mode 100644 index 0000000000..3b74b1f592 --- /dev/null +++ b/ext/tk/sample/tkextlib/tcllib/plotdemos3.rb @@ -0,0 +1,83 @@ +#!/usr/bin/ruby + +require 'tk' +require 'tkextlib/tcllib/plotchart' + +############################### +# Set up a strip chart +############################### + +Tk::Tcllib::Plotchart::Stripchart.new([0.0, 100.0, 10.0], + [0.0, 100.0, 20.0], + :background=>'white', + :width=>400, :height=>200){|chart| + title "Aha!" + pack(:fill=>:both, :side=>:top) + + series1 = Tk::Tcllib::Plotchart::PlotSeries.new(chart) + series2 = Tk::Tcllib::Plotchart::PlotSeries.new(chart) + + xd = 15.0 + yd = 30.0 + + TkTimer.new(500, -1, proc{|obj| # obj --> TkTimer object + xold, yold = obj.return_value + xnew = xold + xd + ynew = yold + (rand() - 0.5) * yd + ynew2 = yold + (rand() - 0.5) * 2.0 * yd + + series1.plot(xnew, ynew) + series2.plot(xnew, ynew2) + + obj.stop if xnew >= 200 + + [xnew, ynew] # return_value + }).start(100, proc{ [0.0, 50.0] }) # init return_value +} + +############################### +# Set up an isometric plot +############################### +Tk::Tcllib::Plotchart::IsometricPlot.new([0.0, 100.0], [0.0, 200.0], :noaxes, + :background=>'white', + :width=>400, :height=>200){|chart| + pack(:fill=>:both, :side=>:top) + set_zoom_pan + + chart.plot('rectangle', [10.0, 10.0, 50.0, 50.0], 'green') + chart.plot('filled-rectangle', [20.0, 20.0, 40.0, 40.0], 'red') + chart.plot('filled-circle', [70.0, 70.0, 40.0], 'yellow') + chart.plot('circle', [70.0, 70.0, 42.0]) +} + +############################### +# Check the symbols +############################### +TkToplevel.new(:title=>'h'){|h| + Tk::Tcllib::Plotchart::XYPlot.new(h, [0.0, 100.0, 10.0], + [0.0, 100.0, 20.0], + :bg=>'white', + :width=>400, :height=>200){|chart| + pack(:fill=>:both) + + yconfig(:format=>"%12.2e") + + series1 = Tk::Tcllib::Plotchart::PlotSeries.new(chart, :colour=>'red', + :type=>:symbol) + series2 = Tk::Tcllib::Plotchart::PlotSeries.new(chart, :colour=>'green', + :type=>:both) + + x = 5.0 + %w(plus cross circle up down dot upfilled downfilled).each{|sym| + series1.dataconfig(:symbol=>sym) + series2.dataconfig(:symbol=>sym) + series1.plot(x, 50.0) + series2.plot(x, 20) + x += 10 + } + } +} + +############################## + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tcllib/xyplot.rb b/ext/tk/sample/tkextlib/tcllib/xyplot.rb new file mode 100644 index 0000000000..116609e34f --- /dev/null +++ b/ext/tk/sample/tkextlib/tcllib/xyplot.rb @@ -0,0 +1,17 @@ +#!/usr/bin/ruby + +require 'tk' +require 'tkextlib/tcllib/plotchart' + +TkCanvas.new(:background=>'white', :width=>400, :height=>200){|c| + pack(:fill=>:both) + Tk::Tcllib::Plotchart::XYPlot.new(c, [0.0, 100.0, 10.0], + [0.0, 100.0, 20.0]){ + [ [0.0, 32.0], [10.0, 50.0], [25.0, 60.0], [78.0, 11.0] ].each{|x, y| + plot('series1', x, y) + } + title("Data series") + } +} + +Tk.mainloop diff --git a/ext/tk/sample/tkextlib/tkHTML/README b/ext/tk/sample/tkextlib/tkHTML/README new file mode 100644 index 0000000000..1208e270b4 --- /dev/null +++ b/ext/tk/sample/tkextlib/tkHTML/README @@ -0,0 +1,12 @@ + + [ TkHtml widget example ] + +The directory page1 -- page4 are referd from "test" directory of +original TkHtml extension's source archive. +( see http://www.hwaci.com/sw/tkhtml/index.html ) + +You can see the HTML documents on the 'hv.rb' or 'ss.rb' sample script. + + e.g. + LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH /usr/local/bin/ruby ./hv.rb page1/index.html + diff --git a/ext/tk/sample/tkextlib/tkHTML/hv.rb b/ext/tk/sample/tkextlib/tkHTML/hv.rb new file mode 100644 index 0000000000..cf93ad3ba5 --- /dev/null +++ b/ext/tk/sample/tkextlib/tkHTML/hv.rb @@ -0,0 +1,306 @@ +#!/usr/bin/env ruby +# +# This script implements the "hv" application. Type "hv FILE" to +# view FILE as HTML. +# +# This application is used for testing the HTML widget. It can +# also server as an example of how to use the HTML widget. +# +require 'tk' +require 'tkextlib/tkHTML' + +root = TkRoot.new(:title=>'HTML File Viewer', :iconname=>'HV') + +file = ARGV[0] + +# +# These images are used in place of GIFs or of form elements +# +biggray = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhPAA+APAAALi4uAAAACwAAAAAPAA+AAACQISPqcvtD6OctNqLs968+w+G4kiW5omm + 6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNFgsAO/// +EOD + +smgray = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhOAAYAPAAALi4uAAAACwAAAAAOAAYAAACI4SPqcvtD6OctNqLs968+w+G4kiW5omm + 6sq27gvH8kzX9m0VADv/ +EOD + +nogifbig = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhJAAkAPEAAACQkADQ0PgAAAAAACwAAAAAJAAkAAACmISPqcsQD6OcdJqKM71PeK15 + AsSJH0iZY1CqqKSurfsGsex08XuTuU7L9HywHWZILAaVJssvgoREk5PolFo1XrHZ29IZ8oo0 + HKEYVDYbyc/jFhz2otvdcyZdF68qeKh2DZd3AtS0QWcDSDgWKJXY+MXS9qY4+JA2+Vho+YPp + FzSjiTIEWslDQ1rDhPOY2sXVOgeb2kBbu1AAADv/ +EOD + +nogifsm = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhEAAQAPEAAACQkADQ0PgAAAAAACwAAAAAEAAQAAACNISPacHtD4IQz80QJ60as25d + 3idKZdR0IIOm2ta0Lhw/Lz2S1JqvK8ozbTKlEIVYceWSjwIAO/// +EOD + +# +# define variables +# +ul_hyper = TkVariable.new(0) +show_tbl = TkVariable.new(0) +show_img = TkVariable.new(1) + +# +# A font chooser routine. +# +# html[:fontcommand] = pick_font +pick_font = proc{|size, attrs| + puts "FontCmd: #{size} #{attrs}" + [ ((attrs =~ /fixed/)? 'courier': 'charter'), + (12 * (1.2**(size.to_f - 4.0))).to_i, + ((attrs =~ /italic/)? 'italic': 'roman'), + ((attrs =~ /bold/)? 'bold': 'normal') ].join(' ') +} + +# +# This routine is called for each form element +# +form_cmd = proc{|n, cmd, style, *args| + # puts "FormCmd: $n $cmd $args" + case cmd + when 'select', 'textarea', 'input' + TkLabel.new(:widgetname=>args[0], :image=>nogifsm) + end +} + +# +# This routine is called for every markup +# +images = {} +old_imgs = {} +big_imgs = {} + +hotkey = {} + +move_big_image = proc{|b| + return unless big_imgs.key?(b) + b.copy(big_imgs[b]) + big_imgs[b].delete + big_imgs.delete(b) + Tk.update +} + +image_cmd = proc{|*args| + return smgray unless show_img.bool + fn = args[0] + if old_imgs.key?(fn) + images[fn] = old_imgs[fn] + old_imgs.delete(fn) + return images[fn] + end + + begin + img = TkPhotoImage.new(:file=>fn) + rescue + return smgray + end + + if img.width * img.height > 20000 + b = TkPhotoImage.new(:width=>img.width, :height=>img.height) + big_imgs[b] = img + img = b + Tk.after_idle(proc{ move_big_image.call(b) }) + end + + images[fn] = img + + img +} + +# +# This routine is called for every +

+ + + + + + + + + +
Welcome to SlashdotLinuxNewsUnited StatesEducationSpace
+ + + +
faq
code
awards
privacy
slashNET
older stuff
rob's page
preferences
andover.net
submit story
advertising
supporters
past polls
topics
about
jobs
hof + +
+

+ + + +
Sections
+1/23
+apache
+1/29 (3)
+askslashdot
+1/27
+awards
+1/29 (2)
+books
+1/27
+bsd
+1/28 (2)
+features
+1/28 (2)
+interviews
+1/19
+radio
+1/27 (2)
+science
+1/28 (3)
+yro
Andover.Net
+AndoverNews
Ask Reggie
DaveCentral
FreeCode
MediaBuilder

+

+
Who Bought Linux.Net?
Linux Posted by CmdrTaco on Saturday January 29, @10:52AM
from the this-game-again dept.
So Fred VanKampen (who has to hold the record for most money made by reselling two domain names) e-mailed us to say that the Domain Name for 'Linux.Net' has been sold. He won't say to whom, but it supposedly will be announced at LinuxWorld next week. Of course we have no idea what he got for the entry, but the rumors were that he made several million when he sold Linux.com to VA Linux. Hopefully he'll take me for a ride in his yacht. ;)

( Read More... | 58 of 62 comments )

Book Reviews: E-Mails from (Over?) The Edge
News Posted by Hemos on Saturday January 29, @10:43AM
from the touching-story dept.
I'd like to thank the author of this book for sending it to me. Nick's written a book that's touching and endearing, and one that's well worth reading for everyone who's ever had social struggles to deal with. As well, his involvement with the fine folks of TheVenue. I'll warn you - it's not a tech text. But it's still worth reading. Click below to read more.

( Read More... | 6197 bytes in body | 6 of 22 comments )

Linux Kernel 2.3.41
Linux Posted by CmdrTaco on Saturday January 29, @10:21AM
from the download-compile-reboot-repeat dept.
sdriver writes "For those of us who enjoy *panic*, *oops*, and suddenly seeing their video BIOS... the newest version is out! Be the first on your block to submit a new patch! ;) " If you don't know where to get it, you probably should stick to your warm and cuddly 2.2.x kernel *grin*. Now outta my way, I wanna crash my laptop!

( Read More... | 52 of 57 comments )

Congress Still Figuring Out E-Mail
United States Posted by Roblimo on Saturday January 29, @07:28AM
from the voice-of-the-people-can-get-awfully-loud dept.
Jett writes " Vote.com has an interesting article in their Webmag Fifth Estate about how congressmen have responded to the popularity of e-mail in their daily operations. Quote: 'Of the 440 voting and non-voting House of Representatives members, 22 have no e-mail at all. Even House Speaker Dennis Hastert is wired only halfway -- his office receives e-mail, but does not respond to it. And while all U.S. senators have e-mail, they, like their House counterparts, routinely shun non-constituent mail -- even though they chair committees whose decisions affect the entire country.'"

( Read More... | 66 of 66 comments )

Ask Slashdot: Sci Fi Literature 101?
Education Posted by Cliff on Saturday January 29, @06:56AM
from the recommendations-wanted dept.
ohlaadee asks: "My niece (she's 13) wants to start reading science fiction. I do too. I gave us both Asimov's _The Foundation_  for Christmas. We'll read it together. I suppose we could spend the rest of our lives just reading Asimov, but I'm wondering what books and movies you folks would come up with? What does the /. recommended Science Fiction 101 list include?"

( Read More... | 345 of 345 comments )

Could Distributed.Net Help the Mars Polar Lander?
Space Posted by Roblimo on Saturday January 29, @03:35AM
from the food-for-thought dept.
Anonymous Coward writes "This official JPL press release describes the current attempt to listen for faint signals from the Mars Lander. They get three windows a day, and it takes 18 hours to process data because the signal is so weak (if it's really there). Too bad they don't have a deal with distributed.net." Interesting thought. Is anyone at distributed.net or JPL interested in pursuing it?

( Read More... | 99 of 102 comments )

iCrave TV Loses Battle against U.S. Broadcasters
Television Posted by Roblimo on Saturday January 29, @12:21AM
from the shut-down-just-before-the-super-bowl dept.
Doran writes "C|Net has this story about how the Canadian company iCraveTV.com has lost its latest battle in U.S. courts over whether it can rebroadcast TV signals over the Web. The broadcasters say it's theft, while iCraveTV sez it's just doing what's legal for other cable TV companies in Canada (ie. rebroadcasting TV). Of course, by framing the streaming video iCraveTV is doing more than just rebroadcasting, they're also adding more commercial content, which the broadcasters feel dilutes their TV commercials. "

( Read More... | 152 of 170 comments )

Win2k Security holes found
Microsoft Posted by HeUnique on Friday January 28, @04:58PM
from the and-it's-not-even-out-yet dept.
According to a story posted by ZDNN, two security holes have been found on Windows 2000, and that's even before the official release of Windows 2000! Administrators who rush to incorporate the patch from MS beware - according to one of the talkback posts on ZDNN, the patch creates a new problem with Windows 2000 news server service.

( Read More... | 510 of 534 comments )

Encryption Debate at Mitnick Trial
Encryption Posted by Hemos on Friday January 28, @03:33PM
from the gimmie-the-data dept.
A number of people have written about the latest twist in the Mitnick case. Kevin wants to get his data back, but the government is refusing to do so until he gives them the key. Apparently, the government is unable to crack the encryption that he's got on it - you'd think after having the data for five years, they'd be able to brute-force the darn thing. It's a NYT article - free login required.

( Read More... | 504 of 521 comments )

Forum: Future Ports of Games to Linux
Games Posted by CmdrTaco on Friday January 28, @02:26PM
from the it's-been-awhile dept.
It's been a long time since I posted an open forum like this, but I'm curious what people think on this one. What games do you most want to see ported to Linux in the next few months? Of course, for me personally it's StarCraft and Diablo 2, but I'm curious what games have come out or are due soon that people would most like to see a port of (and note that WINE doesn't count. ;)

( Read More... | 648 of 652 comments )

Features
Voting has begun for the $100k Slashdot Beanie Awards. Talk amongst yourselves and choose who deserves the cash.

The latest installment of Geeks in Space is up at The Sync. Listen to CmdrTaco, Hemos, and Nate talk about the latest events to happen - or not happen in the computer world.

Perhaps you are seeking Jon Katz's series of articles related to recent events in Colorado. These articles include Voices from the Hellmouth, More Stories from the Hellmouth or The Price of Being Different,

For something different, try reading a little essay Thoughts from the Furnace about the internet, and flame.

And for a bit of an amusing take on the Open Source world, check out Open Source as an Ant Farm

Update: 01/03 03:10 by CowboyNeal:

Past Features

Ask Slashdot
  • Sci Fi Literature 101?
  • Linux and Satellite Internet Services
  • Open Defensive Patents?
  • Technologies That Shaped the Last Century?
  • Disk Repair Tools for Linux?
  • Why Can't the Command-Line be More Standardized?
  • Packet Radio Networking with PalmOS?
  • Cheap Rackmount Enclosures/Systems?
  • Open Source Software and Tax Breaks?
  • Building an Upgradable Dual Processor System

    if you have a question for Ask Slashdot, send it to askslashdot@slashdot.org

  • Slashdot Login
    Nickname:

    Password:

    Don't have an account yet? Go Create One. A user account will allow you to customize all these nutty little boxes, tailor the stories you see, as well as remember your comment viewing preferences.

    Slashdot Poll
    The Tech Advance I Most Want Is:
    Nanotechnology
    Cold Fusion
    Powerful Fuel Cells
    Hard Wiring my Body
    Universal Strong Crypto
    Interstellar Travel
    Cybernetic Body Armor
    ColecoVision
    [ Results | Polls ]
    Comments:656 | Votes:29121

    Older Stuff

    Friday January 28

  • Abstract Programming and GPL Enforcement (235)
  • Interview: FreeDOS Leader Jim Hall Answers (86)
  • Open Source's Achilles Heel (466)
  • The Virtue of Communal Instincts (237)
  • Gartner Group Debunking Open Source Myths (165)
  • DoubleClick Taken to Court (310)
  • Updated Slash & Server 51 (81)
  • XMMS 1.0.0 Released (128)
  • Linux and Satellite Internet Services (138)
  • UN Wants to Combat Online Racism (531)

    Thursday January 27

  • Crackdowns, Fools and the MPAA (351)
  • Heroes of Might and Magic III Demo Released (157)
  • Sandia Labs Venture Into Nanotechnology (117)
  • CA Announces Program Ports to Linux (195)
  • Interview: Larry Augustin Finally Answers (210)
  • Final Call for Voting in Slashdot's Beanie Awards (178)
  • Transmeta Code Morphing != Just In Time (449)
  • Intrusion Detection (65)
  • Using Enzymes to Help Fight CO2 Build-Up (165)
  • Jon Johansen on ABC World News Tonight (415)


    Older Articles
    Yesterday's Edition

  • Book Reviews

    Jon Katz, Resident Gasbag, has a new, very appropriate book coming out soon, Geeks. Preorder now and receive the book early.

    For probably the best fiction read around, check out Neal Stephenson's Cryptonomicon, an engaging read about WWII, cryptography and buried treasure. And data vaults.

    If you've been doing a lot of work in Perl, you've probably figured out you really need Perl in a Nutshell or The Perl Cookbook. If you're still learning, grab Programming Perl.

    And if you want to learn more about how to become a better coder, grab The Unified Software Development Process or The Practice of Programming Additionally, check out Refactoring: Improving the Design of Existing Code .

    Developing a large application? Grab Eric Greenberg's excellent Network Application Frameworks.

    Visit Our Book Reviews Section for more.
    Update: 11/12 05:19 by H:

    Quick Links
    Cool Sites:
  • Linux.com (What is Linux?)
  • Everything (Blow your Mind)
  • After Y2k (This is Post-Apocalyptic?)
  • User Friendly (Laugh)
  • Themes.org (Make X Perty)

    Support Slashdot:

  • ThinkGeek (Clothe Yourself in Slashdot)
  • CDnow (Support Rob's Who Habit)
  • Slashdot Advertiser Index
  • Freshmeat

    January

  • We should get this out of the door now
  • Is Linux for Crazies?
  • SQN Linux 1.6
  • Limo 0.3.2
  • Fusion GS 1.3
  • MMR 1.5.4
  • KUPS 0.3.4
  • 3DSE patch for XMMS 4
  • Linux 2.3.41
  • Free Code for Linux S/390
    Search Freshmeat:

    More Meat...

  • + + + + + + + + + + +
    +
    + + +
    +
    +
      + Wasn't there something about a PASCAL programmer knowing the value of +everything and the Wirth of nothing? + 
    + + + All trademarks and copyrights on this + page are owned by their respective owners. Comments + are owned by the Poster. + The Rest 1997-2000 Andover.Net. + +
    +

    + + + [ home | + awards | + supporters | + rob's homepage | + contribute story | + older articles | + Andover.Net | + advertising | + past polls | + about | + faq ] + +
    + + diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image1 b/ext/tk/sample/tkextlib/tkHTML/page2/image1 new file mode 100644 index 0000000000000000000000000000000000000000..2ed6ddcfe1ca1e2bc82eca40f3ff95260563bfcd GIT binary patch literal 1966 zcmb`^`&W_)8VB%~i}DwA5IWfm#I zB9&X@Qi~j6kt;1qxkZUkDIHy9RVl41gjLmUZC6>_5!PNu5cXcJwpVM{_S&@wyH;=4 zYwdc3QSa!+6(hoAbQIHy$+%)dte7k-7SoCaVYOIRtO&c+x?#0%*byss`^JhRh>eYn zj}HI4+5c-sB8!k;0M46mfuurOS#?Hswz@`Md#+AVfBu59;bLP`^Q9J5>*XuzwyW2! zx8LaK?CS2h*{kX6AGmdUQ2X7GZg}L*sQ&KQc-uiCCq5+5AEL|zGGf{3xqV*^?&U`Z zLIL#f=vZcScnE_*-x}!S?YT8xaKNBSw=?3|$q8}cft0P$W`Xb~r)}c-l)En!kRwDn zS%brUBF!*5*hS&%A5hMEqaj0#kbt7aMdlB6*zjBOw(RBav7X!LwZjXx^j#S|54kNC zS55Nu-p(|vIZ0<*rf_3)@g?2x$+2(oNIVM4ta{OXD{qp>K8^_6)5gSUp z%ruCx9;qWNKRUhGhcb^xWeE+^crPCYmAqD2U5)jKEPPC2W9rh?ah8RP5GUZO3Sxyy1vcQoO=wpn0Y;EyRT&Ehc3sD-g)_(TUWb$~N z-|dv;Y?sr)A~F7zu(&n(anq2vG?!_p*mt(UaF3w4If!xoiwmO(Ls?e;lPGMqsnG0B z^Bj?onuCMdKSif`C3h<3zX%sG(OxxORBOq;t{fTucVD4#5I<>SuX_+<)BcPmI;D6T zoLeZGAg6zT6&UA$fo&K3RU#<(Hw8?|jvdrB-;)}A$PB@yY4tii_kp_QSe$N^>*Sha zes-~X)J${&L=~$AcCZR{y6w< z!cX)ALfRyOVSF*(qpI(oaOVjPPr7t3x|cMgFJmil0KkO7W)cU*hyv7@PkaHj!TWO= z0HYdNv}LbG2pAve>YUEF6-LVD5vHQu&iW)4a%CRDq8>LCrqgXV3d=&x0hl9XHvp^q zca1LwFi!;KVQD<)ElN=zl{;CKN{LB|$iVO1#Q!ms;LXme0R8YWQ(lSSejc6+UghK6 zh)*jGV221x`+QI>#zmdV%EU|<6*3~$%Pb*tPXaJOVpBExc$1LpC3U6%v{QJ;1$sJBG0;j zt!MqqoA>SCmweX&&Mrm+$mSw5hBNKjG5#(_NXjGm zyzronWKY$Q!WLVX1!qQ5w$+tuTK3ZhIRLO+`|Wvl8x_5smj=9YxmJY!#Wf4~*kCyR zFnn_2>l~SdECkSMwbQ;35QV1}40}GcH+{z&TX=<@^H05n50!mrtv`CVgohHQr=l+P zp@RCYOL023I7%VmMT~0J1yIqs}iGDH2_E*f0r2}^}{mB0~P$I7envxMPF9-m(ysP{-NMXd9D5>f9eQD zum^v;>2fCutUoG10T-Ih@*8m-!#$*&x0fD2xUqd`diLwmw=Fh&2kZXPPjQjss>P%b zjKu|o((aPW zq~jrc`i!ZXv38X(8=6QApFfwkSMBpCB<&+bQvd3$+IiicmX(-YJM!@Q%kt3O@!>x- zhAZ2c-z@IRFP*>m%flOqzjo~rj|kg59(88y=+3?{Gj~3Ey-QHpz4zK5C?+6hy*p>N Y`}adLk2Iz0Jt9I+&V4`F@f!Aj0JqyfwEzGB literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image10 b/ext/tk/sample/tkextlib/tkHTML/page2/image10 new file mode 100644 index 0000000000000000000000000000000000000000..3021b68990df6023c144935f8d8eba1f724ea789 GIT binary patch literal 255 zcmZ?wbh9u|Sd}^Y5#dTL>nnFgFPBq~zI$FsIs@CYJSc^M*`H%eR=$(l$G|&~<*U YjnLAi0_=U2tJka%UcX`EMnwi|0N}GySpWb4 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image11 b/ext/tk/sample/tkextlib/tkHTML/page2/image11 new file mode 100644 index 0000000000000000000000000000000000000000..41d1fe36661a675dcbd48183f903c546e0a4ae5b GIT binary patch literal 590 zcmV-U0F zqn&#W`xu zFkip~6+Qp}00000EC2ui09XJd06+!)peK%GX`X1RuB?hpa4gSsZQppV(-LKIz@PyT zga8Nx2M1sX2AP})fWa9W3>Qv8z(^oC8G&F(074l6Np&pNa1hMFMFJQY6r2j+z$j#$ zfPsR8goTEOh>41ejE#ydkdcy;EsmC#n1@3_0|F7BO9T=UZe~pd02x(j6{-pm5(5KK z016TWsT=|W5<^*67XSrdM-mPhbP1zT4H9S%nbFdhl-1VP*xB0KB-7sChC=}30HufI zN9N$`t3Y&APfdVz0s$33;zU~G1QG2V@0K({qs9Q60U8Jfp)-z(9smLosAEU5qQ#3C zGiuzZk(ZKr>YGPj6B$ELHRSclb8wj8Q zhX+0xsL_zXzyYBe8Uzh8)tM@!K2-sUz@UMK3`yZdxUxViA)Xq9Ie{{dO)j2h5C&NQ z;NCNV928#3n??#efK#XfP=bgjods*Vw-x%21H cqf4Joy}I)b*t2Wj&b_<$@8H9W2Ok0eI~8#LCjbBd literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image12 b/ext/tk/sample/tkextlib/tkHTML/page2/image12 new file mode 100644 index 0000000000000000000000000000000000000000..655a686541afd0f6ee26b620828ee0fda8675747 GIT binary patch literal 254 zcmZ?wbh9u|`7eN1zDEXy$(ea^K|$-rskC7 f&oG@l*ROPnDVMP5@)ebJ0MFwjC@bgl^ literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image13 b/ext/tk/sample/tkextlib/tkHTML/page2/image13 new file mode 100644 index 0000000000000000000000000000000000000000..97d5950e8c54253d210769532202714534da0792 GIT binary patch literal 493 zcmV_WA4X^Wx_1*xl#P)#1j?+`Prsv%S%&w9BBZ z#h0YOjhwoJleBt^u5p8@XnUh!jOSi+om6U~iFJ8SbN`Wj`u^&Hx z9XfUm8Z`tJJ^%m!EC2ui0673806+!);3tk`X`X1RiW=s=a4gSsZEIZ4HNd2E48UOl zC~zhKz$24n903MmB1aJBf&&h~SpZlHg3NDBE}PHjH0Q!@yWjA*d`@St?)dyk&F}lo z2mlET1r-j0L`De!90C9t23bf>ITAt)23|oNU6hk#5uu`^q@|{(sHvfPtgWuEuql7D zv}p>62erCtK|VTAS3Nuj0tbt^NCQ<397GjLK!O8XIkyD6*xB0KV|Cu&;Njxq;<4uE z=;`X~?Cm4m@H!ju^kfeQ1`J~LwH5#iV;&gDw{M^Y4hRfT;80;8!5ji5Kr|rHz=MWP zC>UT?rq_=FSvV}JfFwYI2aa=`d;<3Dz@unNsQK&S;LNirI+W#DWFZIy00K}Nc#=;d zhXDdI8VuCOK>|Li3Wh2`z#%I`i#nu=(Fj2x2aOMMG)&8{t=nuJ;>w*% jx31m0c=N_3$G5NFzkmY=_CUC>;lqd%D_+c)a0mc9>nq&L literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image14 b/ext/tk/sample/tkextlib/tkHTML/page2/image14 new file mode 100644 index 0000000000000000000000000000000000000000..6d73ad833ca1407b8ca99a2335be2096e8947e8b GIT binary patch literal 195 zcmZ?wbh9u|V{(yemUY&@IYTh$dJ*O%~93bBaVF|lzoGBPp{4Rk;%L3S~)dL*dyrDV>_ShehsgF=t8QoExFmx!WG zk_fkZf4PTAn=RX<V{s4=p9U~*74g(N?#2J`m=k%{U{g!|6oGrJyH{av< W!O!-{W7@OMWm%eA-bFJoSOWl*xEA#Q literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image16 b/ext/tk/sample/tkextlib/tkHTML/page2/image16 new file mode 100644 index 0000000000000000000000000000000000000000..93aa853cf1d69f17d43b18ff04bb7046c12334e5 GIT binary patch literal 157 zcmV;O0Al|~Nk%v~VGaN!0P_F<|NsBt;o-v0=dHcpqobpgsLXtkvw3-WVT|WYOiVa9 zI51zpA|fIL6+Qt00RR91EC2ui01f~o000D1P^Dwa7y{_+I#X1!ab3wA!3dPBqoib8 z!mC`qn#~@$?xnsGFW7kz9Sp+JaabmniX~%7ty-_xtai(_A->>nctI|k&*-#z&2GEV LjktV1j{pEWXcI(x literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image17 b/ext/tk/sample/tkextlib/tkHTML/page2/image17 new file mode 100644 index 0000000000000000000000000000000000000000..f46f0308cd2004373645cd58d73cc6e9c96c9d7b GIT binary patch literal 81 zcmZ?wbh9u|tYBba_{hMZ;xbdwVw#M8wYXY}4g(N?#2J{h=Jc;T{g!|6oJF^~H{aXy jo4+l|VcN6KWv@ug_k6e)R0)y~iJJKX`ZR{=4gU-(0x< z^8B@zXRbUydiKe_;}3Tpxxek;-Oc-Muit%Z_4XSpwq9Sp<=Vn^m*=j&ICbf{zImtG zXB=;udbEDh;hO$KrJef=+xF%(?ar#-nO3tSwPt%<*_QD9jUl<~ebQFDC#`geU*Q$KF0>)C#9r0 zG4seqs4(&A>oRaLMoThuGf375H7{S`ugAdYq#WHXA-6$Za+}_^oobTxQZo8(y83Do z^#>#+q|}{uE?Ig0f|EJ}uM~sl8(Em=IV{vrI3Ufyu3BU!Tk%M4qUeTauUf@e G7_0#Wx7Hy5 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image19 b/ext/tk/sample/tkextlib/tkHTML/page2/image19 new file mode 100644 index 0000000000000000000000000000000000000000..bd4f6d9677618441b77c2528053c45197470b7ae GIT binary patch literal 53 zcmZ?wbh9u|tYBba_`txR;xdzgfk6j|89*WoOd>7)D^I`WUp!~at?teD_Wb5=dlbUJ GU=09k5D@zS literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image2 b/ext/tk/sample/tkextlib/tkHTML/page2/image2 new file mode 100644 index 0000000000000000000000000000000000000000..7566dda25d463646aedc500833501df5ede789d4 GIT binary patch literal 49 zcmZ?wbhEHbe#@W8$Y2csAPNgH literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image20 b/ext/tk/sample/tkextlib/tkHTML/page2/image20 new file mode 100644 index 0000000000000000000000000000000000000000..358fa95f63de3e7b497639315ebe379fa48ee6e9 GIT binary patch literal 533 zcmZ?wbh9u|tYF|~_{zZW|NsB5-+sOQ@cq@>ug_k6e)R0)y+`k_-+go8`pfgzUY@z~ z{OH*ydyhZZdF1}q19vy?yS;w*t<~FaEZ=f%;kwInR$rXD^jzP(Q%zHk)=xTI-FL9G zbAMsm-rT0$S@k>9YIda7Y>zA35}v;?BzL_}+G^K?6)y2B9AlT;MlQ7sTWl7*P|tUs zy8CPf3V;qsFUT(rZ2t~SE%4Bh>UW>SaWcnh{)H7=G#S@~@GvB7yu_rUeWE==w2NV3 zaq^5)OdJ~h4FWqj7)38_U#;u&zac;%OqxMbSuIx7MNG`OIgLS{h09sF!i9}PMSxMW zOM;;+UZJyb`3h}W0agY95q}oV)oa)LNX1KZuiUfOe*$-%Gee(~7K_USZN+tyoYkwH z&PbnTkcnkx;4kME)!6sofm*`Dr_UPX1zx@K7m{B6TEJJH|L*heD^7{A%wUsrQ5Le< zw8^Q3QBamAM%bv~v@tuISdT!`f<-K%+FDWy?eArlurYTCC@U2%FkxV4s_EX6eN>f4 z+acn$QX&%rZ!DjK#>J0v)=Rh;99H~bOE}c&Fa2cZ8nH(Q7o8a> h^f=hy@9Mke%}v9j5la5dD<4=LVF}r^qKSdQ8UV}*$i)Bv literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image21 b/ext/tk/sample/tkextlib/tkHTML/page2/image21 new file mode 100644 index 0000000000000000000000000000000000000000..c81aa52588bbeeddd4dbd4b1852f64337848af7a GIT binary patch literal 564 zcmZ?wbh9u|tYF|~_{zZW|NsB5-+sOQ@cq@>ug_k6e)R0)y+`kF-G6ue?wbqOU!K4A z^30XzN6$Xld;G!9BlkD$y}f?-ttA_;&RuEmO&$(;7LJ0VoIW)MK@}w@ z4n}@0WpM^^%8HA*D5m zl}E8a(J47M#Yu=US6WNHu(-D1O2HF`T;`o>BJA%@fBXL9=P!3D0p;He%x)Ve9cY-q z&Bmjnz^=HESxAxRPjKUeY3wWvyH=b?IMCeH#<{UHB=J!rBb%^)ol2V`Lj!{h3zPK$ z2EWz}1(`ER3m!N}F|y9uVY!K+;fR0`gPKp!M_0bN`r@Y;GtwCt^+dmj+?g_S#n}!a zA%-~_&Ml2@CDL9?KBV>C*w3h5ZfNVS?%KdHXVTYB29MTuk$SZP**Pp96t{Z$T~J!1 I#KB+<01(g1hX4Qo literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image22 b/ext/tk/sample/tkextlib/tkHTML/page2/image22 new file mode 100644 index 0000000000000000000000000000000000000000..6cbd63022a11b1e011be85b34d635c9f8d1ff931 GIT binary patch literal 81 zcmZ?wbh9u|tYBba_{hNU|BP`!`2~ac11c^vbr^sEB+kI3HK%{&>9_og=PbI_z4_jr j-~4S!4%41>E_-!q+dJ;#2Yjx7>wW&~-1mR{Kt0v~`!FPe literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image23 b/ext/tk/sample/tkextlib/tkHTML/page2/image23 new file mode 100644 index 0000000000000000000000000000000000000000..e8173a74567eabf2ed7329e34db5a69165ceb012 GIT binary patch literal 539 zcmZ?wbh9u|tYF|~_{zZW|BUhXW5(|en7rC+@@$vMqwOa5x0qa8XL@$I>Cr`I2j-dW zm|?bllG*Bh^W{C}b6U)2G+In=u$WwH(OquQUSd&|ZCRFKS(0v<5oeVWZ511472aB5KD#4WI)u1mqV7wto%{ z1s*z5{U??boy@VCAE21kwaOtt$f=Wg#e$Z5E14ULBmyLvGk+;ESSULr6l*o!k>O1c z+3w>j6xh`4t)VO>>?EeHtjNGAslmxAGKrHhMT191l0jXTfqO;)179kqx_G{Zgh-+A zBxcT*En9=yrP#I=?P_6R-hD7I!-Z8{qcb+1VXA0yimL@>h+tqK9W+BlHBjUehWC_#HJ+1rOaRRBW8lYhXZl}QaTJB1#gZ>@GfBR z;81iDW#Cof@L(`yV398Qeo6Aw1f2t0BhO5$RMd2J>9Ao~SL@-{#muQFx35s3P|4YG z4x5HYhJ!$nY!^SDjKmv*w=L_uoU|kj8dmzK*e*J^LMe2mLxa#%?cH(SoQLt3XuR3(}L1L%N6 zKzbQid<0rNSMRlWeRlW%0}4GUne#GMt;>16&sphwN$&lMb?GOF0I`}mF8}}l literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image25 b/ext/tk/sample/tkextlib/tkHTML/page2/image25 new file mode 100644 index 0000000000000000000000000000000000000000..c656fa4f3082cc3bd4672d99b45b9d88e4922bec GIT binary patch literal 453 zcmZ?wbh9u|tYF|~_{zZW|NsB5-+sOQ@cq@>ug_k6e)R0)y+`kF-G6uC`pfgzUY@w{ z^yt|qJCEGocJS`{-M3b6zp-%LW=B%x zwz#q_;rSbbbJqK$t#*uEZX3DOGHkI~@IpP`dFt-78K@0(Kn8;R;=uOGVN!vIj#U4N zB}FH5tmX$O9#E8FR8!$|aNfnG&*+e_IbwoLt4_k(A3WDO0!sYWD>L@=Gk<7gVN+3* zX5g1mVdIjMR!L3Ilw}Z+DPl~MRxX=4D}aHOkBMcrtFpqPWy{?v6lO?@oqsNN*P6`(tKYPwISVfdUR&KkB2-__-1$pkdRUtxYvbVR0 zCNfH#f8(B=9l<2X&>g#Xg6LKjKDNv#?hp?dh6xPbyPKUCab_wcI5slOVE7^xn0bWV fE$zaJogWw{vvo5lDac5sP8AkV^2p+1Vz34PgNm8P literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image26 b/ext/tk/sample/tkextlib/tkHTML/page2/image26 new file mode 100644 index 0000000000000000000000000000000000000000..bc93fdb259d6ad1cc3a85a56b579447579ed4598 GIT binary patch literal 520 zcmZ?wbh9u|tYF|~_{zZW|NsB5-+sOQ@cq@>ug_k6e)R0)y~iK!J$irZ{=4gU-<-ep z^7Q5BN6$Xld;G!9Blou*yt{t)t>s&;EnIhb?&^y(mY<)x^jzP(Q|&X3H%&cS(|@S6 zbAMsm-khf0S@k>9YIda7Y>zA35}v=&CvCN3>~h=4rIulf&4L%|`OZ^!pUprGpaU`l z)Q8y9y6hi0R2SL2O5HwKPVO{O&+Df|pu z*k%NXH=GdJu)v8yHn6$HQy@f|K~hOMTGUmYfl@vv<0e@F)=c3|-V1l`+1nPv!|K9N=fcU^t{Pp*JTs(0#(B4JEyG0x25u(x zA~D9eeGeZs%S?Ivyj5P{_3IZ-;v(-p1++Vfu`u+rOS%cNCu#6yG=9)H%-E>(pu=h5 z!vnMV*`*3C0-TOCCVf73wb&p*!c9?P*2Y^!3XIFFH0&5YDELm{U`ROPqVOSzxrug_k6e)R0)y+`kF-G6ue?wbqOU!K4A z^30XzN6$Xld;G!9Blp+uzO{VIwT0_0&s}|S#`5!1m!9jJcdBXX(fUb;tNRX?cJ421 z+nd|8JF9+YYR&ezvMu5H8-sJ!`=qUQO<3U=yWBQ%sb$z=v*3k#zVp=GXERU(=zt6X z`Ne_lpTm>_4;`s~cR`MmIac#8tk}ZIxWJE>p`q~-lfnx3_6X4?hWVS5Z)gbk_c|P0VvtZ&jumkc6?N`NV~}OxcHv=B5o3_-l9Xc`OLqA)JLtxW`hPkZsx#kHqF*Gn$T1ZDNWJm~;Wf1h}xvXHC zaV$?>fM-E!`m70D3|@0M7@qNk^FP_K;6*_a3&Ye%@mU5@DY~}8j~7kxkh$R@z+epk DQ%lPf literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image28 b/ext/tk/sample/tkextlib/tkHTML/page2/image28 new file mode 100644 index 0000000000000000000000000000000000000000..88f0d7cea6f0a2529388bf55f40379948abcb23e GIT binary patch literal 416 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 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image30 b/ext/tk/sample/tkextlib/tkHTML/page2/image30 new file mode 100644 index 0000000000000000000000000000000000000000..4a419504341d1b3e30f403c18f7851fb83af3b86 GIT binary patch literal 663 zcmZ?wbh9u|tYF|~_{zZW|NsB5-~YV(^y~HepU>a^c>L=7gXiDwKmU65-luanKb*e) z{`i%5d(XVycKqe~L(kXjf3|GblZD$J&ENWH#`*_S*4*n|ey4f<&6-))E2dv7opLp= z|8jcQ#gz67iLK{jo6benpAD-y<6nN#qwu(6&QZIpBUb5$%~B2-#2;Xw63_ve1M-Ul z+rI;o3o1T|^!4x;p3JeDe_=(5*V-<%8$FpXIxX~W2YXyvF~djfIJ3$VACGsFXO|rG zyD`1HMoB15%~e=YT}@b0z1}HY#wj*FI$TLjq$+fpw=6@0Is>aZBZm_YgTi7}XYP43 ztCZ(5Ni(oF{a zz|_E{&R1bIk>LOb`;q{`35VaYtl_<{VIts=y+|Na^3hkTkKP?jwPKM&3!_z4 z#2{2K>)YwW-b%^V zO$-W+&l_16X6bem2z}l)Ro6d;VL>9p(}M&tIak*^yZP2U{yOKkt2r^&%!4FCd{ B|6%|D literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image31 b/ext/tk/sample/tkextlib/tkHTML/page2/image31 new file mode 100644 index 0000000000000000000000000000000000000000..60f13ed5640d2c02079e788b2c37c2a5ce644ed6 GIT binary patch literal 78 zcmZ?wbh9u|tYBbe_{hKzP=3K6{(yeKdIkmt9Ux`^i8C;%_w=tk{g!|6oJF^~H{aXy ho4-xTVcN6KWv@a^c>L=7gXiDwKmU65-lx;o-ygs7 z?%?@1d(XVya`eUeL(kXjf3|GblSSJf&)@oJ#`*`-*Wd44a=Ur{&H6bvYGz%poPMoz z%GHdni|Jh#Q`#>iww{lyKO0(e+OO=SN8xdo{9|@mN37Bho248wh(EwUC7=T`2jmwA zwtojE7ih>BGBC7tp2)G9e_=(5*V-uGS;w7~&)8WUI@h9N*Lm{sr<*B-Hg*qBdYZhP zp}uHcO~=jX{|!N042sSQ3<6F}jOxk^tV}WtY+Swl6DLpQVpW%8kWd$9WD;R05@wK7 zSL0=HUdqJLxOt1SD1+o`C&gw)K2;~S`ReY~hZY=FpFQ{R3K8{X3s=tbVBm0Q%rztW>d;)!C*VipO8 zm=zr#ID%vp=Y10?DD_}sU}YCOp;cwFa!soCQqPDIt*HWyPuLiKoV>iCQ<+ObKq67Z tiHRY`s!8I@Lq-NOhHH7H*@rZmnG2WBEnpB<2vcO)%_ZkEBT0b48UUxx&Cmb< literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image33 b/ext/tk/sample/tkextlib/tkHTML/page2/image33 new file mode 100644 index 0000000000000000000000000000000000000000..c1ecfff6c422579fe3a52ce0a8f3d5fae17acfec GIT binary patch literal 598 zcmZ?wbh9u|tYF|~_{zZW|NsB5-~YV(^y~HepO0UCzyJK}wfmpW-}-R+`upQo-W@pq zX78ET+m63nf9UzLT~8Kme>`u?qZ#WTOkaP$bII-2g}0jL->jc=qh{9i%IViir(DhJ zzntE6F{S-NV(agZKjs)B`#oqdWuDt#WRjxEjl1HDv}SRW*jYcQ1q~ zu-;{DaGJN_&aQg`QVil3m|Ph=PJWvxcbD(RIkkBbSKLxRg}q=}t#R8YhpFP-+ztkY zYmS*54u_iZzZ+%UIk9oEyW&wU$34jj44br^on|b)x;EfQzrjfsiwO@WGw?B}d2n+G zCDkbM&(^3gC_H%fD4*Q2jWw;sv2A=x3k(a`8Cn{d46W0&8WNZrm>B=m`Z6SlbZBug zfm5wW?-42@$JwuhSz)%r&|&l8CV!ZQm;lVl0HyaUKVB?cz~fJmAgYuWzzu$ gW+vvacR3%5rr)zxRVbRlkZ}6Ja?c>L=7ohM(e-ura!=7-bQ-ygs7 zZr|D0+m63nf9Uy|{m+)|da`KyuJDVoLjkgqHKMP3M9tPx+Od^e8;;m~+%F>xfnQVY8G&2Jr_Ns0VaFMuGg|!1m8! za)CvOh|ZBElTK)GXtMUNbTAEQIlHv%^xLZaQ4?K^=Y%*3ak8pBS)!|~`uyOEBfgV* zGMAXeUJ?>dXl`juP-Ws)X5dznWoTk&tYA>+?sev3a1vsWRbyDlz~?lpZTX6oPSOmV z42As+j65n+7?_1Umra?^z@sL^Af&c?)v@DIybOXu+zgWa;;Jm{Qxp^!_+4hntDOtl zr^LXndSv#A7cXDEe)HB@m2vIz-E;S{39&IqKYRDLnU~Rs;lP88NLB`3jno2$%-cJw z7KoG-EL%Qff46r8tA@gA7n8cVHy8pQOqi@5z-{9Buzh2y5aU&!8iyYz9PEtd3h+n> hJen(ZAew<^%I8!jCI*#RD-;S&ZdrM`%#ne?8UPMtyMq7# literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image35 b/ext/tk/sample/tkextlib/tkHTML/page2/image35 new file mode 100644 index 0000000000000000000000000000000000000000..aea44f3017ed8e76642112cbf5db078c47286841 GIT binary patch literal 724 zcmZ?wbh9u|tYF|~_{zZW|NsB5-~YV(^y~HepU>a^c>L=7gXiDwKmU65-luanKb*e) z{`i%52hP9Qd*=1_<1aTHdcOY9^ELaQE!*{E(e}slwmh1#{=xM1_j{M$XtLBxrZU4)52l0is$w-Xa%1B0T_PAvvLt)tn_(xD8D3A-0- zY3yc@(po05>m(D03j-@3E5nkwWuk%%3$(ZyKFG2%s;e+?%P~k_V>-p4s&bFDp}|SQ zhK=(n5?p`KVagmIod=EEn-UkZ} z8hwNsm=9SoBq%Id_RC$^Ibe=J5hH^d18=BC0LOtN+Zb8eq$DOJb@&&nY|grSYU}Fo z=?p(O1Q@<#hgGu~MK~CQyzbOV+d8A_d&1QQ0mYyfTNoHunzH|#pmd-z;Q&XhKuhZa zh6m?u`I-1aL@#kSFmgt!lyL-JbJSUITP`lEajPLbax%8@mm3hOmYuBoq)|a>2e2LLh zan%uUb>y17VM?=s(Ca%45)&4D7vN@;GT|_2;9+a^c>L=7ohM%|-T8R#=7-}~-t9f} zdi|m2YxX}|w(H5F?T_bec{F4FgX!z<_b$KFy6{%>{G0W2ZdA{_UOMG!cJHN>_6rFu z=VP1B`In#cC_L_xf6OlHh*kPwWzcZA|98Nqgjem`af_VY*3mQprOPWc>hC14D$^qrY4VA7RCZQ2CfRJZo$<3YoN_-4rRlAEPkQld_toG3oE#af0mLVk^#A|> literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image37 b/ext/tk/sample/tkextlib/tkHTML/page2/image37 new file mode 100644 index 0000000000000000000000000000000000000000..6c6ba52b45fcccf221988efccd1ff0ce4aec1665 GIT binary patch literal 124 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 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image4 b/ext/tk/sample/tkextlib/tkHTML/page2/image4 new file mode 100644 index 0000000000000000000000000000000000000000..9e5e46b7e589b97a19ee9a61510ee9bc17ec6932 GIT binary patch literal 268 zcmZ?wbh9u|6ku#(O^JZdUTfOXsX)os?FLo!v+y%9qt{Vc^ zeOvY|w)URIum271u}bk;b}Ec)sX{GX-93!?shz1=9EB-f{Mos@eO_k8rE{w)YN{74 fTj^U_vMMN;S77s&#%_WA4X^Wx_1*xl#P)#1j?+`Prsv%S%&w9BBZ z#h0YOjhwoJleBt^u5p8@VT|WqbDdObmrG)jLRySCQHC&Iz%O3CFG_(QKY$%Nb`2Ue z1Qk920000000000EC2ui06G9906+!)U?+}bX`X1Rj#ulxa4gSs?P?le;Cen7fP$tX z5C9200Rf=UNB|5C5QoqWD2C;aQV=i_2%LCKE}PHjG}^*$yWjA*d`@q#?)W@P&F}lu zJ!4P~P#O_T5=#|11QG)S8WaEr5d#840F4fdPf;2Q5sr{!5T&N4sHv)}tgWVcu(7hU zv@3tNxO@P+09U!ce*i`X4?I7UQUExeIXesh63kQ25@XC71-k?hz}?>8;A(Z_?A%TGd49WCjZ~#EDLQ`@U0D$=Hg(X3}`diD^-iEhuV{(yemUY&@I+F@(e{pTsUcFEgT$y$|3o99a!rHkvv zifV@otN92jxeCbJ^UK-rN|~~V+A$CZbU?~Lb~&(CKTzpY(d1!$WYIH8#?6t(BUd@# zu+GW1&$+{O9dx96mp(ZWetK)wnPq+*3=!)i))bvqy_?k2-X}iw-GV@MQ(IT##w&|! z{M5_d|ELjX)D{ur=gSRb=k!ZSZO^lB?hNKiwMgzZ&zfR3ZDK)y;M{rh=a(*8yhLc( K@)au-8LR>A2}d&k literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image7 b/ext/tk/sample/tkextlib/tkHTML/page2/image7 new file mode 100644 index 0000000000000000000000000000000000000000..0e6ac10affc148be9b65f15df8eab96954283fbf GIT binary patch literal 551 zcmV+?0@(dWNk%v~VMPEW0Q3L=|NsB%?(^d2?bzMt&(-0^&D^}j*0a6QskFS=`gOjv+i>`5lsc3tnVT|WqbDdObmrG)jLRySCQHC&Iz%O3CFG_(dSg{>Cb`2Ue z1Qk920000000000EC2ui07U>K06+!)U?+}bX`X1Ru48t&S1iwTZQppFYrG~5JszN- zSpXy&LSTV7XbJ;>pg>6g1_D4t!vFv<5--v?C^(A4>?FBt2H)_wd`_?1d6v9>&+q&H zfPsQ~EQN-Lhj)sLjEfNf1`-Yr8UX?l1ppKp2@w(k0z6?0JXjG800GC7@VG-8x7RX$%W`fL>8Y+C`Ayd>$lrz_`bP02g zw;XZ+IW}+fOgJ$+@%VI2%HX p9!C>oFs}{|$wd>cgW6Peskb~{pxO3~?&AYen-?u{m06VAi?KJ=Z literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image8 b/ext/tk/sample/tkextlib/tkHTML/page2/image8 new file mode 100644 index 0000000000000000000000000000000000000000..ba7fb476b956cedba808f86508fa0fd345faafa0 GIT binary patch literal 497 zcmV_WA4X^Wx_1*xl#P)#1j?+`Prsv%S%&w9BBZ z#h0YOjhwoJleBt^u5p8@VT|WqbDdObmrG)jLRySCQHC&Iz%O3CFG_(fTel@admTD< z4H`8B6+Qp}00000EC2ui06YLB06+!)peK%GX`X1RmRaj&S1iwTZQuC4?HdC~z2Bw* z80;hf0s+9F7zRnh1^}4&b^w7vIvp4Qh0O$TU=%34w0g~MyWjAgWlpc#@A$laZ(sTU zfGTl=goSTDKs*9kOA|;E2UR~J?CtLF@bU6>x%Kw<`1$(#{JQG@00R!Hu!)nvbd(|~tH2<_4u%XYZGae&fd&Q* zqA{3MQCYzLjV9fM7!7E literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/image9 b/ext/tk/sample/tkextlib/tkHTML/page2/image9 new file mode 100644 index 0000000000000000000000000000000000000000..b1cad73ae93bb7377320c87fe9f27d383561ecd0 GIT binary patch literal 492 zcmVS=`gOjv+i>`5lsc3tnVT|WqbDdObmrG)jLRySCQHC&Iz%O3CFG_(eS+gZUdmTD< z4H`8B6+Qp}00000EC2ui05||706+!)peK%GX`X1RdRcqDa4gSsZP#1A8Gu6R3&5b@ z*aQm#z$5}-Y#acG1hCjp0)m2JQvehSKSE%EIOxvkw0g~Mvn}wrd`_?1?|92<&+nVu zfPsQ-3_leD14aN15_Vynqu}T?M_vf)xyvr$GP!5{gIwKMKq}8<-njXI;yb%L5T@6^+E>jgT@OHllYC}F$qH`2@4VyL6~sDh6f8m8F^4)L9-41 z96Cs7aRUYfT8gZhund3zN6d170H{V~1ELLLSXLPzNk^A6CIbc literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page2/index.html b/ext/tk/sample/tkextlib/tkHTML/page2/index.html new file mode 100644 index 0000000000..7eaf2d2cc9 --- /dev/null +++ b/ext/tk/sample/tkextlib/tkHTML/page2/index.html @@ -0,0 +1,433 @@ + + + Tcl Resource Center + + + + + + + + + + +
    Scriptics + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Tcl/Tk
    Scripting Solutions for eBusiness Integration
    ProductsCustomersPartnersServicesTcl ResourcesCompany
    +
    + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Software
    Tcl/Tk Core
    Applications
    Extensions
    Patches
    Tcl & Java
    Tcl/Tk Ports
    Tools
    Documentation
    Community
    What's New
    Add URL
    Keyword Search
    Index
    + + + +
    Resource
    +
    + + + + + + + +
    +   +

    Tcl Resource Center

    +Top>Software Central>Extensions>Tk Widgets
    Viewed by name (By date)

    +

    Tk is a toolkit for building graphical user interfaces with Tcl. + Your Tcl/Tk scripts run on UNIX, Windows, and Macintosh.

    +

      +
      BLT 8.0 Unofficial zip and DLL +
      This is a compiled version of BLT 8.0 "unofficial" for +the Windows platform. Edit + (September 24, 1999 06:31)
      BLT 8.0p2 Unofficial tar file +
      This is a contributed patch to make BLT compatible with Tcl/Tk 8.0p2. While still "unofficial", it is widely used. + Make sure you get the 8.0p2 version because the 8.0 version does + not compile under windows. + There is also a 2.3-8.1 version that has been patched to work with 8.1. + README file. Edit + (August 30, 1999 06:38)
      BLT Home Page +
      + Author George Howlett, Version 2.3, + Works with Tk 4.1 through Tk 8.1 +
      Download, BLT2.3.tar.gz, BLT2.4h.tar.gz, BLT2.4i.tar.gz, blt2.4i-for-8.0.exe, blt2.4i-for-8.1.exe
      BLT is a set of widgets for Tk, including a graph widget, +bar chart, drag&drop, a simple command tracer, and much more. +The 2.4 release, which is still under development, works with 8.0 +or higher. +There are also an "unofficial" release for 8.0p2 +and 8.1a2 that were not done by the author. Edit + (October 26, 1999 09:43)
      BWidget +
      A set of native Tk 8.x Widgets using Tcl8.x namespaces. +The ToolKit is available under Unix/X11 and Windows. +The BWidget(s) have a professional look&feel as in other +well known Toolkits (Tix or Incr Widget) but the concept is +radically different because everything is native +so no platform compilation, no compiled extension +library are needed. The code is 100 Pure Tcl/Tk. +More 30 components : Notebook, PageManager, Tree, PanedWindow, ButtonBox, +ScrollView, ComboBox, SpinBox, ListBox, SelectFont, SelectColor, +ProgressBare ... Edit + (September 06, 1999 09:58)
      Dash Patch for Tk +
      This patch has many enhancements to the Tk and its canvas +widget, including dashed lines, smoothed polygons, +and performance enhancements. Edit + (November 21, 1999 06:33)
      Embedded Tk (et) +
      + Author Richard Hipp, Version 8.0b5, + Works with Tk 4.0, 4.1, 4.2, 8.0 +
      Download: et80b5.tar.gz
      Embedded Tk or ``ET'' is tool for making stand-alone executables out of a mixture of C or C++ and Tcl/Tk. +Using ET you can invoke a short Tcl/Tk script in the middle of a C routine, or you can invoke a C routine in the +middle of a Tcl/Tk script. ET also bundles external Tcl/Tk scripts (including the standard Tcl/Tk startup scripts) +into the executable so that the executable can be run on another binary-compatible computer that doesn't have +Tcl/Tk installed. Edit + (August 19, 1999 15:35)
      Enhanced Tk Console (TkCon) +
      + Author Jeff Hobbs, Version 1.3, + Works with Tk 4.1 through Tk 8.1 +
      Download: tkcon.tar.gz
      TkCon is a replacement for the standard console that comes with Tk (on Windows/Mac, but also works on + +Unix). The console itself provides many more features than the standard console. Edit + (August 23, 1999 12:06)
      Frontier-Tk ScriptMeridian project +
      This project seeks to integrate the Tk toolkit +with the Frontier scripting language. Edit + (August 19, 1999 15:36)
      Img image format extension +
      This package enhances Tk, adding support for many other Image formats: +BMP, XBM, XPM, GIF (with transparency), PNG, +JPEG, TIFF and postscript. +This is implemented as a shared library that can be dynamically loaded into +Tcl/Tk. + Edit + (November 21, 1999 06:35)
      mclistbox - a multi-column listbox widget +
      mclistbox is a multi-column listbox that is +written in pure tcl and runs on all platforms +that support tcl/tk 8.0 or higher. This widget +requires no other extensions; it is completely +standalone. Edit + (August 19, 1999 15:37)
      MFC views C++ class for embedding Tk +
      The idea of embedding Tk in MFC windows always seemed very enticing but information was sparse and contradictory - on a + scale between "very easy" and "not yet possible". The only thing for it was to have a go and lo, it wasn't that hard after all. + CTkView is a C++ class which can be used in MFC SDI or MDI applications. An instance of CTkView hosts an embedded Tk + toplevel widget and performs some management chores for the widget so that it can size, update and react correctly to Windows + events. Edit + (August 19, 1999 15:38)
      Pad++ +
      + Author Ben Bederson et al, Version 0.9p1, + Works with 8.0 +
      Download: download.html
      Pad++ is a Tk widget that provides a Zoomable User Interface (ZUI) that supports real-time interactive zoomable graphics in a fashion similar to the Tk Canvas widget. Pad++ supports tens of thousands of objects which include text, images, graphics, portals, lenses, simple html (and more), including transparency and rotation. Edit + (August 19, 1999 15:39)
      Progressbar +
      Progressbar is a megawidget written in pure tcl (ie: no compiling required - runs on all platforms Macintosh, Unix, Windows). +Its primary purpose is to show the progress of any action in percent. Edit + (January 24, 2000 09:19)
      scwoop (Simple Composite Widget Object Oriented Package) +
      Scwoop is a composite widget (also known as mega widget) extension to the great Tk widget library. Scwoop is +entirely written in Tcl using the stooop (Simple Tcl Only Object Oriented Programming) extension. Edit + (January 09, 2000 02:10)
      Supertext - tk text widget with unlimited undo +
      + Author Bryan Oakley, Version 1.0b1, + Works with Tcl 8.0 +
      Download: supertext.tcl
      Supertext is a package that provides a tk text widget with full undo and the ability to execute procedures both before and after a text +widget command has been processed. Supertext may be used as-is, or for the brave it may be used in place of the standard text +widget. Edit + (August 23, 1999 12:06)
      Tabbed Notebook Widget +
      + Author Richard Hipp, Version 1.0, + Works with Tk 4.1 or later. +
      Download: notebook.tcl
      This implements a tabbed notebook using +a canvas widget and embedded frames. +This is pure Tcl +code - not a C extension. Edit + (August 23, 1999 12:08)
      Tcl GD - graphics +
      + Author John Ellson and Spencer Thomas, Version 2.0, + Works with 8.0 and higher +
      Download: Gdtclft2.0.tar.gz
      + Thomas Boutell's Gd package provides a convenient way to generate + PNG images with a C program. If you prefer Tcl for CGI + applications, you'll want the TCL GD extension. Edit + (August 19, 1999 14:52)
      The Meta-GUI Tools +
      The Meta-GUI tools provide a framework for quickly building full +GUI applications. The GUI is rendered by a run-time engine +based on a hierarchical set of definitions you provide. At the bottom +of the hierarchy are abstract data types such as length, angle, +string, etc., and these are used to progressively build up frames, +dialogs, toolbars, menus, and operations. Edit + (August 23, 1999 12:10)
      Tkpiechart Home Page +
      Tkpiechart is a Tcl-only extension that allows the programmer to create and dynamically update 2D or 3D pie +charts in a Tcl/Tk application. This uses the stooop package and builds +pie charts on a Tk canvas. Edit + (January 09, 2000 02:12)
      TkPrint +
      TkPrint is an extension that allows you to print from a + Tk widget. Edit + (October 11, 1999 09:58)
      TkTable Home Page +
      The TkTable widget. The table command creates a +2-dimensional grid of cells. The table can use a Tcl array variable or Tcl + +command for data storage and retrieval. Edit + (November 18, 1999 09:25)
      TkTextMatrix (spreadsheet) +
      + Author John Arthur Tucker, Version 4.1, + Works with Tk 4.1 +
      Download: download.htm, textmatrix4.1.tar.gz
      A Tcl/Tk spreadsheet widget, TkTextmatrix, which is implemented in C++ and is + basically a Tk Canvas widget plus extra behavior for manipulating rows and columns of cell + items many times faster than with a plain Tk Canvas. It actually inserts text nearly as fast + as the Tk Text widget. If you work with or are interested in creating your own Tcl/Tk widgets + in C++, you might want to take a look at the C++ widget library included with this + distribution. Edit + (August 23, 1999 12:14)
      ToGL - a Tk Open GL widget +
      Togl is a Tk widget for OpenGL rendering. Togl is based on OGLTK, originally written by Benjamin Bederson at the +University of New Mexico (who has since moved to the University of Maryland). Togl adds the new features: +
        +
      • color-index mode support including color allocation functions +
      • support for requesting stencil, accumulation, alpha buffers, etc +
      • multiple OpenGL drawing widgets +
      • OpenGL extension testing from Tcl +
      • simple, portable font support +
      • overlay plane support +
      +Togl allows one to create and manage a special Tk/OpenGL widget with Tcl and render into it with a C program. That is, +a typical Togl program will have Tcl code for managing the user interface and a C program for computations and +OpenGL rendering. Edit + (August 23, 1999 12:14)
      Tree Widget +
      This implements a tree display in a canvas widget. +It is similar in layout to that of the +Windows explorer file viewer. This is pure Tcl +code - not a C extension. Edit + (September 29, 1999 14:37)
      Windows Extensions for Tcl/Tk (Michael Schwartz) +
      This site has pointers to several extensions specific to the +Windows platform. The extensions provide printing, +a MAPI interface to send email, and an interface to manipulate +.INI files, among other things. Edit + (October 07, 1999 10:50)
      [incr Widgets] Home Page +
      [incr Widgets] is a set of megawidgets (combo boxes, etc.) that are +upon the [incr Tcl] object system and the [incr Tk] megawidget +framework. This comes bundled with the +[incr Tcl] distributions. Edit + (September 05, 1999 16:08)
      combobox +
      + Author Bryan Oakley, Version 1.03, + Works with 8.x +
      Download: combobox.tcl
      combobox is a pure-tcl implementation of a combobox widget. It is +entirely self contained and does not require any other OO or megawidget +extension. It supports both editable and non-editable entries, and +provides the ability to call a procedure anytime the value of the combobox +changes. Edit + (August 23, 1999 12:15)
      Rnotebook +
      + Author Daniel Roche, Version 1.0, + Works with 8.0 or higher +
      Download: index.html
      This implements a resizeable notebook +widget in pure tcl/tk Edit + (August 19, 1999 15:39)
      saMDI v1.0a1 Multi-Document Interface Extension +
      A multi-document interface (MDI) extension for TCL/Tk 8.0. +This is a common interface format in Microsoft Windows that lets a parent window contain multiple child windows. +In effect you get a window manager inside a window! +Uses and includes the STOOOP object-oriented extension by +Jean-Luc Fontaine. +saMDI v1.0a1 GPL Copyright 1998 Sam Tregar. Edit + (August 23, 1999 12:07)
      Tix Support Site +
      + Author Ioi Lam, (adopted by Gregg Squires), Version 4.1, + Works with Tcl 7.4 through Tcl 8.0 +
      Download, Tix4.1.0.006.tar.gz, Tix41p6.zip, win41p6bin.zip
      Tix has found a new home! +
      + Tix provides over 40 new Tk including the +combo box, file selection dialogs, paned widget, +notebook, hierarchical list, directory tree, and more. + Edit + (August 23, 1999 12:11)
      Tk Tree Widget (C++) +
      Tk Tree widget for Tcl8.0.3. + +This version contains (optional) support for \[incr Tcl\] and \[incr Tk\] +version 3.0. +
      +With the tree widget, you can display a tree in a Tk canvas. The nodes +can be made up of any number of canvas items or even other Tk widgets. +You create the objects that make up a node and the line that connects +it to its parent and pass them to the tree widget. After this the tree +widget manages the positions of the nodes and end points of the tree +lines. Operations are available for inserting, moving and removing +nodes and subtrees and for querrying the position of a node in the +tree. The tree can be displayed horizontally or vertically. + Edit + (August 25, 1999 03:14)
      widget, simple megawidget package +
      + Author Jeffrey Hobbs, Version 0.9, + Works with Tcl/Tk 8.0 or higher +
      Download: widget-0.9.tar.gz
      This is a package of + megawidgets (i.e., compound widgets) that work almost exactly like Tk widgets. + You can also build your own new megawidgets. +Includes: combobox, hierarchy, console, progressbar, +tabnotebook, validating entry, pane geometry manager, baloon help. Edit + (August 23, 1999 12:16)
      +


      Top
      Home + | Products + | Customers + | Partners + | Services + | Tcl Resources + | Company +
      Search + | Site Map + | Feedback + | Contact Us + | info@scriptics.com + +
      + + © 1998-2000 Scriptics Corporation. All rights reserved. + Legal Notice | + Privacy Statement +
      + + \ No newline at end of file diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image1 b/ext/tk/sample/tkextlib/tkHTML/page3/image1 new file mode 100644 index 0000000000000000000000000000000000000000..814d1e8f08deefc7659d4a7d75f8784f1d69ce8d GIT binary patch literal 113 zcmZ?wbhEHblxL7*_`m=H|NsA2{K>+|z`)3$1LA{Z7??bI`d6NoWtbBqaPIf2qrTaG zmGT`Oax-VDub35a+s{DftV#0uL^<`Ex*v?ePIDi(DRoU^Q#s|?w5iHd^Z2htc3T7A Ng&Yl8C&9{K4FK(qDBu79 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image10 b/ext/tk/sample/tkextlib/tkHTML/page3/image10 new file mode 100644 index 0000000000000000000000000000000000000000..45001faf0523aef6d70c7d90e8c788094463f425 GIT binary patch literal 5088 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 X$98z?d#1qu9 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image12 b/ext/tk/sample/tkextlib/tkHTML/page3/image12 new file mode 100644 index 0000000000000000000000000000000000000000..903e7344a68a8e3799c9810b10f9fe1c10d49479 GIT binary patch literal 3579 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 BKn(x@ literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image13 b/ext/tk/sample/tkextlib/tkHTML/page3/image13 new file mode 100644 index 0000000000000000000000000000000000000000..226d4f68c2eb97dd50a157945d92d57bfef9afb2 GIT binary patch literal 5119 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 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image14 b/ext/tk/sample/tkextlib/tkHTML/page3/image14 new file mode 100644 index 0000000000000000000000000000000000000000..8e8c71814c1a751707f31cc34b6a23dc2637251b GIT binary patch literal 3603 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 ZD!QU9+M+J{qA(hxGAg4ZilRXP06Q&8Jj(z8 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image2 b/ext/tk/sample/tkextlib/tkHTML/page3/image2 new file mode 100644 index 0000000000000000000000000000000000000000..2ddeb3258ce8b4a9b8f228dd4839b3bbc02667f4 GIT binary patch literal 74 zcmZ?wbhEHblwjax_`m=H|NsA2{K>+|z`)3$1LA{Z7?>1$`d98|;OQ@(csBC#-kWdu YlOB3ZTbw>G=$B@~^P+-3F02gJ00bHs-T(jq literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image3 b/ext/tk/sample/tkextlib/tkHTML/page3/image3 new file mode 100644 index 0000000000000000000000000000000000000000..1651ba7e415c7ffb7ecd0a6dce27a23555bdffb6 GIT binary patch literal 681 zcmZ?wbhEHblw#m#_{IPNOiWBHEG#@cJOTm&Vq#(v5)v{pGHPmS8X6ipIy!oKdPYV@ zW@cs<78X`kRyH;^c6N3S4h~LEPA)Dk9v&WEUS2*vK7M|FAt51QKok}h5fKp;6%`W` z6BiekkdTm+l$4T^l97>-m6er~larU1S5Qz;R8&+_Qc_k{Rslp66;)MLH8nMLb#)C5 z4NXl=EiEl=ZEYPL9bH{reSLkCCQX_$Wy-W^(`L+=F>BVWdGqEiSg>HxqD4!VELpZ} z*``gKwrtt5ZQHgTJ9g{>qFuZ8?AdeRz=0!2jvPC7?8J!^r%s(ZbLPyYOP8)(xpM8= zwHrWmUM~@yodGh4hvuCefy?XQJ&AWH+K79D_<;#~JKYoCNhqi>` zPZmZ7hByWtkTsww@D!j93Hw&biM4~D8IyImv&3>*|3ycxyW7)(|? cJM7IXsh6i>^hn8tnMsh%;pALva{&fx09W+ppa1{> literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image4 b/ext/tk/sample/tkextlib/tkHTML/page3/image4 new file mode 100644 index 0000000000000000000000000000000000000000..b565c8dd0e9d428c1da4c333c5fa408213992584 GIT binary patch literal 3056 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 TukcK`!WYi)hCAF82><{)ex7A` literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image6 b/ext/tk/sample/tkextlib/tkHTML/page3/image6 new file mode 100644 index 0000000000000000000000000000000000000000..1a6b260b4076c404788dba623dc62806c8349ae8 GIT binary patch literal 79 zcmZ?wbhEHb6k_0I_{hNU|NnoB4FwEfp!k!8k%57UK?lSG$ulr1OzF>DxcA_l#*lMa c@@K5lUMb!-Ra0R0Qcs&ZXTrXM7a|PS09Q&FBme*a literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page3/image7 b/ext/tk/sample/tkextlib/tkHTML/page3/image7 new file mode 100644 index 0000000000000000000000000000000000000000..cec7aa04d8ff92800b4f446a76050641bad9c79d GIT binary patch literal 1613 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 +
      +

      Embedding Tcl in C/C++ Applications

      + + + + + +
      + Presented At: +
      + The Tcl2K Conference
      + Austin, Texas
      + 9:00am, February 15, 2000
      +
      +
        + Instructor: +
      + D. Richard Hipp
      + drh@hwaci.com
      + http://www.hwaci.com/drh/
      + 704.948.4565 +
      +

      +

      + +
      +

      + Copies of these notes, example source code,
      and other + resources related to this tutorial
      are available online at + + http://www.hwaci.com/tcl2k/

      +

      $Id$

      +
      +

      + +


      +

      Tutorial Outline

      +

      • Introduction
      • +
      • Building It Yourself
      • +
        • "Hello, World!" using Tcl
        • +
        • Tcl scripts as C strings
        • +
        • Adding new Tcl commands
        • +
        • A tour of the Tcl API
        • +
        • Tcl initialization scripts
        • +
        • Adding Tk
        • +
      • Tools Survey
      • +
      • Mktclapp
      • +
        • "Hello World" using mktclapp
        • +
        • Adding C code
        • +
        • Other Features
        • +
        • Invoking Tcl from C
        • +
        • Running mktclapp directly
        • +
        • Real-world examples
        • +
      • Summary
      • +

      +


      +

      Embedding Tcl in C/C++ Applications

      +

      • You know how to program in Tcl/Tk
      • You know how to program in C/C++
      • This tutorial is about how to do both at the same time.

      +


      +

      Why Mix C With Tcl/Tk?

      +

      • Use C for the things C is good at and Tcl for the things + Tcl is good at.
      • Generate standalone executables. +
        • Eliminate the need to install Tcl/Tk.
        • +
        • Prevent problems when the wrong version of Tcl/Tk is installed.
        • +
      • Prevent end users from changing the source code. +
        • Keeps users from creating new bugs.
        • +
        • Protects proprietary code.
        • +
      • Office politics
      • Use Tcl/Tk as a portability layer for a large C program
      • Use Tcl as a testing interface

      +


      +

      Why Mix C With Tcl/Tk?

      +

      + "Use C for the things C is good at and use Tcl/Tk for the things + Tcl/Tk is good at." +

      + + + + + +
      + C is good at: +
        +
      • Speed
      • +
      • Complex data structures
      • +
      • Computation
      • +
      • Interacting with hardware
      • +
      • Byte-by-byte data analysis
      • +
      +
        + Tcl/Tk is good at: +
        +
      • Building a user interface
      • +
      • Manipulation of strings
      • +
      • Portability
      • +
      • Opening sockets
      • +
      • Handling events
      • +
      +
      +


      +

      Programming Models

      + + + + + + + + + + + + + + + + +
      + +

      Mainstream Tcl Programming Model:

      +
        + +

      Embedded Tcl Programming Model:  

      +
      + +
      • Add bits of C code to a large Tcl program
      +
        + +
      • Add bits of Tcl code to a large C program
      +
      + +
      • Main Tcl script loads extensions written in C
      +
        + +
      • Main C procedure invokes the Tcl interpreter
      +
      + +
      • Tcl/Tk is a programming language
      +
        + +
      • Tcl/Tk is a C library
      +
      + +

      + Most of the Tcl2K conference is about
      +
        + +

      + This tutorial is about
      +
      + +


      +

      "Hello, World!" Using The Tcl Library

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>    Always include <tcl.h>
      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();    Create a new Tcl interpreter
      +  Tcl_Eval(interp, "puts {Hello, World!}");    Execute a Tcl command.
      +  return 0;
      +}
      + +


      +

      Compiling "Hello, World!"

      +

      Unix:

      +
      + $ gcc hello.c -ltcl -lm -ldl
      + $ ./a.out
      + Hello, World!
      + +

      Windows using Cygwin:

      +
      + C:> gcc hello.c -ltcl80 -lm
      + C:> a.exe
      + Hello, World!
      + +

      Windows using Mingw32:

      +
      + C:> gcc -mno-cygwin hello.c -ltcl82 -lm
      +
      + +
      Also works with VC++

      +


      +

      Where Does -ltcl Come From On Unix?

      +

      Build it yourself using these steps:

      +

      • Get tcl8.2.2.tar.gz from Scriptics
      • zcat tcl8.2.2.tar.gz | tar vx
      • cd tcl8.2.2/unix
      • ./configure --disable-shared
      • make
      • Move libtcl8.2.a to your lib directory.
      • Copy ../generic/tcl.h into /usr/include.

      +


      +

      What Other Libraries Are Required For Unix?

      +

      • The sequence of -l options after -ltcl + varies from system to system
      • Observe what libraries the TCL makefile inserts when + it is building tclsh
      • Examples in this talk are for RedHat Linux 6.0 for Intel

      +


      +

      How To Compile Under Unix Without Installing Tcl

      +

      Specify the *.a file directly:

      +
      +  $ gcc -I../tcl8.2.2/generic hello.c \ 
      +      ../tcl8.2.2/unix/libtcl8.2.a -lm -ldl
      +  $ strip a.out
      +  $ ./a.out
      +  Hello, World!
      + +

      Or, tell the C compiler where to look for *.a files:

      +
      +  $ gcc -I../tcl8.2.2/generic hello.c \ 
      +      -L../tcl8.2.2/unix -ltcl -lm -ldl
      +  $ strip a.out
      +  $ ./a.out
      +  Hello, World!
      + +
      The -I../tcl8.2.2 argument + tells the compiler where to + find <tcl.h>.

      +


      +

      What's "Cygwin"?

      +

      • An implementation of GCC/G++ and all development tools + for Windows95/98/NT/2000
      • Available for free download at +
        + http://sourceware.cygnus.com/cygwin/ +
      • Also available shrink-wrapped at your local software retailer or + online at +
        + http://www.cygnus.com/cygwin/index.html +
      • Programs compiled using Cygwin require a special + DLL (cygwin1.dll) that provides a POSIX system API
      • Cygwin1.dll cannot be shipped with proprietary programs + without purchasing a license from Cygnus.
      • Mingw32 is the same compiler as Cygwin, but generates + binaries that do not use cygwin1.dll

      +


      +

      Where Does -ltcl82 Come From On Windows?

      +

      Build it like this:

      +

      • Get tcl82.lib and tcl82.dll from Scriptics.
      • echo EXPORTS >tcl82.def
      • nm tcl82.lib | grep 'T _' | sed 's/.* T _//' >>tcl82.def
      • dlltool --def tcl82.def --dllname tcl82.dll --output-lib libtcl82.a
      • Move libtcl82.a to the lib directory and tcl82.dll + to the bin directory.

      +


      +

      Where Does Your Code Go?

      + + + + + + + + + + + + + +
      +#include <tcl.h>

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  /* Your application code goes here */    Insert C code here to do whatever it is your program is + suppose to do
      +  return 0;
      +}
      + +


      +

      Building A Simple TCLSH

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  char *z;
      +  char zLine[2000];
      +  interp = Tcl_CreateInterp();
      +  while( fgets(zLine,sizeof(zLine),stdin) ){    Get one line of input
      +    Tcl_Eval(interp, zLine);    Execute the input as Tcl.
      +    z = Tcl_GetStringResult(interp);
      +    if( z[0] ){
      +      printf("厚PX\n", z);
      +    }
          Print result if not empty
      +  }
      +  return 0;
      +}
      +

      +
      What if user types more than 2000 characters?
      +

      + +


      +

      Building A Simple TCLSH

      +

      Use TCL to handle input. Allows input lines of unlimited length.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +/* Tcl code to implement the
      +** input loop */
      +static char zLoop[] = 
      +  "while {![eof stdin]} {\n"
      +  "  set line [gets stdin]\n"    Get one line of input
      +  "  set result [eval $line]\n"    Execute input as Tcl
      +  "  if {$result!=\"\"} {puts $result}\n"    Print result
      +  "}\n"
      +;

      +
      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_Eval(interp, zLoop);    Run the Tcl input loop
      +  return 0;
      +}
      +

      +
      But what about commands that span multiple lines of input?
      +

      + +


      +

      Better Handling Of Command-Line Input

      +

      The file "input.tcl"

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +set line {}
      +while {![eof stdin]} {
      +  if {$line!=""} {
      +    puts -nonewline "> "
      +  } else {
      +    puts -nonewline "% "
      +  }
      +  flush stdout
          Prompt for user input. The prompt is normally "%" + but changes to ">" if the current line is a continuation.
      +  append line [gets stdin]
      +  if {[info complete $line]} {
      +    if {[catch {uplevel #0 $line} result]} {    If the command is complete, execute it.
      +      puts stderr "Error: $result"
      +    } elseif {$result!=""} {
      +      puts $result
      +    }
      +    set line {}
      +  } else {
      +    append line \n
      +  }
          If the command is incomplete, append a newline and get + another line of text.
      +}
      + +


      +

      Better Handling Of Command-Line Input

      +

      The file "input.c"

      + + + + + + + + + + + + + +
      +#include <tcl.h>

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_Eval(interp, "source input.tcl");    Read and execute the input loop
      +  return 0;
      +}
      +

      +
      But now the program is not standalone!
      +

      + +


      +

      Converting Scripts Into C Strings

      + + + + +
      +static char zInputLoop[] = 
      +  "set line {}\n"
      +  "while {![eof stdin]} {\n"
      +  "  if {$line!=\"\"} {\n"
      +  "    puts -nonewline \"> \"\n"
      +  "  } else {\n"
      +  "    puts -nonewline \"% \"\n"
      +  "  }\n"
      +  "  flush stdout\n"
      +  "  append line [gets stdin]\n"
      +  "  if {[info complete $line]} {\n"
      +  "    if {[catch {uplevel #0 $line} result]} {\n"
      +  "      puts stderr \"Error: $result\"\n"
      +  "    } elseif {$result!=\"\"} {\n"
      +  "      puts $result\n"
      +  "    }\n"
      +  "    set line {}\n"
      +  "  } else {\n"
      +  "    append line \\n\n"
      +  "  }\n"
      +  "}\n"
      +;
      + +


      +

      Compile Tcl Scripts Into C Programs

      + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>
      +
      +
      +static char zInputLoop[] = 
      +  /* Actual code omitted */
      +;
          Copy and paste the converted Tcl script here
      +
      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_Eval(interp, zInputLoop);    Execute the Tcl code
      +  return 0;
      +}
      + +


      +

      Converting Scripts To Strings
      Using SED Or TCLSH

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +sed -e 's/\\/\\\\/g' \     Convert \ into \\
      +  -e 's/"/\\"/g' \     Convert " into \"
      +  -e 's/^/  "/' \     Add " to start of each line
      +  -e 's/$/\\n"/' input.tcl    Add \n" to end of each line
      +

      +

      +
      +while {![eof stdin]} {
      +  set line [gets stdin]
      +  regsub -all {\} $line {&&} line    Convert \ into \\
      +  regsub -all {"} $line {\"} line    Convert " into \"
      +  puts "\"$line\\n\""    Add " in front and \n" at the end
      +}
      + +


      +

      Converting Scripts Into C Strings

      +

      You may want to save space by removing comments and extra whitespace + from scripts.

      + + + + +
      +static char zInputLoop[] = 
      +  "set line {}\n"
      +  "while {![eof stdin]} {\n"
      +  "if {$line!=\"\"} {\n"
      +  "puts -nonewline \"> \"\n"
      +  "} else {\n"
      +  "puts -nonewline \"% \"\n"
      +  "}\n"
      +  "flush stdout\n"
      +  "append line [gets stdin]\n"
      +  "if {[info complete $line]} {\n"
      +  "if {[catch {uplevel #0 $line} result]} {\n"
      +  "puts stderr \"Error: $result\"\n"
      +  "} elseif {$result!=\"\"} {\n"
      +  "puts $result\n"
      +  "}\n"
      +  "set line {}\n"
      +  "} else {\n"
      +  "append line \\n\n"
      +  "}\n"
      +  "}\n"
      +;
      + +


      +

      Converting Scripts To Strings

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +sed -e 's/\\/\\\\/g' \ 
      +  -e 's/"/\\"/g' \ 
      +  -e '/^ *#/d' \     Delete lines that begin with #
      +  -e '/^ *$/d' \     Delete blank lines
      +  -e 's/^ */  "/' \     Delete leading spaces
      +  -e 's/$/\\n"/' input.tcl

      +

      +

      +while {![eof stdin]} {
      +  set line [gets stdin]
      +  set line [string trimleft $line]    Remove leading space
      +  if {$line==""} continue    Delete blank lines
      +  if {[string index $line 0]=="#"} {
      +    continue
      +  }
          Delete lines starting with #
      +  regsub -all {\} $line {&&} line
      +  regsub -all {"} $line {\"} line
      +  puts "\"$line\\n\""
      +}
      + +


      +

      Removing Comments Or Leading Space
      Will Break Some Tcl Scripts!

      + + + + + + + + + + + + + + + + + + + + + + +
      +image create bitmap smiley -data {
      +#define smile_width 15
      +#define smile_height 15
          These lines begin with # but are not comment
      +static unsigned char smile_bits[] = {
      +   0xc0, 0x01, 0x30, 0x06, 0x0c, 0x18,
      +   0x04, 0x10, 0x22, 0x22, 0x52, 0x25,
      +   0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
      +   0x12, 0x24, 0xe2, 0x23, 0x04, 0x10,
      +   0x0c, 0x18, 0x30, 0x06, 0xc0, 0x01};
      +}

      +

      +text .t
      +pack .t
      +.t insert end [string trim {
      +She walks in beauty, like the night
      +     Of cloudless climes and starry skies;
      +And all that's best of dark and bright
      +     Meet in her aspect and her eyes;
          Indentation is deleted on lines 2 + and 4
      +}] 

      +
      +

      +
      Problems like these are rare
      +

      + +


      +

      Adding A "continue" Command

      + + + + + + + + + + + + + +
      +set line {}
      +while {![eof stdin]} {
      +  if {$line!=""} {
      +    puts -nonewline "> "
      +  } else {
      +    puts -nonewline "% "
      +  }
      +  flush stdout
      +  append line [gets stdin]
      +  if {[info complete $line]} {
      +    if {[lindex $line 0]=="continue"} {
      +      break;
          Break out of the loop if the command + is "continue"
      +    } elseif {[catch {uplevel #0 $line} result]} {
      +      puts stderr "Error: $result"
      +    } elseif {$result!=""} {
      +      puts $result
      +    }
      +    set line {}
      +  } else {
      +    append line \n
      +  }
      +}
      + +


      +

      Stop For Tcl Input At Various Points
      In A C Program

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +static char zInputLoop[] = 
      +  /* Tcl Input loop as a C string */
      +;

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  /* Application C code */    Do some computation
      +  Tcl_Eval(interp, zInputLoop);    Stop for some Tcl input
      +  /* More application C code */    Do more computation
      +  Tcl_Eval(interp, zInputLoop);    Stop for more Tcl input
      +  /* Finish up the application */    Finish the computation
      +  return 0;
      +}
      + +


      +

      Using Tcl For Testing

      + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +static char zInputLoop[] = 
      +  /* Tcl Input loop as a C string */
      +;

      +
      +int main(int argc, char **argv){
      +#ifdef TESTING
      +  Tcl_Interp *interp;
          Create interpreter only if TESTING + is defined
      +  interp = Tcl_CreateInterp();
      +#endif
      +  /* Application C code */
      +#ifdef TESTING
      +  Tcl_Eval(interp, zInputLoop);
      +#endif
          Accept command-line input only if TESTING + is defined
      +  /* More application C code */
      +#ifdef TESTING
      +  Tcl_Eval(interp, zInputLoop);
      +#endif
      +  /* Finish up the application */
      +  return 0;
      +}
      + +


      +

      Creating A New Tcl Command In C

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +int NewCmd(
      +  void *clientData,
      +  Tcl_Interp *interp,
      +  int argc,
      +  char **argv
          The Tcl command is implemented as + a C function with four arguments.
      +){
      +  printf("Hello, World!\n");
      +  return TCL_OK;    Returns TCL_OK or TCL_ERROR
      +}

      +static char zInputLoop[] = 
      +  /* Tcl code omitted... */
      +;

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_CreateCommand(interp, "helloworld",
      +                    NewCmd, 0, 0);
          Tell the interpreter which C function to call when the + "helloworld" Tcl command is executed
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      + +


      +

      Linkage From Tcl To C

      +

      • 3rd parameter of Tcl_CreateCommand() is a pointer to the C subroutine + that implements the command.
      • 4th parameter to Tcl_CreateCommand() becomes the 1st parameter to + the C routine whenever the Tcl command is executed.
      • 1st parameter to Tcl_CreateCommand() must be a valid Tcl interpreter. + The same pointer appears as the second parameter to the C routine + whenever the Tcl command is executed.

      + +


      +

      Linkage From Tcl To C

      +

      • 5th parameter of Tcl_CreateCommand() is a pointer to the C subroutine + that is called when the Tcl command is deleted.
      • 4th parameter to Tcl_CreateCommand() becomes the 1st parameter to + the C routine.

      + +


      +

      When To Use A Delete Proc

      +

      Examples of where the delete proc is used in standard Tcl/Tk:

      + + + + + + + + + + + + + + + + + + + + + + +
      +button .b -text Hello
      +pack .b
      +rename .b {}    Deleting the .b command causes the button to be destroyed
      +

      +
      +image create photo smiley \ 
      +    -file smiley.gif
      +rename smiley {}    Deleting the smiley command destroys the image and reclaims the + memory used to hold the image
      +

      • Always use a delete proc if the clientData is a pointer to + malloced memory or some other resource that needs freeing
      • Delete procs are never used in the Tcl core but are used + extensively in Tk

      + +


      +

      Linkage From Tcl To C

      +

      The argc and argv parameters work just like in + main()

      + + + + + + + +
      +helloworld one {two three} four    argc = 4
      + argv[0] = "helloworld"
      + argv[1] = "one"
      + argv[2] = "two three"
      + argv[3] = "four"
      + argv[4] = NULL
      + +


      +

      A Short-Cut

      +

      In a program with many new Tcl commands implemented in C, it becomes + tedious to type the same four parameters over and over again. So + we define a short-cut.

      + + + + + + + + + + + + + + + + + + + +
      +#define TCLARGS \ 
      +    void *clientData, \ 
      +    Tcl_Interp *interp, \ 
      +    int argc, \ 
      +    char *argv
          Define TCLARGS once in a header file
      + 

      +int NewCmd(TCLARGS){    Use the TCLARGS macro to define new C functions + that implement Tcl commands.
      +   /* implementation... */
      +}
      +

      +
      For brevity, we will use the TCLARGS macro during the + rest of this talk.
      +

      + +


      +

      Returning A Value From C Back To Tcl

      + + + + + + + + + + + + + + + + +
      +int NewCmd(TCLARGS){    Note that the C function returns an "int"
      +  return TCL_OK;    Return value is TCL_OK or TCL_ERROR
      +}
      +

      • TCL_OK and TCL_ERROR are defined in <tcl.h>
      • Other valid return values TCL_RETURN, TCL_BREAK and TCL_CONTINUE + are rarely used
      • Common mistake: forgetting to return TCL_OK

      + +


      +

      Returning A Value From C Back To Tcl

      + + + + + + + + + + + + + +
      +int NewCmd(TCLARGS){
      +  Tcl_SetResult(interp,"Hello!",TCL_STATIC);    Set the result to "Hello!"
      +  return TCL_OK;
      +}
      +

      • Result should be the text of an error message if you + return TCL_ERROR.
      • 3rd argument to Tcl_SetResult() can be TCL_STATIC, + TCL_DYNAMIC, TCL_VOLATILE, or a function pointer.
      • Also consider using Tcl_AppendResult().
      • Direct access to interp->result is deprecated.
      • See the man pages for details.

      + +


      +

      The Tcl_Obj Interface

      +

      • A new way to write Tcl commands in C code
      • First introduced in Tcl8.0
      • Can be much faster, especially for lists or numeric values.
      • Able to handle arbitrary binary data.
      • More difficult to program.

      +


      +

      The Tcl_Obj Interface

      + + + + + + + + + + + + + + + + + + + + + + +
      +int NewObjCmd(
      +  void *clientData,
      +  Tcl_Interp *interp,
      +  int objc,
      +  Tcl_Obj *const* objv    4th parameter is an array Tcl_Objs, not an array of strings
      +){
      +  /* Implementation... */
      +  return TCL_OK;
      +}

      +static char zInputLoop[] = 
      +  /* Tcl code omitted... */
      +;

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_CreateObjCommand(interp, "newcmd",
      +                       NewObjCmd, 0, 0);
          Use a different function to register the command
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      + +


      +

      The Tcl_Obj Interface

      +

      • There are countless access methods for reading information from and + placing information in Tcl_Objs. Always use the access methods.
      • Details provided at Lee Bernhard's talk this afternoon.
      • Definitely use Tcl_Objs if you are writing a new Tcl extension.
      • Tcl_Objs address some of the weaknesses of Tcl relative to C/C++. +
          +
        • Tcl_Objs are faster
        • +
        • Tcl_Objs work with binary data
        • +
        + But C/C++ is faster still and better for working with binary data.
      • When mixing C/C++ with Tcl/Tk the benefits of Tcl_Objs are + less important. Using Tcl_Objs in this context may not be + worth the extra trouble.
      • This talk will focus on the string interface.

      +


      +

      Nickel Tour Of The Tcl API

      +

      Memory allocation functions

      +
      + + + +
      + Tcl_Alloc
      +
      + Tcl_Free
      +
      + Tcl_Realloc
      +

      Functions useful in the implementation of new Tcl commands

      +
      + + + +
      + Tcl_AppendElement
      + Tcl_AppendResult
      + Tcl_GetBoolean
      +
      + Tcl_GetDouble
      + Tcl_GetInt
      + Tcl_GetStringResult
      +
      + Tcl_ResetResult
      + Tcl_SetResult
      +

      Functions for controlling the Tcl interpreter

      +
      + + + +
      + Tcl_CreateCommand
      + Tcl_CreateInterp
      +
      + Tcl_CreateObjCommand
      + Tcl_DeleteCommand
      +
      + Tcl_DeleteInterp
      + Tcl_Exit
      +

      +


      +

      Nickel Tour Of The Tcl API

      +

      I/O functions

      +
      + + + +
      + Tcl_Close
      + Tcl_Eof
      + Tcl_Flush
      + Tcl_GetChannel
      + Tcl_GetChannelMode
      + Tcl_GetChannelName
      +
      + Tcl_Gets
      + Tcl_OpenCommandChannel
      + Tcl_OpenFileChannel
      + Tcl_OpenTcpClient
      + Tcl_OpenTcpServer
      + Tcl_Read
      +
      + Tcl_Seek
      + Tcl_Tell
      + Tcl_Ungets
      + Tcl_Write
      + Tcl_WriteChars
      +

      Names and meanings of system error codes

      +
      + + + +
      + Tcl_ErrnoId
      + Tcl_ErrnoMsg
      +
      + Tcl_GetErrno
      + Tcl_SetErrno
      +
      + Tcl_SignalId
      + Tcl_SignalMsg
      +

      +


      +

      Nickel Tour Of The Tcl API

      +

      General Operating System Calls

      +
      + + + +
      + Tcl_Access
      + Tcl_Chdir
      + Tcl_GetCwd
      +
      + Tcl_GetHostName
      + Tcl_GetNameOfExecutable
      + Tcl_Sleep
      +
      + Tcl_Stat
      +

      String Manipulation And Comparison

      +
      + + + +
      + Tcl_Concat
      + Tcl_Merge
      +
      + Tcl_SplitList
      + Tcl_StringCaseMatch
      +
      + Tcl_StringMatch
      +

      Dynamically Resizable Strings

      +
      + + +
      + Tcl_DStringAppend
      + Tcl_DStringAppendElement
      + Tcl_DStringEndSublist
      + Tcl_DStringInit
      + Tcl_DStringLength
      +
      + Tcl_DStringResult
      + Tcl_DStringSetLength
      + Tcl_DStringStartSublist
      + Tcl_DStringValue
      +

      +


      +

      Nickel Tour Of The Tcl API

      +

      Event Handlers

      +
      + + +
      + Tcl_CancelIdleCall
      + Tcl_CreateChannelHandler
      + Tcl_CreateTimerHandler
      + Tcl_DeleteChannelHandler
      +
      + Tcl_DeleteTimerHandler
      + Tcl_DoOneEvent
      + Tcl_DoWhenIdle
      +

      Functions For Reading And Writing Tcl Variables

      +
      + + + +
      + Tcl_GetVar
      + Tcl_GetVar2
      + Tcl_LinkVar
      + Tcl_SetVar
      + Tcl_SetVar2
      +
      + Tcl_TraceVar
      + Tcl_TraceVar2
      + Tcl_UnlinkVar
      + Tcl_UnsetVar
      + Tcl_UnsetVar2
      +
      + Tcl_UntraceVar
      + Tcl_UntraceVar2
      + Tcl_UpdateLinkedVar
      +

      Functions For Executing Tcl Code

      +
      + + + +
      + Tcl_Eval
      + Tcl_EvalFile
      +
      + Tcl_EvalObj
      + Tcl_GlobalEval
      +
      + Tcl_GlobalEvalObj
      + Tcl_VarEval
      +

      +


      +

      Nickel Tour Of The Tcl API

      +

      Functions For Dealing With Unicode

      +
      + + +
      + Tcl_NumUtfChars
      + Tcl_UniCharAtIndex
      + Tcl_UniCharIsAlnum
      + Tcl_UniCharIsAlpha
      + Tcl_UniCharIsControl
      + Tcl_UniCharIsDigit
      + Tcl_UniCharIsGraph
      + Tcl_UniCharIsLower
      + Tcl_UniCharIsPrint
      + Tcl_UniCharIsPunct
      + Tcl_UniCharIsSpace
      + Tcl_UniCharIsUpper
      + Tcl_UniCharIsWordChar
      + Tcl_UniCharLen
      + Tcl_UniCharNcmp
      + Tcl_UniCharToLower
      + Tcl_UniCharToTitle
      +
      + Tcl_UniCharToUpper
      + Tcl_UniCharToUtf
      + Tcl_UniCharToUtfDString
      + Tcl_UtfAtIndex
      + Tcl_UtfBackslash
      + Tcl_UtfCharComplete
      + Tcl_UtfFindFirst
      + Tcl_UtfFindLast
      + Tcl_UtfNcasecmp
      + Tcl_UtfNcmp
      + Tcl_UtfNext
      + Tcl_UtfPrev
      + Tcl_UtfToLower
      + Tcl_UtfToTitle
      + Tcl_UtfToUniChar
      + Tcl_UtfToUniCharDString
      + Tcl_UtfToUpper
      +
      +

      Functions For Dealing With Tcl_Objs

      +
      Too numerous to list...

      +


      +

      Documentation Of The Tcl API

      +

      • Tcl comes with excellent man pages
      • "Use the source, Luke"
      • See tclDecl.h for a list of API functions
      • The header comments on the implementation of API functions usually + gives a good description of what the function does and how it should + be used.
      • Most API functions are used within Tcl and Tk. Use grep to locate + examples.

      +


      +

      Initialization Scripts

      +

      • Run the mini TCLSH implemented above and execute the parray command
      • It doesn't work! What's wrong?

      • parray is really a Tcl proc that is read in when the + interpreter is initialized.

      • parray (and several other commands) are stored in a + handful of "Initialization Scripts"

      • All the initialization scripts are stored in the + "Tcl Library" - a directory on the host + computer.

      +
      Invoke the Tcl_Init() function to locate and read the + Tcl initialization scripts.

      +


      +

      The Tcl_Init() Function

      + + + + + + + + + + + + + +
      +#include <tcl.h>

      +static char zInputLoop[] = 
      +  /* Tcl code omitted... */
      +;

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_Init(interp);    Locate and read the initialization scripts
      +  /* Call Tcl_CreateCommand()? */
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      +

      +
      But Tcl_Init() can fail. We need to check its return value...
      +

      + +


      +

      The Tcl_Init() Function

      + + + + + + + + + + + + + +
      +#include <tcl.h>

      +static char zInputLoop[] = 
      +  /* Tcl code omitted... */
      +;

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  if( Tcl_Init(interp)!=TCL_OK ){
      +    fprintf(stderr,"Tcl_Init() failed: 厚PX",
      +       Tcl_GetStringResult(interp));
      +  }
          Print error message if Tcl_Init() fails
      +  /* Call Tcl_CreateCommand()? */
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      +

      +
      But now the program is not standalone.
      +

      + +


      +

      How Tcl_Init() Works

      +

      • Computes the value of variable tcl_libPath.
      • Invokes the procedure named "tclInit"
      • A default tclInit procedure is built into Tcl. + You can define an alternative tclInit procedure + prior to calling Tcl_Init().

      +


      +

      The Default initTcl Procedure

      + + + + +
      +set errors {}
      +set dirs {}
      +if {[info exists tcl_library]} {
      +  lappend dirs $tcl_library
      +} else {
      +  if {[info exists env(TCL_LIBRARY)]} {
      +    lappend dirs $env(TCL_LIBRARY)
      +  }
      +  lappend dirs $tclDefaultLibrary
      +  unset tclDefaultLibrary
      +  set dirs [concat $dirs $tcl_libPath]
      +}
      +foreach i $dirs {
      +  set tcl_library $i
      +  set tclfile [file join $i init.tcl]
      +  if {[file exists $tclfile]} {
      +    if {![catch {uplevel #0 [list source $tclfile]} msg]} {
      +      return
      +    } else {
      +      append errors "$tclfile: $msg\n$errorInfo\n"
      +    }
      +  }
      +}
      +error "Can't find a usable init.tcl ..."
      + +


      +

      The Default Initialization Sequence

      +

      • The tclInit procedure locates and sources the init.tcl + script. The directory that contains init.tcl is stored in + the tcl_library variable.
      • The init.tcl script creates an unknown procedure. + The unknown procedure will run whenever Tcl encounters an + unknown command.
      • The unknown procedure consults the file tclIndex in the + tcl_library directory to see if the command is defined by one of + the initialization scripts.
      • The unknown procedure sources any needed initialization scripts + and retries the command.
      +
      Commands defined in the initialization scripts are loaded + on demand.

      +


      +

      Standalone Initialization Techniques

      +

      Manually execute all initialization scripts

      +
      • Convert all initialization scripts into C strings and + put them in the executable.
      • Call Tcl_Eval() on each initialization script and omit the + call to Tcl_Init()
      • Or, redefine tclInit so that it does not attempt to source + init.tcl then call Tcl_Eval() on each initialization + script after Tcl_Init() returns.
      +
      This approach is not recommended

      +


      +

      Standalone Initialization Techniques

      +

      Redefining the builtin source command

      +
      • Convert all initialization scripts into C strings and + put them in the executable.
      • Create a new source command that + calls Tcl_Eval() on the appropriate built-in string + instead of reading from the disk.
      • Read from disk if the named file is not one that is built in.

      +


      +

      Redefining source

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +static char zInitTcl[] = "...";
      +static char zParrayTcl[] = "...";
          Scripts init.tcl and parray.tcl
      +
      +int NewSourceCmd(TCLARGS){
      +  if( !strcmp(argv[1],"/builtin/init.tcl") )
      +    return Tcl_Eval(interp, zInitTcl);
      +  if( !strcmp(argv[1],"/builtin/parray.tcl") )
      +    return Tcl_Eval(interp, zParrayTcl);
          Call Tcl_Eval() on builtin strings if the names match
      +  return Tcl_EvalFile(interp, argv[1]);    Call Tcl_EvalFile() if no match
      +}

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  setenv("TCL_LIBRARY","/builtin");    Causes tclInit to look for init.tcl in /builtin
      +  interp = Tcl_CreateInterp();
      +  Tcl_CreateCommand(interp, "source",
      +                    NewSourceCmd, 0, 0);
          Redefine source
      +  Tcl_Init(interp);
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      + +


      +

      Redefining source

      +

      • This approach works for all versions of Tcl and Tk.
      • Also need to redefine the "file exists" Tcl command since it + too is used by tclInit.
      • To verify that the program is really standalone, remove the call + to Tcl_EvalFile().

      +


      +

      Standalone Initialization Techniques

      +

      Use the Tcl*InsertProc() functions

      +
      • Three routines that overload basic file I/O operations: +
          +
        • TclStatInsertProc()
        • +
        • TclAccessInsertProc()
        • +
        • TclOpenFileChannelInsertProc()
        • +
      • Allows us to implement a virtual filesystem that overlays the + real filesystem.
      • The virtual filesystem contains all the initialization scripts + as compiled-in strings. The initialization scripts look like + they are resident on disk even though they are built in.
      • These functions first appeared in Tcl8.0.3. + Presumably to support TclPro Wrapper.
      • The only documentation is comments on the code. + See the Tcl source file generic/tclIOUtil.c

      +


      +

      The TclStatInsertProc() Function

      +

      • Sole argument is a pointer to a function whose interface is the + same as stat()
      • Functions are stacked. Tcl tries each stat function on the + list, beginning with the most recently inserted, until one succeeds.

      +


      +

      The TclStatInsertProc() Function

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tclInt.h>    Rather than <tcl.h>!
      +
      +static int
      +BltinFileStat(char *path,struct stat *buf){
      +  char *zData;
      +  int nData;
      +  zData = FindBuiltinFile(path, 0, &nData);    Check if path is a builtin
      +  if( zData==0 ){
      +    return -1;
      +  }
          Fail if path is not a builtin
      +  memset(buf, 0, sizeof(*buf));
      +  buf->st_mode = 0400;
      +  buf->st_size = nData;
      +  return 0;    Success if it is builtin
      +}

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  TclStatInsertProc(BltinFileStat);    Register new stat function
      +  interp = Tcl_CreateInterp();
      +  Tcl_Init(interp);
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      + +


      +

      The TclAccessInsertProc() Function

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tclInt.h>    Rather than <tcl.h>!
      +
      +/* BltinFileStat() not shown... */

      +static int
      +BltinFileAccess(char *path, int mode){
      +  char *zData;
      +  if( mode & 3 ) return -1;    All builtins are read-only
      +  zData = FindBuiltinFile(path, 0, &nData);    Check if path is a builtin
      +  if( zData==0 ) return -1;    Fail if path is not a builtin
      +  return 0;    Success if it is builtin
      +}

      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  TclStatInsertProc(BltinFileStat);
      +  TclAccessInsertProc(BltinFileAccess);
          Register new stat and access functions
      +  interp = Tcl_CreateInterp();
      +  Tcl_Init(interp);
      +  Tcl_Eval(interp, zInputLoop);
      +  return 0;
      +}
      + +


      +

      The TclOpenFileChannelInsertProc() Function

      + + + + +
      +static Tcl_Channel BuiltinFileOpen(
      +  Tcl_Interp *interp,   /* The TCL interpreter doing the open */
      +  char *zFilename,      /* Name of the file to open */
      +  char *modeString,     /* Mode string for the open (ignored) */
      +  int permissions       /* Permissions for a newly created file (ignored) */
      +){
      +  char *zData;
      +  BuiltinFileStruct *p;
      +  int nData;
      +  char zName[50];
      +  Tcl_Channel chan;
      +  static int count = 1;

      +  zData = FindBuiltinFile(zFilename, 1, &nData);
      +  if( zData==0 ) return NULL;
      +  p = (BuiltinFileStruct*)Tcl_Alloc( sizeof(BuiltinFileStruct) );
      +  if( p==0 ) return NULL;
      +  p->zData = zData;
      +  p->nData = nData;
      +  p->cursor = 0;
      +  sprintf(zName,"etbi_bffffc7c_8049b04",((int)BuiltinFileOpen)>>12,count++);
      +  chan = Tcl_CreateChannel(&builtinChannelType, zName, 
      +                           (ClientData)p, TCL_READABLE);
      +  return chan;
      +}
      + +


      +

      The TclOpenFileChannelInsertProc() Function

      + + + + +
      +static Tcl_ChannelType builtinChannelType = {
      +  "builtin",          /* Type name. */
      +  NULL,               /* Always non-blocking.*/
      +  BuiltinFileClose,   /* Close proc. */
      +  BuiltinFileInput,   /* Input proc. */
      +  BuiltinFileOutput,  /* Output proc. */
      +  BuiltinFileSeek,    /* Seek proc. */
      +  NULL,               /* Set option proc. */
      +  NULL,               /* Get option proc. */
      +  BuiltinFileWatch,   /* Watch for events on console. */
      +  BuiltinFileHandle,  /* Get a handle from the device. */
      +};
      +

      +

      For additional information see:

      +
        +
      • The man page for Tcl_CreateChannel()
      • +
      • Tk source code file generic/tkConsole.c
      • +
      +

      + +


      +

      Initializing Tk

      +

      • All the same initialization script issues as Tcl
      • Tk initialization scripts are in a different directory + than the Tcl initialization scripts - the "Tk Library"
      • Call Tk_Init() after Tcl_Init()
      • Must have an event loop or Tk will not work!

      +


      +

      Implementing An Event Loop

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      +button .b -text Hello -command exit
      +pack .b
          Create a Tk interface
      +
      +
      +bind . <Destroy> {
      +  if {![winfo exists .]} exit
      +}
          Close the application when the main window + is destroyed
      +
      +
      +while 1 {vwait forever}    The event loop
      + +


      +

      "Hello, World!" Using Tk

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tk.h>

      +
      +static char zHello[] =     The application code
      +  "button .b "
      +    "-text {Hello, World} "
      +    "-command exit\n"
      +  "pack .b\n";

      +
      +static char zEventLoop[] =    The event loop
      +  "bind . <Destroy> {\n"
      +  "  if {![winfo exists .]} exit\n"
      +  "}\n"
      +  "while 1 {vwait forever}\n";

      +
      +int main(int argc, char **argv){
      +  Tcl_Interp *interp;
      +  interp = Tcl_CreateInterp();
      +  Tcl_Init(interp);
      +  Tk_Init(interp);
          We really should check the return values of the init functions...
      +  Tcl_Eval(interp, zHello);
      +  Tcl_Eval(interp, zEventLoop);    The event loop never returns
      +  /*NOTREACHED*/
      +}
      + +


      +

      Compiling "Hello, World!" For Tk

      +

      Unix:

      +
      +  $ gcc hello.c -ltk -L/usr/X11R6/lib \ 
      +        -lX11 -ltcl -lm -ldl
      +  $ ./a.out
      + +

      Windows using Cygwin:

      +
      +  C:> gcc hello.c -mwindows -ltk80 -ltcl80 -lm
      +  C:> a.exe
      + +

      Windows using Mingw32:

      +
      +  C:> gcc -mno-cygwin hello.c -mwindows \ 
      +           -ltk82 -ltcl82 -lm
      +  C:> a.exe

      +


      +

      Making The Program Standalone

      +

      To make a Tcl application standalone you have to convert the following + initialization scripts to C strings and compile them into the + executable:

      + + + + + +
      +   auto.tcl
      +   history.tcl
      +   init.tcl +
      +   ldAout.tcl
      +   package.tcl +
      +   parray.tcl
      +   safe.tcl +
      +   tclIndex
      +   word.tcl +
      + +

      To make a Tk application standalone requires these additional + initialization scripts from the Tk Library:

      + + + + + +
      +   bgerror.tcl
      +   button.tcl
      +   clrpick.tcl
      +   comdlg.tcl
      +   console.tcl
      +   dialog.tcl +
      +   entry.tcl
      +   focus.tcl
      +   listbox.tcl
      +   menu.tcl
      +   msgbox.tcl
      +   optMenu.tcl +
      +   palette.tcl
      +   safetk.tcl
      +   scale.tcl
      +   scrlbar.tcl
      +   tclIndex
      +   tearoff.tcl +
      +   text.tcl
      +   tk.tcl
      +   tkfbox.tcl
      +   xmfbox.tcl +
      + +

      Total of about 13K lines and 400K bytes of text or 9K lines and + 250K bytes if you strip comments and leading spaces

      +


      +

      A Review Of The Features We Want

      +

        +
      1. + Combine C/C++ with Tcl/Tk into a single executable. +
      + +
        +
      1. + The executable should be standalone. It must not depend + on files not normally found on the system. +
      + +
        +
      1. + It should be difficult for end users to alter the program + (and introduce bugs). +

      +


      +

      Available Programming Aids

      +

      Several tools are available. The chart below shows which tools + help achieve which objectives.

      + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + Features The Tool Helps To Achieve
      Tool NameMix C and TclStandaloneHide Source
      SWIG  
      TclPro Wrapper 
      FreeWrap 
      Wrap  
      mktclapp

      +


      +

      SWIG

      + +

      • Creates an interface between an existing C/C++ library and a high-level + programming language. Support for: +
          +
        • Tcl/Tk
        • +
        • Perl
        • +
        • Python
        • +
        • Java
        • +
        • Eiffel
        • +
        • Guile
        • +
      • No changes required to C/C++ code. Can be used with legacy libraries.
      • Generates an extension, not a standalone binary
      • The tutorial on SWIG was yesterday afternoon.
      • http://www.swig.org/

      + +


      +

      Wrapper Programs

      + +

      • Convert a pure Tcl/Tk program into a standalone binary
      • Several wrapper programs are available: +
          +
        • TclPro Wrapper - http://www.scriptics.com/
        • +
        • FreeWrap - http://www.albany.net/~dlabelle/freewrap/freewrap.html
        • +
        • Wrap - http://members1.chello.nl/~j.nijtmans/wrap.html
        • +
      • No C compiler required!
      • TclPro will convert Tcl script into bytecode so that it cannot be + easily read by the end user. FreeWrap encrypts the scripts.
      • FreeWrap uses compression on its executable. + Wrap uses compression on both the executable and on the bundled script files.
      • Usually include extensions like winico and/or BLT

      + +


      +

      mktclapp

      + +

      • Mix C/C++ with Tcl/Tk into a standalone binary
      +
      • mktclapp generates an application initialization file + that contains Tcl scripts as strings and makes all necessary calls + to Tcl_Init, Tcl_CreateCommand, + Tcl*InsertProc, etc.
      • Features to make it easier to write new Tcl command in C
      • xmktclapp.tcl provides a GUI interface to mktclapp
      • http://www.hwaci.com/sw/mktclapp/

      + +


      +

      "Hello, World!" Using Mktclapp

      +

      • Download mktclapp.c and xmktclapp.tcl from + http://www.hwaci.com/sw/mktclapp/
      • Compile mktclapp: +
        +  cc -o mktclapp mktclapp.c
        +  
      • Create "Hello, World!" as a Tcl script in file hw.tcl: +
        +  button .b -text {Hello, World!} -command exit
        +  pack .b
        +  
      • Launch xmktclapp: +
        +  wish xmktclapp.tcl
        +  

      +


      +

      "Hello, World!" Using Mktclapp

      + +

      • Set "Command Line Input?" to "None"
      • Set "Standalone?" to "Yes"
      • Enter "hw.mta" for the Configuration File
      • Enter "hw.c" for the Output C File

      + +


      +

      "Hello, World!" Using Mktclapp

      + +

      • Go to the "Tcl Scripts" page
      • Press "Insert" and add hw.tcl to the list of + Tcl scripts
      • Change the "Startup Script" to be hw.tcl.
      • Select File/Build and File/Exit

      + +


      +

      "Hello, World!" Using Mktclapp

      +

      • Mktclapp generates hw.c. + Compile it something like this: +
        +  cc hw.c -ltk -L/usr/X11R6/lib -lX11 -ltcl -lm -ldl
        +  
      • Or, if using Cygwin: +
        +  gcc hw.c -mwindows -ltk80 -ltcl80 -lm
        +  
      • Or, if using Mingw32: +
        +  gcc -mno-cygwin hw.c -mwindows -ltk82 -ltcl82 -lm
        +  
      • And you're done!

      +


      +

      Adding C Code To Your Program

      +

      Put the new C code in a new source file named "add.c"

      + + + + + + + + + + + + + + + + + + + +
      +#include "hw.h"    Generated by mktclapp
      +
      +int ET_COMMAND_add(ET_TCLARGS){    ET_TCLARGS is a macro defined in hw.h
      +  int a, b;
      +  char zResult[30];
      +  a = atoi(argv[1]);
      +  b = atoi(argv[2]);
      +  sprintf(zResult, "-1073742724", a+b);
      +  Tcl_SetResult(interp, zResult, TCL_VOLATILE);
      +  return TCL_OK;
      +}
      + +


      +

      Adding C Code To Your Program

      + +

      • Go to the "C/C++ Modules" page of xmktclapp.tcl
      +
      • Press "Insert" and add add.c to the list of + C/C++ modules

      • Select File/Build and File/Exit

      + +


      +

      Adding C Code To Your Program

      +

      • Compile as follows: +
        +  cc add.c hw.c -ltk -L/usr/X11R6/lib -ltcl -lm -ldl
        +  
      • Or construct a Makefile that compiles add.c into add.o + and hw.c into hw.o and then links them.
      • Compile the same way for Windows except use the usual Windows + libraries and options...
      +
      Don't have to worry with Tcl_CreateCommand() - Mktclapp takes + care of that automatically.

      +


      +

      Checking Parameters In The add Command

      +

      Modify add.c to insure the add command + is called with exactly two integer arguments

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include "hw.h"

      +int ET_COMMAND_add(ET_TCLARGS){
      +  int a, b;
      +  char zResult[30];
      +  if( argc!=3 ){
      +    Tcl_AppendResult(interp,
      +      "wrong # args: should be: \"",
      +      argv[0], " VALUE VALUE\"", 0);
      +    return TCL_ERROR;
      +  }
          Report an error if there are not exactly + 2 arguments
      +  if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ){
      +    return TCL_ERROR;
      +  }
          Report an error if the first argument is + not an integer
      +  if( Tcl_GetInt(interp, argv[2], &b)!=TCL_OK ){
      +    return TCL_ERROR;
      +  }
          Do the same for the second argument
      +  sprintf(zResult, "-1073742724", a+b);
      +  Tcl_SetResult(interp, zResult, TCL_VOLATILE);
      +  return TCL_OK;
      +}
      + +


      +

      Using The Tcl_Obj Interface

      +

      In the file objadd.c put this code:

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include "hw.h"
      +
      +int ET_OBJCOMMAND_add2(ET_OBJARGS){
      +  int a, b;
          Use "ET_OBJCOMMAND" instead of "ET_COMMAND" and + "ET_OBJARGS" instead of "ET_TCLARGS"
      +  if( objc!=3 ){
      +    Tcl_WrongNumArgs(interp, 1, objv,
      +      "number number");
      +    return TCL_ERROR;
      +  }
          A special routine for "wrong # args" error
      +  if( Tcl_GetIntFromObj(interp, objv[1], &a) ){    Instead of Tcl_GetInt
      +    return TCL_ERROR;
      +  }
      +  if( Tcl_GetIntFromObj(interp, objv[2], &b) ){
      +    return TCL_ERROR;
      +  }
      +  Tcl_SetIntObj(Tcl_GetObjResult(interp), a+b);    Result stored as integer, not a string
      +  return TCL_OK;
      +}
      + +


      +

      Speed Of Tcl_Obj Versus "char*" Interfaces

      +

      • Compile both add and add2 into the same executable.
      • Compare their speeds: +
        +   time {add 123456 654321} 10000
        +  26 microseconds per iteration
        +   time {add2 123456 654321} 10000
        +  4 microseconds per iteration
        +  
      • The Tcl_Obj version is 650 faster!
      • Replace the addition with a "real" computation that takes + 10 milliseconds.
      • Now the Tcl_Obj version is only 0.2 faster!
      +
      In many real-world problems, the Tcl_Obj interface has no noticeable + speed advantage over the string interface.

      +


      +

      More About Built-in Tcl Scripts

      + +

      • Comments and leading white-space are removed from the + script by default. Use the "Don't Strip Comments" + button to change this.
      • The file name must exactly match the name that is + used by the source command.

      + +


      +

      Locations Of Libraries

      + +

      • Tells mktclapp where to look for script libraries.
      • All Tcl scripts in the indicated directories are + compiled into the appinit.c file.
      • Comments and extra white-space are removed. + There is no way to turn this off.

      + +


      +

      Built-in Binary Data Files

      + +

      • Arbitrary files become part of the virtual filesystem
      • No comment or white-space removal is attempted
      • Useful for images or other binary data

      + +


      +

      New Commands In Namespaces

      +

      Two underscores (__) are replaced by two colons (::) in + command names, thus giving the ability to define new commands + in a namespace

      + + + + + + + + + + + + + +
      +#include <hw.h>
      +
      +int ET_COMMAND_adder__add(ET_TCLARGS){
      +  int a, b;
          Creates the Tcl command called "adder::add"
      +  char *zResult[30];
      +  if( argc!=3 ){
      +    Tcl_AppendResult(interp,
      +      "wrong # args: should be: \"",
      +      argv[0], " VALUE VALUE\"", 0);
      +    return TCL_ERROR;
      +  }
      +  if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ){
      +    return TCL_ERROR;
      +  }
      +  if( Tcl_GetInt(interp, argv[1], &b)!=TCL_OK ){
      +    return TCL_ERROR;
      +  }
      +  sprintf(zResult, "-1073742724", a+b);
      +  Tcl_SetResult(interp, zResult, TCL_VOLATILE);
      +  return TCL_OK;
      +}
      + +


      +

      Adding Your Own main()

      + + + + + + + + + + + + + +
      +int main(int argc, char **argv){
      +  /* Application specific initialization */
      +  Et_Init(argc, argv);    Never returns!
      +  /*NOTREACHED*/
      +  return 0;
      +}
      +

      +
      The "Autofork" feature is disabled if you supply your own main()
      +

      + +


      +

      Initializing The Tcl Interpreter

      + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +int counter = 0;

      +int main(int argc, char **argv){
      +   Et_Init(argc, argv);
      +   /*NOTREACHED*/
      +   return 0;
      +}

      +int Et_AppInit(Tcl_Interp *interp){
      +  if( Blt_Init(Interp) ){
      +    return TCL_ERROR;
      +  }
          Example: Initialize an extension
      +  Tcl_LinkVar(interp, "counter", &counter,
      +              TCL_LINK_INT);
          Or link a C variable to a Tcl variable
      +  return TCL_OK;    Return TCL_OK if successful
      +}
      + +


      +

      Writing Your Own Event Loop

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>
      +
      +void Et_CustomMainLoop(Tcl_Interp *interp){    Replaces the default event loop
      +  return;    Ex: Return without handling any events.
      +}

      +int main(int argc, char **argv){
      +  Et_Init(argc, argv);    This now returns after initializing Tcl
      +  /* Application code here */
      +  return 0;
      +}
      + +


      +

      Writing Your Own Event Loop

      + + + + + + + + + + + + + + + + + + + + + + +
      +#include <tcl.h>

      +void Et_CustomMainLoop(Tcl_Interp *interp){
      +  for(;;){
      +    Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
      +    /* Other processing... */
      +  }
          Intermix processing and event handling
      +}

      +int main(int argc, char **argv){
      +  Et_Init(argc, argv);    Never returns
      +  /*NOTREACHED*/
      +  return 0;
      +}
      + +


      +

      Mktclapp Initialization Sequence

      +

      • Initialization starts when the Et_Init() + function is called either by client code or by + the main() that mktclapp generates
      • Create the main Tcl interpreter
      • Construct the virtual filesystem overlay by redefining + the source command and by using the + Tcl*InsertProc() functions
      • Call Et_PreInit() if the client defines it
      • Call Tcl_Init() and Tk_Init()
      • Call Tcl_CreateCommand() and Tcl_CreateObjCommand() + for every ET_COMMAND_* and ET_OBJCOMMAND_* function + in the client code
      • Call Et_AppInit() if the client defines it
      • Run the main Tcl script if there is one
      • Call Et_CustomMainLoop() if defined by client code or + else run the built-in event loop

      +


      +

      Invoking Tcl From C

      +

      • Use one of the built-in evaluation functions: +
        + + +
          +
        • Tcl_Eval()
        • +
        • Tcl_VarEval()
        • +
        • Tcl_EvalFile()
        • +
        • Tcl_GlobalEval()
        • +
          +
        • Tcl_EvalObj()
        • +
        • Tcl_GlobalEvalObj()
        • +
      • Mktclapp provides evaluation functions with variable argument + lists as in printf(): +
          +
        • Et_EvalF()
        • +
        • Et_GlobalEvalF()
        • +
      • Mktclapp provides a global variable Et_Interp which is + a pointer to the main interpreter

      +


      +

      Invoking Tcl From C

      +

      Example: A C function that pops up an error message dialog box

      + + + + +
      +#include "appinit.h"

      +void ErrMsg(char *zMsg){
      +  Tcl_SetVar(Et_Interp, "zMsg", zMsg, TCL_GLOBAL_ONLY);
      +  Tcl_GlobalEval(Et_Interp, 
      +    "tk_messageBox -icon error -msg $zMsg -type ok");
      +  Tcl_UnsetVar(Et_Interp, "zMsg", TCL_GLOBAL_ONLY);
      +}
      + +


      +

      Invoking Tcl From C

      +

      The same C function implemented using Et_EvalF() instead + of Tcl_GlobalEval()

      + + + + +
      +#include "appinit.h"

      +void ErrMsg(char *zMsg){
      +  Et_EvalF(Et_Interp, 
      +    "tk_messageBox -icon error -msg {厚PX} -type ok",
      +    zMsg);
      +}
      +

      +

      • + Suppose the function is called as follows: +
        + ErrMsg("Syntax error near \"}\""); +
        +
      + +
      • + The command that gets executed is: +
        +    tk_messageBox -icon error -msg \ 
        +        {Syntax error near "}"} -type ok
        +  
        +
      + +
      • + But this is an ill-formed Tcl command! +
      +

      + +


      +

      Invoking Tcl From C

      +

      Use the "" format to generate a quoted string

      + + + + +
      +#include "appinit.h"

      +void ErrMsg(char *zMsg){
      +  Et_EvalF(Et_Interp, 
      +    "tk_messageBox -icon error -msg \"%\" -type ok",
      +    zMsg);
      +}
      +

      • The puts a backslash before all characters that + are special to Tcl
      • The Tcl command becomes: +
        +    tk_messageBox -icon error -msg \ 
        +        "Syntax error near \"\}\"" -type ok
        +  

      + +


      +

      Other Functions Provided By Mktclapp

      +

      • void Et_ResultF(Tcl_Interp*, ...);
      • char *Et_DStringAppendF(Tcl_DString*, ...);
      • int Et_AppendObjF(Tcl_Obj*, ...);
      • char *mprintf(const char *format, ...);
        + char *vmprintf(const char *format, va_list);
      • void Et_NewBuiltinFile(char *filename, char *data, int amt);

      +


      +

      Operating Mktclapp From The Command Line

      +

      • Generate the appinit.h header file like this: +
        + mktclapp -header >appinit.h +
      • Generate the appinit.c file like this: +
        + mktclapp -f appinit.mta >appinit.c +
      • The *.mta file is just a list of command-line options
      • Enter +
        + mktclapp -help +
        + to get a list of available options
      • Look at MTA files generated by xmktclapp.tcl for examples

      +


      +

      Format Of An MTA File

      + + + + + + + + + + + + + + + + + + + +
      +# Configuration file generated by xmktclapp
      +# Hand editing is not recommended
      +#
          Comments begin with one #
      +## Autofork No
      +## CFile:add.c 1
      +## CFile:objadd.c 1
      +## CmdLine Console
      +## ConfigFile hw.mta
      +## Data:check.gif 1
      +## MainScript hw.tcl
      +## Mode Tcl/Tk
      +## NoSource No
      +## OutputFile hw.c
      +## Shroud No
      +## Standalone Yes
      +## TclFile:hw.tcl 1
      +## TclLib /usr/lib/tcl8.0
      +## TkLib /usr/lib/tk8.0
          Lines beginning with two #s are used + by xmktclapp.tcl and ignored by mktclapp
      +-console
      +-main-script "hw.tcl"
      +-tcl-library "/usr/lib/tcl8.0"
      +-tk-library "/usr/lib/tk8.0"
      +"add.c"
      +"objadd.c"
      +-i "check.gif"
      +-strip-tcl "hw.tcl"
          All other lines are read by mktclapp and + ignored by xmktclapp.tcl
      + +


      +

      Summary

      +

      • Use Tcl for the things Tcl is good at and use C/C++ for the things that + C/C++ is good at
      • Use wrapper programs to make pure Tcl programs standalone
      • Use mktclapp to combine Tcl/Tk with C/C++ into a standalone

      +


      diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image1 b/ext/tk/sample/tkextlib/tkHTML/page4/image1 new file mode 100644 index 0000000000000000000000000000000000000000..da26d7092e2ab1e6b127f2af153e5e42af7a6e13 GIT binary patch literal 42 lcmZ?wbhEHbWMp7u_`m=Kia%KxK};PG0g_>0Vq{^k1^|0{1S$Xk literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image2 b/ext/tk/sample/tkextlib/tkHTML/page4/image2 new file mode 100644 index 0000000000000000000000000000000000000000..e176a96a552e45de1ad70b5b117af0fdb7262eea GIT binary patch literal 14343 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 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image3 b/ext/tk/sample/tkextlib/tkHTML/page4/image3 new file mode 100644 index 0000000000000000000000000000000000000000..e829d3712cc41f9c50aab42628a353613f90d914 GIT binary patch literal 17750 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 ktU1IvNvk&5D6v72jUnGDYMPxzdUHvR*Hpt zhhwjX;+=wS7Dpig9&gPnT`HU63h(6kD5bQD&wVDi%OIfB;ZCAZgwPG$qg%w{MP>-I zDiyPZGi!82>$-(&G54#bDrW1{%QdCvhTA!&b1>8@HZU|z7G{}}ljpP0&`M5_!5RP; CszJU0 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image7 b/ext/tk/sample/tkextlib/tkHTML/page4/image7 new file mode 100644 index 0000000000000000000000000000000000000000..ba0d26ec18af4fb51381a116c29fcba4ba4e7204 GIT binary patch literal 149 zcmZ?wbh9u|6lD-)_{0DL3JMAq7M7Kj)xEvl`}XaQ}^zpAOs(RwO^8P#~hE2l$) zEUUPEqYGO*CWAYbr3dPH!(z%rUCUnk^*AU=09@Swd?7 literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/image9 b/ext/tk/sample/tkextlib/tkHTML/page4/image9 new file mode 100644 index 0000000000000000000000000000000000000000..f0a352f9d0d29417442469d7f2d5c395233f29f2 GIT binary patch literal 1504 zcma)#{Xf$Q0LQ;uvdu$A%S99$wrtc{iq(sy!o0Ybr)H(3Xk*AQPd#WBw&_j}Os0;E z&3f1Cgjio4g2|KQ%gecrG4>-F&?`FePsECsMYn;uw2uh#>3 zJf2EjU0nbm001fg;8#5!uV0k{fxc@Efj~f|Qdh&Z{(pm8E7!h&_4;VLqS*L~xVy5% znP&`~nwd0|CHr!|(p$k98;63oh=u0borL@jO3ZYbZ&=VIqsD;HqOQekDd@CjF_#H! zNl)bUm4BfgAF|S)_A!VP$#5zuI|XEx%gWC7&%DeG%}PwA!!c({OBg4Jd~6WEki{+r znWn)-alpCSctJ>5S_Jpzt%@B*bP=-fw=%~@0ZIlGIJTUDLLi2QUC`Wi4*eh_sSe$M zQYPN}eMcj`=jl}^MS1Hnt&^-1vfeiLtlX?cH;o*v7}<2Z2QE@t&f9piHc;}C4@aW!- zViw2%|2!Xer0B3b7w&f*P@yYb%gzRRohPN(ID)>Or8@=#n2_+$9{0uexjqLmj(p(> zX-d66(d-5JFxMjYwKUS$!{7&^E3D;Ef@Sq-ja~GnA~A)3H{oqy$wA(sMr{f@ssd($ zaK#9cyIBsf%6GJqLoP@91HHZ(E~gAN#W4EZ7*A+mLm1SiS(6n%tw7(G;AU4CMoeJK zQE<4@{jkLlPU;gZpJW41f2~sMDK|OYA|rCNf6&AfjY&+l87(CvsYC;(acTUZqiRmp8=)aAZ=b@IaBm zPw}&5fvUPvH!K-BzYsT}-oq&17MeddT`IIYb8Si)v-H9d36v7f4r7aE+iLg0qMOkf zuoCA_m5bjW6%_M6HbF05+0~+q%y{Tg!P!M>i?`lu9zc{>Pg9gvJjC=*@S*orh#>M# z-ni=@!q8JR5O1SK4=pBHX@7+?ol$3Q7ZS$U<36A6-HlZ_UMGpP2xROla1*~Qs**w++p>g&x}9;;L4*f@6=OygfWi+T&$EChtZ+eH3zsyx^; zc}5meL^(pwyJJE8tS~OOfe@v_DK-mxr@mA9w)2i^UBnE%1e^J?zc^}XBJ35#cq#p> zi1wgQtq(@EXxtJTEubOorL=Lry|V0eeYF1r7lIqgM^!pCq$r(#FKrglW^|jEgTKsq zd6mY^Ki((xzuSwGV+z!LG8BJfopy3Xb1NacT3fMF>|*OA_t-pRvJ%xA(e$s}q~U(X zoUkcLnXMamXEjYY(Dm%2oaZ|^3c-KOHKTIn$7vmS2kpx`dd7;adr7xf#XklhTdU|- z56Zgh%kPn&d_pQi6l_u91-6M2Y|i*0rnxR A_5c6? literal 0 HcmV?d00001 diff --git a/ext/tk/sample/tkextlib/tkHTML/page4/index.html b/ext/tk/sample/tkextlib/tkHTML/page4/index.html new file mode 100644 index 0000000000..c7bfde35a5 --- /dev/null +++ b/ext/tk/sample/tkextlib/tkHTML/page4/index.html @@ -0,0 +1,768 @@ + + + +[fm] welcome to freshmeat.net + + + +
      +
      +
      +
      + + + + + +
      freshmeat.net +
      +find:
      +linux.com partner
      + + + + +
      news |
      +appindex |
      +editorials |
      lounge |
      +contribute |
      +feedback |
      about |
      +awards |
      +FAQ |
      + +
      + +
      +
      + + + +sort by: [ date | name | urgency ]
       
      + +
      +We should get this out of the door now
      +scoop - January 29th 2000, 23:59 EST +

      Everyone else is talking about it, so we should announce it ourselves +before you start to think it's a government hoax. Server 51 is our new hosting service for Open Source projects, based on Super Cool Space Alien Technology(TM). We hadn't planned to announce it quite so soon, and it's still in the alpha stage as we work day and night at integrating SCSAT with our terrestrial systems, but feel free to take a look around and see what's going on. When we're out of the testing stage and ready to make room for your project, we'll send word via your implants. Be listening. + + + +

      [ comments (8) ] +

      Category: freshmeat + + homepage   +
      +
      + + +
      + +
      +Is Linux for Crazies?
      +jeff covey - January 29th 2000, 23:59 EST +

      Ray Woodcock writes: "In terms relevant to Linux, this freshmeat +editorial glances at the tendency of mainstream viewpoints to dismiss +other viewpoints as 'fringe,' the propensity of dissident movements to +splinter into factions before they can effectively counter their +primary adversaries, and the difficulty of creating stability without +squelching curiosity." +

      [ comments (2), 2065 words in body ] +

      Category: Editorial + +   +
      +
      + + +
      + +
      +RabbIT 2.0.2
      +Ernimril - January 29th 2000, 18:29 EST +

      RabbIt is the mutating, caching webproxy which is used to speed up surfing over slow links like modems. It does this by removing advertising and background images and scaling down images to low quality JPEGs. RabbIT is written in Java and should be able to run on any platform. It does depend upon an image converter if imagescaleing is on. The recommended image converter is "convert" from the ImageMagick package.

      +

      Changes: Fixes have been made for a few bugs concerning keep alive and the HTTP response header, a bug with NT and cache directories, a bug concerning requests without a response body, a bug in GZIPHandler that caused it to not gzip already compressed (gzip or compress) streams, a bug in HTTPHeader regarding response phrases that are multiline, and a few bugs in ImageHandler and NCache. GZIPHandler has been built as an intermediate(*) to FilterHandler (this means that it is possible to gzip text/plain, etc., without filtering those streams) uuencoding has been added to the Coder, RabbIT now uses HTTP/1.1, HTMLParser now compiles cleanly with Jikes, and GeneralHeader has been created to allow for HTTPFooter (which is useful when sending chunked data). +

      Urgency: low +

      [ comments (0) ] +

      License: freely distributable
      + Category: Daemons/Proxy
      +download homepage appindex record   +
      +
      + + +
      + +
      +nmpg 1.1.3
      +Joel Lindau - January 29th 2000, 18:18 EST +

      nmpg is a small command-driven frontend and network-jukebox for mpg123.

      +

      Changes: Bugfixes, better memory managment, a new .nmpgrc parser, and new options. +

      Urgency: low +

      [ comments (0) ] +

      License: OpenSource
      + Category: Console/Sound
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +mod_dtcl 0.7.3
      +David Welton - January 29th 2000, 18:11 EST +

      Mod_dtcl is a free/open source implementation of server-parsed Tcl under Apache. It allows you to tightly integrate HTML with Tcl, a widely-used scripting language with many years of development invested in it. There are also many external Tcl modules that you can load into mod_dtcl, to create images, access databases, etc.

      +

      Changes: A major overhaul of header handling and internal buffering, and the addition of the ability to handle binary data. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Web/Development
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +CoreLinux++ 0.4.6
      +Frank V. Castellucci - January 29th 2000, 18:07 EST +

      CoreLinux++ is an initiative to normalize methods and conventions for OOA/OOD/C++ development for Linux, materialized in a set of Open Source C++ class libraries (libcorelinux++ and libcoreframework++) to support common patterns and exploit the C++ standards.

      +

      Changes: This release adds AbstractFactory and AssociativeIterator analysis, design, implementations, test code, a CVS daily tarball, a Patch Submission facility and updated FAQ, Web Pages, and defect reporting guidelines. +

      Urgency: medium +

      [ comments (0) ] +

      License: LGPL
      + Category: Development/Libraries
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +scribe 0.2
      +ChromeBob - January 29th 2000, 12:12 EST +

      scribe writes functions prototypes for your C code, so you don't have to. It also compares unique functions between source code files and will 'extern' when appropriate. C++ methods support is also planned.

      +

      Changes: A fix for an fflush() bug and better documentation. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Development/Tools
      +download homepage appindex record   +
      +
      + + +
      + +
      +E theme updater 0.1
      +Hallvar Helleseth - January 29th 2000, 12:04 EST +

      E theme Updater is a bash script to automatically update all of your Enlightenment themes from e.themes.org.

      +

      Changes: Initial release. + +

      [ comments (0) ] +

      License: GPL
      + Category: Console/Misc
      +download homepage appindex record   +
      +
      + + +
      + +
      +Powertweak-Linux 0.1.7
      +Dave Jones - January 29th 2000, 12:03 EST +

      Powertweak-Linux is a port of the Microsoft Windows tool of the same name rewritten from the ground up. Its main function is to tune your system to its optimal performance settings. Currently, it tunes PCI chipsets and can set /proc/sys entries.

      +

      Changes: A major GUI overhaul, the ability to generate configuration files, extended PCI information tabs, extra information support for the Matrox G200, and numerous other bugfixes & improvements. +

      Urgency: low +

      [ comments (2) ] +

      License: GPL
      + Category: Console/System
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +Pexeso Beta
      +Pavol Krigler - January 29th 2000, 11:55 EST +

      pexeso is a simple graphic card game for one or two players.

      +

      Changes: Initial public release. + +

      [ comments (0) ] +

      License: Freeware
      + Category: Console/Games
      +download homepage appindex record   +
      +
      + + +
      + +
      +XZX 2.9.2
      +E. Kunze - January 29th 2000, 11:54 EST +

      XZX is a portable emulator of ZX Spectrum 48K/128K/+3 (8-bit home computers made by Sir Clive Sinclair) and Pentagon/Scorpion (Spectrum clones made in Russia) for machines running UNIX and the X Window system. XZX is completely written in C and emulates Spectrum 48K, 128K, +2 and +3, Pentagon and Scorpion, Interface I with up to 8 microdrives, Multiface 128 and Multiface 3, BetaDisk 128 interface by Technology Research Ltd with 4 disk drives, +D interface by Miles Gordon Technology with 2 disk drives, Kempston mouse, Kempston joystick and built-in machine code monitor.

      +

      Changes: Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES. +

      Urgency: low +

      [ comments (0) ] +

      License: Shareware
      + Category: X11/Emulators
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +DistroLib 0.4
      +PhiR - January 29th 2000, 11:54 EST +

      DistroLib is an abstraction library designed to make the development of distributed application easier. Its main target is currently compute-bound tasks based on a one server, many clients model (much like distributed.net), but it is quite generic and could be used for any client/server app. It is lightweight, easy-to-use, and relies heavily on threads.

      +

      Changes: Important bug fixes and command history support. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Development/Libraries
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +ToutDoux 1.1.7
      +yeupou - January 29th 2000, 11:54 EST +

      ToutDoux is a project manager which lets you design a plan of action using a tree structure, with translations in French and English.

      +

      Changes: A new menu and XML standard for save files. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: GNOME/Tools
      +download homepage appindex record   +
      +
      + + +
      + +
      +goMP 1.0.3
      +Gautier - January 29th 2000, 11:52 EST +

      goMP is a set of CGI scripts that allows you to remotely control, via a Web browser, a computer acting as an MP3 jukebox. This program is very useful for someone who's got a dedicated computer with a lot of MP3 files but that doesn't have any output and input devices except network and sound card. It's main advantages are built-in cataloging, fast access to music, and no special software needed on the client side.

      +

      Changes: Bugfixes, a password-protected config page, basic search function, easier installation thanks to an install script, and relocation of HTML docs and CGIs to a subdirectory. +

      Urgency: medium +

      [ comments (0) ] +

      License: Artistic
      + Category: Web/Tools
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +APSEND 1.40
      +M.K. - January 29th 2000, 11:50 EST +

      APSEND is a TCP/IP packet sender to test firewalls and other network applications. It also includes a syn flood option, the land DoS attack, and a DoS attack against tcpdump running on a UNIX-based system. Future updates will include support for a scripting language to construct TCP packets and a few more options and protocols like UDP and ICMP. A port of APSEND from Perl to C is planned as well.

      +

      Changes: The stream attack, bugfixes, and rewrites for parts of the code. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Console/Networking
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +ecasound 1.6.12r10
      +Kai Vehmanen - January 29th 2000, 11:48 EST +

      Ecasound is a software package designed for multitrack audio processing. It can be used for simple tasks like audio playback, recording and format conversions, as well as for multitrack effect processing, mixing, recording and signal recycling. Ecasound supports a wide range of audio inputs, outputs and effect algorithms. Ecasound has a chain-based design that allows effects to be easily combined both in series and in parallel. Oscillators and MIDI-CCs can be used for controlling effect parameters. Includes a versatile console mode interface, a Qt-based X-interface and various command-line utils suitable for batch processing.

      +

      Changes: Support for 24- and 32-bit audio formats and for ALSA 0.5, multichannel noisegate, a new 2nd order lowpass filter, some ia-mode commands, and various bugfixes and low-level improvements. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Console/Sound
      +download homepage changelog appindex record   +
      +
      + + +
      + +
      +SCEZ 20000129
      +endergone Zwiebeltuete - January 29th 2000, 11:46 EST +

      SCEZ is a library that should make the handling of smart cards (not memory cards) and card readers as simple as possible and be at the same time small and easily portable. Currently supported are Dumb Mouse, CT-API and Towitoko readers and Schlumberger Cryptoflex, Gemplus GPK4000, GSM SIM and Telesec SigG cards. A PKCS#15 implementation is in the design phase. There are ports to PalmOS and MS-Windows available.

      +

      Changes: More card and reader drivers, and an application to read out GSM SIM card (phone book and SMS) and write it to the card. +

      Urgency: low +

      [ comments (0) ] +

      License: BSD type
      + Category: Development/Libraries
      +download homepage appindex record   +
      +
      + + +
      + +
      +Comicq 0.2.0
      +Terminal6 - January 29th 2000, 11:45 EST +

      COMICQ is a command line ICQ messaging tool that allows a user to connect to ICQ using your UIN and password, then sends a message to the destination UIN.

      +

      Changes: Several bugfixes, icq99a compliance, and a new option --ip that allows you to get any user's IP by their UIN. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Console/Communication
      +download homepage appindex record   +
      +
      + + +
      + +
      +senv 0.2
      +Zbyszek Sobiecki - January 29th 2000, 11:44 EST +

      Senv allows you to run programs with a specified environment. It can set uid, gid, root directory, working directory, limits, and environment variables. It is useful in init scripts and as a shell for users for setting resource limits and environment variables. You can create sets of configurations and specify the one to use from command line.

      +

      Changes: Login shell limits and environment setting for users, permanent resource limits for specified groups of users and environment variables, and other minor bugfixes. +

      Urgency: low +

      [ comments (0) ] +

      License: GPL
      + Category: Console/Administration
      +download changelog appindex record   +
      +
      + + +
      + +
      +XZX 2.9.2
      +E. Kunze - January 29th 2000, 10:55 EST +

      XZX is a portable emulator of ZX Spectrum 48K/128K/+3 (8-bit home computers made by Sir Clive Sinclair) and Pentagon/Scorpion (Spectrum clones made in Russia) for machines running UNIX and the X Window system. XZX is completely written in C and emulates Spectrum 48K, 128K, +2 and +3, Pentagon and Scorpion, Interface I with up to 8 microdrives, Multiface 128 and Multiface 3, BetaDisk 128 interface by Technology Research Ltd with 4 disk drives, +D interface by Miles Gordon Technology with 2 disk drives, Kempston mouse, Kempston joystick and built-in machine code monitor.

      +

      Changes: Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES. +

      Urgency: low +

      [ comments (0) ] +

      License: Shareware
      + Category: X11/Emulators
      +download homepage changelog appindex record   +
      +
      + + +

      [ full page for today | yesterday's edition ]
      + +
      + +
      navigator
      +- full page for today
      +- yesterday's edition
      +- new: fm news via NNTP

      +
      + +
      eye catcher
      +Free Shirts
      We give away a free freshmeat t-shirt every week for the best comment added to an application announcement or story posted on freshmeat. +

      #freshmeat
      If you want to chat about what's new on freshmeat and hang out with other fm lounge lizards and the fm staff, head over to #freshmeat on irc.freshmeat.net, part of The Open Projects Network. + 

      +
      + +
      site notes
      +- We should get this out of the door now (Jan 29th)
      +- freshmeat Y2K report (Jan 01st)
      +- Assorted freshmeat notes (Aug 16th)

      +
      + +
      recent editorials
      +- Is Linux for Crazies? (Jan 29th)
      +- A New Business Plan for Free Software (Jan 22nd)
      +- Is Linux Going to Reunite the UNIX Market? (Jan 15th)

      +
      + +
      andover.net
      +
      Mirror Logo

      +- Animation Factory
      +- DaveCentral
      +- FreeCode
      +- Internet Traffic Report
      +- IT Manager's Journal
      +- MediaBuilder
      +- Slashdot
      +- Slaughterhouse
      +- TechMailings
      +- TechSightings
      +

      E-Commerce

      +- ThinkGeek (Stuff for smart masses)

      +
      + +
      supported sites
      +- Userfriendly.org
      +- SecurityFocus
      +- copyleft
      +- Filewatcher
      +- Linux.com
      +- LinuxTelephony
      +- LinuxToday
      +- Openprojects
      +- 32bitsonline
      +- The GNU Project

      +
      + +
      saturday
      +- We should get this out of the door now
      +- Is Linux for Crazies?
      +- RabbIT 2.0.2
      +- nmpg 1.1.3
      +- mod_dtcl 0.7.3
      +- CoreLinux++ 0.4.6
      +- scribe 0.2
      +- E theme updater 0.1
      +- Powertweak-Linux 0.1.7
      +- Pexeso Beta
      +- XZX 2.9.2
      +- DistroLib 0.4
      +- ToutDoux 1.1.7
      +- goMP 1.0.3
      +- APSEND 1.40
      +- ecasound 1.6.12r10
      +- SCEZ 20000129
      +- Comicq 0.2.0
      +- senv 0.2
      +- XZX 2.9.2
      +- log4j 0.7.5
      +- SQN Linux 1.6
      +- Limo 0.3.2
      +- Fusion GS 1.3
      +- MMR 1.5.4
      +- KUPS 0.3.4
      +- 3DSE patch for XMMS 4
      +- Linux 2.3.41
      +- Free Code for Linux S/390
      +- CircleMUD 3.0 beta patchlevel 17
      +- NiL Isn't Liero 000128
      +- OpenSSH Unix Port 1.2.2
      +- KBoxes! 1.3
      +- phpLanParty 0.23
      +- DGen/SDL 1.20
      +- EdcomLib 1.0 alpha 5
      +- Etherboot 4.4.2
      +- BLADE 0.18.0
      +- Sapphire 0.13.7
      +- ippl 1.99.3
      +- Saint 1.5patch1
      +- Zircon 1.18.232
      +- nmap 2.3BETA14
      +- xterm patch #124
      +- MyThreads-Links v0.5.2
      +- sudo 1.6.2p1
      +- MIT Photonic-Bands 0.10
      +- Launcher 0.86
      +- nano 0.8.1
      +- Gtk-- 1.1.8
      +- tkchooser 0.65
      +- XShipWars 1.33a
      +- Lamerpad 0.1

      +
      + +
      friday
      +- fsv 0.9
      +- popsneaker 0.1.1
      +- eyep-updater.sh 1.0
      +- W3Mail 0.5.0
      +- The Urgent Decision 0.9.9
      +- LTSP 1.02
      +- Production BASIC 0.2.12
      +- Postfix 19991231-pl03
      +- Mp3 Commander 0.7
      +- iManager 1.0.1b
      +- Eterm 0.9
      +- dqd_dirindex 1.0
      +- Tidings 1.0.4
      +- localscan 2.1
      +- WMKeyboard 0.3
      +- fcmp 1.0.2
      +- Akkord 0.3.1
      +- HiM 0.1.1
      +- cdrecord 1.8
      +- eMixer 0.05.5
      +- FreeVSD 1.4.0
      +- Common C++ Libraries 0.0
      +- Moonshine 1.0beta2
      +- swim 0.3.5
      +- Xmame/xmess 0.36b15.1
      +- pcmcia-cs 3.1.9
      +- gPS 0.5.2
      +- Snort 1.5.1
      +- Pygmy Linux 0.7 beta
      +- Intro to Bash Programming HOWTO 0.3
      +- GNU Pth 1.3b2
      +- Laonux 0.1
      +- x-wvdial 0.12
      +- Intro to Bash Programming HOWTO 0.3
      +- Catalog 1.02
      +- harvest 1.5.20-kj-0.9
      +- wmseti 0.3.0a
      +- RIG 1.02
      +- FreeAddr 0.2
      +- GtkAda 1.2.5
      +- dot.conf 0.6.0
      +- dep.pl 1.28.0
      +- Prae's Scripts 1.1
      +- Project Clock 0.1
      +- Xtheater 0.2.1
      +- i-no Chart 0.1
      +- spliff 0.8.1
      +- Regexx 0.95
      +- RBook 0.5.0
      +- RIG 1.01
      +- wchat 1.2.0
      +- PCCS MySQLDatabase Admin Tool 1.2.2

      +
      + +
      thursday
      +- CADUBI 1.1b1
      +- Angus' Chess Clock 0.8.1
      +- MP3 Report Generator 1.0.0
      +- 4DOM 0.9.2
      +- 4XSLT 0.8.2
      +- OpenNaken 1.10
      +- iManager 1.0b
      +- QuakeForge 0.1.0
      +- pylice 0.7.0
      +- Solfege 0.6.0
      +- xinetd 2.1.8.7p1
      +- jac 0.13
      +- Xmms 1.0.0
      +- KSrnd 0.97
      +- getpg / UW-IMAP 0.54
      +- getpg 0.53
      +- setserial 2.17
      +- Pan 0.7.3
      +- jwhois 2.4.1
      +- Kmp3 1.0
      +- xPine 0.0.12
      +- Avenger's News System 2.1 Alpha
      +- RIG 1.0
      +- scroller 1.0
      +- Perl EyeP Client 0.1
      +- sfront 0.54
      +- XFrisk 1.2
      +- Moffy 0.0.1
      +- Solid POP3 0.14
      +- php3guest 1.5
      +- crUD 01.27.2000
      +- crUD 01.27.2000
      +- Free Pascal Compiler 0.99.14
      +- gtk-font-hack 0.2-gtk-1.2.6
      +- Linux 2.2.15pre5
      +- krunseti 0.2.1
      +- CompuPic 5.0.1036
      +- gfontview 0.3.3
      +- authlocal 1.0.2
      +- bigwig 1.1
      +- CAFire 0.0.11
      +- ANVLOGIN 2.0
      +- sawmill.el 1.9
      +- Perlsh 20000127
      +- sitescooper 2.1.2
      +- MHDns 1.4
      +- JChemPaint 0.5
      +- Filesystems HOWTO 0.7.3
      +- KSnes9x 1.2
      +- Mozilla M13
      +- edna 0.3
      +- GMasqdialer 0.99.8
      +- spliff 0.8
      +- MultiSeti 0.3
      +- rude 0.50
      +- cgi-util++ 0.0
      +- Cricket 0.72
      +- nuni 0.04
      +- Ksetiwatch 0.3.0
      +- SiteMgrYAP 0.1.2
      +- phpLanParty 0.21
      +- Glitter Newsreader 0.1
      +- Fastresolve 2.4
      +- ColdSync 1.1.2
      +- DDD 3.2
      +- X Northern Captain 4.2.1
      +- abcde 1.0.2
      +- Gnapster 1.3.2
      +- xmix 1.0 Alpha
      +- gtktetcolor 0.3
      +- muttzilla 0.40
      +- muttzilla 0.40
      +- asp2php 0.73.6
      +- mod_ticket 1.0
      +- MegaHAL for Eggdrop .01
      +- Jetty 2.3.5
      +- xlpotdb 1.0
      +- Koala Complete MUD Server 0.1.1a
      +- mcountd 0.4
      +- cdbackup 0.5.0
      +- The Java SSH/Telnet Application/Applet 2.0 RC1

      +
      + +
      slashdot
      +- Petition Apple for Linux QuickTime
      +- GNUstep 0.6.5 freeze
      +- YETI@Home
      +- Documents Unsealed in Microsoft/Caldera Case
      +- Who Bought Linux.Net?
      +- E-Mails from (Over?) The Edge
      +- Linux Kernel 2.3.41
      +- Congress Still Figuring Out E-Mail
      +- Sci Fi Literature 101?
      +- Could Distributed.Net Help the Mars Polar Lander?

      +
      + +
      securityfocus
      +- Win2000 security hole a 'major threat'
      +- Visa acknowledges cracker break-ins
      +- What's Wrong With Microsoft Security?
      +- Microsoft posts first Win2K security patch
      +- Libnids 1.12
      +- New hack attack is greater threat than imagined
      +- Student charged with hacking
      +- Building and Managing Virtual Private Networks (book)
      +- Threats, Vulnerabilities and Real-Worl Responses: The Foundations of the TruSecure Process
      +- The Hundredth Window : Protecting Your Privacy and Security in the Age of the Internet (boo

      +
      + +
      bebits
      +- Pe 3.0a3
      +- Rarscript 1.5
      +- CD Manager 0.66a beta
      +- TraX 1.1
      +- BeMath 1.2.2
      +- simple blackjack 1
      +- HtmlTree 0.5.3
      +- Yacp 0.1
      +- TicTacToe 1.5
      +- Pe 3.0a2

      +
      + +
      linuxtoday
      +- Linux Journal: KDE--The Next Generation
      +- Kernel Cousin gimp-devel #11 Is Out
      +- Infoworld: Corel Linux OS ideal for the desktop
      +- Technology Evaluation: IBM Jumps on the Linux Bandwagon with Both Feet, Sort Of
      +- Tobias Hvekamp: European Union acknowledges
      +- &
      +- #34;Open Source Software
      +- &
      +- #34;

      +
      + +
      linuxtelephony
      +- Traverse Technologies releases NETspider-U in US
      +- Quicknet releases new GPL'd Linux Drivers!
      +- Natural Microsystems Delivers Carrier-Class Linux
      +- Quicknet is hiring programmers of all kinds!
      +- Babylon MLPPP Software Released under GPL
      +- Linux Telephony Server Project?
      +- Vovida Networks to Hire Telephony Software Engineers
      +- SPIRO-Linux Introduces Web-Enabled Phone Administration
      +- LinuxTelephony sponsors area at LinuxFest 2000
      +- GSM-Mobile Switching Center (MSC) with Linux-PC

      +
      + +
      32bitsonline
      +- Game: Homeworld
      +- DVD Lawsuit Spreads Its Own 'Trade Secrets'
      +- Register.com Adds 'One-step' Domain Registration
      +- WebEvent: Keeping you organized
      +- Y2K Officers Defend $100 Bil Investment
      +- DON'T BE FOOLED
      +- Microsoft Scorns Think-Tank's Breakup Idea
      +- Yahoo Accused Of Stalking Internet Users
      +- eToys.com Settles Spat With Swiss Artist Group
      +- [more articles/news]

      +

      +

      + +
      +
      + + +
      copyright 1997-2000 Andover.Net - +icons courtesy of tigert@gimp.org - +code revision 20000101 - +our privacy policy
      + + + + diff --git a/ext/tk/sample/tkextlib/tkHTML/ss.rb b/ext/tk/sample/tkextlib/tkHTML/ss.rb new file mode 100644 index 0000000000..e71c26f7dc --- /dev/null +++ b/ext/tk/sample/tkextlib/tkHTML/ss.rb @@ -0,0 +1,404 @@ +#!/usr/bin/env ruby +# +# This script implements the "ss" application. "ss" implements +# a presentation slide-show based on HTML slides. +# +require 'tk' +require 'tkextlib/tkHTML' + +root = TkRoot.new(:title=>'HTML File Viewer', :iconname=>'HV') +fswin = nil + +html = nil +html_fs = nil + +hotkey = {} + +file = ARGV[0] + + +# These are images to use with the actual image specified in a +# "" markup can't be found. +# +biggray = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhPAA+APAAALi4uAAAACwAAAAAPAA+AAACQISPqcvtD6OctNqLs968+w+G4kiW5omm + 6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNFgsAO/// +EOD + +smgray = TkPhotoImage.new(:data=><<'EOD') + R0lGODdhOAAYAPAAALi4uAAAACwAAAAAOAAYAAACI4SPqcvtD6OctNqLs968+w+G4kiW5omm + 6sq27gvH8kzX9m0VADv/ +EOD + + +# +# A font chooser routine. +# +# html[:fontcommand] = pick_font +pick_font = proc{|size, attrs| + # puts "FontCmd: #{size} #{attrs}" + [ ((attrs =~ /fixed/)? 'courier': 'charter'), + (12 * (1.2**(size.to_f - 4.0))).to_i, + ((attrs =~ /italic/)? 'italic': 'roman'), + ((attrs =~ /bold/)? 'bold': 'normal') ].join(' ') +} + +# This routine is called to pick fonts for the fullscreen view. +# +baseFontSize = 24 +pick_font_fs = proc{|size, attrs| + # puts "FontCmd: #{size} #{attrs}" + [ ((attrs =~ /fixed/)? 'courier': 'charter'), + (baseFontSize * (1.2**(size.to_f - 4.0))).to_i, + ((attrs =~ /italic/)? 'italic': 'roman'), + ((attrs =~ /bold/)? 'bold': 'normal') ].join(' ') +} + +# +# +hyper_cmd = proc{|*args| + puts "HyperlinkCommand: #{args.inspect}" +} + +# This routine is called to run an applet +# +applet_arg = TkVarAccess.new_hash('AppletArg') +run_applet = proc{|size, w, arglist| + applet_arg.value = Hash[*simplelist(arglist)] + + return unless applet_arg.key?('src') + + src = html.remove(applet_arg['src']) + + applet_arg['window'] = w + applet_arg['fontsize'] = size + + begin + Tk.load_tclscript(src) + rescue => e + puts "Applet error: #{e.message}" + end +} + +# +# +form_cmd = proc{|n, cmd, *args| +} + +# +# +images = {} +old_imgs = {} +big_imgs = {} + +# +# +move_big_image = proc{|b| + return unless big_imgs.key?(b) + b.copy(big_imgs[b]) + big_imgs[b].delete + big_imgs.delete(b) +} + +image_cmd = proc{|hs, *args| + fn = args[0] + + if old_imgs.key?(fn) + return (images[fn] = old_imgs.delete(fn)) + end + + begin + img = TkPhotoImage.new(:file=>fn) + rescue + return ((hs)? smallgray: biggray) + end + + if hs + img2 = TkPhotoImage.new + img2.copy(img, :subsample=>[2,2]) + img.delete + img = img2 + end + + if img.width * img.height > 20000 + b = TkPhotoImage.new(:width=>img.width, :height=>img.height) + big_imgs[b] = img + img = b + Tk.after_idle(proc{ move_big_image.call(b) }) + end + + images[fn] = img + + img +} + + +# +# This routine is called for every